Commit 3f3b358f by Jamie Madill

Vulkan: Fix cube map attachment clears and readpixels.

These were both missing the correct layer offset. Cache the layer inside the RenderTargetVk for easy access. Bug: angleproject:2470 Change-Id: I690dbf0702d7ec52f44ba0a9429b6ef0e51baf6b Reviewed-on: https://chromium-review.googlesource.com/1225910 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 7f232939
...@@ -211,8 +211,10 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -211,8 +211,10 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
} }
// If we clear the depth OR the stencil but not both, and we have a packed depth stencil // If we clear the depth OR the stencil but not both, and we have a packed depth stencil
// attachment, we need to use clearAttachment instead of clearDepthStencil since Vulkan won't // attachment, we need to use clearAttachments instead of clearDepthStencil since Vulkan won't
// allow us to clear one or the other separately. // allow us to clear one or the other separately.
// Note: this might be bugged if we emulate single depth or stencil with a packed format.
// TODO(jmadill): Investigate emulated packed formats. http://anglebug.com/2815
bool isSingleClearOnPackedDepthStencilAttachment = bool isSingleClearOnPackedDepthStencilAttachment =
depthStencilAttachment && (clearDepth != clearStencil); depthStencilAttachment && (clearDepth != clearStencil);
if (glState.isScissorTestEnabled() || isSingleClearOnPackedDepthStencilAttachment) if (glState.isScissorTestEnabled() || isSingleClearOnPackedDepthStencilAttachment)
...@@ -275,7 +277,10 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -275,7 +277,10 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
ASSERT(colorRenderTarget); ASSERT(colorRenderTarget);
vk::ImageHelper *image = colorRenderTarget->getImageForWrite(this); vk::ImageHelper *image = colorRenderTarget->getImageForWrite(this);
GLint mipLevelToClear = (attachment->type() == GL_TEXTURE) ? attachment->mipLevel() : 0; GLint mipLevelToClear = (attachment->type() == GL_TEXTURE) ? attachment->mipLevel() : 0;
image->clearColor(modifiedClearColorValue, mipLevelToClear, 1, commandBuffer);
// If we're clearing a cube map face ensure we only clear the selected layer.
image->clearColorLayer(modifiedClearColorValue, mipLevelToClear, 1,
colorRenderTarget->getLayerIndex(), 1, commandBuffer);
} }
return gl::NoError(); return gl::NoError();
...@@ -885,10 +890,7 @@ angle::Result FramebufferVk::clearWithClearAttachments(ContextVk *contextVk, ...@@ -885,10 +890,7 @@ angle::Result FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
vk::RecordingMode mode = vk::RecordingMode::Start; vk::RecordingMode mode = vk::RecordingMode::Start;
ANGLE_TRY(getCommandBufferForDraw(contextVk, &commandBuffer, &mode)); ANGLE_TRY(getCommandBufferForDraw(contextVk, &commandBuffer, &mode));
// TODO(jmadill): Cube map attachments. http://anglebug.com/2470 // The array layer is offset by the ImageView. So we shouldn't need to set a base array layer.
// We assume for now that we always need to clear only 1 layer starting at the
// baseArrayLayer 0, this might need to change depending how we'll implement
// cube maps, 3d textures and array textures.
VkClearRect clearRect; VkClearRect clearRect;
clearRect.baseArrayLayer = 0; clearRect.baseArrayLayer = 0;
clearRect.layerCount = 1; clearRect.layerCount = 1;
...@@ -1187,7 +1189,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1187,7 +1189,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
region.imageOffset.y = area.y; region.imageOffset.y = area.y;
region.imageOffset.z = 0; region.imageOffset.z = 0;
region.imageSubresource.aspectMask = copyAspectFlags; region.imageSubresource.aspectMask = copyAspectFlags;
region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.baseArrayLayer = renderTarget->getLayerIndex();
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageSubresource.mipLevel = 0; region.imageSubresource.mipLevel = 0;
......
...@@ -17,8 +17,9 @@ namespace rx ...@@ -17,8 +17,9 @@ namespace rx
{ {
RenderTargetVk::RenderTargetVk(vk::ImageHelper *image, RenderTargetVk::RenderTargetVk(vk::ImageHelper *image,
vk::ImageView *imageView, vk::ImageView *imageView,
vk::CommandGraphResource *resource) vk::CommandGraphResource *resource,
: mImage(image), mImageView(imageView), mResource(resource) size_t layerIndex)
: mImage(image), mImageView(imageView), mResource(resource), mLayerIndex(layerIndex)
{ {
} }
...@@ -27,7 +28,10 @@ RenderTargetVk::~RenderTargetVk() ...@@ -27,7 +28,10 @@ RenderTargetVk::~RenderTargetVk()
} }
RenderTargetVk::RenderTargetVk(RenderTargetVk &&other) RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
: mImage(other.mImage), mImageView(other.mImageView), mResource(other.mResource) : mImage(other.mImage),
mImageView(other.mImageView),
mResource(other.mResource),
mLayerIndex(other.mLayerIndex)
{ {
} }
......
...@@ -35,7 +35,8 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -35,7 +35,8 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
public: public:
RenderTargetVk(vk::ImageHelper *image, RenderTargetVk(vk::ImageHelper *image,
vk::ImageView *imageView, vk::ImageView *imageView,
vk::CommandGraphResource *resource); vk::CommandGraphResource *resource,
size_t layerIndex);
~RenderTargetVk(); ~RenderTargetVk();
// Used in std::vector initialization. // Used in std::vector initialization.
...@@ -61,6 +62,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -61,6 +62,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
const vk::Format &getImageFormat() const; const vk::Format &getImageFormat() const;
const gl::Extents &getImageExtents() const; const gl::Extents &getImageExtents() const;
size_t getLayerIndex() const { return mLayerIndex; }
// Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
// RenderTargetVk pointer. // RenderTargetVk pointer.
...@@ -70,6 +72,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -70,6 +72,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
vk::ImageHelper *mImage; vk::ImageHelper *mImage;
vk::ImageView *mImageView; vk::ImageView *mImageView;
vk::CommandGraphResource *mResource; vk::CommandGraphResource *mResource;
size_t mLayerIndex;
}; };
} // namespace rx } // namespace rx
......
...@@ -24,7 +24,7 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}}; ...@@ -24,7 +24,7 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}};
} // anonymous namespace } // anonymous namespace
RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
: RenderbufferImpl(state), mRenderTarget(&mImage, &mImageView, this) : RenderbufferImpl(state), mRenderTarget(&mImage, &mImageView, this, 0)
{ {
} }
......
...@@ -59,7 +59,7 @@ constexpr VkImageUsageFlags kSurfaceVKDepthStencilImageUsageFlags = ...@@ -59,7 +59,7 @@ constexpr VkImageUsageFlags kSurfaceVKDepthStencilImageUsageFlags =
} // namespace } // namespace
OffscreenSurfaceVk::AttachmentImage::AttachmentImage(vk::CommandGraphResource *commandGraphResource) OffscreenSurfaceVk::AttachmentImage::AttachmentImage(vk::CommandGraphResource *commandGraphResource)
: renderTarget(&image, &imageView, commandGraphResource) : renderTarget(&image, &imageView, commandGraphResource, 0)
{ {
} }
...@@ -268,8 +268,8 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, ...@@ -268,8 +268,8 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState,
mSurface(VK_NULL_HANDLE), mSurface(VK_NULL_HANDLE),
mInstance(VK_NULL_HANDLE), mInstance(VK_NULL_HANDLE),
mSwapchain(VK_NULL_HANDLE), mSwapchain(VK_NULL_HANDLE),
mColorRenderTarget(nullptr, nullptr, this), mColorRenderTarget(nullptr, nullptr, this, 0),
mDepthStencilRenderTarget(&mDepthStencilImage, &mDepthStencilImageView, this), mDepthStencilRenderTarget(&mDepthStencilImage, &mDepthStencilImageView, this, 0),
mCurrentSwapchainImageIndex(0) mCurrentSwapchainImageIndex(0)
{ {
} }
......
...@@ -429,7 +429,9 @@ PixelBuffer::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other ...@@ -429,7 +429,9 @@ PixelBuffer::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other
// TextureVk implementation. // TextureVk implementation.
TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer) TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
: TextureImpl(state), mRenderTarget(&mImage, &mBaseLevelImageView, this), mPixelBuffer(renderer) : TextureImpl(state),
mRenderTarget(&mImage, &mBaseLevelImageView, this, 0),
mPixelBuffer(renderer)
{ {
} }
...@@ -1086,7 +1088,7 @@ angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk) ...@@ -1086,7 +1088,7 @@ angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
ANGLE_TRY(mImage.initLayerImageView(contextVk, gl::TextureType::CubeMap, ANGLE_TRY(mImage.initLayerImageView(contextVk, gl::TextureType::CubeMap,
VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
&imageView, 1, cubeMapFaceIndex, 1)); &imageView, 1, cubeMapFaceIndex, 1));
mCubeMapRenderTargets.emplace_back(&mImage, &imageView, this); mCubeMapRenderTargets.emplace_back(&mImage, &imageView, this, cubeMapFaceIndex);
} }
return angle::Result::Continue(); return angle::Result::Continue();
} }
......
...@@ -790,9 +790,20 @@ void ImageHelper::changeLayoutWithStages(VkImageAspectFlags aspectMask, ...@@ -790,9 +790,20 @@ void ImageHelper::changeLayoutWithStages(VkImageAspectFlags aspectMask,
} }
void ImageHelper::clearColor(const VkClearColorValue &color, void ImageHelper::clearColor(const VkClearColorValue &color,
uint32_t mipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
CommandBuffer *commandBuffer) CommandBuffer *commandBuffer)
{
clearColorLayer(color, baseMipLevel, levelCount, 0, mLayerCount, commandBuffer);
}
void ImageHelper::clearColorLayer(const VkClearColorValue &color,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer)
{ {
ASSERT(valid()); ASSERT(valid());
...@@ -802,10 +813,10 @@ void ImageHelper::clearColor(const VkClearColorValue &color, ...@@ -802,10 +813,10 @@ void ImageHelper::clearColor(const VkClearColorValue &color,
VkImageSubresourceRange range; VkImageSubresourceRange range;
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
range.baseMipLevel = mipLevel; range.baseMipLevel = baseMipLevel;
range.levelCount = levelCount; range.levelCount = levelCount;
range.baseArrayLayer = 0; range.baseArrayLayer = baseArrayLayer;
range.layerCount = mLayerCount; range.layerCount = layerCount;
commandBuffer->clearColorImage(mImage, mCurrentLayout, color, 1, &range); commandBuffer->clearColorImage(mImage, mCurrentLayout, color, 1, &range);
} }
......
...@@ -228,10 +228,17 @@ class ImageHelper final : angle::NonCopyable ...@@ -228,10 +228,17 @@ class ImageHelper final : angle::NonCopyable
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
void clearColor(const VkClearColorValue &color, void clearColor(const VkClearColorValue &color,
uint32_t mipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
void clearColorLayer(const VkClearColorValue &color,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags aspectFlags, void clearDepthStencil(VkImageAspectFlags aspectFlags,
const VkClearDepthStencilValue &depthStencil, const VkClearDepthStencilValue &depthStencil,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
......
...@@ -768,7 +768,7 @@ TEST_P(MipmapTest, MipMapGenerationD3D9Bug) ...@@ -768,7 +768,7 @@ TEST_P(MipmapTest, MipMapGenerationD3D9Bug)
TEST_P(MipmapTest, TextureCubeGeneralLevelZero) TEST_P(MipmapTest, TextureCubeGeneralLevelZero)
{ {
// This test seems to fail only on Android Vulkan. // This test seems to fail only on Android Vulkan.
// TODO(jmadill): Diagnose and fix. http://anglebug.com/2470 // TODO(jmadill): Diagnose and fix. http://anglebug.com/2817
ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid()); ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
......
...@@ -1374,8 +1374,7 @@ TEST_P(Texture2DTestWithDrawScale, MipmapsTwice) ...@@ -1374,8 +1374,7 @@ TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
// https://code.google.com/p/angleproject/issues/detail?id=849 // https://code.google.com/p/angleproject/issues/detail?id=849
TEST_P(TextureCubeTest, CubeMapFBO) TEST_P(TextureCubeTest, CubeMapFBO)
{ {
GLuint fbo; GLFramebuffer fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube); glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
...@@ -1383,10 +1382,74 @@ TEST_P(TextureCubeTest, CubeMapFBO) ...@@ -1383,10 +1382,74 @@ TEST_P(TextureCubeTest, CubeMapFBO)
mTextureCube, 0); mTextureCube, 0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
EXPECT_GL_NO_ERROR();
glDeleteFramebuffers(1, &fbo); // Test clearing the six mip faces individually.
std::array<GLColor, 6> faceColors = {{GLColor::red, GLColor::green, GLColor::blue,
GLColor::yellow, GLColor::cyan, GLColor::magenta}};
EXPECT_GL_NO_ERROR(); for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
Vector4 clearColorF = faceColors[faceIndex].toNormalizedVector();
glClearColor(clearColorF.x(), clearColorF.y(), clearColorF.z(), clearColorF.w());
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex]);
}
// Iterate the faces again to make sure the colors haven't changed.
for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex])
<< "face color " << faceIndex << " shouldn't change";
}
}
// Tests clearing a cube map with a scissor enabled.
TEST_P(TextureCubeTest, CubeMapFBOScissoredClear)
{
// TODO(jie.a.chen): Diagnose and fix. http://anglebug.com/2822
ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
constexpr size_t kSize = 16;
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, kSize, kSize);
GLTexture texcube;
glBindTexture(GL_TEXTURE_CUBE_MAP, texcube);
for (GLenum face = 0; face < 6; face++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
}
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
texcube, 0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
ASSERT_GL_NO_ERROR();
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
glEnable(GL_SCISSOR_TEST);
glScissor(kSize / 2, 0, kSize / 2, kSize);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize / 2 + 1, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
} }
// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
......
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