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 ...@@ -71,6 +71,10 @@ class Serial final
{ {
return mValue != kInvalid && mValue == other.mValue; 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 constexpr bool operator!=(const Serial &other) const
{ {
return mValue == kInvalid || mValue != other.mValue; return mValue == kInvalid || mValue != other.mValue;
...@@ -80,6 +84,11 @@ class Serial final ...@@ -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<=(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: private:
friend class SerialFactory; friend class SerialFactory;
constexpr explicit Serial(uint64_t value) : mValue(value) {} constexpr explicit Serial(uint64_t value) : mValue(value) {}
......
...@@ -170,21 +170,9 @@ class ContextVk : public ContextImpl, public ResourceVk ...@@ -170,21 +170,9 @@ class ContextVk : public ContextImpl, public ResourceVk
vk::Pipeline mCurrentPipeline; vk::Pipeline mCurrentPipeline;
GLenum mCurrentDrawMode; GLenum mCurrentDrawMode;
// Keep CreateInfo structures cached so that we can quickly update them when creating // Keep a cached pipeline description structure that can be used to query the pipeline cache.
// updated pipelines. When we move to a pipeline cache, we will want to use a more compact // Kept in a pointer so allocations can be aligned, and structs can be portably packed.
// structure that we can use to query the pipeline cache in the Renderer. std::unique_ptr<vk::PipelineDesc> mPipelineDesc;
// 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;
// The descriptor pool is externally sychronized, so cannot be accessed from different threads // 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. // simulataneously. Hence, we keep it in the ContextVk instead of the RendererVk.
......
...@@ -167,6 +167,8 @@ void ProgramVk::reset(VkDevice device) ...@@ -167,6 +167,8 @@ void ProgramVk::reset(VkDevice device)
mLinkedFragmentModule.destroy(device); mLinkedFragmentModule.destroy(device);
mLinkedVertexModule.destroy(device); mLinkedVertexModule.destroy(device);
mVertexModuleSerial = Serial();
mFragmentModuleSerial = Serial();
// Descriptor Sets are pool allocated, so do not need to be explicitly freed. // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
mDescriptorSets.clear(); mDescriptorSets.clear();
...@@ -228,6 +230,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -228,6 +230,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
vertexShaderInfo.pCode = vertexCode.data(); vertexShaderInfo.pCode = vertexCode.data();
ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo)); ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
mVertexModuleSerial = renderer->issueProgramSerial();
} }
{ {
...@@ -239,6 +242,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -239,6 +242,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
fragmentShaderInfo.pCode = fragmentCode.data(); fragmentShaderInfo.pCode = fragmentCode.data();
ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo)); ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
mFragmentModuleSerial = renderer->issueProgramSerial();
} }
ANGLE_TRY(initDescriptorSets(contextVk)); ANGLE_TRY(initDescriptorSets(contextVk));
...@@ -546,12 +550,22 @@ const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const ...@@ -546,12 +550,22 @@ const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
return mLinkedVertexModule; return mLinkedVertexModule;
} }
Serial ProgramVk::getVertexModuleSerial() const
{
return mVertexModuleSerial;
}
const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
{ {
ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE); ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
return mLinkedFragmentModule; return mLinkedFragmentModule;
} }
Serial ProgramVk::getFragmentModuleSerial() const
{
return mFragmentModuleSerial;
}
vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk) vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
{ {
ASSERT(mDescriptorSets.empty()); ASSERT(mDescriptorSets.empty());
......
...@@ -100,7 +100,9 @@ class ProgramVk : public ProgramImpl ...@@ -100,7 +100,9 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override; const GLfloat *coeffs) override;
const vk::ShaderModule &getLinkedVertexModule() const; const vk::ShaderModule &getLinkedVertexModule() const;
Serial getVertexModuleSerial() const;
const vk::ShaderModule &getLinkedFragmentModule() const; const vk::ShaderModule &getLinkedFragmentModule() const;
Serial getFragmentModuleSerial() const;
vk::Error updateUniforms(ContextVk *contextVk); vk::Error updateUniforms(ContextVk *contextVk);
...@@ -127,7 +129,9 @@ class ProgramVk : public ProgramImpl ...@@ -127,7 +129,9 @@ class ProgramVk : public ProgramImpl
void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType); void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType);
vk::ShaderModule mLinkedVertexModule; vk::ShaderModule mLinkedVertexModule;
Serial mVertexModuleSerial;
vk::ShaderModule mLinkedFragmentModule; vk::ShaderModule mLinkedFragmentModule;
Serial mFragmentModuleSerial;
// State for the default uniform blocks. // State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable struct DefaultUniformBlock final : private angle::NonCopyable
......
...@@ -1070,4 +1070,10 @@ vk::Error RendererVk::initGraphicsPipelineLayout() ...@@ -1070,4 +1070,10 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
return vk::NoError(); return vk::NoError();
} }
Serial RendererVk::issueProgramSerial()
{
return mProgramSerialFactory.generate();
}
} // namespace rx } // namespace rx
...@@ -147,6 +147,9 @@ class RendererVk : angle::NonCopyable ...@@ -147,6 +147,9 @@ 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;
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueProgramSerial();
private: private:
vk::Error initializeDevice(uint32_t queueFamilyIndex); vk::Error initializeDevice(uint32_t queueFamilyIndex);
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
...@@ -179,6 +182,7 @@ class RendererVk : angle::NonCopyable ...@@ -179,6 +182,7 @@ class RendererVk : angle::NonCopyable
vk::CommandPool mCommandPool; vk::CommandPool mCommandPool;
GlslangWrapper *mGlslangWrapper; GlslangWrapper *mGlslangWrapper;
SerialFactory mQueueSerialFactory; SerialFactory mQueueSerialFactory;
SerialFactory mProgramSerialFactory;
Serial mLastCompletedQueueSerial; Serial mLastCompletedQueueSerial;
Serial mCurrentQueueSerial; Serial mCurrentQueueSerial;
......
...@@ -29,8 +29,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state) ...@@ -29,8 +29,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
{ {
mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE); mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
mCurrentArrayBufferResources.fill(nullptr); mCurrentArrayBufferResources.fill(nullptr);
mCurrentVertexBindingDescs.reserve(state.getMaxAttribs());
mCurrentVertexAttribDescs.reserve(state.getMaxAttribs());
} }
VertexArrayVk::~VertexArrayVk() VertexArrayVk::~VertexArrayVk()
...@@ -131,11 +129,10 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode, ...@@ -131,11 +129,10 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandBufferNode *readNode,
void VertexArrayVk::invalidateVertexDescriptions() void VertexArrayVk::invalidateVertexDescriptions()
{ {
mCurrentVertexDescsValid = false; 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) if (mCurrentVertexDescsValid)
{ {
...@@ -147,29 +144,16 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context) ...@@ -147,29 +144,16 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context)
const gl::Program *programGL = context->getGLState().getProgram(); const gl::Program *programGL = context->getGLState().getProgram();
pipelineDesc->resetVertexInputState();
for (auto attribIndex : programGL->getActiveAttribLocationsMask()) for (auto attribIndex : programGL->getActiveAttribLocationsMask())
{ {
const auto &attrib = attribs[attribIndex]; const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex]; const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled) if (attrib.enabled)
{ {
VkVertexInputBindingDescription bindingDesc; pipelineDesc->updateVertexInputInfo(static_cast<uint32_t>(attribIndex), binding,
bindingDesc.binding = static_cast<uint32_t>(mCurrentVertexBindingDescs.size()); attrib);
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);
} }
else else
{ {
...@@ -180,14 +164,4 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context) ...@@ -180,14 +164,4 @@ void VertexArrayVk::updateVertexDescriptions(const gl::Context *context)
mCurrentVertexDescsValid = true; mCurrentVertexDescsValid = true;
} }
const std::vector<VkVertexInputBindingDescription> &VertexArrayVk::getVertexBindingDescs() const
{
return mCurrentVertexBindingDescs;
}
const std::vector<VkVertexInputAttributeDescription> &VertexArrayVk::getVertexAttribDescs() const
{
return mCurrentVertexAttribDescs;
}
} // namespace rx } // namespace rx
...@@ -36,10 +36,7 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -36,10 +36,7 @@ class VertexArrayVk : public VertexArrayImpl
DrawType drawType); DrawType drawType);
void invalidateVertexDescriptions(); void invalidateVertexDescriptions();
void updateVertexDescriptions(const gl::Context *context); void updateVertexDescriptions(const gl::Context *context, vk::PipelineDesc *pipelineDesc);
const std::vector<VkVertexInputBindingDescription> &getVertexBindingDescs() const;
const std::vector<VkVertexInputAttributeDescription> &getVertexAttribDescs() const;
private: private:
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles; gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
...@@ -49,8 +46,6 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -49,8 +46,6 @@ class VertexArrayVk : public VertexArrayImpl
// Keep a cache of binding and attribute descriptions for easy pipeline updates. // Keep a cache of binding and attribute descriptions for easy pipeline updates.
// TODO(jmadill): Update this when we support pipeline caching. // TODO(jmadill): Update this when we support pipeline caching.
bool mCurrentVertexDescsValid; bool mCurrentVertexDescsValid;
std::vector<VkVertexInputBindingDescription> mCurrentVertexBindingDescs;
std::vector<VkVertexInputAttributeDescription> mCurrentVertexAttribDescs;
}; };
} // namespace rx } // 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