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,
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
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
......@@ -53,7 +56,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
mCurrentDrawMode(GL_NONE),
mDynamicDescriptorPool(),
mTexturesDirty(false),
mVertexArrayBindingHasChanged(false)
mVertexArrayBindingHasChanged(false),
mClearColorMask(kAllColorChannelsMask)
{
memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
......@@ -117,8 +121,8 @@ gl::Error ContextVk::initPipeline()
mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc());
// TODO(jmadill): Validate with ASSERT against physical device limits/caps?
ANGLE_TRY(mRenderer->getPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask,
&mCurrentPipeline));
ANGLE_TRY(mRenderer->getAppPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask,
&mCurrentPipeline));
return gl::NoError();
}
......@@ -404,8 +408,14 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
mPipelineDesc->updateBlendEquations(glState.getBlendState());
break;
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;
}
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
WARN() << "DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED unimplemented";
break;
......@@ -750,4 +760,8 @@ const VkClearValue &ContextVk::getClearDepthStencilValue() const
return mClearDepthStencilValue;
}
VkColorComponentFlags ContextVk::getClearColorMask() const
{
return mClearColorMask;
}
} // namespace rx
......@@ -158,6 +158,7 @@ class ContextVk : public ContextImpl
const VkClearValue &getClearColorValue() const;
const VkClearValue &getClearDepthStencilValue() const;
VkColorComponentFlags getClearColorMask() const;
const VkRect2D &getScissor() const { return mPipelineDesc->getScissor(); }
private:
......@@ -184,9 +185,10 @@ class ContextVk : public ContextImpl
bool mTexturesDirty;
bool mVertexArrayBindingHasChanged;
// Cached clear value for color and depth/stencil.
// Cached clear value/mask for color and depth/stencil.
VkClearValue mClearColorValue;
VkClearValue mClearDepthStencilValue;
VkColorComponentFlags mClearColorMask;
};
} // namespace rx
......
......@@ -54,12 +54,22 @@ FramebufferVk *FramebufferVk::CreateDefaultFBO(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)
: FramebufferImpl(state), mBackbuffer(backbuffer), mRenderPassDesc(), mFramebuffer()
: FramebufferImpl(state),
mBackbuffer(backbuffer),
mRenderPassDesc(),
mFramebuffer(),
mActiveColorComponents(0),
mMaskedClearDescriptorSet(VK_NULL_HANDLE)
{
}
......@@ -70,8 +80,9 @@ FramebufferVk::~FramebufferVk()
void FramebufferVk::destroy(const gl::Context *context)
{
RendererVk *renderer = vk::GetImpl(context)->getRenderer();
renderer->releaseResource(*this, &mFramebuffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.buffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.memory);
}
void FramebufferVk::destroyDefault(const egl::Display *display)
......@@ -129,6 +140,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthStencilAttachment();
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
// attachment, we need to use clearAttachment instead of clearDepthStencil since Vulkan won't
// allow us to clear one or the other separately.
......@@ -179,16 +199,15 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
writingNode = getCurrentWritingNode();
}
// TODO(jmadill): Check for masked color clear. http://anglebug.com/2455
// TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
const auto &colorRenderTargets = mRenderTargetCache.getColors();
const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
for (size_t colorIndex : mState.getEnabledDrawBuffers())
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
ASSERT(colorRenderTarget);
colorRenderTarget->resource->onWriteResource(writingNode, currentSerial);
colorRenderTarget->image->clearColor(contextVk->getClearColorValue().color, commandBuffer);
colorRenderTarget->image->clearColor(clearColorValue, commandBuffer);
}
return gl::NoError();
......@@ -349,11 +368,28 @@ gl::Error FramebufferVk::syncState(const gl::Context *context,
size_t colorIndex =
static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
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;
}
}
}
mActiveColorComponents = gl_vk::GetColorComponentFlags(
mActiveColorComponentMasks[0].any(), mActiveColorComponentMasks[1].any(),
mActiveColorComponentMasks[2].any(), mActiveColorComponentMasks[3].any());
mRenderPassDesc.reset();
renderer->releaseResource(*this, &mFramebuffer);
......@@ -466,6 +502,8 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
{
RendererVk *renderer = contextVk->getRenderer();
getNewWritingNode(renderer);
// This command can only happen inside a render pass, so obtain one if its already happening
// or create a new one if not.
vk::CommandGraphNode *node = nullptr;
......@@ -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
// in Vulkan.
gl::Rectangle intersection;
if (!ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
&intersection))
if (!gl::ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
&intersection))
{
// There is nothing to clear since the scissor is outside of the render area.
return gl::NoError();
}
clearRect.rect = gl_vk::GetRect(intersection);
gl::AttachmentArray<VkClearAttachment> clearAttachments;
......@@ -552,6 +589,132 @@ gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
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
{
UNIMPLEMENTED();
......@@ -625,4 +788,11 @@ gl::Error FramebufferVk::getCommandGraphNodeForDraw(ContextVk *contextVk,
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
......@@ -99,12 +99,24 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
bool clearColor,
bool clearDepth,
bool clearStencil);
gl::Error clearWithDraw(ContextVk *contextVk, VkColorComponentFlags colorMaskFlags);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
WindowSurfaceVk *mBackbuffer;
Optional<vk::RenderPassDesc> mRenderPassDesc;
vk::Framebuffer mFramebuffer;
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
......
......@@ -220,6 +220,7 @@ RendererVk::~RendererVk()
}
mGraphicsPipelineLayout.destroy(mDevice);
mInternalUniformPipelineLayout.destroy(mDevice);
mRenderPassCache.destroy(mDevice);
mPipelineCache.destroy(mDevice);
......@@ -874,7 +875,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
uint32_t blockCount = 0;
{
auto &layoutBinding = uniformBindings[blockCount];
VkDescriptorSetLayoutBinding &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
......@@ -886,7 +887,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
}
{
auto &layoutBinding = uniformBindings[blockCount];
VkDescriptorSetLayoutBinding &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
......@@ -951,15 +952,43 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
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()
{
return mShaderSerialFactory.generate();
}
vk::Error RendererVk::getPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut)
vk::Error RendererVk::getAppPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut)
{
ASSERT(programVk->getVertexModuleSerial() ==
desc.getShaderStageInfo()[vk::ShaderType::VertexShader].moduleSerial);
......@@ -975,6 +1004,27 @@ vk::Error RendererVk::getPipeline(const ProgramVk *programVk,
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()
{
return &mShaderLibrary;
......
......@@ -113,10 +113,19 @@ class RendererVk : angle::NonCopyable
const vk::AttachmentOpsArray &ops,
vk::RenderPass **renderPassOut);
vk::Error getPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut);
// For getting a vk::Pipeline for the an application's draw call. RenderPassDesc is automatic.
vk::Error getAppPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
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.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering.
......@@ -125,6 +134,10 @@ class RendererVk : angle::NonCopyable
const vk::PipelineLayout &getGraphicsPipelineLayout() 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.
Serial issueShaderSerial();
......@@ -189,6 +202,9 @@ class RendererVk : angle::NonCopyable
vk::PipelineLayout mGraphicsPipelineLayout;
std::vector<vk::DescriptorSetLayout> mGraphicsDescriptorSetLayouts;
// Used for internal shaders.
vk::PipelineLayout mInternalUniformPipelineLayout;
// Internal shader library.
vk::ShaderLibrary mShaderLibrary;
};
......
......@@ -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)
{
......
......@@ -300,7 +300,7 @@ class PipelineDesc final
void updateBlendColor(const gl::ColorF &color);
void updateBlendFuncs(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.
void updateDepthTestEnabled(const gl::DepthStencilState &depthStencilState);
......
......@@ -242,7 +242,6 @@ class ImageHelper final : angle::NonCopyable
// Cached properties.
uint32_t mLayerCount;
};
} // namespace vk
} // namespace rx
......
......@@ -555,6 +555,15 @@ void CommandBuffer::executeCommands(uint32_t commandBufferCount,
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::Image()
{
......@@ -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) |
(blendState.colorMaskGreen ? VK_COLOR_COMPONENT_G_BIT : 0) |
(blendState.colorMaskBlue ? VK_COLOR_COMPONENT_B_BIT : 0) |
(blendState.colorMaskAlpha ? VK_COLOR_COMPONENT_A_BIT : 0);
return (red ? VK_COLOR_COMPONENT_R_BIT : 0) | (green ? VK_COLOR_COMPONENT_G_BIT : 0) |
(blue ? VK_COLOR_COMPONENT_B_BIT : 0) | (alpha ? VK_COLOR_COMPONENT_A_BIT : 0);
}
} // namespace gl_vk
} // namespace rx
......
......@@ -397,6 +397,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
const uint32_t *dynamicOffsets);
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>
......@@ -682,7 +686,7 @@ void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset);
void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent);
VkImageType GetImageType(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 rx
......
......@@ -188,10 +188,6 @@
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
// 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.implementation_limits.* = 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