Commit be7f44fb by jchen10 Committed by Commit Bot

Vulkan: Use push constant for masked clear color

Storing the color in an uniform buffer, and updating it by vkCmdUpdateBuffer can hit a driver bug. Using vkCmdPushConstants instead can workaround this bug. Besides, push constant is expected to outperform memory-backed resource update according to the vkspec (section 13.2.6). Bug: angleproject:2547 Change-Id: I319cd8e07e0a1d0cb56005b78a46466d9fca436e Reviewed-on: https://chromium-review.googlesource.com/1067247 Commit-Queue: Jie A Chen <jie.a.chen@intel.com> Reviewed-by: 's avatarLuc Ferron <lucferron@chromium.org>
parent b1e91380
......@@ -61,7 +61,6 @@ FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
mRenderPassDesc(),
mFramebuffer(),
mActiveColorComponents(0),
mMaskedClearDescriptorSet(VK_NULL_HANDLE),
mReadPixelsBuffer(VK_BUFFER_USAGE_TRANSFER_DST_BIT, kMinReadPixelsBufferSize)
{
}
......@@ -72,7 +71,6 @@ FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk
mRenderPassDesc(),
mFramebuffer(),
mActiveColorComponents(0),
mMaskedClearDescriptorSet(VK_NULL_HANDLE),
mReadPixelsBuffer(VK_BUFFER_USAGE_TRANSFER_DST_BIT, kMinReadPixelsBufferSize)
{
}
......@@ -86,8 +84,6 @@ void FramebufferVk::destroy(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
renderer->releaseResource(*this, &mFramebuffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.buffer);
renderer->releaseResource(*this, &mMaskedClearUniformBuffer.memory);
mReadPixelsBuffer.destroy(contextVk->getDevice());
}
......@@ -615,12 +611,12 @@ gl::Error FramebufferVk::clearWithDraw(ContextVk *contextVk, VkColorComponentFla
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::ShaderAndSerial *pushConstantColor = nullptr;
ANGLE_TRY(shaderLibrary->getShader(renderer, vk::InternalShaderID::PushConstantColor_frag,
&pushConstantColor));
const vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY(renderer->getInternalUniformPipelineLayout(&pipelineLayout));
ANGLE_TRY(renderer->getInternalPushConstantPipelineLayout(&pipelineLayout));
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
......@@ -633,7 +629,7 @@ gl::Error FramebufferVk::clearWithDraw(ContextVk *contextVk, VkColorComponentFla
pipelineDesc.initDefaults();
pipelineDesc.updateColorWriteMask(colorMaskFlags);
pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), uniformColor->queueSerial());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
pipelineDesc.updateViewport(node->getRenderPassRenderArea(), 0.0f, 1.0f);
const gl::State &glState = contextVk->getGLState();
......@@ -654,75 +650,17 @@ gl::Error FramebufferVk::clearWithDraw(ContextVk *contextVk, VkColorComponentFla
}
vk::PipelineAndSerial *pipeline = nullptr;
ANGLE_TRY(renderer->getInternalPipeline(*fullScreenQuad, *uniformColor, *pipelineLayout,
ANGLE_TRY(renderer->getInternalPipeline(*fullScreenQuad, *pushConstantColor, *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());
VkClearColorValue clearColorValue = contextVk->getClearColorValue().color;
drawCommandBuffer->pushConstants(*pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
sizeof(VkClearColorValue), clearColorValue.float32);
// 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.
......
......@@ -116,10 +116,6 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
VkColorComponentFlags mActiveColorComponents;
gl::DrawBufferMask mActiveColorComponentMasks[4];
// For use in masked clear.
vk::BufferAndMemory mMaskedClearUniformBuffer;
VkDescriptorSet mMaskedClearDescriptorSet;
vk::DynamicBuffer mReadPixelsBuffer;
};
......
......@@ -220,7 +220,7 @@ RendererVk::~RendererVk()
}
mGraphicsPipelineLayout.destroy(mDevice);
mInternalUniformPipelineLayout.destroy(mDevice);
mInternalPushConstantPipelineLayout.destroy(mDevice);
mRenderPassCache.destroy(mDevice);
mPipelineCache.destroy(mDevice);
......@@ -952,30 +952,30 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
return vk::NoError();
}
const vk::DescriptorSetLayout &RendererVk::getInternalUniformDescriptorSetLayout() const
vk::Error RendererVk::getInternalPushConstantPipelineLayout(
const vk::PipelineLayout **pipelineLayoutOut)
{
return mGraphicsDescriptorSetLayouts[0];
}
vk::Error RendererVk::getInternalUniformPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut)
{
*pipelineLayoutOut = &mInternalUniformPipelineLayout;
if (mInternalUniformPipelineLayout.valid())
*pipelineLayoutOut = &mInternalPushConstantPipelineLayout;
if (mInternalPushConstantPipelineLayout.valid())
{
return vk::NoError();
}
// Here we use the knowledge that the "graphics" descriptor set has uniform blocks at offset 0.
VkPushConstantRange pushConstantRange;
pushConstantRange.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(VkClearColorValue);
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;
createInfo.setLayoutCount = 0;
createInfo.pSetLayouts = nullptr;
createInfo.pushConstantRangeCount = 1;
createInfo.pPushConstantRanges = &pushConstantRange;
ANGLE_TRY(mInternalUniformPipelineLayout.init(mDevice, createInfo));
ANGLE_TRY(mInternalPushConstantPipelineLayout.init(mDevice, createInfo));
return vk::NoError();
}
......
......@@ -135,8 +135,7 @@ class RendererVk : angle::NonCopyable
const std::vector<vk::DescriptorSetLayout> &getGraphicsDescriptorSetLayouts() const;
// Used in internal shaders.
vk::Error getInternalUniformPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut);
const vk::DescriptorSetLayout &getInternalUniformDescriptorSetLayout() const;
vk::Error getInternalPushConstantPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut);
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial();
......@@ -203,7 +202,7 @@ class RendererVk : angle::NonCopyable
std::vector<vk::DescriptorSetLayout> mGraphicsDescriptorSetLayouts;
// Used for internal shaders.
vk::PipelineLayout mInternalUniformPipelineLayout;
vk::PipelineLayout mInternalPushConstantPipelineLayout;
// Internal shader library.
vk::ShaderLibrary mShaderLibrary;
......
// Overload400-PrecQual.2000 12-Apr-2017
#pragma once
const uint32_t kUniformColor_frag[] = {
const uint32_t kPushConstantColor_frag[] = {
0x07230203,0x00010000,0x00080002,0x00000012,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004,
......@@ -8,13 +8,12 @@ const uint32_t kUniformColor_frag[] = {
0x00050005,0x00000009,0x6f6c6f63,0x74754f72,0x00000000,0x00040005,0x0000000a,0x636f6c62,
0x0000006b,0x00050006,0x0000000a,0x00000000,0x6f6c6f63,0x006e4972,0x00030005,0x0000000c,
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00050048,0x0000000a,0x00000000,
0x00000023,0x00000000,0x00030047,0x0000000a,0x00000002,0x00040047,0x0000000c,0x00000022,
0x00000000,0x00040047,0x0000000c,0x00000021,0x00000001,0x00020013,0x00000002,0x00030021,
0x00000023,0x00000000,0x00030047,0x0000000a,0x00000002,0x00020013,0x00000002,0x00030021,
0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,
0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,0x00000009,
0x00000003,0x0003001e,0x0000000a,0x00000007,0x00040020,0x0000000b,0x00000002,0x0000000a,
0x0004003b,0x0000000b,0x0000000c,0x00000002,0x00040015,0x0000000d,0x00000020,0x00000001,
0x0004002b,0x0000000d,0x0000000e,0x00000000,0x00040020,0x0000000f,0x00000002,0x00000007,
0x00000003,0x0003001e,0x0000000a,0x00000007,0x00040020,0x0000000b,0x00000009,0x0000000a,
0x0004003b,0x0000000b,0x0000000c,0x00000009,0x00040015,0x0000000d,0x00000020,0x00000001,
0x0004002b,0x0000000d,0x0000000e,0x00000000,0x00040020,0x0000000f,0x00000009,0x00000007,
0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,
0x0000000f,0x00000010,0x0000000c,0x0000000e,0x0004003d,0x00000007,0x00000011,0x00000010,
0x0003003e,0x00000009,0x00000011,0x000100fd,0x00010038
......
......@@ -3,11 +3,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UniformColor.frag: Simple solid color fragment shader.
// PushConstantColor.frag: Simple solid color fragment shader.
#version 450 core
layout(set = 0, binding = 1) uniform block {
layout(push_constant) uniform block {
vec4 colorIn;
};
......
......@@ -21,10 +21,10 @@ namespace priv
namespace
{
#include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/UniformColor.frag.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/PushConstantColor.frag.inc"
constexpr ShaderBlob kShaderBlobs[] = {{kFullScreenQuad_vert, sizeof(kFullScreenQuad_vert)},
{kUniformColor_frag, sizeof(kUniformColor_frag)}};
{kPushConstantColor_frag, sizeof(kPushConstantColor_frag)}};
} // anonymous namespace
const ShaderBlob &GetInternalShaderBlob(InternalShaderID shaderID)
......
......@@ -10,5 +10,5 @@
angle_vulkan_internal_shaders = [
"shaders/gen/FullScreenQuad.vert.inc",
"shaders/gen/UniformColor.frag.inc",
"shaders/gen/PushConstantColor.frag.inc",
]
......@@ -23,7 +23,7 @@ namespace vk
enum class InternalShaderID
{
FullScreenQuad_vert,
UniformColor_frag,
PushConstantColor_frag,
EnumCount
};
......
......@@ -596,6 +596,16 @@ void CommandBuffer::updateBuffer(const vk::Buffer &buffer,
vkCmdUpdateBuffer(mHandle, buffer.getHandle(), dstOffset, dataSize, data);
}
void CommandBuffer::pushConstants(const PipelineLayout &layout,
VkShaderStageFlags flag,
uint32_t offset,
uint32_t size,
const void *data)
{
ASSERT(valid() && layout.valid());
vkCmdPushConstants(mHandle, layout.getHandle(), flag, offset, size, data);
}
// Image implementation.
Image::Image()
{
......
......@@ -405,6 +405,11 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void *data);
void pushConstants(const PipelineLayout &layout,
VkShaderStageFlags flag,
uint32_t offset,
uint32_t size,
const void *data);
};
class Image final : public WrappedObject<Image, VkImage>
......
......@@ -480,10 +480,6 @@ TEST_P(ScissoredClearTest, ScissoredColorAndDepthClear)
// Tests combined color+depth clear.
TEST_P(ClearTest, MaskedColorAndDepthClear)
{
// Possible Intel driver bug on Intel 630.
// TODO(jmadill): Re-enable when possible. http://anglebug.com/2547
ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsVulkan());
// Flaky on Android Nexus 5x, possible driver bug.
// TODO(jmadill): Re-enable when possible. http://anglebug.com/2548
ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());
......
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