Commit eb0479e2 by Cody Northrop Committed by Commit Bot

Vulkan: Texture 3D and 2DArray layers as framebuffer attachments

Support glFramebufferTextureLayer by correctly handling layers from 3D and 2DArray textures. Modeled after CubeMap layers support. Bug: angleproject:3188 Bug: angleproject:3189 Change-Id: Ic73a6017134e9d2b49beed103487454397a97167 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1738436Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Cody Northrop <cnorthrop@google.com>
parent bd203b57
...@@ -1439,9 +1439,23 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1439,9 +1439,23 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
size_t level = renderTarget->getLevelIndex(); size_t level = renderTarget->getLevelIndex();
size_t layer = renderTarget->getLayerIndex(); size_t layer = renderTarget->getLayerIndex();
VkOffset3D srcOffset = {area.x, area.y, 0}; VkOffset3D srcOffset = {area.x, area.y, 0};
VkImageSubresourceLayers srcSubresource = {};
srcSubresource.aspectMask = copyAspectFlags;
srcSubresource.mipLevel = level;
srcSubresource.baseArrayLayer = layer;
srcSubresource.layerCount = 1;
VkExtent3D srcExtent = {static_cast<uint32_t>(area.width), static_cast<uint32_t>(area.height), VkExtent3D srcExtent = {static_cast<uint32_t>(area.width), static_cast<uint32_t>(area.height),
1}; 1};
if (srcImage->getExtents().depth > 1)
{
// Depth > 1 means this is a 3D texture and we need special handling
srcOffset.z = layer;
srcSubresource.baseArrayLayer = 0;
}
// If the source image is multisampled, we need to resolve it into a temporary image before // If the source image is multisampled, we need to resolve it into a temporary image before
// performing a readback. // performing a readback.
bool isMultisampled = srcImage->getSamples() > 1; bool isMultisampled = srcImage->getSamples() > 1;
...@@ -1461,10 +1475,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1461,10 +1475,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
ASSERT(copyAspectFlags == VK_IMAGE_ASPECT_COLOR_BIT); ASSERT(copyAspectFlags == VK_IMAGE_ASPECT_COLOR_BIT);
VkImageResolve resolveRegion = {}; VkImageResolve resolveRegion = {};
resolveRegion.srcSubresource.aspectMask = copyAspectFlags; resolveRegion.srcSubresource = srcSubresource;
resolveRegion.srcSubresource.mipLevel = level;
resolveRegion.srcSubresource.baseArrayLayer = layer;
resolveRegion.srcSubresource.layerCount = 1;
resolveRegion.srcOffset = srcOffset; resolveRegion.srcOffset = srcOffset;
resolveRegion.dstSubresource.aspectMask = copyAspectFlags; resolveRegion.dstSubresource.aspectMask = copyAspectFlags;
resolveRegion.dstSubresource.mipLevel = 0; resolveRegion.dstSubresource.mipLevel = 0;
...@@ -1483,6 +1494,9 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1483,6 +1494,9 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
level = 0; level = 0;
layer = 0; layer = 0;
srcOffset = {0, 0, 0}; srcOffset = {0, 0, 0};
srcSubresource.baseArrayLayer = 0;
srcSubresource.layerCount = 1;
srcSubresource.mipLevel = 0;
} }
VkBuffer bufferHandle = VK_NULL_HANDLE; VkBuffer bufferHandle = VK_NULL_HANDLE;
...@@ -1493,16 +1507,13 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1493,16 +1507,13 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
ANGLE_TRY(mReadPixelBuffer.allocate(contextVk, allocationSize, &readPixelBuffer, &bufferHandle, ANGLE_TRY(mReadPixelBuffer.allocate(contextVk, allocationSize, &readPixelBuffer, &bufferHandle,
&stagingOffset, nullptr)); &stagingOffset, nullptr));
VkBufferImageCopy region = {}; VkBufferImageCopy region = {};
region.bufferImageHeight = srcExtent.height; region.bufferImageHeight = srcExtent.height;
region.bufferOffset = stagingOffset; region.bufferOffset = stagingOffset;
region.bufferRowLength = srcExtent.width; region.bufferRowLength = srcExtent.width;
region.imageExtent = srcExtent; region.imageExtent = srcExtent;
region.imageOffset = srcOffset; region.imageOffset = srcOffset;
region.imageSubresource.aspectMask = copyAspectFlags; region.imageSubresource = srcSubresource;
region.imageSubresource.baseArrayLayer = layer;
region.imageSubresource.layerCount = 1;
region.imageSubresource.mipLevel = level;
commandBuffer->copyImageToBuffer(srcImage->getImage(), srcImage->getCurrentLayout(), commandBuffer->copyImageToBuffer(srcImage->getImage(), srcImage->getCurrentLayout(),
bufferHandle, 1, &region); bufferHandle, 1, &region);
......
...@@ -65,6 +65,12 @@ bool ForceCpuPathForCopy(RendererVk *renderer, vk::ImageHelper *image) ...@@ -65,6 +65,12 @@ bool ForceCpuPathForCopy(RendererVk *renderer, vk::ImageHelper *image)
{ {
return image->getLayerCount() > 1 && renderer->getFeatures().forceCpuPathForCubeMapCopy.enabled; return image->getLayerCount() > 1 && renderer->getFeatures().forceCpuPathForCubeMapCopy.enabled;
} }
uint32_t GetRenderTargetLayerCount(vk::ImageHelper *image)
{
// Depth > 1 means this is a 3D texture and depth is our layer count
return image->getExtents().depth > 1 ? image->getExtents().depth : image->getLayerCount();
}
} // anonymous namespace } // anonymous namespace
angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk, angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
...@@ -892,8 +898,9 @@ void TextureVk::setImageHelper(ContextVk *contextVk, ...@@ -892,8 +898,9 @@ void TextureVk::setImageHelper(ContextVk *contextVk,
mRenderTarget.init(mImage, &mDrawBaseLevelImageView, &mFetchBaseLevelImageView, mRenderTarget.init(mImage, &mDrawBaseLevelImageView, &mFetchBaseLevelImageView,
getNativeImageLevel(0), getNativeImageLayer(0)); getNativeImageLevel(0), getNativeImageLayer(0));
// Force re-creation of cube map render targets next time they are needed // Force re-creation of layered render targets next time they are needed
mCubeMapRenderTargets.clear(); mCubeMapRenderTargets.clear();
m3DRenderTargets.clear();
mSerial = contextVk->generateTextureSerial(); mSerial = contextVk->generateTextureSerial();
} }
...@@ -1116,6 +1123,11 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context, ...@@ -1116,6 +1123,11 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
case gl::TextureType::_2D: case gl::TextureType::_2D:
*rtOut = &mRenderTarget; *rtOut = &mRenderTarget;
break; break;
case gl::TextureType::_2DArray:
case gl::TextureType::_3D:
ANGLE_TRY(init3DRenderTargets(contextVk));
*rtOut = &m3DRenderTargets[imageIndex.getLayerIndex()];
break;
case gl::TextureType::CubeMap: case gl::TextureType::CubeMap:
ANGLE_TRY(initCubeMapRenderTargets(contextVk)); ANGLE_TRY(initCubeMapRenderTargets(contextVk));
*rtOut = &mCubeMapRenderTargets[imageIndex.cubeMapFaceIndex()]; *rtOut = &mCubeMapRenderTargets[imageIndex.cubeMapFaceIndex()];
...@@ -1162,6 +1174,38 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk, ...@@ -1162,6 +1174,38 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk,
commandBuffer); commandBuffer);
} }
angle::Result TextureVk::init3DRenderTargets(ContextVk *contextVk)
{
// Lazy init. Check if already initialized.
if (!m3DRenderTargets.empty())
return angle::Result::Continue;
uint32_t layerCount = GetRenderTargetLayerCount(mImage);
mLayerFetchImageView.resize(layerCount);
m3DRenderTargets.resize(layerCount);
for (size_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
{
vk::ImageView *drawView;
ANGLE_TRY(getLayerLevelDrawImageView(contextVk, layerIndex, 0, &drawView));
// Users of the render target expect the views to directly view the desired layer, so we
// need create a fetch view for each layer as well.
gl::SwizzleState mappedSwizzle;
MapSwizzleState(contextVk, mImage->getFormat(), mState.getSwizzleState(), &mappedSwizzle);
gl::TextureType arrayType = vk::Get2DTextureType(layerCount, mImage->getSamples());
ANGLE_TRY(mImage->initLayerImageView(contextVk, arrayType, mImage->getAspectFlags(),
mappedSwizzle, &mLayerFetchImageView[layerIndex],
getNativeImageLevel(0), 1,
getNativeImageLayer(layerIndex), 1));
m3DRenderTargets[layerIndex].init(mImage, drawView, &mLayerFetchImageView[layerIndex],
getNativeImageLevel(0), getNativeImageLayer(layerIndex));
}
return angle::Result::Continue;
}
angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk) angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
{ {
// Lazy init. Check if already initialized. // Lazy init. Check if already initialized.
...@@ -1333,10 +1377,13 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context, ...@@ -1333,10 +1377,13 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
ASSERT(mImage->valid()); ASSERT(mImage->valid());
ASSERT(!mImage->getFormat().imageFormat().isBlock); ASSERT(!mImage->getFormat().imageFormat().isBlock);
// For 3D textures, layer count is tracked as depth
uint32_t layerCount = mState.getType() == gl::TextureType::_3D ? mImage->getExtents().depth
: mImage->getLayerCount();
// Lazily allocate the storage for image views // Lazily allocate the storage for image views
if (mLayerLevelDrawImageViews.empty()) if (mLayerLevelDrawImageViews.empty())
{ {
mLayerLevelDrawImageViews.resize(mImage->getLayerCount()); mLayerLevelDrawImageViews.resize(layerCount);
} }
ASSERT(mLayerLevelDrawImageViews.size() > layer); ASSERT(mLayerLevelDrawImageViews.size() > layer);
...@@ -1355,7 +1402,8 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context, ...@@ -1355,7 +1402,8 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
// Lazily allocate the image view itself. // Lazily allocate the image view itself.
// Note that these views are specifically made to be used as color attachments, and therefore // Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle. // don't have swizzle.
return mImage->initLayerImageView(context, mState.getType(), mImage->getAspectFlags(), gl::TextureType viewType = vk::Get2DTextureType(layerCount, mImage->getSamples());
return mImage->initLayerImageView(context, viewType, mImage->getAspectFlags(),
gl::SwizzleState(), *imageViewOut, getNativeImageLevel(level), gl::SwizzleState(), *imageViewOut, getNativeImageLevel(level),
1, getNativeImageLayer(layer), 1); 1, getNativeImageLayer(layer), 1);
} }
...@@ -1488,6 +1536,7 @@ void TextureVk::releaseImage(ContextVk *contextVk) ...@@ -1488,6 +1536,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
releaseImageViews(contextVk); releaseImageViews(contextVk);
mCubeMapRenderTargets.clear(); mCubeMapRenderTargets.clear();
m3DRenderTargets.clear();
onStagingBufferChange(); onStagingBufferChange();
} }
......
...@@ -282,6 +282,7 @@ class TextureVk : public TextureImpl ...@@ -282,6 +282,7 @@ class TextureVk : public TextureImpl
const vk::Format &format, const vk::Format &format,
uint32_t levelCount, uint32_t levelCount,
uint32_t layerCount); uint32_t layerCount);
angle::Result init3DRenderTargets(ContextVk *contextVk);
angle::Result initCubeMapRenderTargets(ContextVk *contextVk); angle::Result initCubeMapRenderTargets(ContextVk *contextVk);
angle::Result ensureImageInitializedImpl(ContextVk *contextVk, angle::Result ensureImageInitializedImpl(ContextVk *contextVk,
...@@ -315,6 +316,7 @@ class TextureVk : public TextureImpl ...@@ -315,6 +316,7 @@ class TextureVk : public TextureImpl
RenderTargetVk mRenderTarget; RenderTargetVk mRenderTarget;
std::vector<vk::ImageView> mLayerFetchImageView; std::vector<vk::ImageView> mLayerFetchImageView;
std::vector<RenderTargetVk> m3DRenderTargets;
std::vector<RenderTargetVk> mCubeMapRenderTargets; std::vector<RenderTargetVk> mCubeMapRenderTargets;
// The serial is used for cache indexing. // The serial is used for cache indexing.
......
...@@ -535,12 +535,6 @@ ...@@ -535,12 +535,6 @@
// MAX_FRAGMENT_INPUT_COMPONENTS is 0 // MAX_FRAGMENT_INPUT_COMPONENTS is 0
3676 VULKAN : dEQP-GLES3.functional.state_query.integers.max_fragment_input_components_get* = FAIL 3676 VULKAN : dEQP-GLES3.functional.state_query.integers.max_fragment_input_components_get* = FAIL
// 3D texture:
3188 VULKAN : dEQP-GLES3.functional.fbo.color.tex3d.* = SKIP
// 2D array (anglebug.com/3189), new formats in ES 3.0 (anglebug.com/3190):
3189 VULKAN : dEQP-GLES3.functional.fbo.color.tex2darray.* = SKIP
// New or broken formats in ES 3.0: // New or broken formats in ES 3.0:
3190 VULKAN : dEQP-GLES3.functional.texture.specification.texstorage2d.format.depth32* = FAIL 3190 VULKAN : dEQP-GLES3.functional.texture.specification.texstorage2d.format.depth32* = FAIL
3190 VULKAN : dEQP-GLES3.functional.texture.specification.texstorage3d.format.depth32* = FAIL 3190 VULKAN : dEQP-GLES3.functional.texture.specification.texstorage3d.format.depth32* = FAIL
......
...@@ -564,6 +564,9 @@ TEST_P(DrawBuffersTestES3, 3DTextures) ...@@ -564,6 +564,9 @@ TEST_P(DrawBuffersTestES3, 3DTextures)
{ {
ANGLE_SKIP_TEST_IF(!setupTest()); ANGLE_SKIP_TEST_IF(!setupTest());
// Fails on Intel (intel-hd-630) Ubuntu 17.04 with Vulkan: http://anglebug.com/3784
ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
GLTexture texture; GLTexture texture;
glBindTexture(GL_TEXTURE_3D, texture.get()); glBindTexture(GL_TEXTURE_3D, texture.get());
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), getWindowWidth(), glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), getWindowWidth(),
...@@ -653,4 +656,4 @@ ANGLE_INSTANTIATE_TEST(DrawBuffersTest, ...@@ -653,4 +656,4 @@ ANGLE_INSTANTIATE_TEST(DrawBuffersTest,
ANGLE_INSTANTIATE_TEST(DrawBuffersWebGL2Test, ES3_D3D11(), ES3_OPENGL(), ES3_VULKAN()); ANGLE_INSTANTIATE_TEST(DrawBuffersWebGL2Test, ES3_D3D11(), ES3_OPENGL(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(DrawBuffersTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(DrawBuffersTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN());
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