Commit 20fa8d5c by Jamie Madill Committed by Commit Bot

Vulkan: Implement cube map texture sampling.

This changes the TextureVk class to have a queue of staging copies, instead of a single copy at a time. This will allow us to upload multiple sub regions of a texture image at once when we need to resolve the Image at sampling time. Enables the remainder of the texture.format tests, and all non-mipped tests in the texture.size tests. Also updates the expectations with the bug number for mipmap support. Bug: angleproject:2318 Change-Id: Ie55f8f2dc24d7b133ad735e37f0f78937f022b5b Reviewed-on: https://chromium-review.googlesource.com/980775Reviewed-by: 's avatarLuc Ferron <lucferron@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 016105bb
#include "ImageIndex.h"
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
......@@ -8,8 +7,10 @@
// ImageIndex.cpp: Implementation for ImageIndex methods.
#include "libANGLE/ImageIndex.h"
#include "libANGLE/Constants.h"
#include "common/utilities.h"
#include "libANGLE/Constants.h"
#include "libANGLE/angletypes.h"
#include <tuple>
......@@ -99,7 +100,7 @@ TextureTarget ImageIndex::getTarget() const
GLint ImageIndex::cubeMapFaceIndex() const
{
ASSERT(mType == TextureType::CubeMap);
ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < 6);
ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(CUBE_FACE_COUNT));
return mLayerIndex;
}
......@@ -149,7 +150,9 @@ ImageIndex ImageIndex::MakeFromType(TextureType type,
GLint layerIndex,
GLint layerCount)
{
return ImageIndex(type, levelIndex, layerIndex, layerCount);
GLint overrideLayerCount =
(type == TextureType::CubeMap && layerIndex == kEntireLevel ? CUBE_FACE_COUNT : layerCount);
return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
}
ImageIndex ImageIndex::Make2DMultisample()
......
......@@ -81,7 +81,7 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context,
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
ANGLE_TRY(mImage.init2D(device, extents, vkFormat, 1, usage));
ANGLE_TRY(mImage.init(device, gl::TextureType::_2D, extents, vkFormat, 1, usage));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
......@@ -91,7 +91,8 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context,
(textureFormat.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0) |
(textureFormat.redBits > 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0);
ANGLE_TRY(mImage.initImageView(device, aspect, gl::SwizzleState(), &mImageView));
ANGLE_TRY(mImage.initImageView(device, gl::TextureType::_2D, aspect, gl::SwizzleState(),
&mImageView));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
......
......@@ -396,8 +396,8 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
{
SwapchainImage &member = mSwapchainImages[imageIndex];
member.image.init2DWeakReference(swapchainImages[imageIndex], extents, format, 1);
member.image.initImageView(device, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
&member.imageView);
member.image.initImageView(device, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT,
gl::SwizzleState(), &member.imageView);
// Set transfer dest layout, and clear the image to black.
member.image.clearColor(transparentBlack, commandBuffer);
......@@ -418,7 +418,8 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
ANGLE_TRY(mDepthStencilImage.init2D(device, extents, dsFormat, 1, usage));
ANGLE_TRY(
mDepthStencilImage.init(device, gl::TextureType::_2D, extents, dsFormat, 1, usage));
ANGLE_TRY(mDepthStencilImage.initMemory(device, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
......@@ -431,8 +432,8 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
// Set transfer dest layout, and clear the image.
mDepthStencilImage.clearDepthStencil(aspect, depthStencilClearValue, commandBuffer);
ANGLE_TRY(mDepthStencilImage.initImageView(device, aspect, gl::SwizzleState(),
&mDepthStencilImageView));
ANGLE_TRY(mDepthStencilImage.initImageView(device, gl::TextureType::_2D, aspect,
gl::SwizzleState(), &mDepthStencilImageView));
mDepthStencilRenderTarget.resource = this;
mDepthStencilRenderTarget.image = &mDepthStencilImage;
......
......@@ -55,10 +55,11 @@ constexpr size_t kStagingBufferSize = 1024 * 16;
} // anonymous namespace
// StagingStorage implementation.
StagingStorage::StagingStorage()
: mStagingBuffer(kStagingBufferFlags, kStagingBufferSize), mCurrentBufferHandle(VK_NULL_HANDLE)
StagingStorage::StagingStorage() : mStagingBuffer(kStagingBufferFlags, kStagingBufferSize)
{
mStagingBuffer.init(1);
// vkCmdCopyBufferToImage must have an offset that is a multiple of 4.
// https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkBufferImageCopy.html
mStagingBuffer.init(4);
}
StagingStorage::~StagingStorage()
......@@ -71,6 +72,7 @@ void StagingStorage::release(RendererVk *renderer)
}
gl::Error StagingStorage::stageSubresourceUpdate(ContextVk *contextVk,
const gl::ImageIndex &index,
const gl::Extents &extents,
const gl::InternalFormat &formatInfo,
const gl::PixelUnpackState &unpack,
......@@ -103,11 +105,13 @@ gl::Error StagingStorage::stageSubresourceUpdate(ContextVk *contextVk,
size_t outputRowPitch = storageFormat.pixelBytes * extents.width;
size_t outputDepthPitch = outputRowPitch * extents.height;
VkBuffer bufferHandle = VK_NULL_HANDLE;
uint8_t *stagingPointer = nullptr;
bool newBufferAllocated = false;
uint32_t stagingOffset = 0;
size_t allocationSize = outputDepthPitch * extents.depth;
mStagingBuffer.allocate(renderer, allocationSize, &stagingPointer, &mCurrentBufferHandle,
mStagingBuffer.allocate(renderer, allocationSize, &stagingPointer, &bufferHandle,
&stagingOffset, &newBufferAllocated);
const uint8_t *source = pixels + inputSkipBytes;
......@@ -117,16 +121,20 @@ gl::Error StagingStorage::stageSubresourceUpdate(ContextVk *contextVk,
loadFunction.loadFunction(extents.width, extents.height, extents.depth, source, inputRowPitch,
inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
mCurrentCopyRegion.bufferOffset = static_cast<VkDeviceSize>(stagingOffset);
mCurrentCopyRegion.bufferRowLength = extents.width;
mCurrentCopyRegion.bufferImageHeight = extents.height;
mCurrentCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
mCurrentCopyRegion.imageSubresource.mipLevel = 0;
mCurrentCopyRegion.imageSubresource.baseArrayLayer = 0;
mCurrentCopyRegion.imageSubresource.layerCount = 1;
VkBufferImageCopy copy;
copy.bufferOffset = static_cast<VkDeviceSize>(stagingOffset);
copy.bufferRowLength = extents.width;
copy.bufferImageHeight = extents.height;
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy.imageSubresource.mipLevel = index.getLevelIndex();
copy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
copy.imageSubresource.layerCount = index.getLayerCount();
gl_vk::GetOffset(gl::Offset(), &mCurrentCopyRegion.imageOffset);
gl_vk::GetExtent(extents, &mCurrentCopyRegion.imageExtent);
gl_vk::GetOffset(gl::Offset(), &copy.imageOffset);
gl_vk::GetExtent(extents, &copy.imageExtent);
mSubresourceUpdates.emplace_back(bufferHandle, copy);
return gl::NoError();
}
......@@ -135,22 +143,42 @@ vk::Error StagingStorage::flushUpdatesToImage(RendererVk *renderer,
vk::ImageHelper *image,
vk::CommandBuffer *commandBuffer)
{
if (mCurrentBufferHandle != VK_NULL_HANDLE)
if (mSubresourceUpdates.empty())
{
// Conservatively flush all writes to the image. We could use a more restricted barrier.
image->changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
ANGLE_TRY(mStagingBuffer.flush(renderer->getDevice()));
commandBuffer->copyBufferToImage(mCurrentBufferHandle, image->getImage(),
image->getCurrentLayout(), 1, &mCurrentCopyRegion);
mCurrentBufferHandle = VK_NULL_HANDLE;
return vk::NoError();
}
// Conservatively flush all writes to the image. We could use a more restricted barrier.
image->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
ANGLE_TRY(mStagingBuffer.flush(renderer->getDevice()));
for (const SubresourceUpdate &update : mSubresourceUpdates)
{
ASSERT(update.bufferHandle != VK_NULL_HANDLE);
commandBuffer->copyBufferToImage(update.bufferHandle, image->getImage(),
image->getCurrentLayout(), 1, &update.copyRegion);
}
mSubresourceUpdates.clear();
return vk::NoError();
}
StagingStorage::SubresourceUpdate::SubresourceUpdate() : bufferHandle(VK_NULL_HANDLE)
{
}
StagingStorage::SubresourceUpdate::SubresourceUpdate(VkBuffer bufferHandleIn,
const VkBufferImageCopy &copyRegionIn)
: bufferHandle(bufferHandleIn), copyRegion(copyRegionIn)
{
}
StagingStorage::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other) = default;
// TextureVk implementation.
TextureVk::TextureVk(const gl::TextureState &state) : TextureImpl(state)
{
......@@ -190,7 +218,11 @@ gl::Error TextureVk::setImage(const gl::Context *context,
VkDevice device = contextVk->getDevice();
// TODO(jmadill): support multi-level textures.
ASSERT(index.getLevelIndex() == 0);
if (index.getLevelIndex() != 0)
{
UNIMPLEMENTED();
return gl::InternalError();
}
// Convert internalFormat to sized internal format.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
......@@ -211,13 +243,6 @@ gl::Error TextureVk::setImage(const gl::Context *context,
return gl::NoError();
}
// TODO(jmadill): Cube map textures. http://anglebug.com/2318
if (index.getTarget() != gl::TextureTarget::_2D)
{
UNIMPLEMENTED();
return gl::InternalError();
}
if (!mSampler.valid())
{
// Create a simple sampler. Force basic parameter settings.
......@@ -251,8 +276,8 @@ gl::Error TextureVk::setImage(const gl::Context *context,
// Handle initial data.
if (pixels)
{
ANGLE_TRY(mStagingStorage.stageSubresourceUpdate(contextVk, size, formatInfo, unpack, type,
pixels));
ANGLE_TRY(mStagingStorage.stageSubresourceUpdate(contextVk, index, size, formatInfo, unpack,
type, pixels));
}
return gl::NoError();
......@@ -269,8 +294,8 @@ gl::Error TextureVk::setSubImage(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
ANGLE_TRY(mStagingStorage.stageSubresourceUpdate(
contextVk, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack, type,
pixels));
contextVk, index, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack,
type, pixels));
return gl::NoError();
}
......@@ -420,7 +445,8 @@ vk::Error TextureVk::ensureImageInitialized(RendererVk *renderer)
VkImageUsageFlags usage =
(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
ANGLE_TRY(mImage.init2D(device, extents, format, 1, usage));
ANGLE_TRY(mImage.init(device, mState.getType(), extents, format, 1, usage));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
......@@ -428,8 +454,9 @@ vk::Error TextureVk::ensureImageInitialized(RendererVk *renderer)
gl::SwizzleState mappedSwizzle;
MapSwizzleState(format.internalFormat, mState.getSwizzleState(), &mappedSwizzle);
ANGLE_TRY(
mImage.initImageView(device, VK_IMAGE_ASPECT_COLOR_BIT, mappedSwizzle, &mImageView));
// TODO(jmadill): Separate imageviews for RenderTargets and Sampling.
ANGLE_TRY(mImage.initImageView(device, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
mappedSwizzle, &mImageView));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
......
......@@ -27,6 +27,7 @@ class StagingStorage final : angle::NonCopyable
void release(RendererVk *renderer);
gl::Error stageSubresourceUpdate(ContextVk *contextVk,
const gl::ImageIndex &index,
const gl::Extents &extents,
const gl::InternalFormat &formatInfo,
const gl::PixelUnpackState &unpack,
......@@ -38,9 +39,18 @@ class StagingStorage final : angle::NonCopyable
vk::CommandBuffer *commandBuffer);
private:
struct SubresourceUpdate
{
SubresourceUpdate();
SubresourceUpdate(VkBuffer bufferHandle, const VkBufferImageCopy &copyRegion);
SubresourceUpdate(const SubresourceUpdate &other);
VkBuffer bufferHandle;
VkBufferImageCopy copyRegion;
};
vk::DynamicBuffer mStagingBuffer;
VkBuffer mCurrentBufferHandle;
VkBufferImageCopy mCurrentCopyRegion;
std::vector<SubresourceUpdate> mSubresourceUpdates;
};
class TextureVk : public TextureImpl, public vk::CommandGraphResource
......
......@@ -66,6 +66,30 @@ VkAccessFlags GetBasicLayoutAccessFlags(VkImageLayout layout)
return 0;
}
}
VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType)
{
if (textureType == gl::TextureType::CubeMap)
{
return VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
else
{
return 0;
}
}
uint32_t GetImageLayerCount(gl::TextureType textureType)
{
if (textureType == gl::TextureType::CubeMap)
{
return gl::CUBE_FACE_COUNT;
}
else
{
return 1;
}
}
} // anonymous namespace
// DynamicBuffer implementation.
......@@ -422,7 +446,8 @@ ImageHelper::ImageHelper()
: mFormat(nullptr),
mSamples(0),
mAllocatedMemorySize(0),
mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED),
mLayerCount(0)
{
}
......@@ -433,8 +458,11 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mFormat(other.mFormat),
mSamples(other.mSamples),
mAllocatedMemorySize(other.mAllocatedMemorySize),
mCurrentLayout(other.mCurrentLayout)
mCurrentLayout(other.mCurrentLayout),
mLayerCount(other.mLayerCount)
{
other.mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
other.mLayerCount = 0;
}
ImageHelper::~ImageHelper()
......@@ -447,29 +475,31 @@ bool ImageHelper::valid() const
return mImage.valid();
}
Error ImageHelper::init2D(VkDevice device,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage)
Error ImageHelper::init(VkDevice device,
gl::TextureType textureType,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage)
{
ASSERT(!valid());
mExtents = extents;
mFormat = &format;
mSamples = samples;
mExtents = extents;
mFormat = &format;
mSamples = samples;
mLayerCount = GetImageLayerCount(textureType);
VkImageCreateInfo imageInfo;
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = nullptr;
imageInfo.flags = 0;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.flags = GetImageCreateFlags(textureType);
imageInfo.imageType = gl_vk::GetImageType(textureType);
imageInfo.format = format.vkTextureFormat;
imageInfo.extent.width = static_cast<uint32_t>(extents.width);
imageInfo.extent.height = static_cast<uint32_t>(extents.height);
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.arrayLayers = mLayerCount;
imageInfo.samples = gl_vk::GetSamples(samples);
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = usage;
......@@ -506,6 +536,7 @@ Error ImageHelper::initMemory(VkDevice device,
}
Error ImageHelper::initImageView(VkDevice device,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut)
......@@ -515,7 +546,7 @@ Error ImageHelper::initImageView(VkDevice device,
viewInfo.pNext = nullptr;
viewInfo.flags = 0;
viewInfo.image = mImage.getHandle();
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.viewType = gl_vk::GetImageViewType(textureType);
viewInfo.format = mFormat->vkTextureFormat;
viewInfo.components.r = gl_vk::GetSwizzle(swizzleMap.swizzleRed);
viewInfo.components.g = gl_vk::GetSwizzle(swizzleMap.swizzleGreen);
......@@ -525,7 +556,7 @@ Error ImageHelper::initImageView(VkDevice device,
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
viewInfo.subresourceRange.layerCount = mLayerCount;
ANGLE_TRY(imageViewOut->init(device, viewInfo));
return NoError();
......@@ -535,6 +566,8 @@ void ImageHelper::destroy(VkDevice device)
{
mImage.destroy(device);
mDeviceMemory.destroy(device);
mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
mLayerCount = 0;
}
void ImageHelper::init2DWeakReference(VkImage handle,
......@@ -544,9 +577,10 @@ void ImageHelper::init2DWeakReference(VkImage handle,
{
ASSERT(!valid());
mExtents = extents;
mFormat = &format;
mSamples = samples;
mExtents = extents;
mFormat = &format;
mSamples = samples;
mLayerCount = 1;
mImage.setHandle(handle);
}
......@@ -559,9 +593,10 @@ Error ImageHelper::init2DStaging(VkDevice device,
{
ASSERT(!valid());
mExtents = extents;
mFormat = &format;
mSamples = 1;
mExtents = extents;
mFormat = &format;
mSamples = 1;
mLayerCount = 1;
// Use Preinitialized for writable staging images - in these cases we want to map the memory
// before we do a copy. For readback images, use an undefined layout.
......@@ -659,7 +694,7 @@ void ImageHelper::changeLayoutWithStages(VkImageAspectFlags aspectMask,
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
imageMemoryBarrier.subresourceRange.levelCount = 1;
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.layerCount = mLayerCount;
// TODO(jmadill): Test all the permutations of the access flags.
imageMemoryBarrier.srcAccessMask = GetBasicLayoutAccessFlags(mCurrentLayout);
......@@ -701,7 +736,7 @@ void ImageHelper::clearColor(const VkClearColorValue &color, CommandBuffer *comm
range.baseMipLevel = 0;
range.levelCount = 1;
range.baseArrayLayer = 0;
range.layerCount = 1;
range.layerCount = mLayerCount;
commandBuffer->clearColorImage(mImage, mCurrentLayout, color, 1, &range);
}
......
......@@ -12,6 +12,11 @@
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace gl
{
class ImageIndex;
} // namespace gl;
namespace rx
{
namespace vk
......@@ -152,15 +157,17 @@ class ImageHelper final : angle::NonCopyable
bool valid() const;
Error init2D(VkDevice device,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage);
Error init(VkDevice device,
gl::TextureType textureType,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage);
Error initMemory(VkDevice device,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags);
Error initImageView(VkDevice device,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut);
......@@ -224,6 +231,9 @@ class ImageHelper final : angle::NonCopyable
// Current state.
VkImageLayout mCurrentLayout;
// Cached properties.
uint32_t mLayerCount;
};
} // namespace vk
......
......@@ -1278,6 +1278,36 @@ void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent)
vkExtent->height = glExtent.height;
vkExtent->depth = glExtent.depth;
}
VkImageType GetImageType(gl::TextureType textureType)
{
switch (textureType)
{
case gl::TextureType::_2D:
return VK_IMAGE_TYPE_2D;
case gl::TextureType::CubeMap:
return VK_IMAGE_TYPE_2D;
default:
// We will need to implement all the texture types for ES3+.
UNIMPLEMENTED();
return VK_IMAGE_TYPE_MAX_ENUM;
}
}
VkImageViewType GetImageViewType(gl::TextureType textureType)
{
switch (textureType)
{
case gl::TextureType::_2D:
return VK_IMAGE_VIEW_TYPE_2D;
case gl::TextureType::CubeMap:
return VK_IMAGE_VIEW_TYPE_CUBE;
default:
// We will need to implement all the texture types for ES3+.
UNIMPLEMENTED();
return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
}
}
} // namespace gl_vk
} // namespace rx
......
......@@ -658,6 +658,8 @@ VkComponentSwizzle GetSwizzle(const GLenum swizzle);
VkIndexType GetIndexType(GLenum elementType);
void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset);
void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent);
VkImageType GetImageType(gl::TextureType textureType);
VkImageViewType GetImageViewType(gl::TextureType textureType);
} // namespace gl_vk
} // namespace rx
......
......@@ -196,31 +196,39 @@
2161 VULKAN : dEQP-GLES2.functional.buffer.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.light_amount.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.shaders.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.a8_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.l8_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.la88_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.rgb565_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.rgb888_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba4444_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba5551_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.format.rgba8888_cube_pot = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_l8_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba4444_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgb888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba8888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_l8_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba4444_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgb888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba8888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_l8_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba4444_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgb888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba8888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_l8_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba4444_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgb888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba8888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.size.cube.* = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.64x64_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.512x512_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.1024x1024_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.2d.2048x2048_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.16x16_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.64x64_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgba4444_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.128x128_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.256x256_rgba8888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_l8_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_rgb888_mipmap = SKIP
2479 VULKAN : dEQP-GLES2.functional.texture.size.cube.512x512_rgba8888_mipmap = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.wrap.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.filtering.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.* = SKIP
......
......@@ -30,6 +30,11 @@ constexpr char kGreenFragmentShader[] =
gl_FragColor = vec4(0, 1, 0, 1);
})";
constexpr std::array<GLenum, 6> kCubeFaces = {
{GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}};
class SimpleOperationTest : public ANGLETest
{
protected:
......@@ -696,7 +701,7 @@ void main()
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
}
// Creates a texture, no other operations.
// Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest, CreateTexture2DNoData)
{
GLTexture texture;
......@@ -705,7 +710,7 @@ TEST_P(SimpleOperationTest, CreateTexture2DNoData)
ASSERT_GL_NO_ERROR();
}
// Creates a texture, no other operations.
// Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest, CreateTexture2DWithData)
{
std::vector<GLColor> colors(16 * 16, GLColor::red);
......@@ -716,6 +721,32 @@ TEST_P(SimpleOperationTest, CreateTexture2DWithData)
ASSERT_GL_NO_ERROR();
}
// Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest, CreateTextureCubeNoData)
{
GLTexture texture;
glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
for (GLenum cubeFace : kCubeFaces)
{
glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
ASSERT_GL_NO_ERROR();
}
// Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest, CreateTextureCubeWithData)
{
std::vector<GLColor> colors(16 * 16, GLColor::red);
GLTexture texture;
glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
for (GLenum cubeFace : kCubeFaces)
{
glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
}
ASSERT_GL_NO_ERROR();
}
// Creates a program with a texture.
TEST_P(SimpleOperationTest, LinkProgramWithTexture)
{
......@@ -723,8 +754,8 @@ TEST_P(SimpleOperationTest, LinkProgramWithTexture)
ASSERT_GL_NO_ERROR();
}
// Creates a program with a texture and renders with it.
TEST_P(SimpleOperationTest, DrawWithTexture)
// Creates a program with a 2D texture and renders with it.
TEST_P(SimpleOperationTest, DrawWith2DTexture)
{
std::array<GLColor, 4> colors = {
{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
......@@ -793,6 +824,138 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
}
// Creates a program with a cube texture and renders with it.
TEST_P(SimpleOperationTest, DrawWithCubeTexture)
{
std::array<Vector2, 6 * 4> positions = {{
{0, 1}, {1, 1}, {1, 2}, {0, 2} /* first face */,
{1, 0}, {2, 0}, {2, 1}, {1, 1} /* second face */,
{1, 1}, {2, 1}, {2, 2}, {1, 2} /* third face */,
{1, 2}, {2, 2}, {2, 3}, {1, 3} /* fourth face */,
{2, 1}, {3, 1}, {3, 2}, {2, 2} /* fifth face */,
{3, 1}, {4, 1}, {4, 2}, {3, 2} /* sixth face */,
}};
const float w4 = 1.0f / 4.0f;
const float h3 = 1.0f / 3.0f;
// This draws a "T" shape based on the four faces of the cube. The window is divided into four
// tiles horizontally and three tiles vertically (hence the w4 and h3 variable naming).
for (Vector2 &pos : positions)
{
pos.data()[0] = pos.data()[0] * w4 * 2.0f - 1.0f;
pos.data()[1] = pos.data()[1] * h3 * 2.0f - 1.0f;
}
const Vector3 posX(1, 0, 0);
const Vector3 negX(-1, 0, 0);
const Vector3 posY(0, 1, 0);
const Vector3 negY(0, -1, 0);
const Vector3 posZ(0, 0, 1);
const Vector3 negZ(0, 0, -1);
std::array<Vector3, 6 * 4> coords = {{
posX, posX, posX, posX /* first face */, negX, negX, negX, negX /* second face */,
posY, posY, posY, posY /* third face */, negY, negY, negY, negY /* fourth face */,
posZ, posZ, posZ, posZ /* fifth face */, negZ, negZ, negZ, negZ /* sixth face */,
}};
const std::array<std::array<GLColor, 4>, 6> colors = {{
{GLColor::red, GLColor::red, GLColor::red, GLColor::red},
{GLColor::green, GLColor::green, GLColor::green, GLColor::green},
{GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
{GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
{GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
}};
GLTexture texture;
glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
{
glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
colors[faceIndex].data());
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
constexpr char kVertexShader[] = R"(attribute vec2 pos;
attribute vec3 coord;
varying vec3 texCoord;
void main()
{
gl_Position = vec4(pos, 0, 1);
texCoord = coord;
})";
constexpr char kFragmentShader[] = R"(precision mediump float;
varying vec3 texCoord;
uniform samplerCube tex;
void main()
{
gl_FragColor = textureCube(tex, texCoord);
})";
ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
GLint samplerLoc = glGetUniformLocation(program, "tex");
ASSERT_EQ(samplerLoc, 0);
glUseProgram(program);
GLint posLoc = glGetAttribLocation(program, "pos");
ASSERT_NE(-1, posLoc);
GLint coordLoc = glGetAttribLocation(program, "coord");
ASSERT_NE(-1, coordLoc);
GLBuffer posBuffer;
glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(Vector2), positions.data(),
GL_STATIC_DRAW);
glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(posLoc);
GLBuffer coordBuffer;
glBindBuffer(GL_ARRAY_BUFFER, coordBuffer);
glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(Vector3), coords.data(), GL_STATIC_DRAW);
glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(coordLoc);
auto quadIndices = GetQuadIndices();
std::array<GLushort, 6 * 6> kElementsData;
for (GLushort quadIndex = 0; quadIndex < 6; ++quadIndex)
{
for (GLushort elementIndex = 0; elementIndex < 6; ++elementIndex)
{
kElementsData[quadIndex * 6 + elementIndex] = quadIndices[elementIndex] + 4 * quadIndex;
}
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLBuffer elementBuffer;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kElementsData.size() * sizeof(GLushort),
kElementsData.data(), GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(kElementsData.size()), GL_UNSIGNED_SHORT,
nullptr);
ASSERT_GL_NO_ERROR();
for (int faceIndex = 0; faceIndex < 6; ++faceIndex)
{
int index = faceIndex * 4;
Vector2 center = (positions[index] + positions[index + 1] + positions[index + 2] +
positions[index + 3]) /
4.0f;
center *= 0.5f;
center += Vector2(0.5f);
center *= Vector2(getWindowWidth(), getWindowHeight());
EXPECT_PIXEL_COLOR_EQ(center.x(), center.y(), colors[faceIndex][0]);
}
}
// Tests rendering to a user framebuffer.
TEST_P(SimpleOperationTest, RenderToTexture)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment