Vulkan: Implement cube map render targets. Each TextureVk now stores vectors of RenderTargetVks and ImageViews associated with the image faces. They are initialized lazily when the RenderTarget is queried in getAttachmentRenderTarget. There's still one missing edge case for handling clear with the Framebuffer when using cube maps. Also one additional test failure on Android. Bug: angleproject:2470 Change-Id: Ib959a3434a992cef010a11940cf2ee49e118ac17 Reviewed-on: https://chromium-review.googlesource.com/1220727 Reviewed-by: Frank Henigman <fjhenigman@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp index be4ad90..9a4a0f3 100644 --- a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp +++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
@@ -26,6 +26,11 @@ { } +RenderTargetVk::RenderTargetVk(RenderTargetVk &&other) + : mImage(other.mImage), mImageView(other.mImageView), mResource(other.mResource) +{ +} + void RenderTargetVk::onColorDraw(vk::CommandGraphResource *framebufferVk, vk::CommandBuffer *commandBuffer, vk::RenderPassDesc *renderPassDesc)
diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.h b/src/libANGLE/renderer/vulkan/RenderTargetVk.h index 6708e49..f4d1ef3 100644 --- a/src/libANGLE/renderer/vulkan/RenderTargetVk.h +++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.h
@@ -38,6 +38,9 @@ vk::CommandGraphResource *resource); ~RenderTargetVk(); + // Used in std::vector initialization. + RenderTargetVk(RenderTargetVk &&other); + // Note: RenderTargets should be called in order, with the depth/stencil onRender last. void onColorDraw(vk::CommandGraphResource *framebufferVk, vk::CommandBuffer *commandBuffer,
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp index 566de58..122c224 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.cpp +++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -1025,16 +1025,25 @@ const gl::ImageIndex &imageIndex, FramebufferAttachmentRenderTarget **rtOut) { - // TODO(jmadill): Handle cube textures. http://anglebug.com/2470 - ASSERT(imageIndex.getType() == gl::TextureType::_2D); - // Non-zero mip level attachments are an ES 3.0 feature. - ASSERT(imageIndex.getLevelIndex() == 0 && !imageIndex.hasLayer()); + ASSERT(imageIndex.getLevelIndex() == 0); ContextVk *contextVk = vk::GetImpl(context); ANGLE_TRY(ensureImageInitialized(contextVk)); - *rtOut = &mRenderTarget; + switch (imageIndex.getType()) + { + case gl::TextureType::_2D: + *rtOut = &mRenderTarget; + break; + case gl::TextureType::CubeMap: + ANGLE_TRY(initCubeMapRenderTargets(contextVk)); + *rtOut = &mCubeMapRenderTargets[imageIndex.cubeMapFaceIndex()]; + break; + default: + UNREACHABLE(); + } + return gl::NoError(); } @@ -1060,7 +1069,25 @@ ANGLE_TRY(initImage(contextVk, format, baseLevelExtents, levelCount, commandBuffer)); } - ANGLE_TRY(mPixelBuffer.flushUpdatesToImage(contextVk, levelCount, &mImage, commandBuffer)); + return mPixelBuffer.flushUpdatesToImage(contextVk, levelCount, &mImage, commandBuffer); +} + +angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk) +{ + // Lazy init. Check if already initialized. + if (!mCubeMapFaceImageViews.empty()) + return angle::Result::Continue(); + + mCubeMapFaceImageViews.resize(gl::kCubeFaceCount); + + for (size_t cubeMapFaceIndex = 0; cubeMapFaceIndex < gl::kCubeFaceCount; ++cubeMapFaceIndex) + { + vk::ImageView &imageView = mCubeMapFaceImageViews[cubeMapFaceIndex]; + ANGLE_TRY(mImage.initLayerImageView(contextVk, gl::TextureType::CubeMap, + VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), + &imageView, 1, cubeMapFaceIndex, 1)); + mCubeMapRenderTargets.emplace_back(&mImage, &imageView, this); + } return angle::Result::Continue(); } @@ -1101,8 +1128,7 @@ samplerInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; samplerInfo.unnormalizedCoordinates = VK_FALSE; - ANGLE_TRY(mSampler.init(contextVk, samplerInfo)); - return gl::NoError(); + return mSampler.init(contextVk, samplerInfo); } gl::Error TextureVk::setStorageMultisample(const gl::Context *context, @@ -1190,6 +1216,14 @@ mImage.release(renderer->getCurrentQueueSerial(), renderer); renderer->releaseObject(getStoredQueueSerial(), &mBaseLevelImageView); renderer->releaseObject(getStoredQueueSerial(), &mMipmapImageView); + + for (vk::ImageView &imageView : mCubeMapFaceImageViews) + { + renderer->releaseObject(getStoredQueueSerial(), &imageView); + } + mCubeMapFaceImageViews.clear(); + mCubeMapRenderTargets.clear(); + onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS); }
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h index 98fef25..499437e 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.h +++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -250,6 +250,7 @@ angle::Result getCommandBufferForWrite(ContextVk *contextVk, vk::CommandBuffer **commandBufferOut); uint32_t getLevelCount() const; + angle::Result initCubeMapRenderTargets(ContextVk *contextVk); vk::ImageHelper mImage; vk::ImageView mBaseLevelImageView; @@ -257,6 +258,8 @@ vk::Sampler mSampler; RenderTargetVk mRenderTarget; + std::vector<vk::ImageView> mCubeMapFaceImageViews; + std::vector<RenderTargetVk> mCubeMapRenderTargets; PixelBuffer mPixelBuffer; };
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp index 40bca9e..4f0fa99 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp +++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -584,6 +584,19 @@ ImageView *imageViewOut, uint32_t levelCount) { + return initLayerImageView(context, textureType, aspectMask, swizzleMap, imageViewOut, + levelCount, 0, mLayerCount); +} + +angle::Result ImageHelper::initLayerImageView(Context *context, + gl::TextureType textureType, + VkImageAspectFlags aspectMask, + const gl::SwizzleState &swizzleMap, + ImageView *imageViewOut, + uint32_t levelCount, + uint32_t baseArrayLayer, + uint32_t layerCount) +{ VkImageViewCreateInfo viewInfo; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.pNext = nullptr; @@ -608,8 +621,8 @@ viewInfo.subresourceRange.aspectMask = aspectMask; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = levelCount; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = mLayerCount; + viewInfo.subresourceRange.baseArrayLayer = baseArrayLayer; + viewInfo.subresourceRange.layerCount = layerCount; ANGLE_TRY(imageViewOut->init(context, viewInfo)); return angle::Result::Continue();
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h index 0e5323e..ef45095 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.h +++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -180,6 +180,14 @@ angle::Result initMemory(Context *context, const MemoryProperties &memoryProperties, VkMemoryPropertyFlags flags); + angle::Result initLayerImageView(Context *context, + gl::TextureType textureType, + VkImageAspectFlags aspectMask, + const gl::SwizzleState &swizzleMap, + ImageView *imageViewOut, + uint32_t levelCount, + uint32_t baseArrayLayer, + uint32_t layerCount); angle::Result initImageView(Context *context, gl::TextureType textureType, VkImageAspectFlags aspectMask,
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp index 8e65449..383dc43 100644 --- a/src/tests/gl_tests/CopyTextureTest.cpp +++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -684,9 +684,6 @@ // Test that copying to cube maps works TEST_P(CopyTextureTest, CubeMapTarget) { - // TODO(jmadill): Support cube map framebuffer attachments. http://anglebug.com/2470 - ANGLE_SKIP_TEST_IF(IsVulkan()); - if (!checkExtensions()) { return;
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp index 3a5a1ef..af6d8bc 100644 --- a/src/tests/gl_tests/FramebufferTest.cpp +++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -272,9 +272,6 @@ // Test that binding an incomplete cube map is rejected by ANGLE. TEST_P(FramebufferFormatsTest, IncompleteCubeMap) { - // TODO(jmadill): Handle cube textures. http://anglebug.com/2470 - ANGLE_SKIP_TEST_IF(IsVulkan()); - // First make a complete CubeMap. glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp index 48cd42e..d6f7c60 100644 --- a/src/tests/gl_tests/MipmapTest.cpp +++ b/src/tests/gl_tests/MipmapTest.cpp
@@ -767,8 +767,9 @@ // works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero. TEST_P(MipmapTest, TextureCubeGeneralLevelZero) { - // TODO(jmadill): Cube map attachments http://anglebug.com/2470 - ANGLE_SKIP_TEST_IF(IsVulkan()); + // This test seems to fail only on Android Vulkan. + // TODO(jmadill): Diagnose and fix. http://anglebug.com/2470 + ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid()); glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); @@ -808,9 +809,6 @@ // This test ensures that rendering to level-zero of a TextureCube works as expected. TEST_P(MipmapTest, TextureCubeRenderToLevelZero) { - // TODO(jmadill): Cube map attachments http://anglebug.com/2470 - ANGLE_SKIP_TEST_IF(IsVulkan()); - glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); // Draw. Since the negative-Y face's is blue, this should be blue.
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp index e413f37..f2a117c 100644 --- a/src/tests/gl_tests/TextureTest.cpp +++ b/src/tests/gl_tests/TextureTest.cpp
@@ -1374,9 +1374,6 @@ // https://code.google.com/p/angleproject/issues/detail?id=849 TEST_P(TextureCubeTest, CubeMapFBO) { - // TODO(jmadill): Cube map render targets. http://anglebug.com/2470 - ANGLE_SKIP_TEST_IF(IsVulkan()); - GLuint fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);