Commit 9aef3670 by Jamie Madill Committed by Commit Bot

Vulkan: Implement masked color clears.

This implements masked color clear using clear shaders. The shaders themselves were introduced in a prior patch. In order to get the right setup for the draw call to trigger the shaders, we create an internal pipeline from the pipeline cache. We also use a special pipeline layout with only uniform buffers. The masked out color channels are disabled via settings on the pipeline. This fixes the dEQP masked color clear tests. It doesn't handle masked color clears combined with the depth clear bit. It's likely we don't have test coverage for this case. Bug: angleproject:2455 Change-Id: I513248cc0f7e58f490fc16ac9afb40119d730ccc Reviewed-on: https://chromium-review.googlesource.com/1031373 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 78feddc2
...@@ -45,6 +45,9 @@ constexpr gl::Rectangle kMaxSizedScissor(0, ...@@ -45,6 +45,9 @@ constexpr gl::Rectangle kMaxSizedScissor(0,
std::numeric_limits<int>::max(), std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
constexpr VkColorComponentFlags kAllColorChannelsMask =
(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT);
} // anonymous namespace } // anonymous namespace
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
...@@ -53,7 +56,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -53,7 +56,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
mCurrentDrawMode(GL_NONE), mCurrentDrawMode(GL_NONE),
mDynamicDescriptorPool(), mDynamicDescriptorPool(),
mTexturesDirty(false), mTexturesDirty(false),
mVertexArrayBindingHasChanged(false) mVertexArrayBindingHasChanged(false),
mClearColorMask(kAllColorChannelsMask)
{ {
memset(&mClearColorValue, 0, sizeof(mClearColorValue)); memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue)); memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
...@@ -117,8 +121,8 @@ gl::Error ContextVk::initPipeline() ...@@ -117,8 +121,8 @@ gl::Error ContextVk::initPipeline()
mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc()); mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc());
// TODO(jmadill): Validate with ASSERT against physical device limits/caps? // TODO(jmadill): Validate with ASSERT against physical device limits/caps?
ANGLE_TRY(mRenderer->getPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask, ANGLE_TRY(mRenderer->getAppPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask,
&mCurrentPipeline)); &mCurrentPipeline));
return gl::NoError(); return gl::NoError();
} }
...@@ -404,8 +408,14 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -404,8 +408,14 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
mPipelineDesc->updateBlendEquations(glState.getBlendState()); mPipelineDesc->updateBlendEquations(glState.getBlendState());
break; break;
case gl::State::DIRTY_BIT_COLOR_MASK: case gl::State::DIRTY_BIT_COLOR_MASK:
mPipelineDesc->updateColorWriteMask(glState.getBlendState()); {
const gl::BlendState &blendState = glState.getBlendState();
mClearColorMask = gl_vk::GetColorComponentFlags(
blendState.colorMaskRed, blendState.colorMaskGreen, blendState.colorMaskBlue,
blendState.colorMaskAlpha);
mPipelineDesc->updateColorWriteMask(mClearColorMask);
break; break;
}
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
WARN() << "DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED unimplemented"; WARN() << "DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED unimplemented";
break; break;
...@@ -750,4 +760,8 @@ const VkClearValue &ContextVk::getClearDepthStencilValue() const ...@@ -750,4 +760,8 @@ const VkClearValue &ContextVk::getClearDepthStencilValue() const
return mClearDepthStencilValue; return mClearDepthStencilValue;
} }
VkColorComponentFlags ContextVk::getClearColorMask() const
{
return mClearColorMask;
}
} // namespace rx } // namespace rx
...@@ -158,6 +158,7 @@ class ContextVk : public ContextImpl ...@@ -158,6 +158,7 @@ class ContextVk : public ContextImpl
const VkClearValue &getClearColorValue() const; const VkClearValue &getClearColorValue() const;
const VkClearValue &getClearDepthStencilValue() const; const VkClearValue &getClearDepthStencilValue() const;
VkColorComponentFlags getClearColorMask() const;
const VkRect2D &getScissor() const { return mPipelineDesc->getScissor(); } const VkRect2D &getScissor() const { return mPipelineDesc->getScissor(); }
private: private:
...@@ -184,9 +185,10 @@ class ContextVk : public ContextImpl ...@@ -184,9 +185,10 @@ class ContextVk : public ContextImpl
bool mTexturesDirty; bool mTexturesDirty;
bool mVertexArrayBindingHasChanged; bool mVertexArrayBindingHasChanged;
// Cached clear value for color and depth/stencil. // Cached clear value/mask for color and depth/stencil.
VkClearValue mClearColorValue; VkClearValue mClearColorValue;
VkClearValue mClearDepthStencilValue; VkClearValue mClearDepthStencilValue;
VkColorComponentFlags mClearColorMask;
}; };
} // namespace rx } // namespace rx
......
...@@ -99,12 +99,24 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource ...@@ -99,12 +99,24 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
bool clearColor, bool clearColor,
bool clearDepth, bool clearDepth,
bool clearStencil); bool clearStencil);
gl::Error clearWithDraw(ContextVk *contextVk, VkColorComponentFlags colorMaskFlags);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
WindowSurfaceVk *mBackbuffer; WindowSurfaceVk *mBackbuffer;
Optional<vk::RenderPassDesc> mRenderPassDesc; Optional<vk::RenderPassDesc> mRenderPassDesc;
vk::Framebuffer mFramebuffer; vk::Framebuffer mFramebuffer;
RenderTargetCache<RenderTargetVk> mRenderTargetCache; RenderTargetCache<RenderTargetVk> mRenderTargetCache;
// These two variables are used to quickly compute if we need to do a masked clear. If a color
// channel is masked out, we check against the Framebuffer Attachments (RenderTargets) to see
// if the masked out channel is present in any of the attachments.
VkColorComponentFlags mActiveColorComponents;
gl::DrawBufferMask mActiveColorComponentMasks[4];
// For use in masked clear.
vk::BufferAndMemory mMaskedClearUniformBuffer;
VkDescriptorSet mMaskedClearDescriptorSet;
}; };
} // namespace rx } // namespace rx
......
...@@ -220,6 +220,7 @@ RendererVk::~RendererVk() ...@@ -220,6 +220,7 @@ RendererVk::~RendererVk()
} }
mGraphicsPipelineLayout.destroy(mDevice); mGraphicsPipelineLayout.destroy(mDevice);
mInternalUniformPipelineLayout.destroy(mDevice);
mRenderPassCache.destroy(mDevice); mRenderPassCache.destroy(mDevice);
mPipelineCache.destroy(mDevice); mPipelineCache.destroy(mDevice);
...@@ -874,7 +875,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout() ...@@ -874,7 +875,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
uint32_t blockCount = 0; uint32_t blockCount = 0;
{ {
auto &layoutBinding = uniformBindings[blockCount]; VkDescriptorSetLayoutBinding &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount; layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
...@@ -886,7 +887,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout() ...@@ -886,7 +887,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
} }
{ {
auto &layoutBinding = uniformBindings[blockCount]; VkDescriptorSetLayoutBinding &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount; layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
...@@ -951,15 +952,43 @@ vk::Error RendererVk::initGraphicsPipelineLayout() ...@@ -951,15 +952,43 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
return vk::NoError(); return vk::NoError();
} }
const vk::DescriptorSetLayout &RendererVk::getInternalUniformDescriptorSetLayout() const
{
return mGraphicsDescriptorSetLayouts[0];
}
vk::Error RendererVk::getInternalUniformPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut)
{
*pipelineLayoutOut = &mInternalUniformPipelineLayout;
if (mInternalUniformPipelineLayout.valid())
{
return vk::NoError();
}
// Here we use the knowledge that the "graphics" descriptor set has uniform blocks at offset 0.
VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.setLayoutCount = 1;
createInfo.pSetLayouts = mGraphicsDescriptorSetLayouts[0].ptr();
createInfo.pushConstantRangeCount = 0;
createInfo.pPushConstantRanges = nullptr;
ANGLE_TRY(mInternalUniformPipelineLayout.init(mDevice, createInfo));
return vk::NoError();
}
Serial RendererVk::issueShaderSerial() Serial RendererVk::issueShaderSerial()
{ {
return mShaderSerialFactory.generate(); return mShaderSerialFactory.generate();
} }
vk::Error RendererVk::getPipeline(const ProgramVk *programVk, vk::Error RendererVk::getAppPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc, const vk::PipelineDesc &desc,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut) vk::PipelineAndSerial **pipelineOut)
{ {
ASSERT(programVk->getVertexModuleSerial() == ASSERT(programVk->getVertexModuleSerial() ==
desc.getShaderStageInfo()[vk::ShaderType::VertexShader].moduleSerial); desc.getShaderStageInfo()[vk::ShaderType::VertexShader].moduleSerial);
...@@ -975,6 +1004,27 @@ vk::Error RendererVk::getPipeline(const ProgramVk *programVk, ...@@ -975,6 +1004,27 @@ vk::Error RendererVk::getPipeline(const ProgramVk *programVk,
programVk->getLinkedFragmentModule(), desc, pipelineOut); programVk->getLinkedFragmentModule(), desc, pipelineOut);
} }
vk::Error RendererVk::getInternalPipeline(const vk::ShaderAndSerial &vertexShader,
const vk::ShaderAndSerial &fragmentShader,
const vk::PipelineLayout &pipelineLayout,
const vk::PipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut)
{
ASSERT(vertexShader.queueSerial() ==
pipelineDesc.getShaderStageInfo()[vk::ShaderType::VertexShader].moduleSerial);
ASSERT(fragmentShader.queueSerial() ==
pipelineDesc.getShaderStageInfo()[vk::ShaderType::FragmentShader].moduleSerial);
// Pull in a compatible RenderPass.
vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(getCompatibleRenderPass(pipelineDesc.getRenderPassDesc(), &compatibleRenderPass));
return mPipelineCache.getPipeline(mDevice, *compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, vertexShader.get(),
fragmentShader.get(), pipelineDesc, pipelineOut);
}
vk::ShaderLibrary *RendererVk::getShaderLibrary() vk::ShaderLibrary *RendererVk::getShaderLibrary()
{ {
return &mShaderLibrary; return &mShaderLibrary;
......
...@@ -113,10 +113,19 @@ class RendererVk : angle::NonCopyable ...@@ -113,10 +113,19 @@ class RendererVk : angle::NonCopyable
const vk::AttachmentOpsArray &ops, const vk::AttachmentOpsArray &ops,
vk::RenderPass **renderPassOut); vk::RenderPass **renderPassOut);
vk::Error getPipeline(const ProgramVk *programVk, // For getting a vk::Pipeline for the an application's draw call. RenderPassDesc is automatic.
const vk::PipelineDesc &desc, vk::Error getAppPipeline(const ProgramVk *programVk,
const gl::AttributesMask &activeAttribLocationsMask, const vk::PipelineDesc &desc,
vk::PipelineAndSerial **pipelineOut); const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut);
// For getting a vk::Pipeline for an internal draw call. Use an explicit RenderPass.
vk::Error getInternalPipeline(const vk::ShaderAndSerial &vertexShader,
const vk::ShaderAndSerial &fragmentShader,
const vk::PipelineLayout &pipelineLayout,
const vk::PipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut);
// This should only be called from ResourceVk. // This should only be called from ResourceVk.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering. // TODO(jmadill): Keep in ContextVk to enable threaded rendering.
...@@ -125,6 +134,10 @@ class RendererVk : angle::NonCopyable ...@@ -125,6 +134,10 @@ class RendererVk : angle::NonCopyable
const vk::PipelineLayout &getGraphicsPipelineLayout() const; const vk::PipelineLayout &getGraphicsPipelineLayout() const;
const std::vector<vk::DescriptorSetLayout> &getGraphicsDescriptorSetLayouts() const; const std::vector<vk::DescriptorSetLayout> &getGraphicsDescriptorSetLayouts() const;
// Used in internal shaders.
vk::Error getInternalUniformPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut);
const vk::DescriptorSetLayout &getInternalUniformDescriptorSetLayout() const;
// Issues a new serial for linked shader modules. Used in the pipeline cache. // Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial(); Serial issueShaderSerial();
...@@ -189,6 +202,9 @@ class RendererVk : angle::NonCopyable ...@@ -189,6 +202,9 @@ class RendererVk : angle::NonCopyable
vk::PipelineLayout mGraphicsPipelineLayout; vk::PipelineLayout mGraphicsPipelineLayout;
std::vector<vk::DescriptorSetLayout> mGraphicsDescriptorSetLayouts; std::vector<vk::DescriptorSetLayout> mGraphicsDescriptorSetLayouts;
// Used for internal shaders.
vk::PipelineLayout mInternalUniformPipelineLayout;
// Internal shader library. // Internal shader library.
vk::ShaderLibrary mShaderLibrary; vk::ShaderLibrary mShaderLibrary;
}; };
......
...@@ -727,9 +727,9 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState) ...@@ -727,9 +727,9 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState)
} }
} }
void PipelineDesc::updateColorWriteMask(const gl::BlendState &blendState) void PipelineDesc::updateColorWriteMask(VkColorComponentFlags colorComponentFlags)
{ {
uint8_t colorMask = static_cast<uint8_t>(gl_vk::GetColorComponentFlags(blendState)); uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
for (PackedColorBlendAttachmentState &blendAttachmentState : mColorBlendStateInfo.attachments) for (PackedColorBlendAttachmentState &blendAttachmentState : mColorBlendStateInfo.attachments)
{ {
......
...@@ -300,7 +300,7 @@ class PipelineDesc final ...@@ -300,7 +300,7 @@ class PipelineDesc final
void updateBlendColor(const gl::ColorF &color); void updateBlendColor(const gl::ColorF &color);
void updateBlendFuncs(const gl::BlendState &blend_state); void updateBlendFuncs(const gl::BlendState &blend_state);
void updateBlendEquations(const gl::BlendState &blend_state); void updateBlendEquations(const gl::BlendState &blend_state);
void updateColorWriteMask(const gl::BlendState &blendState); void updateColorWriteMask(VkColorComponentFlags colorComponentFlags);
// Depth/stencil states. // Depth/stencil states.
void updateDepthTestEnabled(const gl::DepthStencilState &depthStencilState); void updateDepthTestEnabled(const gl::DepthStencilState &depthStencilState);
......
...@@ -242,7 +242,6 @@ class ImageHelper final : angle::NonCopyable ...@@ -242,7 +242,6 @@ class ImageHelper final : angle::NonCopyable
// Cached properties. // Cached properties.
uint32_t mLayerCount; uint32_t mLayerCount;
}; };
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -555,6 +555,15 @@ void CommandBuffer::executeCommands(uint32_t commandBufferCount, ...@@ -555,6 +555,15 @@ void CommandBuffer::executeCommands(uint32_t commandBufferCount,
vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr()); vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
} }
void CommandBuffer::updateBuffer(const vk::Buffer &buffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void *data)
{
ASSERT(valid() && buffer.valid());
vkCmdUpdateBuffer(mHandle, buffer.getHandle(), dstOffset, dataSize, data);
}
// Image implementation. // Image implementation.
Image::Image() Image::Image()
{ {
...@@ -1364,12 +1373,10 @@ VkImageViewType GetImageViewType(gl::TextureType textureType) ...@@ -1364,12 +1373,10 @@ VkImageViewType GetImageViewType(gl::TextureType textureType)
} }
} }
VkColorComponentFlags GetColorComponentFlags(const gl::BlendState &blendState) VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bool alpha)
{ {
return (blendState.colorMaskRed ? VK_COLOR_COMPONENT_R_BIT : 0) | return (red ? VK_COLOR_COMPONENT_R_BIT : 0) | (green ? VK_COLOR_COMPONENT_G_BIT : 0) |
(blendState.colorMaskGreen ? VK_COLOR_COMPONENT_G_BIT : 0) | (blue ? VK_COLOR_COMPONENT_B_BIT : 0) | (alpha ? VK_COLOR_COMPONENT_A_BIT : 0);
(blendState.colorMaskBlue ? VK_COLOR_COMPONENT_B_BIT : 0) |
(blendState.colorMaskAlpha ? VK_COLOR_COMPONENT_A_BIT : 0);
} }
} // namespace gl_vk } // namespace gl_vk
} // namespace rx } // namespace rx
......
...@@ -397,6 +397,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -397,6 +397,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
const uint32_t *dynamicOffsets); const uint32_t *dynamicOffsets);
void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers); void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
void updateBuffer(const vk::Buffer &buffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void *data);
}; };
class Image final : public WrappedObject<Image, VkImage> class Image final : public WrappedObject<Image, VkImage>
...@@ -682,7 +686,7 @@ void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset); ...@@ -682,7 +686,7 @@ void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset);
void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent); void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent);
VkImageType GetImageType(gl::TextureType textureType); VkImageType GetImageType(gl::TextureType textureType);
VkImageViewType GetImageViewType(gl::TextureType textureType); VkImageViewType GetImageViewType(gl::TextureType textureType);
VkColorComponentFlags GetColorComponentFlags(const gl::BlendState &blendState); VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bool alpha);
} // namespace gl_vk } // namespace gl_vk
} // namespace rx } // namespace rx
......
...@@ -188,10 +188,6 @@ ...@@ -188,10 +188,6 @@
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
// Vulkan failures // Vulkan failures
2455 VULKAN : dEQP-GLES2.functional.color_clear.masked_rg* = FAIL
2455 VULKAN : dEQP-GLES2.functional.color_clear.masked_scissor* = FAIL
2455 VULKAN : dEQP-GLES2.functional.color_clear.complex_* = FAIL
2455 VULKAN : dEQP-GLES2.functional.color_clear.long_masked_* = FAIL
2161 VULKAN : dEQP-GLES2.functional.prerequisite.* = SKIP 2161 VULKAN : dEQP-GLES2.functional.prerequisite.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.implementation_limits.* = SKIP 2161 VULKAN : dEQP-GLES2.functional.implementation_limits.* = SKIP
2161 VULKAN : dEQP-GLES2.functional.buffer.* = SKIP 2161 VULKAN : dEQP-GLES2.functional.buffer.* = SKIP
......
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