Commit f2f6d379 by Jamie Madill Committed by Commit Bot

Vulkan: Add PipelineDesc.

The PipelineDesc class is a 512-byte packed description of the entire Vulkan pipeline state. It uses the alignas keyword and some static asserts to verify that the structures are packed. This ensures that when ANGLE uses MurmurHash to hash the entire struct, and memcmp to check for identity, that there are no garbage padding bits. This CL does not implement the Pipeline cache, but it will help, since now we have a packed type that can be used as the key to a hash map. Bug: angleproject:2163 Change-Id: I16efa927f08d30d89a9c4c8943edd211c6878ac8 Reviewed-on: https://chromium-review.googlesource.com/829893 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent b0accd45
......@@ -71,6 +71,10 @@ class Serial final
{
return mValue != kInvalid && mValue == other.mValue;
}
constexpr bool operator==(uint32_t value) const
{
return mValue != kInvalid && mValue == static_cast<uint64_t>(value);
}
constexpr bool operator!=(const Serial &other) const
{
return mValue == kInvalid || mValue != other.mValue;
......@@ -80,6 +84,11 @@ class Serial final
constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
constexpr bool operator<=(const Serial &other) const { return mValue <= other.mValue; }
constexpr bool operator<(uint32_t value) const { return mValue < static_cast<uint64_t>(value); }
// Useful for serialization.
constexpr uint64_t getValue() const { return mValue; }
private:
friend class SerialFactory;
constexpr explicit Serial(uint64_t value) : mValue(value) {}
......
......@@ -170,21 +170,9 @@ class ContextVk : public ContextImpl, public ResourceVk
vk::Pipeline mCurrentPipeline;
GLenum mCurrentDrawMode;
// Keep CreateInfo structures cached so that we can quickly update them when creating
// updated pipelines. When we move to a pipeline cache, we will want to use a more compact
// structure that we can use to query the pipeline cache in the Renderer.
// TODO(jmadill): Update this when we move to a pipeline cache.
VkPipelineShaderStageCreateInfo mCurrentShaderStages[2];
VkPipelineVertexInputStateCreateInfo mCurrentVertexInputState;
VkPipelineInputAssemblyStateCreateInfo mCurrentInputAssemblyState;
VkViewport mCurrentViewportVk;
VkRect2D mCurrentScissorVk;
VkPipelineViewportStateCreateInfo mCurrentViewportState;
VkPipelineRasterizationStateCreateInfo mCurrentRasterState;
VkPipelineMultisampleStateCreateInfo mCurrentMultisampleState;
VkPipelineColorBlendAttachmentState mCurrentBlendAttachmentState;
VkPipelineColorBlendStateCreateInfo mCurrentBlendState;
VkGraphicsPipelineCreateInfo mCurrentPipelineInfo;
// Keep a cached pipeline description structure that can be used to query the pipeline cache.
// Kept in a pointer so allocations can be aligned, and structs can be portably packed.
std::unique_ptr<vk::PipelineDesc> mPipelineDesc;
// The descriptor pool is externally sychronized, so cannot be accessed from different threads
// simulataneously. Hence, we keep it in the ContextVk instead of the RendererVk.
......
......@@ -167,6 +167,8 @@ void ProgramVk::reset(VkDevice device)
mLinkedFragmentModule.destroy(device);
mLinkedVertexModule.destroy(device);
mVertexModuleSerial = Serial();
mFragmentModuleSerial = Serial();
// Descriptor Sets are pool allocated, so do not need to be explicitly freed.
mDescriptorSets.clear();
......@@ -228,6 +230,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
vertexShaderInfo.pCode = vertexCode.data();
ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
mVertexModuleSerial = renderer->issueProgramSerial();
}
{
......@@ -239,6 +242,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
fragmentShaderInfo.pCode = fragmentCode.data();
ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
mFragmentModuleSerial = renderer->issueProgramSerial();
}
ANGLE_TRY(initDescriptorSets(contextVk));
......@@ -546,12 +550,22 @@ const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
return mLinkedVertexModule;
}
Serial ProgramVk::getVertexModuleSerial() const
{
return mVertexModuleSerial;
}
const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
{
ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
return mLinkedFragmentModule;
}
Serial ProgramVk::getFragmentModuleSerial() const
{
return mFragmentModuleSerial;
}
vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
{
ASSERT(mDescriptorSets.empty());
......
......@@ -100,7 +100,9 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override;
const vk::ShaderModule &getLinkedVertexModule() const;
Serial getVertexModuleSerial() const;
const vk::ShaderModule &getLinkedFragmentModule() const;
Serial getFragmentModuleSerial() const;
vk::Error updateUniforms(ContextVk *contextVk);
......@@ -127,7 +129,9 @@ class ProgramVk : public ProgramImpl
void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType);
vk::ShaderModule mLinkedVertexModule;
Serial mVertexModuleSerial;
vk::ShaderModule mLinkedFragmentModule;
Serial mFragmentModuleSerial;
// State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable
......
......@@ -1070,4 +1070,10 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
return vk::NoError();
}
Serial RendererVk::issueProgramSerial()
{
return mProgramSerialFactory.generate();
}
} // namespace rx
......@@ -147,6 +147,9 @@ class RendererVk : angle::NonCopyable
const vk::PipelineLayout &getGraphicsPipelineLayout() const;
const std::vector<vk::DescriptorSetLayout> &getGraphicsDescriptorSetLayouts() const;
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueProgramSerial();
private:
vk::Error initializeDevice(uint32_t queueFamilyIndex);
void ensureCapsInitialized() const;
......@@ -179,6 +182,7 @@ class RendererVk : angle::NonCopyable
vk::CommandPool mCommandPool;
GlslangWrapper *mGlslangWrapper;
SerialFactory mQueueSerialFactory;
SerialFactory mProgramSerialFactory;
Serial mLastCompletedQueueSerial;
Serial mCurrentQueueSerial;
......
......@@ -29,8 +29,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
{
mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
mCurrentArrayBufferResources.fill(nullptr);
mCurrentVertexBindingDescs.reserve(state.getMaxAttribs());
mCurrentVertexAttribDescs.reserve(state.getMaxAttribs());
}
VertexArrayVk::~VertexArrayVk()
......@@ -131,11 +129,10 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode,
void VertexArrayVk::invalidateVertexDescriptions()
{
mCurrentVertexDescsValid = false;
mCurrentVertexBindingDescs.clear();
mCurrentVertexAttribDescs.clear();
}
void VertexArrayVk::updateVertexDescriptions(const gl::Context *context)
void VertexArrayVk::updateVertexDescriptions(const gl::Context *context,
vk::PipelineDesc *pipelineDesc)
{
if (mCurrentVertexDescsValid)
{
......@@ -147,29 +144,16 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context)
const gl::Program *programGL = context->getGLState().getProgram();
pipelineDesc->resetVertexInputState();
for (auto attribIndex : programGL->getActiveAttribLocationsMask())
{
const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled)
{
VkVertexInputBindingDescription bindingDesc;
bindingDesc.binding = static_cast<uint32_t>(mCurrentVertexBindingDescs.size());
bindingDesc.stride = static_cast<uint32_t>(gl::ComputeVertexAttributeTypeSize(attrib));
bindingDesc.inputRate = (binding.getDivisor() > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE
: VK_VERTEX_INPUT_RATE_VERTEX);
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
VkVertexInputAttributeDescription attribDesc;
attribDesc.binding = bindingDesc.binding;
attribDesc.format = vk::GetNativeVertexFormat(vertexFormatType);
attribDesc.location = static_cast<uint32_t>(attribIndex);
attribDesc.offset =
static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
mCurrentVertexBindingDescs.push_back(bindingDesc);
mCurrentVertexAttribDescs.push_back(attribDesc);
pipelineDesc->updateVertexInputInfo(static_cast<uint32_t>(attribIndex), binding,
attrib);
}
else
{
......@@ -180,14 +164,4 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context)
mCurrentVertexDescsValid = true;
}
const std::vector<VkVertexInputBindingDescription> &VertexArrayVk::getVertexBindingDescs() const
{
return mCurrentVertexBindingDescs;
}
const std::vector<VkVertexInputAttributeDescription> &VertexArrayVk::getVertexAttribDescs() const
{
return mCurrentVertexAttribDescs;
}
} // namespace rx
......@@ -36,10 +36,7 @@ class VertexArrayVk : public VertexArrayImpl
DrawType drawType);
void invalidateVertexDescriptions();
void updateVertexDescriptions(const gl::Context *context);
const std::vector<VkVertexInputBindingDescription> &getVertexBindingDescs() const;
const std::vector<VkVertexInputAttributeDescription> &getVertexAttribDescs() const;
void updateVertexDescriptions(const gl::Context *context, vk::PipelineDesc *pipelineDesc);
private:
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
......@@ -49,8 +46,6 @@ class VertexArrayVk : public VertexArrayImpl
// Keep a cache of binding and attribute descriptions for easy pipeline updates.
// TODO(jmadill): Update this when we support pipeline caching.
bool mCurrentVertexDescsValid;
std::vector<VkVertexInputBindingDescription> mCurrentVertexBindingDescs;
std::vector<VkVertexInputAttributeDescription> mCurrentVertexAttribDescs;
};
} // namespace rx
......
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