Commit 43163491 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Unresolve depth/stencil MSRTT attachments

Using the same shader that unresolves color, this change allows depth/stencil to be unresolved as well. In turn, this allows the depth and stencil loadOp/storeOp of the implicit multisampled image associated with a multisampled-render-to-texture renderbuffer to be set to DONT_CARE. Stencil unresolve depends on VK_EXT_shader_stencil_export. In the absence of this extension, the stencil aspect is not unresolved and must continue to use loadOp=LOAD and storeOp=STORE. This is not ideal, but the expected use-case of depth/stencil MSRTT renderbuffers is that they get invalidated, so that load and store wouldn't happen in practice. Bug: angleproject:4836 Change-Id: I9939d1e15e10fa8ed285acdd6fe6edb42c59054f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2427049Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 74ed9b65
...@@ -511,6 +511,9 @@ template <size_t N> ...@@ -511,6 +511,9 @@ template <size_t N>
using BitSet8 = BitSetT<N, uint8_t>; using BitSet8 = BitSetT<N, uint8_t>;
template <size_t N> template <size_t N>
using BitSet16 = BitSetT<N, uint16_t>;
template <size_t N>
using BitSet32 = BitSetT<N, uint32_t>; using BitSet32 = BitSetT<N, uint32_t>;
template <size_t N> template <size_t N>
......
...@@ -2243,7 +2243,10 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2243,7 +2243,10 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// Initialize RenderPass info. // Initialize RenderPass info.
vk::AttachmentOpsArray renderPassAttachmentOps; vk::AttachmentOpsArray renderPassAttachmentOps;
vk::PackedClearValuesArray packedClearValues; vk::PackedClearValuesArray packedClearValues;
gl::DrawBufferMask previousUnresolveMask = mRenderPassDesc.getColorUnresolveAttachmentMask(); gl::DrawBufferMask previousUnresolveColorMask =
mRenderPassDesc.getColorUnresolveAttachmentMask();
bool previousUnresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
bool previousUnresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
// Color attachments. // Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors(); const auto &colorRenderTargets = mRenderTargetCache.getColors();
...@@ -2318,6 +2321,9 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2318,6 +2321,9 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget(); RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
const bool canExportStencil =
contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
// depth stencil attachment always immediately follows color attachment // depth stencil attachment always immediately follows color attachment
depthStencilAttachmentIndex = colorIndexVk; depthStencilAttachmentIndex = colorIndexVk;
...@@ -2337,14 +2343,16 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2337,14 +2343,16 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
} }
// If depth/stencil image is transient, no need to store its data at the end of the render
// pass. If shader stencil export is not supported, stencil data cannot be unresolved on
// the next render pass, so it must be stored/loaded. If the image is entirely transient,
// there is no resolve/unresolve and the image data is never stored/loaded.
if (depthStencilRenderTarget->isImageTransient()) if (depthStencilRenderTarget->isImageTransient())
{ {
// TODO(syoussefi): currently, depth/stencil unresolve is not implemented. Until then, depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
// don't change storeOp to DONT_CARE, unless the attachment is entirely transient (i.e.
// depth textures from EXT_multisampled_render_to_texture2. http://anglebug.com/4836 if (canExportStencil || depthStencilRenderTarget->isEntirelyTransient())
if (depthStencilRenderTarget->isEntirelyTransient())
{ {
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
} }
...@@ -2391,6 +2399,40 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2391,6 +2399,40 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
// Similar to color attachments, if there's a resolve attachment and the multisampled image
// is transient, depth/stencil data need to be unresolved in an initial subpass.
//
// Note that stencil unresolve is currently only possible if shader stencil export is
// supported.
if (depthStencilRenderTarget->hasResolveAttachment() &&
depthStencilRenderTarget->isImageTransient())
{
const bool unresolveDepth = depthLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD;
const bool unresolveStencil =
stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD && canExportStencil;
if (unresolveDepth)
{
depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
if (unresolveStencil)
{
stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
if (unresolveDepth || unresolveStencil)
{
mRenderPassDesc.packDepthStencilUnresolveAttachment(unresolveDepth,
unresolveStencil);
}
else
{
mRenderPassDesc.removeDepthStencilUnresolveAttachment();
}
}
renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp); renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp, renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
stencilStoreOp); stencilStoreOp);
...@@ -2418,13 +2460,28 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2418,13 +2460,28 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// Note that render passes are compatible only if the differences are in loadOp/storeOp values, // Note that render passes are compatible only if the differences are in loadOp/storeOp values,
// or the existence of resolve attachments in single subpass render passes. The modification // or the existence of resolve attachments in single subpass render passes. The modification
// here can add/remove a subpass, or modify its input attachments. // here can add/remove a subpass, or modify its input attachments.
gl::DrawBufferMask unresolveMask = mRenderPassDesc.getColorUnresolveAttachmentMask(); gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
if (previousUnresolveMask != unresolveMask) bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
if (previousUnresolveColorMask != unresolveColorMask ||
previousUnresolveDepth != unresolveDepth || previousUnresolveStencil != unresolveStencil)
{ {
contextVk->onDrawFramebufferRenderPassDescChange(this); contextVk->onDrawFramebufferRenderPassDescChange(this);
// Make sure framebuffer is recreated. // Make sure framebuffer is recreated.
mFramebuffer = nullptr; mFramebuffer = nullptr;
mCurrentFramebufferDesc.updateColorUnresolveMask(unresolveMask);
vk::FramebufferNonResolveAttachmentMask unresolveMask(unresolveColorMask.bits());
if (unresolveDepth)
{
unresolveMask.set(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
}
if (unresolveStencil)
{
unresolveMask.set(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1);
}
mCurrentFramebufferDesc.updateUnresolveMask(unresolveMask);
} }
vk::Framebuffer *framebuffer = nullptr; vk::Framebuffer *framebuffer = nullptr;
...@@ -2450,11 +2507,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2450,11 +2507,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
depthStencilRenderTarget->onDepthStencilDraw(contextVk, mReadOnlyDepthStencilMode); depthStencilRenderTarget->onDepthStencilDraw(contextVk, mReadOnlyDepthStencilMode);
} }
if (unresolveMask.any()) if (unresolveColorMask.any() || unresolveDepth || unresolveStencil)
{ {
// Unresolve attachments if any. // Unresolve attachments if any.
UtilsVk::UnresolveParameters params; UtilsVk::UnresolveParameters params;
params.unresolveMask = unresolveMask; params.unresolveColorMask = unresolveColorMask;
params.unresolveDepth = unresolveDepth;
params.unresolveStencil = unresolveStencil;
ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params)); ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params));
......
...@@ -125,8 +125,8 @@ void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly) ...@@ -125,8 +125,8 @@ void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly)
mImage); mImage);
if (mResolveImage) if (mResolveImage)
{ {
contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment, contextVk->onImageRenderPassWrite(
mResolveImage); aspectFlags, vk::ImageLayout::DepthStencilResolveAttachment, mResolveImage);
} }
} }
......
...@@ -166,7 +166,9 @@ class UtilsVk : angle::NonCopyable ...@@ -166,7 +166,9 @@ class UtilsVk : angle::NonCopyable
struct UnresolveParameters struct UnresolveParameters
{ {
gl::DrawBufferMask unresolveMask; gl::DrawBufferMask unresolveColorMask;
bool unresolveDepth;
bool unresolveStencil;
}; };
// Based on the maximum number of levels in GenerateMipmap.comp. // Based on the maximum number of levels in GenerateMipmap.comp.
...@@ -406,30 +408,33 @@ class UtilsVk : angle::NonCopyable ...@@ -406,30 +408,33 @@ class UtilsVk : angle::NonCopyable
ImageClear = 0, ImageClear = 0,
ImageCopy = 1, ImageCopy = 1,
BlitResolve = 2, BlitResolve = 2,
// Note: unresolve is special as it has a different layout per attachment // Note: unresolve is special as it has a different layout per attachment count. Depth and
Unresolve1Attachment = 3, // stencil each require a binding, so are counted separately.
Unresolve2Attachments = 4, Unresolve1Attachment = 3,
Unresolve3Attachments = 5, Unresolve2Attachments = 4,
Unresolve4Attachments = 6, Unresolve3Attachments = 5,
Unresolve5Attachments = 7, Unresolve4Attachments = 6,
Unresolve6Attachments = 8, Unresolve5Attachments = 7,
Unresolve7Attachments = 9, Unresolve6Attachments = 8,
Unresolve8Attachments = 10, Unresolve7Attachments = 9,
Unresolve8Attachments = 10,
Unresolve9Attachments = 11,
Unresolve10Attachments = 12,
// Functions implemented in compute // Functions implemented in compute
ComputeStartIndex = 11, // Special value to separate draw and dispatch functions. ComputeStartIndex = 13, // Special value to separate draw and dispatch functions.
ConvertIndexBuffer = 11, ConvertIndexBuffer = 13,
ConvertVertexBuffer = 12, ConvertVertexBuffer = 14,
BlitResolveStencilNoExport = 13, BlitResolveStencilNoExport = 15,
OverlayCull = 14, OverlayCull = 16,
OverlayDraw = 15, OverlayDraw = 17,
ConvertIndexIndirectBuffer = 16, ConvertIndexIndirectBuffer = 18,
ConvertIndexIndirectLineLoopBuffer = 17, ConvertIndexIndirectLineLoopBuffer = 19,
ConvertIndirectLineLoopBuffer = 18, ConvertIndirectLineLoopBuffer = 20,
GenerateMipmap = 19, GenerateMipmap = 21,
InvalidEnum = 20, InvalidEnum = 22,
EnumCount = 20, EnumCount = 22,
}; };
// Common function that creates the pipeline for the specified function, binds it and prepares // Common function that creates the pipeline for the specified function, binds it and prepares
......
...@@ -118,6 +118,7 @@ using FramebufferAttachmentsVector = angle::FixedVector<T, kMaxFramebufferAttach ...@@ -118,6 +118,7 @@ using FramebufferAttachmentsVector = angle::FixedVector<T, kMaxFramebufferAttach
constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1; constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
template <typename T> template <typename T>
using FramebufferNonResolveAttachmentArray = std::array<T, kMaxFramebufferNonResolveAttachments>; using FramebufferNonResolveAttachmentArray = std::array<T, kMaxFramebufferNonResolveAttachments>;
using FramebufferNonResolveAttachmentMask = angle::BitSet16<kMaxFramebufferNonResolveAttachments>;
class alignas(4) RenderPassDesc final class alignas(4) RenderPassDesc final
{ {
...@@ -145,6 +146,10 @@ class alignas(4) RenderPassDesc final ...@@ -145,6 +146,10 @@ class alignas(4) RenderPassDesc final
void removeColorUnresolveAttachment(size_t colorIndexGL); void removeColorUnresolveAttachment(size_t colorIndexGL);
// Indicate that a depth/stencil attachment should have a corresponding resolve attachment. // Indicate that a depth/stencil attachment should have a corresponding resolve attachment.
void packDepthStencilResolveAttachment(bool resolveDepth, bool resolveStencil); void packDepthStencilResolveAttachment(bool resolveDepth, bool resolveStencil);
// Indicate that a depth/stencil attachment should take its data from the resolve attachment
// initially.
void packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil);
void removeDepthStencilUnresolveAttachment();
size_t hash() const; size_t hash() const;
...@@ -182,6 +187,18 @@ class alignas(4) RenderPassDesc final ...@@ -182,6 +187,18 @@ class alignas(4) RenderPassDesc final
{ {
return (mAttachmentFormats.back() & kResolveStencilFlag) != 0; return (mAttachmentFormats.back() & kResolveStencilFlag) != 0;
} }
bool hasDepthStencilUnresolveAttachment() const
{
return (mAttachmentFormats.back() & (kUnresolveDepthFlag | kUnresolveStencilFlag)) != 0;
}
bool hasDepthUnresolveAttachment() const
{
return (mAttachmentFormats.back() & kUnresolveDepthFlag) != 0;
}
bool hasStencilUnresolveAttachment() const
{
return (mAttachmentFormats.back() & kUnresolveStencilFlag) != 0;
}
// Get the number of attachments in the Vulkan render pass, i.e. after removing disabled // Get the number of attachments in the Vulkan render pass, i.e. after removing disabled
// color attachments. // color attachments.
...@@ -260,8 +277,10 @@ class alignas(4) RenderPassDesc final ...@@ -260,8 +277,10 @@ class alignas(4) RenderPassDesc final
static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7; static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7;
// Flags stored in the upper 5 bits of mAttachmentFormats.back(). // Flags stored in the upper 5 bits of mAttachmentFormats.back().
static constexpr uint8_t kResolveDepthFlag = 0x80; static constexpr uint8_t kResolveDepthFlag = 0x80;
static constexpr uint8_t kResolveStencilFlag = 0x40; static constexpr uint8_t kResolveStencilFlag = 0x40;
static constexpr uint8_t kUnresolveDepthFlag = 0x20;
static constexpr uint8_t kUnresolveStencilFlag = 0x10;
}; };
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs); bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
...@@ -1061,7 +1080,7 @@ class FramebufferDesc ...@@ -1061,7 +1080,7 @@ class FramebufferDesc
void updateColor(uint32_t index, ImageViewSubresourceSerial serial); void updateColor(uint32_t index, ImageViewSubresourceSerial serial);
void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial); void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial);
void updateColorUnresolveMask(gl::DrawBufferMask colorUnresolveMask); void updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask);
void updateDepthStencil(ImageViewSubresourceSerial serial); void updateDepthStencil(ImageViewSubresourceSerial serial);
void updateDepthStencilResolve(ImageViewSubresourceSerial serial); void updateDepthStencilResolve(ImageViewSubresourceSerial serial);
size_t hash() const; size_t hash() const;
...@@ -1082,12 +1101,11 @@ class FramebufferDesc ...@@ -1082,12 +1101,11 @@ class FramebufferDesc
// Note: this is an exclusive index. If there is one index it will be "1". // Note: this is an exclusive index. If there is one index it will be "1".
uint16_t mMaxIndex; uint16_t mMaxIndex;
uint8_t mPadding;
// If the render pass contains an initial subpass to unresolve a number of attachments, the // If the render pass contains an initial subpass to unresolve a number of attachments, the
// subpass description is derived from the following mask, specifying which attachments need // subpass description is derived from the following mask, specifying which attachments need
// to be unresolved. // to be unresolved. Includes both color and depth/stencil attachments.
gl::DrawBufferMask mColorUnresolveAttachmentMask; FramebufferNonResolveAttachmentMask mUnresolveAttachmentMask;
FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials; FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials;
}; };
......
...@@ -384,6 +384,22 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -384,6 +384,22 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilResolveAttachment,
ImageMemoryBarrierData{
"DepthStencilResolveAttachment",
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
// Note: depth/stencil resolve uses color output stage and mask!
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// Transition from: all writes must finish before barrier.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write,
PipelineStage::ColorAttachmentOutput,
},
},
{
ImageLayout::Present, ImageLayout::Present,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"Present", "Present",
...@@ -5743,8 +5759,8 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk, ...@@ -5743,8 +5759,8 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk,
} }
// 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 framebuffer attachments, and
// don't have swizzle. // therefore don't have swizzle.
gl::TextureType viewType = Get2DTextureType(1, image.getSamples()); gl::TextureType viewType = Get2DTextureType(1, image.getSamples());
return image.initLayerImageView(contextVk, viewType, image.getAspectFlags(), gl::SwizzleState(), return image.initLayerImageView(contextVk, viewType, image.getAspectFlags(), gl::SwizzleState(),
imageView, levelVk, 1, layer, 1); imageView, levelVk, 1, layer, 1);
......
...@@ -1204,6 +1204,7 @@ enum class ImageLayout ...@@ -1204,6 +1204,7 @@ enum class ImageLayout
ColorAttachment, ColorAttachment,
DepthStencilReadOnly, DepthStencilReadOnly,
DepthStencilAttachment, DepthStencilAttachment,
DepthStencilResolveAttachment,
Present, Present,
InvalidEnum, InvalidEnum,
......
...@@ -1638,6 +1638,126 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot ...@@ -1638,6 +1638,126 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot
EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize / 2 - 1, GLColor::red); EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize / 2 - 1, GLColor::red);
} }
// Tests that multisampled-render-to-texture depth/stencil renderbuffers don't ever load depth data.
// Stencil data may still be loaded if VK_EXT_shader_stencil_export is not supported.
TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShouldNotLoad)
{
// http://anglebug.com/5083
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
const rx::vk::PerfCounters &counters = hackANGLE();
uint32_t expectedDepthClearCount = counters.depthClears + 1;
uint32_t expectedDepthLoadCount = counters.depthLoads;
uint32_t expectedStencilClearCount = counters.stencilClears + 1;
uint32_t expectedStencilLoadCountMin = counters.stencilLoads;
uint32_t expectedStencilLoadCountMax = counters.stencilLoads + 4;
GLFramebuffer FBO;
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
constexpr GLsizei kSize = 6;
// Create multisampled framebuffer to draw into, with both color and depth attachments.
GLTexture colorMS;
glBindTexture(GL_TEXTURE_2D, colorMS);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLRenderbuffer depthStencilMS;
glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
GLFramebuffer fboMS;
glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
colorMS, 0, 4);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencilMS);
ASSERT_GL_NO_ERROR();
// Set up texture for copy operation that breaks the render pass
GLTexture copyTex;
glBindTexture(GL_TEXTURE_2D, copyTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// Set viewport and clear depth
glViewport(0, 0, kSize, kSize);
glClearDepthf(1);
glClearStencil(0x55);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// If stencil is not clear to 0x55, rendering would fail.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
// Set up program
ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(drawColor);
GLint colorUniformLocation =
glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
// Draw red
glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.75f);
ASSERT_GL_NO_ERROR();
// Break the render pass
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
ASSERT_GL_NO_ERROR();
// Draw green
glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
// Break the render pass
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
ASSERT_GL_NO_ERROR();
// Draw blue
glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
ASSERT_GL_NO_ERROR();
// Break the render pass
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
ASSERT_GL_NO_ERROR();
// Draw yellow
glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
// Break the render pass
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
ASSERT_GL_NO_ERROR();
// Verify the counters
EXPECT_EQ(counters.depthClears, expectedDepthClearCount);
EXPECT_EQ(counters.depthLoads, expectedDepthLoadCount);
EXPECT_EQ(counters.stencilClears, expectedStencilClearCount);
EXPECT_GE(counters.stencilLoads, expectedStencilLoadCountMin);
EXPECT_LE(counters.stencilLoads, expectedStencilLoadCountMax);
// Verify that copies were done correctly.
GLFramebuffer verifyFBO;
glBindFramebuffer(GL_FRAMEBUFFER, verifyFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, kSize / 2, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
}
// Ensures we use read-only depth layout when there is no write // Ensures we use read-only depth layout when there is no write
TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout) TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
{ {
......
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