Commit db4ed317 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: glClearBuffer* implementation

Refactors FramebufferVk::clear such that specific render targets could be cleared, with clear values not necessarily set through glClearColor etc. FramebufferVk::clearWithRenderPassOp is modified so that loadOp and clear values are set after the render pass has been registered in the graph. This allows multiple glClearBuffer calls to coalesce into the same render pass. glClearBuffer calls are then implemented simply as calls to the refactored clear function with the appropriate parameters. Bug: angleproject:3187 Change-Id: I2fdfcbea5bf244f63ec981b91caca47f5ee3cd3a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1545204 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 750935f4
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc":
"287c50011ced97a7338b47a0a50127bf", "287c50011ced97a7338b47a0a50127bf",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageClear.frag.00000000.inc": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageClear.frag.00000000.inc":
"2d4b01d728c41ef1304ad3ef1305a1c7", "94ccd6f202120a83e81202e5ce419fad",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000000.inc": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000000.inc":
"aa438413134a29ec32ae4551a04e60b5", "aa438413134a29ec32ae4551a04e60b5",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000001.inc": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ImageCopy.frag.00000001.inc":
...@@ -296,7 +296,7 @@ ...@@ -296,7 +296,7 @@
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert":
"1743adf55153edf91363fa7b4350d859", "1743adf55153edf91363fa7b4350d859",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ImageClear.frag": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ImageClear.frag":
"98d490413d20118e92dd2b160c1dfc6e", "037fb888e77491bf7ae746069ea89a55",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ImageCopy.frag": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ImageCopy.frag":
"9b9fd690321f53163221f1ebba9f006d", "9b9fd690321f53163221f1ebba9f006d",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp":
......
...@@ -101,6 +101,24 @@ class CommandGraphNode final : angle::NonCopyable ...@@ -101,6 +101,24 @@ class CommandGraphNode final : angle::NonCopyable
const AttachmentOpsArray &renderPassAttachmentOps, const AttachmentOpsArray &renderPassAttachmentOps,
const std::vector<VkClearValue> &clearValues); const std::vector<VkClearValue> &clearValues);
void clearRenderPassColorAttachment(size_t attachmentIndex, const VkClearColorValue &clearValue)
{
mRenderPassAttachmentOps[attachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mRenderPassClearValues[attachmentIndex].color = clearValue;
}
void clearRenderPassDepthAttachment(size_t attachmentIndex, float depth)
{
mRenderPassAttachmentOps[attachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mRenderPassClearValues[attachmentIndex].depthStencil.depth = depth;
}
void clearRenderPassStencilAttachment(size_t attachmentIndex, uint32_t stencil)
{
mRenderPassAttachmentOps[attachmentIndex].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mRenderPassClearValues[attachmentIndex].depthStencil.stencil = stencil;
}
// Dependency commands order node execution in the command graph. // Dependency commands order node execution in the command graph.
// Once a node has commands that must happen after it, recording is stopped and the node is // Once a node has commands that must happen after it, recording is stopped and the node is
// frozen forever. // frozen forever.
...@@ -291,6 +309,32 @@ class CommandGraphResource : angle::NonCopyable ...@@ -291,6 +309,32 @@ class CommandGraphResource : angle::NonCopyable
} }
} }
// Returns true if the render pass is started, but there are no commands yet recorded in it.
// This is useful to know if the render pass ops can be modified.
bool renderPassStartedButEmpty() const
{
return hasStartedRenderPass() &&
mCurrentWritingNode->getInsideRenderPassCommands()->empty();
}
void clearRenderPassColorAttachment(size_t attachmentIndex, const VkClearColorValue &clearValue)
{
ASSERT(renderPassStartedButEmpty());
mCurrentWritingNode->clearRenderPassColorAttachment(attachmentIndex, clearValue);
}
void clearRenderPassDepthAttachment(size_t attachmentIndex, float depth)
{
ASSERT(renderPassStartedButEmpty());
mCurrentWritingNode->clearRenderPassDepthAttachment(attachmentIndex, depth);
}
void clearRenderPassStencilAttachment(size_t attachmentIndex, uint32_t stencil)
{
ASSERT(renderPassStartedButEmpty());
mCurrentWritingNode->clearRenderPassStencilAttachment(attachmentIndex, stencil);
}
// Accessor for RenderPass RenderArea. // Accessor for RenderPass RenderArea.
const gl::Rectangle &getRenderPassRenderArea() const; const gl::Rectangle &getRenderPassRenderArea() const;
......
...@@ -31,7 +31,15 @@ namespace rx ...@@ -31,7 +31,15 @@ namespace rx
namespace namespace
{ {
// The value to assign an alpha channel that's emulated. The type is unsigned int, though it will
// automatically convert to the actual data type.
constexpr unsigned int kEmulatedAlphaValue = 1;
constexpr size_t kMinReadPixelsBufferSize = 128000; constexpr size_t kMinReadPixelsBufferSize = 128000;
// Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp. When starting a
// new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
// in case of a bug.
constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context, const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context,
RenderTargetVk *renderTarget) RenderTargetVk *renderTarget)
...@@ -95,6 +103,25 @@ const angle::Format &GetDepthStencilImageToBufferFormat(const angle::Format &ima ...@@ -95,6 +103,25 @@ const angle::Format &GetDepthStencilImageToBufferFormat(const angle::Format &ima
return imageFormat; return imageFormat;
} }
} }
void SetEmulatedAlphaValue(const vk::Format &format, VkClearColorValue *value)
{
if (format.vkFormatIsInt)
{
if (format.vkFormatIsUnsigned)
{
value->uint32[3] = kEmulatedAlphaValue;
}
else
{
value->int32[3] = kEmulatedAlphaValue;
}
}
else
{
value->float32[3] = kEmulatedAlphaValue;
}
}
} // anonymous namespace } // anonymous namespace
// static // static
...@@ -165,35 +192,76 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -165,35 +192,76 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
bool clearColor = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
bool clearDepth = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
gl::DrawBufferMask clearColorBuffers;
if (clearColor)
{
clearColorBuffers = mState.getEnabledDrawBuffers();
}
const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
const VkClearDepthStencilValue &clearDepthStencilValue =
contextVk->getClearDepthStencilValue().depthStencil;
return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
clearDepthStencilValue);
}
angle::Result FramebufferVk::clearImpl(const gl::Context *context,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue)
{
ContextVk *contextVk = vk::GetImpl(context);
const gl::State &glState = context->getState();
const gl::Rectangle &scissor = glState.getScissor();
const gl::Rectangle renderArea(0, 0, mState.getDimensions().width,
mState.getDimensions().height);
gl::Rectangle scissorRenderAreaIntersection;
// Discard clear altogether if scissor has 0 width or height.
if (glState.isScissorTestEnabled() &&
!gl::ClipRectangle(scissor, renderArea, &scissorRenderAreaIntersection))
{
return angle::Result::Continue;
}
mFramebuffer.updateQueueSerial(contextVk->getRenderer()->getCurrentQueueSerial());
// This function assumes that only enabled attachments are asked to be cleared.
ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
bool clearColor = clearColorBuffers.any();
// This command buffer is only started once. // This command buffer is only started once.
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment(); const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment();
bool clearDepth = (depthAttachment && (mask & GL_DEPTH_BUFFER_BIT) != 0); clearDepth = clearDepth && depthAttachment;
ASSERT(!clearDepth || depthAttachment->isAttached()); ASSERT(!clearDepth || depthAttachment->isAttached());
// If depth write is disabled, pretend that GL_DEPTH_BUFFER_BIT is not specified altogether. // If depth write is disabled, pretend that depth clear is not requested altogether.
clearDepth = clearDepth && contextVk->getState().getDepthStencilState().depthMask; clearDepth = clearDepth && contextVk->getState().getDepthStencilState().depthMask;
const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment(); const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
bool clearStencil = (stencilAttachment && (mask & GL_STENCIL_BUFFER_BIT) != 0); clearStencil = clearStencil && stencilAttachment;
ASSERT(!clearStencil || stencilAttachment->isAttached()); ASSERT(!clearStencil || stencilAttachment->isAttached());
bool clearColor = IsMaskFlagSet(static_cast<int>(mask), GL_COLOR_BUFFER_BIT);
// If the only thing to be cleared was depth and it's masked, there's nothing to do. // If the only thing to be cleared was depth and it's masked, there's nothing to do.
if (!clearColor && !clearDepth && !clearStencil) if (!clearColor && !clearDepth && !clearStencil)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
const gl::State &glState = context->getState(); VkClearDepthStencilValue modifiedDepthStencilValue = clearDepthStencilValue;
VkClearDepthStencilValue clearDepthStencilValue =
contextVk->getClearDepthStencilValue().depthStencil;
// Apply the stencil mask to the clear value. // Apply the stencil mask to the clear value.
clearDepthStencilValue.stencil &= contextVk->getState().getDepthStencilState().stencilWritemask; // 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 // 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 // single aspect, but it's emulated with a depth/stencil format, clear both aspects, setting the
...@@ -207,23 +275,20 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -207,23 +275,20 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
if (format.angleFormat().stencilBits == 0) if (format.angleFormat().stencilBits == 0)
{ {
clearStencil = true; clearStencil = true;
clearDepthStencilValue.stencil = 0; modifiedDepthStencilValue.stencil = 0;
} }
// GL_STENCIL_INDEX8 may or may not be emulated. // GL_STENCIL_INDEX8 may or may not be emulated.
else if (format.angleFormat().depthBits == 0 && format.vkTextureFormat != VK_FORMAT_S8_UINT) else if (format.angleFormat().depthBits == 0 && format.vkTextureFormat != VK_FORMAT_S8_UINT)
{ {
clearDepth = true; clearDepth = true;
clearDepthStencilValue.depth = 0; modifiedDepthStencilValue.depth = 0;
} }
} }
// If scissor is enabled, but covers the whole of framebuffer, it can be considered disabled for // If scissor is enabled, but covers the whole of framebuffer, it can be considered disabled for
// the sake of clear. // the sake of clear.
const gl::Rectangle &scissorRect = glState.getScissor();
const gl::Rectangle renderArea(0, 0, mState.getDimensions().width,
mState.getDimensions().height);
bool isScissorTestEffectivelyEnabled = bool isScissorTestEffectivelyEnabled =
glState.isScissorTestEnabled() && scissorRect != renderArea; glState.isScissorTestEnabled() && scissorRenderAreaIntersection != renderArea;
// We can use render pass load ops if clearing depth/stencil or unmasked color. If there's a // 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 // depth mask, depth clearing is disabled. If there's a stencil mask, the clear value is
...@@ -233,16 +298,26 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -233,16 +298,26 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
bool maskedClearColor = bool maskedClearColor =
clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents; clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents;
bool clearColorWithRenderPassLoadOp = clearColor && !maskedClearColor; bool clearColorWithRenderPassLoadOp = clearColor && !maskedClearColor;
// At least one of color, depth or stencil should be clearable with render pass loadOp for us
// to use this clear path.
bool clearAnyWithRenderPassLoadOp = bool clearAnyWithRenderPassLoadOp =
clearColorWithRenderPassLoadOp || clearDepth || clearStencil; clearColorWithRenderPassLoadOp || clearDepth || clearStencil;
if (clearAnyWithRenderPassLoadOp && !isScissorTestEffectivelyEnabled && if (clearAnyWithRenderPassLoadOp && !isScissorTestEffectivelyEnabled &&
!contextVk->getRenderer()->getFeatures().disableClearWithRenderPassLoadOp) !contextVk->getRenderer()->getFeatures().disableClearWithRenderPassLoadOp)
{ {
// Clearing color is indicated by the set bits in this mask. If not clearing colors with
// render pass loadOp, the default value of all-zeros means the clear is not done in
// clearWithRenderPassOp below.
gl::DrawBufferMask clearBuffersWithRenderPassLoadOp;
if (clearColorWithRenderPassLoadOp)
{
clearBuffersWithRenderPassLoadOp = clearColorBuffers;
}
// If there's a color mask, only clear depth/stencil with render pass loadOp. // If there's a color mask, only clear depth/stencil with render pass loadOp.
ANGLE_TRY(clearWithRenderPassOp(contextVk, clearColorWithRenderPassLoadOp, clearDepth, ANGLE_TRY(clearWithRenderPassOp(contextVk, clearBuffersWithRenderPassLoadOp, clearDepth,
clearStencil, contextVk->getClearColorValue().color, clearStencil, clearColorValue, modifiedDepthStencilValue));
clearDepthStencilValue));
// Fallback to other methods for whatever isn't cleared here. // Fallback to other methods for whatever isn't cleared here.
clearDepth = false; clearDepth = false;
...@@ -263,7 +338,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -263,7 +338,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
// this method. Similarly for depth/stencil clear. // this method. Similarly for depth/stencil clear.
if (maskedClearColor) if (maskedClearColor)
{ {
ANGLE_TRY(clearWithDraw(contextVk, colorMaskFlags)); ANGLE_TRY(clearWithDraw(contextVk, clearColorBuffers, clearColorValue, colorMaskFlags));
// Stencil clears must be handled separately. The only way to write out a stencil value from // 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 // a fragment shader in Vulkan is with VK_EXT_shader_stencil_export. Support for this
...@@ -273,8 +348,9 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -273,8 +348,9 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
if (clearDepth || clearStencil) if (clearDepth || clearStencil)
{ {
ANGLE_TRY(clearWithClearAttachments(contextVk, false, clearDepth, clearStencil, ANGLE_TRY(clearWithClearAttachments(contextVk, gl::DrawBufferMask(), clearDepth,
clearDepthStencilValue)); clearStencil, clearColorValue,
modifiedDepthStencilValue));
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -284,8 +360,8 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -284,8 +360,8 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
// With scissor test enabled, we clear very differently and we don't need to access // With scissor test enabled, we clear very differently and we don't need to access
// the image inside each attachment we can just use clearCmdAttachments with our // the image inside each attachment we can just use clearCmdAttachments with our
// scissor region instead. // scissor region instead.
ANGLE_TRY(clearWithClearAttachments(contextVk, clearColor, clearDepth, clearStencil, ANGLE_TRY(clearWithClearAttachments(contextVk, clearColorBuffers, clearDepth, clearStencil,
clearDepthStencilValue)); clearColorValue, modifiedDepthStencilValue));
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -312,7 +388,8 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -312,7 +388,8 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
} }
vk::ImageHelper *image = renderTarget->getImageForWrite(&mFramebuffer); vk::ImageHelper *image = renderTarget->getImageForWrite(&mFramebuffer);
image->clearDepthStencil(aspectFlags, clearAspects, clearDepthStencilValue, commandBuffer); image->clearDepthStencil(aspectFlags, clearAspects, modifiedDepthStencilValue,
commandBuffer);
} }
if (!clearColor) if (!clearColor)
...@@ -320,9 +397,6 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -320,9 +397,6 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
return angle::Result::Continue; return angle::Result::Continue;
} }
const auto *attachment = mState.getFirstNonNullAttachment();
ASSERT(attachment && attachment->isAttached());
if (!commandBuffer) if (!commandBuffer)
{ {
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
...@@ -330,8 +404,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -330,8 +404,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
// TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
const auto &colorRenderTargets = mRenderTargetCache.getColors(); const auto &colorRenderTargets = mRenderTargetCache.getColors();
const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color; for (size_t colorIndex : clearColorBuffers)
for (size_t colorIndex : mState.getEnabledDrawBuffers())
{ {
VkClearColorValue modifiedClearColorValue = clearColorValue; VkClearColorValue modifiedClearColorValue = clearColorValue;
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex]; RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
...@@ -341,7 +414,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -341,7 +414,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
// clear value is in that case. // clear value is in that case.
if (mEmulatedAlphaAttachmentMask[colorIndex]) if (mEmulatedAlphaAttachmentMask[colorIndex])
{ {
modifiedClearColorValue.float32[3] = 1.0; SetEmulatedAlphaValue(colorRenderTarget->getImageFormat(), &modifiedClearColorValue);
} }
ASSERT(colorRenderTarget); ASSERT(colorRenderTarget);
...@@ -360,8 +433,27 @@ angle::Result FramebufferVk::clearBufferfv(const gl::Context *context, ...@@ -360,8 +433,27 @@ angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
GLint drawbuffer, GLint drawbuffer,
const GLfloat *values) const GLfloat *values)
{ {
ANGLE_VK_UNREACHABLE(vk::GetImpl(context)); VkClearValue clearValue;
return angle::Result::Stop;
bool clearDepth = false;
gl::DrawBufferMask clearColorBuffers;
if (buffer == GL_DEPTH)
{
clearDepth = true;
clearValue.depthStencil.depth = values[0];
}
else
{
clearColorBuffers.set(drawbuffer);
clearValue.color.float32[0] = values[0];
clearValue.color.float32[1] = values[1];
clearValue.color.float32[2] = values[2];
clearValue.color.float32[3] = values[3];
}
return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
clearValue.depthStencil);
} }
angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context, angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
...@@ -369,8 +461,18 @@ angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context, ...@@ -369,8 +461,18 @@ angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
GLint drawbuffer, GLint drawbuffer,
const GLuint *values) const GLuint *values)
{ {
ANGLE_VK_UNREACHABLE(vk::GetImpl(context)); VkClearValue clearValue;
return angle::Result::Stop;
gl::DrawBufferMask clearColorBuffers;
clearColorBuffers.set(drawbuffer);
clearValue.color.uint32[0] = values[0];
clearValue.color.uint32[1] = values[1];
clearValue.color.uint32[2] = values[2];
clearValue.color.uint32[3] = values[3];
return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
clearValue.depthStencil);
} }
angle::Result FramebufferVk::clearBufferiv(const gl::Context *context, angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
...@@ -378,8 +480,28 @@ angle::Result FramebufferVk::clearBufferiv(const gl::Context *context, ...@@ -378,8 +480,28 @@ angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
GLint drawbuffer, GLint drawbuffer,
const GLint *values) const GLint *values)
{ {
ANGLE_VK_UNREACHABLE(vk::GetImpl(context)); VkClearValue clearValue;
return angle::Result::Stop;
bool clearStencil = false;
gl::DrawBufferMask clearColorBuffers;
if (buffer == GL_STENCIL)
{
clearStencil = true;
clearValue.depthStencil.stencil =
gl::clamp(values[0], 0, std::numeric_limits<uint8_t>::max());
}
else
{
clearColorBuffers.set(drawbuffer);
clearValue.color.int32[0] = values[0];
clearValue.color.int32[1] = values[1];
clearValue.color.int32[2] = values[2];
clearValue.color.int32[3] = values[3];
}
return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
clearValue.depthStencil);
} }
angle::Result FramebufferVk::clearBufferfi(const gl::Context *context, angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
...@@ -388,8 +510,13 @@ angle::Result FramebufferVk::clearBufferfi(const gl::Context *context, ...@@ -388,8 +510,13 @@ angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
GLfloat depth, GLfloat depth,
GLint stencil) GLint stencil)
{ {
ANGLE_VK_UNREACHABLE(vk::GetImpl(context)); VkClearValue clearValue;
return angle::Result::Stop;
clearValue.depthStencil.depth = depth;
clearValue.depthStencil.stencil = gl::clamp(stencil, 0, std::numeric_limits<uint8_t>::max());
return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
clearValue.depthStencil);
} }
GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const
...@@ -942,22 +1069,69 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffe ...@@ -942,22 +1069,69 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffe
angle::Result FramebufferVk::clearWithRenderPassOp( angle::Result FramebufferVk::clearWithRenderPassOp(
ContextVk *contextVk, ContextVk *contextVk,
bool clearColor, gl::DrawBufferMask clearColorBuffers,
bool clearDepth, bool clearDepth,
bool clearStencil, bool clearStencil,
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue) const VkClearDepthStencilValue &clearDepthStencilValue)
{ {
// If render pass hasn't started, start it. If it's started and contains commands, we cannot
// modify its ops, so start a new render pass.
if (!mFramebuffer.valid() || !mFramebuffer.renderPassStartedButEmpty())
{
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
return startNewRenderPassImpl(contextVk, clearColor, clearDepth, clearStencil, clearColorValue, ANGLE_TRY(startNewRenderPass(contextVk, &commandBuffer));
clearDepthStencilValue, &commandBuffer); }
size_t attachmentIndex = 0;
// Go through clearColorBuffers and set the appropriate loadOp and clear values.
// TODO: Support gaps in RenderTargets. http://anglebug.com/2394
for (size_t colorIndex : mState.getEnabledDrawBuffers())
{
if (clearColorBuffers.test(colorIndex))
{
RenderTargetVk *renderTarget = getColorReadRenderTarget();
// If the render target doesn't have alpha, but its emulated format has it, clear the
// alpha to 1.
VkClearColorValue value = clearColorValue;
if (mEmulatedAlphaAttachmentMask[colorIndex])
{
SetEmulatedAlphaValue(renderTarget->getImageFormat(), &value);
}
mFramebuffer.clearRenderPassColorAttachment(attachmentIndex, value);
}
++attachmentIndex;
}
// Set the appropriate loadOp and clear values for depth and stencil.
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
if (clearDepth)
{
mFramebuffer.clearRenderPassDepthAttachment(attachmentIndex,
clearDepthStencilValue.depth);
}
if (clearStencil)
{
mFramebuffer.clearRenderPassStencilAttachment(attachmentIndex,
clearDepthStencilValue.stencil);
}
}
return angle::Result::Continue;
} }
angle::Result FramebufferVk::clearWithClearAttachments( angle::Result FramebufferVk::clearWithClearAttachments(
ContextVk *contextVk, ContextVk *contextVk,
bool clearColor, gl::DrawBufferMask clearColorBuffers,
bool clearDepth, bool clearDepth,
bool clearStencil, bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue) const VkClearDepthStencilValue &clearDepthStencilValue)
{ {
// Trigger a new command node to ensure overlapping writes happen sequentially. // Trigger a new command node to ensure overlapping writes happen sequentially.
...@@ -995,21 +1169,21 @@ angle::Result FramebufferVk::clearWithClearAttachments( ...@@ -995,21 +1169,21 @@ angle::Result FramebufferVk::clearWithClearAttachments(
gl::AttachmentArray<VkClearAttachment> clearAttachments; gl::AttachmentArray<VkClearAttachment> clearAttachments;
int clearAttachmentIndex = 0; int clearAttachmentIndex = 0;
if (clearColor) if (clearColorBuffers.any())
{ {
RenderTargetVk *renderTarget = getColorReadRenderTarget(); RenderTargetVk *renderTarget = getColorReadRenderTarget();
const vk::Format &format = renderTarget->getImageFormat(); const vk::Format &format = renderTarget->getImageFormat();
VkClearValue modifiedClear = contextVk->getClearColorValue(); VkClearValue modifiedClear = {clearColorValue};
// We need to make sure we are not clearing the alpha channel if we are using a buffer // We need to make sure we are not clearing the alpha channel if we are using a buffer
// format that doesn't have an alpha channel. // format that doesn't have an alpha channel.
if (format.angleFormat().alphaBits == 0) if (format.angleFormat().alphaBits == 0)
{ {
modifiedClear.color.float32[3] = 1.0; SetEmulatedAlphaValue(format, &modifiedClear.color);
} }
// TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
for (size_t colorIndex : mState.getEnabledDrawBuffers()) for (size_t colorIndex : clearColorBuffers)
{ {
VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex]; VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
...@@ -1059,29 +1233,20 @@ angle::Result FramebufferVk::clearWithClearAttachments( ...@@ -1059,29 +1233,20 @@ angle::Result FramebufferVk::clearWithClearAttachments(
} }
angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk, angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
const VkClearColorValue &clearColorValue,
VkColorComponentFlags colorMaskFlags) VkColorComponentFlags colorMaskFlags)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
// If the format of the framebuffer does not have an alpha channel, we need to make sure we do
// not affect the alpha channel of the type we're using to emulate the format.
// TODO(jmadill): Implement EXT_draw_buffers http://anglebug.com/2394
RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[0];
ASSERT(renderTarget);
UtilsVk::ClearImageParameters params = {}; UtilsVk::ClearImageParameters params = {};
params.colorMaskFlags = colorMaskFlags; params.colorMaskFlags = colorMaskFlags;
params.renderAreaHeight = mState.getDimensions().height;
params.clearValue = clearColorValue;
params.alphaMask = &getEmulatedAlphaAttachmentMask(); params.alphaMask = &getEmulatedAlphaAttachmentMask();
params.clearBufferMask = &clearColorBuffers;
params.renderPassDesc = &getRenderPassDesc(); params.renderPassDesc = &getRenderPassDesc();
const vk::Format &imageFormat = renderTarget->getImageFormat();
params.clearValue = contextVk->getClearColorValue().color;
bool overrideAlphaWithOne =
imageFormat.textureFormat().alphaBits > 0 && imageFormat.angleFormat().alphaBits == 0;
params.clearValue.float32[3] = overrideAlphaWithOne ? 1.0f : params.clearValue.float32[3];
params.renderAreaHeight = mState.getDimensions().height;
return renderer->getUtils().clearImage(contextVk, this, params); return renderer->getUtils().clearImage(contextVk, this, params);
} }
...@@ -1112,22 +1277,6 @@ angle::Result FramebufferVk::getCommandBufferForDraw(ContextVk *contextVk, ...@@ -1112,22 +1277,6 @@ angle::Result FramebufferVk::getCommandBufferForDraw(ContextVk *contextVk,
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
VkClearColorValue unusedColor = {};
VkClearDepthStencilValue unusedDepthStencil = {};
return startNewRenderPassImpl(contextVk, false, false, false, unusedColor, unusedDepthStencil,
commandBufferOut);
}
angle::Result FramebufferVk::startNewRenderPassImpl(
ContextVk *contextVk,
bool clearColor,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue,
vk::CommandBuffer **commandBufferOut)
{
vk::Framebuffer *framebuffer = nullptr; vk::Framebuffer *framebuffer = nullptr;
ANGLE_TRY(getFramebuffer(contextVk, &framebuffer)); ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
...@@ -1137,9 +1286,6 @@ angle::Result FramebufferVk::startNewRenderPassImpl( ...@@ -1137,9 +1286,6 @@ angle::Result FramebufferVk::startNewRenderPassImpl(
vk::CommandBuffer *writeCommands = nullptr; vk::CommandBuffer *writeCommands = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands)); ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
VkClearValue clearValue;
clearValue.color = clearColorValue;
vk::RenderPassDesc renderPassDesc; vk::RenderPassDesc renderPassDesc;
// Initialize RenderPass info. // Initialize RenderPass info.
...@@ -1153,27 +1299,10 @@ angle::Result FramebufferVk::startNewRenderPassImpl( ...@@ -1153,27 +1299,10 @@ angle::Result FramebufferVk::startNewRenderPassImpl(
ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk, &mFramebuffer, writeCommands, ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk, &mFramebuffer, writeCommands,
&renderPassDesc)); &renderPassDesc));
VkAttachmentLoadOp colorLoadOp = renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
clearColor ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
renderPassAttachmentOps.setLayout(attachmentClearValues.size(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
renderPassAttachmentOps.setLoadOp(attachmentClearValues.size(), colorLoadOp, attachmentClearValues.emplace_back(kUninitializedClearValue);
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
renderPassAttachmentOps.setStoreOp(attachmentClearValues.size(),
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_STORE_OP_DONT_CARE);
// If the render target doesn't have alpha, but its emulated format has it, clear the alpha
// to 1.
VkClearValue value = clearValue;
if (mEmulatedAlphaAttachmentMask[colorIndex])
{
value.color.float32[3] = 1.0;
}
attachmentClearValues.emplace_back(value);
} }
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil(); RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
...@@ -1182,21 +1311,10 @@ angle::Result FramebufferVk::startNewRenderPassImpl( ...@@ -1182,21 +1311,10 @@ angle::Result FramebufferVk::startNewRenderPassImpl(
ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk, &mFramebuffer, ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk, &mFramebuffer,
writeCommands, &renderPassDesc)); writeCommands, &renderPassDesc));
VkAttachmentLoadOp depthLoadOp = renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
clearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentLoadOp stencilLoadOp =
clearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
renderPassAttachmentOps.setLayout(attachmentClearValues.size(),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
renderPassAttachmentOps.setLoadOp(attachmentClearValues.size(), depthLoadOp, stencilLoadOp); attachmentClearValues.emplace_back(kUninitializedClearValue);
renderPassAttachmentOps.setStoreOp(attachmentClearValues.size(),
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_STORE_OP_STORE);
clearValue.depthStencil = clearDepthStencilValue;
attachmentClearValues.emplace_back(clearValue);
} }
gl::Rectangle renderArea = gl::Rectangle renderArea =
......
...@@ -125,14 +125,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -125,14 +125,6 @@ class FramebufferVk : public FramebufferImpl
const gl::FramebufferState &state, const gl::FramebufferState &state,
WindowSurfaceVk *backbuffer); WindowSurfaceVk *backbuffer);
angle::Result startNewRenderPassImpl(ContextVk *context,
bool clearColor,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue,
vk::CommandBuffer **commandBufferOut);
// Helper for appendToStarted/else startNewRenderPass. // Helper for appendToStarted/else startNewRenderPass.
angle::Result getCommandBufferForDraw(ContextVk *contextVk, angle::Result getCommandBufferForDraw(ContextVk *contextVk,
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
...@@ -167,18 +159,28 @@ class FramebufferVk : public FramebufferImpl ...@@ -167,18 +159,28 @@ class FramebufferVk : public FramebufferImpl
angle::Result getFramebuffer(ContextVk *contextVk, vk::Framebuffer **framebufferOut); angle::Result getFramebuffer(ContextVk *contextVk, vk::Framebuffer **framebufferOut);
angle::Result clearImpl(const gl::Context *context,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithRenderPassOp(ContextVk *contextVk, angle::Result clearWithRenderPassOp(ContextVk *contextVk,
bool clearColor, gl::DrawBufferMask clearColorBuffers,
bool clearDepth, bool clearDepth,
bool clearStencil, bool clearStencil,
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithClearAttachments(ContextVk *contextVk, angle::Result clearWithClearAttachments(ContextVk *contextVk,
bool clearColor, gl::DrawBufferMask clearColorBuffers,
bool clearDepth, bool clearDepth,
bool clearStencil, bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithDraw(ContextVk *contextVk, VkColorComponentFlags colorMaskFlags); angle::Result clearWithDraw(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
const VkClearColorValue &clearColorValue,
VkColorComponentFlags colorMaskFlags);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a); void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc(); void updateRenderPassDesc();
......
...@@ -489,6 +489,8 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -489,6 +489,8 @@ class SecondaryCommandBuffer final : angle::NonCopyable
// The SecondaryCommandBuffer is valid if it's been initialized // The SecondaryCommandBuffer is valid if it's been initialized
bool valid() const { return mAllocator != nullptr; } bool valid() const { return mAllocator != nullptr; }
bool empty() const { return mCommands.size() == 0 || mCommands[0]->id == CommandID::Invalid; }
private: private:
template <class StructType> template <class StructType>
ANGLE_INLINE StructType *commonInit(CommandID cmdID, size_t allocationSize) ANGLE_INLINE StructType *commonInit(CommandID cmdID, size_t allocationSize)
......
...@@ -603,12 +603,8 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, ...@@ -603,12 +603,8 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
std::vector<VkClearValue> clearValues = {{}}; std::vector<VkClearValue> clearValues = {{}};
ASSERT(clearValues.size() == 1); ASSERT(clearValues.size() == 1);
renderPassAttachmentOps.setLayout(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, renderPassAttachmentOps.initWithLoadStore(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
renderPassAttachmentOps.setLoadOp(0, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
renderPassAttachmentOps.setStoreOp(0, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_STORE_OP_DONT_CARE);
ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc, ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, clearValues, commandBufferOut)); renderPassAttachmentOps, clearValues, commandBufferOut));
...@@ -635,6 +631,27 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk, ...@@ -635,6 +631,27 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
ImageClearShaderParams shaderParams; ImageClearShaderParams shaderParams;
shaderParams.clearValue = params.clearValue; shaderParams.clearValue = params.clearValue;
// TODO(syoussefi): Currently, this only supports float clears. Having the shader as-is support
// a mixture of types results in a large number of shader variations. The solution would be to
// clear the render targets one by one. However, we don't want to recreate the render pass for
// each one, so the shader should be able to select the render target to clear. The variations
// of the shader could look like:
//
// "RenderTarget": [
// "RT0",
// "RT1",
// ...
// "RT7",
// ],
// "Format": [
// "IsFloat",
// "IsInt",
// "IsUint"
// ]
//
// http://anglebug.com/3187
shaderParams.clearBufferMask = static_cast<uint32_t>(params.clearBufferMask->bits());
vk::GraphicsPipelineDesc pipelineDesc; vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults();
pipelineDesc.setColorWriteMask(params.colorMaskFlags, *params.alphaMask); pipelineDesc.setColorWriteMask(params.colorMaskFlags, *params.alphaMask);
...@@ -650,11 +667,6 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk, ...@@ -650,11 +667,6 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
VkRect2D scissor; VkRect2D scissor;
const gl::State &glState = contextVk->getState(); const gl::State &glState = contextVk->getState();
gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor); gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
// TODO(courtneygo): workaround for scissor issue on some devices. http://anglebug.com/3114
if ((scissor.extent.width == 0) || (scissor.extent.height == 0))
{
return angle::Result::Continue;
}
pipelineDesc.setScissor(scissor); pipelineDesc.setScissor(scissor);
vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary(); vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
......
...@@ -65,6 +65,7 @@ class UtilsVk : angle::NonCopyable ...@@ -65,6 +65,7 @@ class UtilsVk : angle::NonCopyable
VkColorComponentFlags colorMaskFlags; VkColorComponentFlags colorMaskFlags;
GLint renderAreaHeight; GLint renderAreaHeight;
const gl::DrawBufferMask *alphaMask; const gl::DrawBufferMask *alphaMask;
const gl::DrawBufferMask *clearBufferMask;
const vk::RenderPassDesc *renderPassDesc; const vk::RenderPassDesc *renderPassDesc;
}; };
...@@ -142,6 +143,7 @@ class UtilsVk : angle::NonCopyable ...@@ -142,6 +143,7 @@ class UtilsVk : angle::NonCopyable
{ {
// Structure matching PushConstants in ImageClear.frag // Structure matching PushConstants in ImageClear.frag
VkClearColorValue clearValue = {}; VkClearColorValue clearValue = {};
uint32_t clearBufferMask = 0;
}; };
struct ImageCopyShaderParams struct ImageCopyShaderParams
......
// 7.11.3170 // 7.11.3170
#pragma once #pragma once
const uint32_t kImageClear_frag_00000000[] = { const uint32_t kImageClear_frag_00000000[] = {
0x07230203,0x00010000,0x00080007,0x00000012,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x00080007,0x00000061,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004, 0x000d000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000017,0x00000022,0x0000002c,
0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000, 0x00000036,0x00000040,0x0000004a,0x00000054,0x0000005e,0x00030010,0x00000004,0x00000007,
0x00050005,0x00000009,0x6f6c6f63,0x74754f72,0x00000000,0x00060005,0x0000000a,0x68737550, 0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000,0x00060005,
0x736e6f43,0x746e6174,0x00000073,0x00060006,0x0000000a,0x00000000,0x61656c63,0x6c6f4372, 0x00000009,0x68737550,0x736e6f43,0x746e6174,0x00000073,0x00060006,0x00000009,0x00000000,
0x0000726f,0x00040005,0x0000000c,0x61726170,0x0000736d,0x00040047,0x00000009,0x0000001e, 0x61656c63,0x6c6f4372,0x0000726f,0x00070006,0x00000009,0x00000001,0x61656c63,0x66754272,
0x00000000,0x00050048,0x0000000a,0x00000000,0x00000023,0x00000000,0x00030047,0x0000000a, 0x4d726566,0x006b7361,0x00040005,0x0000000b,0x61726170,0x0000736d,0x00050005,0x00000017,
0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006, 0x6f6c6f63,0x74754f72,0x00000030,0x00050005,0x00000022,0x6f6c6f63,0x74754f72,0x00000031,
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003, 0x00050005,0x0000002c,0x6f6c6f63,0x74754f72,0x00000032,0x00050005,0x00000036,0x6f6c6f63,
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x0003001e,0x0000000a,0x00000007, 0x74754f72,0x00000033,0x00050005,0x00000040,0x6f6c6f63,0x74754f72,0x00000034,0x00050005,
0x00040020,0x0000000b,0x00000009,0x0000000a,0x0004003b,0x0000000b,0x0000000c,0x00000009, 0x0000004a,0x6f6c6f63,0x74754f72,0x00000035,0x00050005,0x00000054,0x6f6c6f63,0x74754f72,
0x00040015,0x0000000d,0x00000020,0x00000001,0x0004002b,0x0000000d,0x0000000e,0x00000000, 0x00000036,0x00050005,0x0000005e,0x6f6c6f63,0x74754f72,0x00000037,0x00050048,0x00000009,
0x00040020,0x0000000f,0x00000009,0x00000007,0x00050036,0x00000002,0x00000004,0x00000000, 0x00000000,0x00000023,0x00000000,0x00050048,0x00000009,0x00000001,0x00000023,0x00000010,
0x00000003,0x000200f8,0x00000005,0x00050041,0x0000000f,0x00000010,0x0000000c,0x0000000e, 0x00030047,0x00000009,0x00000002,0x00040047,0x00000017,0x0000001e,0x00000000,0x00040047,
0x0004003d,0x00000007,0x00000011,0x00000010,0x0003003e,0x00000009,0x00000011,0x000100fd, 0x00000022,0x0000001e,0x00000001,0x00040047,0x0000002c,0x0000001e,0x00000002,0x00040047,
0x00010038 0x00000036,0x0000001e,0x00000003,0x00040047,0x00000040,0x0000001e,0x00000004,0x00040047,
0x0000004a,0x0000001e,0x00000005,0x00040047,0x00000054,0x0000001e,0x00000006,0x00040047,
0x0000005e,0x0000001e,0x00000007,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040015,
0x00000008,0x00000020,0x00000001,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,
0x0000000a,0x00000009,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000009,0x0004002b,
0x00000008,0x0000000c,0x00000001,0x00040020,0x0000000d,0x00000009,0x00000008,0x0004002b,
0x00000008,0x00000011,0x00000000,0x00020014,0x00000012,0x00040020,0x00000016,0x00000003,
0x00000007,0x0004003b,0x00000016,0x00000017,0x00000003,0x00040020,0x00000018,0x00000009,
0x00000007,0x0004002b,0x00000008,0x0000001d,0x00000002,0x0004003b,0x00000016,0x00000022,
0x00000003,0x0004002b,0x00000008,0x00000027,0x00000004,0x0004003b,0x00000016,0x0000002c,
0x00000003,0x0004002b,0x00000008,0x00000031,0x00000008,0x0004003b,0x00000016,0x00000036,
0x00000003,0x0004002b,0x00000008,0x0000003b,0x00000010,0x0004003b,0x00000016,0x00000040,
0x00000003,0x0004002b,0x00000008,0x00000045,0x00000020,0x0004003b,0x00000016,0x0000004a,
0x00000003,0x0004002b,0x00000008,0x0000004f,0x00000040,0x0004003b,0x00000016,0x00000054,
0x00000003,0x0004002b,0x00000008,0x00000059,0x00000080,0x0004003b,0x00000016,0x0000005e,
0x00000003,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,
0x00050041,0x0000000d,0x0000000e,0x0000000b,0x0000000c,0x0004003d,0x00000008,0x0000000f,
0x0000000e,0x000500c7,0x00000008,0x00000010,0x0000000f,0x0000000c,0x000500ab,0x00000012,
0x00000013,0x00000010,0x00000011,0x000300f7,0x00000015,0x00000000,0x000400fa,0x00000013,
0x00000014,0x00000015,0x000200f8,0x00000014,0x00050041,0x00000018,0x00000019,0x0000000b,
0x00000011,0x0004003d,0x00000007,0x0000001a,0x00000019,0x0003003e,0x00000017,0x0000001a,
0x000200f9,0x00000015,0x000200f8,0x00000015,0x00050041,0x0000000d,0x0000001b,0x0000000b,
0x0000000c,0x0004003d,0x00000008,0x0000001c,0x0000001b,0x000500c7,0x00000008,0x0000001e,
0x0000001c,0x0000001d,0x000500ab,0x00000012,0x0000001f,0x0000001e,0x00000011,0x000300f7,
0x00000021,0x00000000,0x000400fa,0x0000001f,0x00000020,0x00000021,0x000200f8,0x00000020,
0x00050041,0x00000018,0x00000023,0x0000000b,0x00000011,0x0004003d,0x00000007,0x00000024,
0x00000023,0x0003003e,0x00000022,0x00000024,0x000200f9,0x00000021,0x000200f8,0x00000021,
0x00050041,0x0000000d,0x00000025,0x0000000b,0x0000000c,0x0004003d,0x00000008,0x00000026,
0x00000025,0x000500c7,0x00000008,0x00000028,0x00000026,0x00000027,0x000500ab,0x00000012,
0x00000029,0x00000028,0x00000011,0x000300f7,0x0000002b,0x00000000,0x000400fa,0x00000029,
0x0000002a,0x0000002b,0x000200f8,0x0000002a,0x00050041,0x00000018,0x0000002d,0x0000000b,
0x00000011,0x0004003d,0x00000007,0x0000002e,0x0000002d,0x0003003e,0x0000002c,0x0000002e,
0x000200f9,0x0000002b,0x000200f8,0x0000002b,0x00050041,0x0000000d,0x0000002f,0x0000000b,
0x0000000c,0x0004003d,0x00000008,0x00000030,0x0000002f,0x000500c7,0x00000008,0x00000032,
0x00000030,0x00000031,0x000500ab,0x00000012,0x00000033,0x00000032,0x00000011,0x000300f7,
0x00000035,0x00000000,0x000400fa,0x00000033,0x00000034,0x00000035,0x000200f8,0x00000034,
0x00050041,0x00000018,0x00000037,0x0000000b,0x00000011,0x0004003d,0x00000007,0x00000038,
0x00000037,0x0003003e,0x00000036,0x00000038,0x000200f9,0x00000035,0x000200f8,0x00000035,
0x00050041,0x0000000d,0x00000039,0x0000000b,0x0000000c,0x0004003d,0x00000008,0x0000003a,
0x00000039,0x000500c7,0x00000008,0x0000003c,0x0000003a,0x0000003b,0x000500ab,0x00000012,
0x0000003d,0x0000003c,0x00000011,0x000300f7,0x0000003f,0x00000000,0x000400fa,0x0000003d,
0x0000003e,0x0000003f,0x000200f8,0x0000003e,0x00050041,0x00000018,0x00000041,0x0000000b,
0x00000011,0x0004003d,0x00000007,0x00000042,0x00000041,0x0003003e,0x00000040,0x00000042,
0x000200f9,0x0000003f,0x000200f8,0x0000003f,0x00050041,0x0000000d,0x00000043,0x0000000b,
0x0000000c,0x0004003d,0x00000008,0x00000044,0x00000043,0x000500c7,0x00000008,0x00000046,
0x00000044,0x00000045,0x000500ab,0x00000012,0x00000047,0x00000046,0x00000011,0x000300f7,
0x00000049,0x00000000,0x000400fa,0x00000047,0x00000048,0x00000049,0x000200f8,0x00000048,
0x00050041,0x00000018,0x0000004b,0x0000000b,0x00000011,0x0004003d,0x00000007,0x0000004c,
0x0000004b,0x0003003e,0x0000004a,0x0000004c,0x000200f9,0x00000049,0x000200f8,0x00000049,
0x00050041,0x0000000d,0x0000004d,0x0000000b,0x0000000c,0x0004003d,0x00000008,0x0000004e,
0x0000004d,0x000500c7,0x00000008,0x00000050,0x0000004e,0x0000004f,0x000500ab,0x00000012,
0x00000051,0x00000050,0x00000011,0x000300f7,0x00000053,0x00000000,0x000400fa,0x00000051,
0x00000052,0x00000053,0x000200f8,0x00000052,0x00050041,0x00000018,0x00000055,0x0000000b,
0x00000011,0x0004003d,0x00000007,0x00000056,0x00000055,0x0003003e,0x00000054,0x00000056,
0x000200f9,0x00000053,0x000200f8,0x00000053,0x00050041,0x0000000d,0x00000057,0x0000000b,
0x0000000c,0x0004003d,0x00000008,0x00000058,0x00000057,0x000500c7,0x00000008,0x0000005a,
0x00000058,0x00000059,0x000500ab,0x00000012,0x0000005b,0x0000005a,0x00000011,0x000300f7,
0x0000005d,0x00000000,0x000400fa,0x0000005b,0x0000005c,0x0000005d,0x000200f8,0x0000005c,
0x00050041,0x00000018,0x0000005f,0x0000000b,0x00000011,0x0004003d,0x00000007,0x00000060,
0x0000005f,0x0003003e,0x0000005e,0x00000060,0x000200f9,0x0000005d,0x000200f8,0x0000005d,
0x000100fd,0x00010038
}; };
#if 0 // Generated from: #if 0 // Generated from:
...@@ -25,12 +86,51 @@ const uint32_t kImageClear_frag_00000000[] = { ...@@ -25,12 +86,51 @@ const uint32_t kImageClear_frag_00000000[] = {
layout(push_constant)uniform PushConstants { layout(push_constant)uniform PushConstants {
vec4 clearColor; vec4 clearColor;
int clearBufferMask;
} params; } params;
layout(location = 0)out vec4 colorOut; layout(location = 0)out vec4 colorOut0;
layout(location = 1)out vec4 colorOut1;
layout(location = 2)out vec4 colorOut2;
layout(location = 3)out vec4 colorOut3;
layout(location = 4)out vec4 colorOut4;
layout(location = 5)out vec4 colorOut5;
layout(location = 6)out vec4 colorOut6;
layout(location = 7)out vec4 colorOut7;
void main() void main()
{ {
colorOut = params . clearColor; if((params . clearBufferMask &(1 << 0))!= 0)
{
colorOut0 = params . clearColor;
}
if((params . clearBufferMask &(1 << 1))!= 0)
{
colorOut1 = params . clearColor;
}
if((params . clearBufferMask &(1 << 2))!= 0)
{
colorOut2 = params . clearColor;
}
if((params . clearBufferMask &(1 << 3))!= 0)
{
colorOut3 = params . clearColor;
}
if((params . clearBufferMask &(1 << 4))!= 0)
{
colorOut4 = params . clearColor;
}
if((params . clearBufferMask &(1 << 5))!= 0)
{
colorOut5 = params . clearColor;
}
if((params . clearBufferMask &(1 << 6))!= 0)
{
colorOut6 = params . clearColor;
}
if((params . clearBufferMask &(1 << 7))!= 0)
{
colorOut7 = params . clearColor;
}
} }
#endif // Preprocessed code #endif // Preprocessed code
...@@ -9,11 +9,51 @@ ...@@ -9,11 +9,51 @@
layout(push_constant) uniform PushConstants { layout(push_constant) uniform PushConstants {
vec4 clearColor; vec4 clearColor;
int clearBufferMask;
} params; } params;
layout(location = 0) out vec4 colorOut; // ANGLE supports a maximum of 8 draw buffers
layout(location = 0) out vec4 colorOut0;
layout(location = 1) out vec4 colorOut1;
layout(location = 2) out vec4 colorOut2;
layout(location = 3) out vec4 colorOut3;
layout(location = 4) out vec4 colorOut4;
layout(location = 5) out vec4 colorOut5;
layout(location = 6) out vec4 colorOut6;
layout(location = 7) out vec4 colorOut7;
void main() void main()
{ {
colorOut = params.clearColor; if ((params.clearBufferMask & (1 << 0)) != 0)
{
colorOut0 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 1)) != 0)
{
colorOut1 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 2)) != 0)
{
colorOut2 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 3)) != 0)
{
colorOut3 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 4)) != 0)
{
colorOut4 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 5)) != 0)
{
colorOut5 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 6)) != 0)
{
colorOut6 = params.clearColor;
}
if ((params.clearBufferMask & (1 << 7)) != 0)
{
colorOut7 = params.clearColor;
}
} }
...@@ -1082,39 +1082,28 @@ void AttachmentOpsArray::initDummyOp(size_t index, ...@@ -1082,39 +1082,28 @@ void AttachmentOpsArray::initDummyOp(size_t index,
VkImageLayout initialLayout, VkImageLayout initialLayout,
VkImageLayout finalLayout) VkImageLayout finalLayout)
{ {
setLayout(index, initialLayout, finalLayout);
setLoadOp(index, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
setStoreOp(index, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void AttachmentOpsArray::setLayout(size_t index,
VkImageLayout initialLayout,
VkImageLayout finalLayout)
{
PackedAttachmentOpsDesc &ops = mOps[index]; PackedAttachmentOpsDesc &ops = mOps[index];
SetBitField(ops.initialLayout, initialLayout); SetBitField(ops.initialLayout, initialLayout);
SetBitField(ops.finalLayout, finalLayout); SetBitField(ops.finalLayout, finalLayout);
SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
SetBitField(ops.storeOp, VK_ATTACHMENT_STORE_OP_STORE);
SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
} }
void AttachmentOpsArray::setLoadOp(size_t index, void AttachmentOpsArray::initWithLoadStore(size_t index,
VkAttachmentLoadOp loadOp, VkImageLayout initialLayout,
VkAttachmentLoadOp stencilLoadOp) VkImageLayout finalLayout)
{
PackedAttachmentOpsDesc &ops = mOps[index];
SetBitField(ops.loadOp, loadOp);
SetBitField(ops.stencilLoadOp, stencilLoadOp);
}
void AttachmentOpsArray::setStoreOp(size_t index,
VkAttachmentStoreOp storeOp,
VkAttachmentStoreOp stencilStoreOp)
{ {
PackedAttachmentOpsDesc &ops = mOps[index]; PackedAttachmentOpsDesc &ops = mOps[index];
SetBitField(ops.storeOp, storeOp); SetBitField(ops.initialLayout, initialLayout);
SetBitField(ops.stencilStoreOp, stencilStoreOp); SetBitField(ops.finalLayout, finalLayout);
SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
SetBitField(ops.storeOp, VK_ATTACHMENT_STORE_OP_STORE);
SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_STORE);
} }
size_t AttachmentOpsArray::hash() const size_t AttachmentOpsArray::hash() const
......
...@@ -115,10 +115,8 @@ class AttachmentOpsArray final ...@@ -115,10 +115,8 @@ class AttachmentOpsArray final
// Initializes an attachment op with whatever values. Used for compatible RenderPass checks. // Initializes an attachment op with whatever values. Used for compatible RenderPass checks.
void initDummyOp(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout); void initDummyOp(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
// Initialize an attachment op with all load and store operations.
void setLayout(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout); void initWithLoadStore(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
void setLoadOp(size_t index, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
void setStoreOp(size_t index, VkAttachmentStoreOp storeOp, VkAttachmentStoreOp stencilStoreOp);
size_t hash() const; size_t hash() const;
......
...@@ -170,6 +170,9 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -170,6 +170,9 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo); VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
// There is no way to know if the command buffer contains any commands.
bool empty() const { return false; }
using WrappedObject::operator=; using WrappedObject::operator=;
static bool SupportsQueries(const VkPhysicalDeviceFeatures &features) static bool SupportsQueries(const VkPhysicalDeviceFeatures &features)
......
...@@ -761,6 +761,9 @@ TEST_P(ClearTestES3, MaskedScissoredClearMultipleAttachments) ...@@ -761,6 +761,9 @@ TEST_P(ClearTestES3, MaskedScissoredClearMultipleAttachments)
// mistakenly clear every channel (including the masked-out ones) // mistakenly clear every channel (including the masked-out ones)
TEST_P(ClearTestES3, MaskedClearBufferBug) TEST_P(ClearTestES3, MaskedClearBufferBug)
{ {
// Vulkan doesn't support gaps in render targets yet. http://anglebug.com/2394
ANGLE_SKIP_TEST_IF(IsVulkan());
unsigned char pixelData[] = {255, 255, 255, 255}; unsigned char pixelData[] = {255, 255, 255, 255};
glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]); glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
...@@ -896,6 +899,9 @@ TEST_P(ClearTestES3, MixedSRGBClear) ...@@ -896,6 +899,9 @@ TEST_P(ClearTestES3, MixedSRGBClear)
// flush or finish after ClearBufferfv or each draw. // flush or finish after ClearBufferfv or each draw.
TEST_P(ClearTestES3, RepeatedClear) TEST_P(ClearTestES3, RepeatedClear)
{ {
// ES3 shaders are not yet supported on Vulkan.
ANGLE_SKIP_TEST_IF(IsVulkan());
constexpr char kVS[] = constexpr char kVS[] =
"#version 300 es\n" "#version 300 es\n"
"in highp vec2 position;\n" "in highp vec2 position;\n"
...@@ -1271,7 +1277,7 @@ ANGLE_INSTANTIATE_TEST(ClearTest, ...@@ -1271,7 +1277,7 @@ ANGLE_INSTANTIATE_TEST(ClearTest,
ES2_OPENGLES(), ES2_OPENGLES(),
ES3_OPENGLES(), ES3_OPENGLES(),
ES2_VULKAN()); ES2_VULKAN());
ANGLE_INSTANTIATE_TEST(ClearTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(ClearTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(ScissoredClearTest, ES2_D3D11(), ES2_OPENGL(), ES2_VULKAN()); ANGLE_INSTANTIATE_TEST(ScissoredClearTest, ES2_D3D11(), ES2_OPENGL(), ES2_VULKAN());
ANGLE_INSTANTIATE_TEST(VulkanClearTest, ES2_VULKAN()); ANGLE_INSTANTIATE_TEST(VulkanClearTest, ES2_VULKAN());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment