Vulkan: fix masked stencil clear
Previously, masked stencil clear was done by clearing every stencil bit
to the ClearValue & Mask. The correct behavior as implemented in this
change is to clear only the bits that are set in Mask. This can only be
done through a draw call, with ClearValue as the stencil reference, and
Mask as the stencil write mask.
Note: this change relies on the depthClamp Vulkan feature which is not
available on ARM.
Bug: angleproject:3241
Change-Id: I0a181c32f881ee813f144e7bdd6f42c8ea6f1966
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1548442
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Tobin Ehlis <tobine@google.com>
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 11e1d90..2520684 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -1349,7 +1349,31 @@
return angle::Result::Continue;
}
- ANGLE_TRY(mImpl->clear(context, mask));
+ // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
+ // color/depth/stencil masks make the clear ineffective we skip it altogether.
+
+ // If all color channels are masked, don't attempt to clear color.
+ if (context->getState().getBlendState().allChannelsMasked())
+ {
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ // If depth write is disabled, don't attempt to clear depth.
+ if (!context->getState().getDepthStencilState().depthMask)
+ {
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+
+ // If all stencil bits are masked, don't attempt to clear stencil.
+ if (context->getState().getDepthStencilState().stencilWritemask == 0)
+ {
+ mask &= ~GL_STENCIL_BUFFER_BIT;
+ }
+
+ if (mask != 0)
+ {
+ ANGLE_TRY(mImpl->clear(context, mask));
+ }
return angle::Result::Continue;
}
@@ -1364,6 +1388,23 @@
return angle::Result::Continue;
}
+ if (buffer == GL_DEPTH)
+ {
+ // If depth write is disabled, don't attempt to clear depth.
+ if (!context->getState().getDepthStencilState().depthMask)
+ {
+ return angle::Result::Continue;
+ }
+ }
+ else
+ {
+ // If all color channels are masked, don't attempt to clear color.
+ if (context->getState().getBlendState().allChannelsMasked())
+ {
+ return angle::Result::Continue;
+ }
+ }
+
ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
return angle::Result::Continue;
@@ -1379,6 +1420,12 @@
return angle::Result::Continue;
}
+ // If all color channels are masked, don't attempt to clear color.
+ if (context->getState().getBlendState().allChannelsMasked())
+ {
+ return angle::Result::Continue;
+ }
+
ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
return angle::Result::Continue;
@@ -1394,6 +1441,23 @@
return angle::Result::Continue;
}
+ if (buffer == GL_STENCIL)
+ {
+ // If all stencil bits are masked, don't attempt to clear stencil.
+ if (context->getState().getDepthStencilState().stencilWritemask == 0)
+ {
+ return angle::Result::Continue;
+ }
+ }
+ else
+ {
+ // If all color channels are masked, don't attempt to clear color.
+ if (context->getState().getBlendState().allChannelsMasked())
+ {
+ return angle::Result::Continue;
+ }
+ }
+
ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
return angle::Result::Continue;
@@ -1410,7 +1474,22 @@
return angle::Result::Continue;
}
- ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
+ bool clearDepth = context->getState().getDepthStencilState().depthMask;
+ bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
+
+ if (clearDepth && clearStencil)
+ {
+ ASSERT(buffer == GL_DEPTH_STENCIL);
+ ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
+ }
+ else if (clearDepth && !clearStencil)
+ {
+ ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
+ }
+ else if (!clearDepth && clearStencil)
+ {
+ ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
+ }
return angle::Result::Continue;
}
diff --git a/src/libANGLE/angletypes.cpp b/src/libANGLE/angletypes.cpp
index 1b51947..838b976 100644
--- a/src/libANGLE/angletypes.cpp
+++ b/src/libANGLE/angletypes.cpp
@@ -59,6 +59,11 @@
memcpy(this, &other, sizeof(BlendState));
}
+bool BlendState::allChannelsMasked() const
+{
+ return !colorMaskRed && !colorMaskGreen && !colorMaskBlue && !colorMaskAlpha;
+}
+
bool operator==(const BlendState &a, const BlendState &b)
{
return memcmp(&a, &b, sizeof(BlendState)) == 0;
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index 12e4122..dcb95f4 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -146,6 +146,8 @@
BlendState();
BlendState(const BlendState &other);
+ bool allChannelsMasked() const;
+
bool blend;
GLenum sourceBlendRGB;
GLenum destBlendRGB;
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index a32aec0..23afd1d 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -234,20 +234,37 @@
// This function assumes that only enabled attachments are asked to be cleared.
ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
- bool clearColor = clearColorBuffers.any();
+
+ // Adjust clear behavior based on whether:
+ //
+ // - the respective attachments are present: if asked to clear a non-existent attachment, don't
+ // attempt to clear it.
+ // - extra clear is necessary: if depth- or stencil-only attachments are emulated with a format
+ // that has both aspects, clear the emulated aspect.
+
+ VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
+ bool clearColor = clearColorBuffers.any();
const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment();
clearDepth = clearDepth && depthAttachment;
ASSERT(!clearDepth || depthAttachment->isAttached());
- // If depth write is disabled, pretend that depth clear is not requested altogether.
- clearDepth = clearDepth && contextVk->getState().getDepthStencilState().depthMask;
-
const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
clearStencil = clearStencil && stencilAttachment;
ASSERT(!clearStencil || stencilAttachment->isAttached());
- // If the only thing to be cleared was depth and it's masked, there's nothing to do.
+ uint8_t stencilMask =
+ static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
+
+ // The front-end should ensure we don't attempt to clear color if all channels are masked.
+ ASSERT(!clearColor || colorMaskFlags != 0);
+ // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
+ ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
+ // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
+ ASSERT(!clearStencil || stencilMask != 0);
+
+ // If there is nothing to clear, return right away (for example, if asked to clear depth, but
+ // there is no depth attachment).
if (!clearColor && !clearDepth && !clearStencil)
{
return angle::Result::Continue;
@@ -255,11 +272,6 @@
VkClearDepthStencilValue modifiedDepthStencilValue = clearDepthStencilValue;
- // Apply the stencil mask to the clear value.
- // TODO(syoussefi): this logic is flawed. See http://anglebug.com/3241#c9.
- modifiedDepthStencilValue.stencil &=
- contextVk->getState().getDepthStencilState().stencilWritemask;
-
// If the depth or stencil is being cleared, and the image was originally requested to have a
// single aspect, but it's emulated with a depth/stencil format, clear both aspects, setting the
// other aspect to 0.
@@ -287,19 +299,19 @@
bool isScissorTestEffectivelyEnabled =
glState.isScissorTestEnabled() && scissorRenderAreaIntersection != renderArea;
- // We can use render pass load ops if clearing depth/stencil or unmasked color. If there's a
- // depth mask, depth clearing is disabled. If there's a stencil mask, the clear value is
- // already masked. There is no depth/stencil condition prohibiting the use of render pass
- // loadOp.
- VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
+ // We can use render pass load ops if clearing depth, unmasked color or unmasked stencil. If
+ // there's a depth mask, depth clearing is already disabled.
bool maskedClearColor =
clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents;
- bool clearColorWithRenderPassLoadOp = clearColor && !maskedClearColor;
+ bool maskedClearStencil = stencilMask != 0xFF;
+
+ bool clearColorWithRenderPassLoadOp = clearColor && !maskedClearColor;
+ bool clearStencilWithRenderPassLoadOp = clearStencil && !maskedClearStencil;
// At least one of color, depth or stencil should be clearable with render pass loadOp for us
// to use this clear path.
bool clearAnyWithRenderPassLoadOp =
- clearColorWithRenderPassLoadOp || clearDepth || clearStencil;
+ clearColorWithRenderPassLoadOp || clearDepth || clearStencilWithRenderPassLoadOp;
if (clearAnyWithRenderPassLoadOp && !isScissorTestEffectivelyEnabled)
{
@@ -313,7 +325,8 @@
}
// If there's a color mask, only clear depth/stencil with render pass loadOp.
ANGLE_TRY(clearWithRenderPassOp(contextVk, clearBuffersWithRenderPassLoadOp, clearDepth,
- clearStencil, clearColorValue, modifiedDepthStencilValue));
+ clearStencilWithRenderPassLoadOp, clearColorValue,
+ modifiedDepthStencilValue));
// On some hardware, having inline commands at this point results in corrupted output. In
// that case, end the render pass immediately. http://anglebug.com/2361
@@ -323,39 +336,34 @@
}
// Fallback to other methods for whatever isn't cleared here.
- clearDepth = false;
- clearStencil = false;
+ clearDepth = false;
if (clearColorWithRenderPassLoadOp)
{
+ clearColorBuffers.reset();
clearColor = false;
}
+ if (clearStencilWithRenderPassLoadOp)
+ {
+ clearStencil = false;
+ }
- if (!clearColor)
+ // If nothing left to clear, early out.
+ if (!clearColor && !clearStencil)
{
return angle::Result::Continue;
}
}
- // The most costly clear mode is when we need to mask out specific color channels. This can
- // only be done with a draw call. The scissor region however can easily be integrated with
- // this method. Similarly for depth/stencil clear.
- if (maskedClearColor)
+ // The most costly clear mode is when we need to mask out specific color channels or stencil
+ // bits. This can only be done with a draw call. The scissor region however can easily be
+ // integrated with this method.
+ //
+ // Since we have to have a draw call for the sake of masked color or stencil, we can make sure
+ // everything else is cleared with the draw call at the same time as well.
+ if (maskedClearColor || maskedClearStencil)
{
- ANGLE_TRY(clearWithDraw(contextVk, clearColorBuffers, clearColorValue, colorMaskFlags));
-
- // Stencil clears must be handled separately. The only way to write out a stencil value from
- // a fragment shader in Vulkan is with VK_EXT_shader_stencil_export. Support for this
- // extension is sparse. Hence, we call into the RenderPass clear path. We similarly clear
- // depth to keep the code simple, but depth clears could be combined with the masked color
- // clears as an optimization.
-
- if (clearDepth || clearStencil)
- {
- ANGLE_TRY(clearWithClearAttachments(contextVk, gl::DrawBufferMask(), clearDepth,
- clearStencil, clearColorValue,
- modifiedDepthStencilValue));
- }
- return angle::Result::Continue;
+ return clearWithDraw(contextVk, clearColorBuffers, clearDepth, clearStencil, colorMaskFlags,
+ stencilMask, clearColorValue, modifiedDepthStencilValue);
}
ASSERT(isScissorTestEffectivelyEnabled);
@@ -1173,15 +1181,25 @@
angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
+ bool clearDepth,
+ bool clearStencil,
+ VkColorComponentFlags colorMaskFlags,
+ uint8_t stencilMask,
const VkClearColorValue &clearColorValue,
- VkColorComponentFlags colorMaskFlags)
+ const VkClearDepthStencilValue &clearDepthStencilValue)
{
RendererVk *renderer = contextVk->getRenderer();
- UtilsVk::ClearImageParameters params = {};
- params.renderAreaHeight = mState.getDimensions().height;
- params.clearValue = clearColorValue;
- params.renderPassDesc = &getRenderPassDesc();
+ UtilsVk::ClearFramebufferParameters params = {};
+ params.renderPassDesc = &getRenderPassDesc();
+ params.renderAreaHeight = mState.getDimensions().height;
+ params.colorClearValue = clearColorValue;
+ params.depthStencilClearValue = clearDepthStencilValue;
+ params.stencilMask = stencilMask;
+
+ params.clearColor = true;
+ params.clearDepth = clearDepth;
+ params.clearStencil = clearStencil;
const auto &colorRenderTargets = mRenderTargetCache.getColors();
for (size_t colorIndex : clearColorBuffers)
@@ -1189,15 +1207,26 @@
const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
ASSERT(colorRenderTarget);
- params.format = &colorRenderTarget->getImage().getFormat().textureFormat();
- params.attachmentIndex = colorIndex;
- params.colorMaskFlags = colorMaskFlags;
+ params.colorFormat = &colorRenderTarget->getImage().getFormat().textureFormat();
+ params.colorAttachmentIndex = colorIndex;
+ params.colorMaskFlags = colorMaskFlags;
if (mEmulatedAlphaAttachmentMask[colorIndex])
{
params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
}
- ANGLE_TRY(renderer->getUtils().clearImage(contextVk, this, params));
+ ANGLE_TRY(renderer->getUtils().clearFramebuffer(contextVk, this, params));
+
+ // Clear depth/stencil only once!
+ params.clearDepth = false;
+ params.clearStencil = false;
+ }
+
+ // If there was no color clear, clear depth/stencil alone.
+ if (params.clearDepth || params.clearStencil)
+ {
+ params.clearColor = false;
+ ANGLE_TRY(renderer->getUtils().clearFramebuffer(contextVk, this, params));
}
return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index dfbcf4e..121cd1b 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -179,8 +179,12 @@
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithDraw(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
+ bool clearDepth,
+ bool clearStencil,
+ VkColorComponentFlags colorMaskFlags,
+ uint8_t stencilMask,
const VkClearColorValue &clearColorValue,
- VkColorComponentFlags colorMaskFlags);
+ const VkClearDepthStencilValue &clearDepthStencilValue);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc();
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 56787fa..4b69479 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -979,6 +979,7 @@
enabledFeatures.features.independentBlend = mPhysicalDeviceFeatures.independentBlend;
enabledFeatures.features.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
enabledFeatures.features.samplerAnisotropy = mPhysicalDeviceFeatures.samplerAnisotropy;
+ enabledFeatures.features.depthClamp = mPhysicalDeviceFeatures.depthClamp;
if (!vk::CommandBuffer::ExecutesInline())
{
enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
index 0c309d9..8adbb3b 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
@@ -200,6 +200,7 @@
{
program.destroy(device);
}
+ mImageClearProgramVSOnly.destroy(device);
for (vk::ShaderProgramHelper &program : mImageClearProgram)
{
program.destroy(device);
@@ -365,7 +366,10 @@
else
{
program->setShader(gl::ShaderType::Vertex, vsShader);
- program->setShader(gl::ShaderType::Fragment, fsCsShader);
+ if (fsCsShader)
+ {
+ program->setShader(gl::ShaderType::Fragment, fsCsShader);
+ }
// This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
const vk::GraphicsPipelineDesc *descPtr;
@@ -637,9 +641,9 @@
return angle::Result::Continue;
}
-angle::Result UtilsVk::clearImage(ContextVk *contextVk,
- FramebufferVk *framebuffer,
- const ClearImageParameters ¶ms)
+angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
+ FramebufferVk *framebuffer,
+ const ClearFramebufferParameters ¶ms)
{
RendererVk *renderer = contextVk->getRenderer();
@@ -652,24 +656,54 @@
}
ImageClearShaderParams shaderParams;
- shaderParams.clearValue = params.clearValue;
-
- uint32_t flags = GetImageClearFlags(*params.format, params.attachmentIndex);
+ shaderParams.clearValue = params.colorClearValue;
vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults();
pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
- pipelineDesc.setSingleColorWriteMask(params.attachmentIndex, params.colorMaskFlags);
+ pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndex, params.colorMaskFlags);
pipelineDesc.setRenderPassDesc(*params.renderPassDesc);
// Note: depth test is disabled by default so this should be unnecessary, but works around an
// Intel bug on windows. http://anglebug.com/3348
pipelineDesc.setDepthWriteEnabled(false);
+ // Clear depth by enabling depth clamping and setting the viewport depth range to the clear
+ // value.
+ if (params.clearDepth)
+ {
+ pipelineDesc.setDepthTestEnabled(true);
+ pipelineDesc.setDepthWriteEnabled(true);
+ pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
+ pipelineDesc.setDepthClampEnabled(true);
+ }
+
+ // Clear stencil by enabling stencil write with the right mask.
+ if (params.clearStencil)
+ {
+ const uint8_t compareMask = 0xFF;
+ const uint8_t clearStencilValue =
+ static_cast<uint8_t>(params.depthStencilClearValue.stencil);
+
+ pipelineDesc.setStencilTestEnabled(true);
+ pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
+ pipelineDesc.setStencilBackFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
+ pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
+ VK_STENCIL_OP_REPLACE);
+ pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
+ VK_STENCIL_OP_REPLACE);
+ pipelineDesc.setStencilFrontWriteMask(params.stencilMask);
+ pipelineDesc.setStencilBackWriteMask(params.stencilMask);
+ }
+
const gl::Rectangle &renderArea = framebuffer->getFramebuffer()->getRenderPassRenderArea();
bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
VkViewport viewport;
- gl_vk::GetViewport(renderArea, 0.0f, 1.0f, invertViewport, params.renderAreaHeight, &viewport);
+ // Set depth range to clear value. If clearing depth, the vertex shader depth output is clamped
+ // to this value, thus clearing the depth buffer to the desired clear value.
+ const float clearDepthValue = params.depthStencilClearValue.depth;
+ gl_vk::GetViewport(renderArea, clearDepthValue, clearDepthValue, invertViewport,
+ params.renderAreaHeight, &viewport);
pipelineDesc.setViewport(viewport);
VkRect2D scissor;
@@ -680,11 +714,18 @@
vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
+ vk::ShaderProgramHelper *imageClearProgram = &mImageClearProgramVSOnly;
+
ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
- ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
+ if (params.clearColor)
+ {
+ uint32_t flags = GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndex);
+ ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
+ imageClearProgram = &mImageClearProgram[flags];
+ }
ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
- &mImageClearProgram[flags], &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
+ imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
sizeof(shaderParams), commandBuffer));
commandBuffer->draw(6, 0);
return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.h b/src/libANGLE/renderer/vulkan/UtilsVk.h
index 39e2b52..8d207d0 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.h
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.h
@@ -59,14 +59,22 @@
size_t destOffset;
};
- struct ClearImageParameters
+ struct ClearFramebufferParameters
{
- VkClearColorValue clearValue;
- VkColorComponentFlags colorMaskFlags;
- GLint renderAreaHeight;
const vk::RenderPassDesc *renderPassDesc;
- const angle::Format *format;
- uint32_t attachmentIndex;
+ GLint renderAreaHeight;
+
+ bool clearColor;
+ bool clearDepth;
+ bool clearStencil;
+
+ uint8_t stencilMask;
+ VkColorComponentFlags colorMaskFlags;
+ uint32_t colorAttachmentIndex;
+ const angle::Format *colorFormat;
+
+ VkClearColorValue colorClearValue;
+ VkClearDepthStencilValue depthStencilClearValue;
};
struct CopyImageParameters
@@ -95,12 +103,9 @@
vk::BufferHelper *src,
const ConvertVertexParameters ¶ms);
- // Note: this function takes a FramebufferVk instead of ImageHelper, as that's the only user,
- // which avoids recreating a framebuffer. An overload taking ImageHelper can be added when
- // necessary.
- angle::Result clearImage(ContextVk *contextVk,
- FramebufferVk *framebuffer,
- const ClearImageParameters ¶ms);
+ angle::Result clearFramebuffer(ContextVk *contextVk,
+ FramebufferVk *framebuffer,
+ const ClearFramebufferParameters ¶ms);
angle::Result copyImage(ContextVk *contextVk,
vk::ImageHelper *dest,
@@ -232,6 +237,7 @@
vk::ShaderProgramHelper
mConvertVertexPrograms[vk::InternalShader::ConvertVertex_comp::kFlagsMask |
vk::InternalShader::ConvertVertex_comp::kConversionMask];
+ vk::ShaderProgramHelper mImageClearProgramVSOnly;
vk::ShaderProgramHelper
mImageClearProgram[vk::InternalShader::ImageClear_frag::kAttachmentIndexMask |
vk::InternalShader::ImageClear_frag::kFormatMask];
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index b7195e8..10de54b 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -85,7 +85,7 @@
}
}
-uint8_t PackGLStencilOp(GLenum compareOp)
+VkStencilOp PackGLStencilOp(GLenum compareOp)
{
switch (compareOp)
{
@@ -107,11 +107,11 @@
return VK_STENCIL_OP_INVERT;
default:
UNREACHABLE();
- return 0;
+ return VK_STENCIL_OP_KEEP;
}
}
-uint8_t PackGLCompareFunc(GLenum compareFunc)
+VkCompareOp PackGLCompareFunc(GLenum compareFunc)
{
switch (compareFunc)
{
@@ -133,7 +133,7 @@
return VK_COMPARE_OP_NOT_EQUAL;
default:
UNREACHABLE();
- return 0;
+ return VK_COMPARE_OP_NEVER;
}
}
@@ -879,26 +879,91 @@
}
}
+void GraphicsPipelineDesc::setDepthTestEnabled(bool enabled)
+{
+ mDepthStencilStateInfo.enable.depthTest = enabled;
+}
+
void GraphicsPipelineDesc::setDepthWriteEnabled(bool enabled)
{
mDepthStencilStateInfo.enable.depthWrite = enabled;
}
+void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
+{
+ SetBitField(mDepthStencilStateInfo.depthCompareOp, op);
+}
+
+void GraphicsPipelineDesc::setDepthClampEnabled(bool enabled)
+{
+ mRasterizationAndMultisampleStateInfo.bits.depthClampEnable = enabled;
+}
+
+void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
+{
+ mDepthStencilStateInfo.enable.stencilTest = enabled;
+}
+
+void GraphicsPipelineDesc::setStencilFrontFuncs(uint8_t reference,
+ VkCompareOp compareOp,
+ uint8_t compareMask)
+{
+ mDepthStencilStateInfo.frontStencilReference = reference;
+ mDepthStencilStateInfo.front.compareMask = compareMask;
+ SetBitField(mDepthStencilStateInfo.front.ops.compare, compareOp);
+}
+
+void GraphicsPipelineDesc::setStencilBackFuncs(uint8_t reference,
+ VkCompareOp compareOp,
+ uint8_t compareMask)
+{
+ mDepthStencilStateInfo.backStencilReference = reference;
+ mDepthStencilStateInfo.back.compareMask = compareMask;
+ SetBitField(mDepthStencilStateInfo.back.ops.compare, compareOp);
+}
+
+void GraphicsPipelineDesc::setStencilFrontOps(VkStencilOp failOp,
+ VkStencilOp passOp,
+ VkStencilOp depthFailOp)
+{
+ SetBitField(mDepthStencilStateInfo.front.ops.fail, failOp);
+ SetBitField(mDepthStencilStateInfo.front.ops.pass, passOp);
+ SetBitField(mDepthStencilStateInfo.front.ops.depthFail, depthFailOp);
+}
+
+void GraphicsPipelineDesc::setStencilBackOps(VkStencilOp failOp,
+ VkStencilOp passOp,
+ VkStencilOp depthFailOp)
+{
+ SetBitField(mDepthStencilStateInfo.back.ops.fail, failOp);
+ SetBitField(mDepthStencilStateInfo.back.ops.pass, passOp);
+ SetBitField(mDepthStencilStateInfo.back.ops.depthFail, depthFailOp);
+}
+
+void GraphicsPipelineDesc::setStencilFrontWriteMask(uint8_t mask)
+{
+ mDepthStencilStateInfo.front.writeMask = mask;
+}
+
+void GraphicsPipelineDesc::setStencilBackWriteMask(uint8_t mask)
+{
+ mDepthStencilStateInfo.back.writeMask = mask;
+}
+
void GraphicsPipelineDesc::updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
const gl::DepthStencilState &depthStencilState,
const gl::Framebuffer *drawFramebuffer)
{
// Only enable the depth test if the draw framebuffer has a depth buffer. It's possible that
// we're emulating a stencil-only buffer with a depth-stencil buffer
- mDepthStencilStateInfo.enable.depthTest =
- static_cast<uint8_t>(depthStencilState.depthTest && drawFramebuffer->hasDepth());
+ setDepthTestEnabled(depthStencilState.depthTest && drawFramebuffer->hasDepth());
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
}
void GraphicsPipelineDesc::updateDepthFunc(GraphicsPipelineTransitionBits *transition,
const gl::DepthStencilState &depthStencilState)
{
- mDepthStencilStateInfo.depthCompareOp = PackGLCompareFunc(depthStencilState.depthFunc);
+ setDepthFunc(PackGLCompareFunc(depthStencilState.depthFunc));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOp));
}
@@ -907,8 +972,7 @@
const gl::Framebuffer *drawFramebuffer)
{
// Don't write to depth buffers that should not exist
- mDepthStencilStateInfo.enable.depthWrite =
- static_cast<uint8_t>(drawFramebuffer->hasDepth() ? depthStencilState.depthMask : 0);
+ setDepthWriteEnabled(drawFramebuffer->hasDepth() ? depthStencilState.depthMask : false);
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
}
@@ -918,8 +982,7 @@
{
// Only enable the stencil test if the draw framebuffer has a stencil buffer. It's possible
// that we're emulating a depth-only buffer with a depth-stencil buffer
- mDepthStencilStateInfo.enable.stencilTest =
- static_cast<uint8_t>(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
+ setStencilTestEnabled(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
}
@@ -927,9 +990,9 @@
GLint ref,
const gl::DepthStencilState &depthStencilState)
{
- mDepthStencilStateInfo.frontStencilReference = static_cast<uint8_t>(ref);
- mDepthStencilStateInfo.front.ops.compare = PackGLCompareFunc(depthStencilState.stencilFunc);
- mDepthStencilStateInfo.front.compareMask = static_cast<uint8_t>(depthStencilState.stencilMask);
+ setStencilFrontFuncs(static_cast<uint8_t>(ref),
+ PackGLCompareFunc(depthStencilState.stencilFunc),
+ static_cast<uint8_t>(depthStencilState.stencilMask));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, frontStencilReference));
}
@@ -938,10 +1001,9 @@
GLint ref,
const gl::DepthStencilState &depthStencilState)
{
- mDepthStencilStateInfo.backStencilReference = static_cast<uint8_t>(ref);
- mDepthStencilStateInfo.back.ops.compare = PackGLCompareFunc(depthStencilState.stencilBackFunc);
- mDepthStencilStateInfo.back.compareMask =
- static_cast<uint8_t>(depthStencilState.stencilBackMask);
+ setStencilBackFuncs(static_cast<uint8_t>(ref),
+ PackGLCompareFunc(depthStencilState.stencilBackFunc),
+ static_cast<uint8_t>(depthStencilState.stencilBackMask));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, backStencilReference));
}
@@ -949,21 +1011,18 @@
void GraphicsPipelineDesc::updateStencilFrontOps(GraphicsPipelineTransitionBits *transition,
const gl::DepthStencilState &depthStencilState)
{
- mDepthStencilStateInfo.front.ops.pass = PackGLStencilOp(depthStencilState.stencilPassDepthPass);
- mDepthStencilStateInfo.front.ops.fail = PackGLStencilOp(depthStencilState.stencilFail);
- mDepthStencilStateInfo.front.ops.depthFail =
- PackGLStencilOp(depthStencilState.stencilPassDepthFail);
+ setStencilFrontOps(PackGLStencilOp(depthStencilState.stencilFail),
+ PackGLStencilOp(depthStencilState.stencilPassDepthPass),
+ PackGLStencilOp(depthStencilState.stencilPassDepthFail));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
}
void GraphicsPipelineDesc::updateStencilBackOps(GraphicsPipelineTransitionBits *transition,
const gl::DepthStencilState &depthStencilState)
{
- mDepthStencilStateInfo.back.ops.pass =
- PackGLStencilOp(depthStencilState.stencilBackPassDepthPass);
- mDepthStencilStateInfo.back.ops.fail = PackGLStencilOp(depthStencilState.stencilBackFail);
- mDepthStencilStateInfo.back.ops.depthFail =
- PackGLStencilOp(depthStencilState.stencilBackPassDepthFail);
+ setStencilBackOps(PackGLStencilOp(depthStencilState.stencilBackFail),
+ PackGLStencilOp(depthStencilState.stencilBackPassDepthPass),
+ PackGLStencilOp(depthStencilState.stencilBackPassDepthFail));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
}
@@ -973,8 +1032,8 @@
const gl::Framebuffer *drawFramebuffer)
{
// Don't write to stencil buffers that should not exist
- mDepthStencilStateInfo.front.writeMask = static_cast<uint8_t>(
- drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0);
+ setStencilFrontWriteMask(static_cast<uint8_t>(
+ drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
}
@@ -984,8 +1043,8 @@
const gl::Framebuffer *drawFramebuffer)
{
// Don't write to stencil buffers that should not exist
- mDepthStencilStateInfo.back.writeMask = static_cast<uint8_t>(
- drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0);
+ setStencilBackWriteMask(static_cast<uint8_t>(
+ drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0));
transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
}
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
index 431f81e..fff720a 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
@@ -373,7 +373,17 @@
const gl::DrawBufferMask &alphaMask);
// Depth/stencil states.
+ void setDepthTestEnabled(bool enabled);
void setDepthWriteEnabled(bool enabled);
+ void setDepthFunc(VkCompareOp op);
+ void setDepthClampEnabled(bool enabled);
+ void setStencilTestEnabled(bool enabled);
+ void setStencilFrontFuncs(uint8_t reference, VkCompareOp compareOp, uint8_t compareMask);
+ void setStencilBackFuncs(uint8_t reference, VkCompareOp compareOp, uint8_t compareMask);
+ void setStencilFrontOps(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp);
+ void setStencilBackOps(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp);
+ void setStencilFrontWriteMask(uint8_t mask);
+ void setStencilBackWriteMask(uint8_t mask);
void updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
const gl::DepthStencilState &depthStencilState,
const gl::Framebuffer *drawFramebuffer);
diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
index 009d64e..f345a36 100644
--- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
@@ -266,12 +266,6 @@
// General Vulkan failures
3300 VULKAN : dEQP-GLES2.functional.shaders.texture_functions.vertex.texturecubelod = FAIL
-// Depth/stencil clear
-3241 VULKAN : dEQP-GLES2.functional.depth_stencil_clear.stencil_masked = FAIL
-3241 VULKAN : dEQP-GLES2.functional.depth_stencil_clear.stencil_scissored_masked = FAIL
-3241 VULKAN : dEQP-GLES2.functional.depth_stencil_clear.depth_stencil_masked = FAIL
-3241 VULKAN : dEQP-GLES2.functional.depth_stencil_clear.depth_stencil_scissored_masked = FAIL
-
// Only seen failing on Android
3241 VULKAN ANDROID : dEQP-GLES2.functional.depth_stencil_clear.depth_scissored_masked = FAIL
@@ -378,4 +372,4 @@
2976 VULKAN NVIDIA : dEQP-GLES2.functional.shaders.invariance.* = FAIL
// Tests were being hidden by flakiness (anglebug.com/3271)
-3328 VULKAN WIN NVIDIA : dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec4_qqqt_vertex = SKIP
\ No newline at end of file
+3328 VULKAN WIN NVIDIA : dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec4_qqqt_vertex = SKIP
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
index f150177..b2ced95 100644
--- a/src/tests/gl_tests/ClearTest.cpp
+++ b/src/tests/gl_tests/ClearTest.cpp
@@ -84,6 +84,7 @@
protected:
void MaskedScissoredColorDepthStencilClear(bool mask,
bool scissor,
+ bool clearColor,
bool clearDepth,
bool clearStencil);
@@ -1131,6 +1132,7 @@
void ClearTest::MaskedScissoredColorDepthStencilClear(bool mask,
bool scissor,
+ bool clearColor,
bool clearDepth,
bool clearStencil)
{
@@ -1143,14 +1145,31 @@
const int whalf = w >> 1;
const int hhalf = h >> 1;
+ constexpr float kPreClearDepth = 0.9f;
+ constexpr float kClearDepth = 0.5f;
+ constexpr uint8_t kPreClearStencil = 0xFF;
+ constexpr uint8_t kClearStencil = 0x16;
+ constexpr uint8_t kStencilMask = 0x59;
+ constexpr uint8_t kMaskedClearStencil =
+ (kPreClearStencil & ~kStencilMask) | (kClearStencil & kStencilMask);
+
// Clear to a random color, 0.9 depth and 0x00 stencil
Vector4 color1(0.1f, 0.2f, 0.3f, 0.4f);
GLColor color1RGB(color1);
glClearColor(color1[0], color1[1], color1[2], color1[3]);
- glClearDepthf(0.9f);
- glClearStencil(0x00);
- glClear(GL_COLOR_BUFFER_BIT | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0) |
+ glClearDepthf(kPreClearDepth);
+ glClearStencil(kPreClearStencil);
+
+ if (!clearColor)
+ {
+ // If not asked to clear color, clear it anyway, but individually. The clear value is
+ // still used to verify that the depth/stencil clear happened correctly. This allows
+ // testing for depth/stencil-only clear implementations.
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ glClear((clearColor ? GL_COLOR_BUFFER_BIT : 0) | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0) |
(clearStencil ? GL_STENCIL_BUFFER_BIT : 0));
ASSERT_GL_NO_ERROR();
@@ -1167,15 +1186,15 @@
Vector4 color2(0.2f, 0.4f, 0.6f, 0.8f);
GLColor color2RGB(color2);
glClearColor(color2[0], color2[1], color2[2], color2[3]);
- glClearDepthf(0.5f);
- glClearStencil(0xFF);
+ glClearDepthf(kClearDepth);
+ glClearStencil(kClearStencil);
if (mask)
{
glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
glDepthMask(GL_FALSE);
- glStencilMask(0x59);
+ glStencilMask(kStencilMask);
}
- glClear(GL_COLOR_BUFFER_BIT | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0) |
+ glClear((clearColor ? GL_COLOR_BUFFER_BIT : 0) | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0) |
(clearStencil ? GL_STENCIL_BUFFER_BIT : 0));
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
@@ -1188,7 +1207,10 @@
// Verify second clear mask worked as expected.
GLColor color2MaskedRGB(color2RGB[0], color1RGB[1], color2RGB[2], color1RGB[3]);
- GLColor expectedCenterColorRGB = mask ? color2MaskedRGB : color2RGB;
+ // If not clearing color, the original color should be left both in the center and corners. If
+ // using a scissor, the corners should be left to the original color, while the center is
+ // possibly changed. If using a mask, the center (and corers if not scissored), h
+ GLColor expectedCenterColorRGB = !clearColor ? color1RGB : mask ? color2MaskedRGB : color2RGB;
GLColor expectedCornerColorRGB = scissor ? color1RGB : expectedCenterColorRGB;
EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, expectedCenterColorRGB, 1);
@@ -1207,8 +1229,8 @@
essl1_shaders::fs::Blue());
glEnable(GL_DEPTH_TEST);
glDepthFunc(mask ? GL_GREATER : GL_EQUAL);
- // - If depth is cleared, but it's masked, 0.9 should be in the depth buffer.
- // - If depth is cleared, but it's not masked, 0.5 should be in the depth buffer.
+ // - If depth is cleared, but it's masked, kPreClearDepth should be in the depth buffer.
+ // - If depth is cleared, but it's not masked, kClearDepth should be in the depth buffer.
// - If depth is not cleared, the if above ensures there is no depth buffer at all,
// which means depth test will always pass.
drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), mask ? 1.0f : 0.0f);
@@ -1237,11 +1259,13 @@
ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
essl1_shaders::fs::Green());
glEnable(GL_STENCIL_TEST);
- // - If stencil is cleared, but it's masked, 0x59 should be in the stencil buffer.
- // - If stencil is cleared, but it's not masked, 0xFF should be in the stencil buffer.
+ // - If stencil is cleared, but it's masked, kMaskedClearStencil should be in the stencil
+ // buffer.
+ // - If stencil is cleared, but it's not masked, kClearStencil should be in the stencil
+ // buffer.
// - If stencil is not cleared, the if above ensures there is no stencil buffer at all,
// which means stencil test will always pass.
- glStencilFunc(GL_EQUAL, mask ? 0x59 : 0xFF, 0xFF);
+ glStencilFunc(GL_EQUAL, mask ? kMaskedClearStencil : kClearStencil, 0xFF);
drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
glDisable(GL_STENCIL_TEST);
ASSERT_GL_NO_ERROR();
@@ -1263,61 +1287,106 @@
// Tests combined color+depth+stencil clears.
TEST_P(ClearTest, MaskedColorAndDepthClear)
{
- MaskedScissoredColorDepthStencilClear(true, false, true, false);
+ MaskedScissoredColorDepthStencilClear(true, false, true, true, false);
}
TEST_P(ClearTest, MaskedColorAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(true, false, false, true);
+ MaskedScissoredColorDepthStencilClear(true, false, true, false, true);
}
TEST_P(ClearTest, MaskedColorAndDepthAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(true, false, true, true);
+ MaskedScissoredColorDepthStencilClear(true, false, true, true, true);
+}
+
+TEST_P(ClearTest, MaskedDepthClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, false, false, true, false);
+}
+
+TEST_P(ClearTest, MaskedStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, false, false, false, true);
+}
+
+TEST_P(ClearTest, MaskedDepthAndStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, false, false, true, true);
}
// Simple scissored clear.
TEST_P(ScissoredClearTest, BasicScissoredColorClear)
{
- MaskedScissoredColorDepthStencilClear(false, true, false, false);
+ MaskedScissoredColorDepthStencilClear(false, true, true, false, false);
}
// Simple scissored masked clear.
TEST_P(ScissoredClearTest, MaskedScissoredColorClear)
{
- MaskedScissoredColorDepthStencilClear(true, true, false, false);
+ MaskedScissoredColorDepthStencilClear(true, true, true, false, false);
}
// Tests combined color+depth+stencil scissored clears.
TEST_P(ScissoredClearTest, ScissoredColorAndDepthClear)
{
- MaskedScissoredColorDepthStencilClear(false, true, true, false);
+ MaskedScissoredColorDepthStencilClear(false, true, true, true, false);
}
TEST_P(ScissoredClearTest, ScissoredColorAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(false, true, false, true);
+ MaskedScissoredColorDepthStencilClear(false, true, true, false, true);
}
TEST_P(ScissoredClearTest, ScissoredColorAndDepthAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(false, true, true, true);
+ MaskedScissoredColorDepthStencilClear(false, true, true, true, true);
+}
+
+TEST_P(ScissoredClearTest, ScissoredDepthClear)
+{
+ MaskedScissoredColorDepthStencilClear(false, true, false, true, false);
+}
+
+TEST_P(ScissoredClearTest, ScissoredStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(false, true, false, false, true);
+}
+
+TEST_P(ScissoredClearTest, ScissoredDepthAndStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(false, true, false, true, true);
}
// Tests combined color+depth+stencil scissored masked clears.
TEST_P(ScissoredClearTest, MaskedScissoredColorAndDepthClear)
{
- MaskedScissoredColorDepthStencilClear(true, true, true, false);
+ MaskedScissoredColorDepthStencilClear(true, true, true, true, false);
}
TEST_P(ScissoredClearTest, MaskedScissoredColorAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(true, true, false, true);
+ MaskedScissoredColorDepthStencilClear(true, true, true, false, true);
}
TEST_P(ScissoredClearTest, MaskedScissoredColorAndDepthAndStencilClear)
{
- MaskedScissoredColorDepthStencilClear(true, true, true, true);
+ MaskedScissoredColorDepthStencilClear(true, true, true, true, true);
+}
+
+TEST_P(ScissoredClearTest, MaskedScissoredgDepthClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, true, false, true, false);
+}
+
+TEST_P(ScissoredClearTest, MaskedScissoredgStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, true, false, false, true);
+}
+
+TEST_P(ScissoredClearTest, MaskedScissoredgDepthAndStencilClear)
+{
+ MaskedScissoredColorDepthStencilClear(true, true, false, true, true);
}
// Tests combined color+stencil scissored masked clears for a depth-stencil-emulated
@@ -1325,25 +1394,49 @@
TEST_P(VulkanClearTest, ColorAndStencilClear)
{
bindColorStencilFBO();
- MaskedScissoredColorDepthStencilClear(false, false, false, true);
+ MaskedScissoredColorDepthStencilClear(false, false, true, false, true);
}
TEST_P(VulkanClearTest, MaskedColorAndStencilClear)
{
bindColorStencilFBO();
- MaskedScissoredColorDepthStencilClear(true, false, false, true);
+ MaskedScissoredColorDepthStencilClear(true, false, true, false, true);
}
TEST_P(VulkanClearTest, ScissoredColorAndStencilClear)
{
bindColorStencilFBO();
- MaskedScissoredColorDepthStencilClear(false, true, false, true);
+ MaskedScissoredColorDepthStencilClear(false, true, true, false, true);
}
TEST_P(VulkanClearTest, MaskedScissoredColorAndStencilClear)
{
bindColorStencilFBO();
- MaskedScissoredColorDepthStencilClear(true, true, false, true);
+ MaskedScissoredColorDepthStencilClear(true, true, true, false, true);
+}
+
+TEST_P(VulkanClearTest, StencilClear)
+{
+ bindColorStencilFBO();
+ MaskedScissoredColorDepthStencilClear(false, false, false, false, true);
+}
+
+TEST_P(VulkanClearTest, MaskedStencilClear)
+{
+ bindColorStencilFBO();
+ MaskedScissoredColorDepthStencilClear(true, false, false, false, true);
+}
+
+TEST_P(VulkanClearTest, ScissoredStencilClear)
+{
+ bindColorStencilFBO();
+ MaskedScissoredColorDepthStencilClear(false, true, false, false, true);
+}
+
+TEST_P(VulkanClearTest, MaskedScissoredStencilClear)
+{
+ bindColorStencilFBO();
+ MaskedScissoredColorDepthStencilClear(true, true, false, false, true);
}
// Tests combined color+depth scissored masked clears for a depth-stencil-emulated
@@ -1352,28 +1445,56 @@
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
bindColorDepthFBO();
- MaskedScissoredColorDepthStencilClear(false, false, true, false);
+ MaskedScissoredColorDepthStencilClear(false, false, true, true, false);
}
TEST_P(VulkanClearTest, MaskedColorAndDepthClear)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
bindColorDepthFBO();
- MaskedScissoredColorDepthStencilClear(true, false, true, false);
+ MaskedScissoredColorDepthStencilClear(true, false, true, true, false);
}
TEST_P(VulkanClearTest, ScissoredColorAndDepthClear)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
bindColorDepthFBO();
- MaskedScissoredColorDepthStencilClear(false, true, true, false);
+ MaskedScissoredColorDepthStencilClear(false, true, true, true, false);
}
TEST_P(VulkanClearTest, MaskedScissoredColorAndDepthClear)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
bindColorDepthFBO();
- MaskedScissoredColorDepthStencilClear(true, true, true, false);
+ MaskedScissoredColorDepthStencilClear(true, true, true, true, false);
+}
+
+TEST_P(VulkanClearTest, DepthClear)
+{
+ ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+ bindColorDepthFBO();
+ MaskedScissoredColorDepthStencilClear(false, false, false, true, false);
+}
+
+TEST_P(VulkanClearTest, MaskedDepthClear)
+{
+ ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+ bindColorDepthFBO();
+ MaskedScissoredColorDepthStencilClear(true, false, false, true, false);
+}
+
+TEST_P(VulkanClearTest, ScissoredDepthClear)
+{
+ ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+ bindColorDepthFBO();
+ MaskedScissoredColorDepthStencilClear(false, true, false, true, false);
+}
+
+TEST_P(VulkanClearTest, MaskedScissoredDepthClear)
+{
+ ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+ bindColorDepthFBO();
+ MaskedScissoredColorDepthStencilClear(true, true, false, true, false);
}
// Test that just clearing a nonexistent drawbuffer of the default framebuffer doesn't cause an