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
......
...@@ -54,12 +54,22 @@ FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state ...@@ -54,12 +54,22 @@ FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state
} }
FramebufferVk::FramebufferVk(const gl::FramebufferState &state) FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
: FramebufferImpl(state), mBackbuffer(nullptr), mRenderPassDesc(), mFramebuffer() : FramebufferImpl(state),
mBackbuffer(nullptr),
mRenderPassDesc(),
mFramebuffer(),
mActiveColorComponents(0),
mMaskedClearDescriptorSet(VK_NULL_HANDLE)
{ {
} }
FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer) FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
: FramebufferImpl(state), mBackbuffer(backbuffer), mRenderPassDesc(), mFramebuffer() : FramebufferImpl(state),
mBackbuffer(backbuffer),
mRenderPassDesc(),
mFramebuffer(),
mActiveColorComponents(0),
mMaskedClearDescriptorSet(VK_NULL_HANDLE)
{ {
} }
...@@ -70,8 +80,9 @@ FramebufferVk::~FramebufferVk() ...@@ -70,8 +80,9 @@ FramebufferVk::~FramebufferVk()
void FramebufferVk::destroy(const gl::Context *context) void FramebufferVk::destroy(const gl::Context *context)
{ {
RendererVk *renderer = vk::GetImpl(context)->getRenderer(); RendererVk *renderer = vk::GetImpl(context)->getRenderer();
renderer->releaseResource(*this, &mFramebuffer); renderer->releaseResource(*this, &mFramebuffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.buffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.memory);
} }
void FramebufferVk::destroyDefault(const egl::Display *display) void FramebufferVk::destroyDefault(const egl::Display *display)
...@@ -129,6 +140,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -129,6 +140,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthStencilAttachment(); const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthStencilAttachment();
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
// 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.
VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
if (clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents)
{
return clearWithDraw(contextVk, colorMaskFlags);
}
// If we clear the depth OR the stencil but not both, and we have a packed depth stencil // If we clear the depth OR the stencil but not both, and we have a packed depth stencil
// attachment, we need to use clearAttachment instead of clearDepthStencil since Vulkan won't // attachment, we need to use clearAttachment instead of clearDepthStencil since Vulkan won't
// allow us to clear one or the other separately. // allow us to clear one or the other separately.
...@@ -179,16 +199,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -179,16 +199,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
writingNode = getCurrentWritingNode(); writingNode = getCurrentWritingNode();
} }
// TODO(jmadill): Check for masked color clear. http://anglebug.com/2455
// 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 : mState.getEnabledDrawBuffers()) for (size_t colorIndex : mState.getEnabledDrawBuffers())
{ {
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex]; RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
ASSERT(colorRenderTarget); ASSERT(colorRenderTarget);
colorRenderTarget->resource->onWriteResource(writingNode, currentSerial); colorRenderTarget->resource->onWriteResource(writingNode, currentSerial);
colorRenderTarget->image->clearColor(contextVk->getClearColorValue().color, commandBuffer); colorRenderTarget->image->clearColor(clearColorValue, commandBuffer);
} }
return gl::NoError(); return gl::NoError();
...@@ -349,11 +368,28 @@ gl::Error FramebufferVk::syncState(const gl::Context *context, ...@@ -349,11 +368,28 @@ gl::Error FramebufferVk::syncState(const gl::Context *context,
size_t colorIndex = size_t colorIndex =
static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndex)); ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndex));
// Update cached masks for masked clears.
RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndex];
if (renderTarget)
{
const angle::Format &format = renderTarget->image->getFormat().textureFormat();
updateActiveColorMasks(colorIndex, format.redBits > 0, format.greenBits > 0,
format.blueBits > 0, format.alphaBits > 0);
}
else
{
updateActiveColorMasks(colorIndex, 0, 0, 0, 0);
}
break; break;
} }
} }
} }
mActiveColorComponents = gl_vk::GetColorComponentFlags(
mActiveColorComponentMasks[0].any(), mActiveColorComponentMasks[1].any(),
mActiveColorComponentMasks[2].any(), mActiveColorComponentMasks[3].any());
mRenderPassDesc.reset(); mRenderPassDesc.reset();
renderer->releaseResource(*this, &mFramebuffer); renderer->releaseResource(*this, &mFramebuffer);
...@@ -466,6 +502,8 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk, ...@@ -466,6 +502,8 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
getNewWritingNode(renderer);
// This command can only happen inside a render pass, so obtain one if its already happening // This command can only happen inside a render pass, so obtain one if its already happening
// or create a new one if not. // or create a new one if not.
vk::CommandGraphNode *node = nullptr; vk::CommandGraphNode *node = nullptr;
...@@ -491,13 +529,12 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk, ...@@ -491,13 +529,12 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
// When clearing, the scissor region must be clipped to the renderArea per the validation rules // When clearing, the scissor region must be clipped to the renderArea per the validation rules
// in Vulkan. // in Vulkan.
gl::Rectangle intersection; gl::Rectangle intersection;
if (!ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(), if (!gl::ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
&intersection)) &intersection))
{ {
// There is nothing to clear since the scissor is outside of the render area. // There is nothing to clear since the scissor is outside of the render area.
return gl::NoError(); return gl::NoError();
} }
clearRect.rect = gl_vk::GetRect(intersection); clearRect.rect = gl_vk::GetRect(intersection);
gl::AttachmentArray<VkClearAttachment> clearAttachments; gl::AttachmentArray<VkClearAttachment> clearAttachments;
...@@ -552,6 +589,132 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk, ...@@ -552,6 +589,132 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
return gl::NoError(); return gl::NoError();
} }
gl::Error FramebufferVk::clearWithDraw(ContextVk *contextVk, VkColorComponentFlags colorMaskFlags)
{
RendererVk *renderer = contextVk->getRenderer();
vk::ShaderLibrary *shaderLibrary = renderer->getShaderLibrary();
const vk::ShaderAndSerial *fullScreenQuad = nullptr;
ANGLE_TRY(shaderLibrary->getShader(renderer, vk::InternalShaderID::FullScreenQuad_vert,
&fullScreenQuad));
const vk::ShaderAndSerial *uniformColor = nullptr;
ANGLE_TRY(
shaderLibrary->getShader(renderer, vk::InternalShaderID::UniformColor_frag, &uniformColor));
const vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY(renderer->getInternalUniformPipelineLayout(&pipelineLayout));
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
vk::CommandGraphNode *node = nullptr;
ANGLE_TRY(getCommandGraphNodeForDraw(contextVk, &node));
// This pipeline desc could be cached.
vk::PipelineDesc pipelineDesc;
pipelineDesc.initDefaults();
pipelineDesc.updateColorWriteMask(colorMaskFlags);
pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), uniformColor->queueSerial());
pipelineDesc.updateViewport(node->getRenderPassRenderArea(), 0.0f, 1.0f);
const gl::State &glState = contextVk->getGLState();
if (glState.isScissorTestEnabled())
{
gl::Rectangle intersection;
if (!gl::ClipRectangle(glState.getScissor(), node->getRenderPassRenderArea(),
&intersection))
{
return gl::NoError();
}
pipelineDesc.updateScissor(intersection);
}
else
{
pipelineDesc.updateScissor(node->getRenderPassRenderArea());
}
vk::PipelineAndSerial *pipeline = nullptr;
ANGLE_TRY(renderer->getInternalPipeline(*fullScreenQuad, *uniformColor, *pipelineLayout,
pipelineDesc, gl::AttributesMask(), &pipeline));
pipeline->updateSerial(renderer->getCurrentQueueSerial());
VkDevice device = renderer->getDevice();
if (!mMaskedClearUniformBuffer.buffer.valid())
{
ASSERT(mMaskedClearDescriptorSet == VK_NULL_HANDLE);
VkBufferUsageFlags bufferUsage =
(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
VkBufferCreateInfo uniformBufferInfo;
uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
uniformBufferInfo.pNext = nullptr;
uniformBufferInfo.flags = 0;
uniformBufferInfo.size = sizeof(VkClearColorValue);
uniformBufferInfo.usage = bufferUsage;
uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
uniformBufferInfo.queueFamilyIndexCount = 0;
uniformBufferInfo.pQueueFamilyIndices = nullptr;
ANGLE_TRY(mMaskedClearUniformBuffer.buffer.init(device, uniformBufferInfo));
VkMemoryPropertyFlags memoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
size_t requiredSize = 0;
ANGLE_TRY(vk::AllocateBufferMemory(renderer, memoryFlags, &mMaskedClearUniformBuffer.buffer,
&mMaskedClearUniformBuffer.memory, &requiredSize));
const vk::DescriptorSetLayout &descriptorSetLayout =
renderer->getInternalUniformDescriptorSetLayout();
// This might confuse the dynamic descriptor pool's counting, but it shouldn't cause
// overflow.
vk::DynamicDescriptorPool *descriptorPool = contextVk->getDynamicDescriptorPool();
descriptorPool->allocateDescriptorSets(contextVk, descriptorSetLayout.ptr(), 1,
&mMaskedClearDescriptorSet);
VkDescriptorBufferInfo bufferInfo;
bufferInfo.buffer = mMaskedClearUniformBuffer.buffer.getHandle();
bufferInfo.offset = 0;
bufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet writeSet;
writeSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeSet.pNext = nullptr;
writeSet.dstSet = mMaskedClearDescriptorSet;
writeSet.dstBinding = 1;
writeSet.dstArrayElement = 0;
writeSet.descriptorCount = 1;
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
writeSet.pImageInfo = nullptr;
writeSet.pBufferInfo = &bufferInfo;
writeSet.pTexelBufferView = nullptr;
vkUpdateDescriptorSets(device, 1, &writeSet, 0, nullptr);
}
VkClearColorValue clearColorValue = contextVk->getClearColorValue().color;
commandBuffer->updateBuffer(mMaskedClearUniformBuffer.buffer, 0, sizeof(VkClearColorValue),
clearColorValue.float32);
vk::CommandBuffer *drawCommandBuffer = nullptr;
ANGLE_TRY(node->beginInsideRenderPassRecording(renderer, &drawCommandBuffer));
std::array<uint32_t, 2> dynamicOffsets = {{0, 0}};
drawCommandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1,
&mMaskedClearDescriptorSet, 2, dynamicOffsets.data());
// TODO(jmadill): Masked combined color and depth/stencil clear. http://anglebug.com/2455
// Any active queries submitted by the user should also be paused here.
drawCommandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->get());
drawCommandBuffer->draw(6, 1, 0, 0);
return gl::NoError();
}
gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -625,4 +788,11 @@ gl::Error FramebufferVk::getCommandGraphNodeForDraw(ContextVk *contextVk, ...@@ -625,4 +788,11 @@ gl::Error FramebufferVk::getCommandGraphNodeForDraw(ContextVk *contextVk,
return gl::NoError(); return gl::NoError();
} }
void FramebufferVk::updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a)
{
mActiveColorComponentMasks[0].set(colorIndex, r);
mActiveColorComponentMasks[1].set(colorIndex, g);
mActiveColorComponentMasks[2].set(colorIndex, b);
mActiveColorComponentMasks[3].set(colorIndex, a);
}
} // 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