Commit 9b168d02 by Jamie Madill Committed by Commit Bot

Vulkan: Store Pipeline/DS Layouts in ProgramVk.

We can keep a shared reference to the Pipeline and Descriptor Set layouts in the Program. This ensures they are not in use when they are deleted. Note that they are allowed to be deleted as long as no command buffers are currently recording with them. If the Program is deleted then there should be no further commands using these layouts. Bug: angleproject:2462 Change-Id: I75161b3ce1ee8eae33dd6becee79b4262b844cdd Reviewed-on: https://chromium-review.googlesource.com/1089807 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent c7918ceb
...@@ -125,11 +125,9 @@ gl::Error ContextVk::initPipeline() ...@@ -125,11 +125,9 @@ gl::Error ContextVk::initPipeline()
// Ensure that the RenderPass description is updated. // Ensure that the RenderPass description is updated.
mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc()); mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc());
const vk::PipelineLayout &pipelineLayout = mRenderer->getGraphicsPipelineLayout();
// TODO(jmadill): Validate with ASSERT against physical device limits/caps? // TODO(jmadill): Validate with ASSERT against physical device limits/caps?
ANGLE_TRY(mRenderer->getAppPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask, ANGLE_TRY(mRenderer->getAppPipeline(programVk, *mPipelineDesc, activeAttribLocationsMask,
pipelineLayout, &mCurrentPipeline)); &mCurrentPipeline));
return gl::NoError(); return gl::NoError();
} }
...@@ -216,7 +214,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -216,7 +214,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
if (!usedRange.empty()) if (!usedRange.empty())
{ {
ASSERT(!descriptorSets.empty()); ASSERT(!descriptorSets.empty());
const vk::PipelineLayout &pipelineLayout = mRenderer->getGraphicsPipelineLayout(); const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
(*commandBufferOut) (*commandBufferOut)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, usedRange.low(), ->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, usedRange.low(),
......
...@@ -172,6 +172,12 @@ vk::Error ProgramVk::reset(ContextVk *contextVk) ...@@ -172,6 +172,12 @@ vk::Error ProgramVk::reset(ContextVk *contextVk)
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{
descriptorSetLayout.reset();
}
mPipelineLayout.reset();
for (auto &uniformBlock : mDefaultUniformBlocks) for (auto &uniformBlock : mDefaultUniformBlocks)
{ {
uniformBlock.storage.destroy(device); uniformBlock.storage.destroy(device);
...@@ -266,10 +272,40 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -266,10 +272,40 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
if (!mState.getSamplerUniformRange().empty()) if (!mState.getSamplerUniformRange().empty())
{ {
// Ensure the descriptor set range includes the textures at position 1. // Ensure the descriptor set range includes the textures at position 1.
mUsedDescriptorSetRange.extend(1); mUsedDescriptorSetRange.extend(kTextureDescriptorSetIndex);
mDirtyTextures = true; mDirtyTextures = true;
} }
// Store a reference to the pipeline and descriptor set layouts. This will create them if they
// don't already exist in the cache.
vk::DescriptorSetLayoutDesc uniformsSetDesc;
uniformsSetDesc.update(kVertexUniformsBindingIndex, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
1);
uniformsSetDesc.update(kFragmentUniformsBindingIndex, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
1);
ANGLE_TRY(renderer->getDescriptorSetLayout(
uniformsSetDesc, &mDescriptorSetLayouts[kUniformsDescriptorSetIndex]));
const uint32_t maxTextures = renderer->getMaxActiveTextures();
vk::DescriptorSetLayoutDesc texturesSetDesc;
for (uint32_t textureIndex = 0; textureIndex < maxTextures; ++textureIndex)
{
// TODO(jmadll): Sampler arrays. http://anglebug.com/2462
texturesSetDesc.update(textureIndex, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1);
}
ANGLE_TRY(renderer->getDescriptorSetLayout(texturesSetDesc,
&mDescriptorSetLayouts[kTextureDescriptorSetIndex]));
vk::PipelineLayoutDesc pipelineLayoutDesc;
pipelineLayoutDesc.updateDescriptorSetLayout(kUniformsDescriptorSetIndex, uniformsSetDesc);
pipelineLayoutDesc.updateDescriptorSetLayout(kTextureDescriptorSetIndex, texturesSetDesc);
ANGLE_TRY(
renderer->getPipelineLayout(pipelineLayoutDesc, mDescriptorSetLayouts, &mPipelineLayout));
return true; return true;
} }
...@@ -701,8 +737,6 @@ Serial ProgramVk::getFragmentModuleSerial() const ...@@ -701,8 +737,6 @@ Serial ProgramVk::getFragmentModuleSerial() const
vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex) vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex)
{ {
RendererVk *renderer = contextVk->getRenderer();
// Write out to a new a descriptor set. // Write out to a new a descriptor set.
vk::DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool(); vk::DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
...@@ -713,8 +747,7 @@ vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descri ...@@ -713,8 +747,7 @@ vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descri
} }
const vk::DescriptorSetLayout &descriptorSetLayout = const vk::DescriptorSetLayout &descriptorSetLayout =
renderer->getGraphicsDescriptorSetLayout(descriptorSetIndex); mDescriptorSetLayouts[descriptorSetIndex].get();
ANGLE_TRY(dynamicDescriptorPool->allocateDescriptorSets(contextVk, descriptorSetLayout.ptr(), 1, ANGLE_TRY(dynamicDescriptorPool->allocateDescriptorSets(contextVk, descriptorSetLayout.ptr(), 1,
&mDescriptorSets[descriptorSetIndex])); &mDescriptorSets[descriptorSetIndex]));
return vk::NoError(); return vk::NoError();
...@@ -925,6 +958,11 @@ void ProgramVk::invalidateTextures() ...@@ -925,6 +958,11 @@ void ProgramVk::invalidateTextures()
mDirtyTextures = true; mDirtyTextures = true;
} }
const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
{
return mPipelineLayout.get();
}
void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
{ {
for (DefaultUniformBlock &block : mDefaultUniformBlocks) for (DefaultUniformBlock &block : mDefaultUniformBlocks)
......
...@@ -121,6 +121,8 @@ class ProgramVk : public ProgramImpl ...@@ -121,6 +121,8 @@ class ProgramVk : public ProgramImpl
gl::Error updateTexturesDescriptorSet(const gl::Context *context); gl::Error updateTexturesDescriptorSet(const gl::Context *context);
void invalidateTextures(); void invalidateTextures();
const vk::PipelineLayout &getPipelineLayout() const;
// For testing only. // For testing only.
void setDefaultUniformBlocksMinSizeForTesting(size_t minSize); void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
...@@ -179,6 +181,11 @@ class ProgramVk : public ProgramImpl ...@@ -179,6 +181,11 @@ class ProgramVk : public ProgramImpl
template <typename T> template <typename T>
using ShaderTextureArray = std::array<T, gl::IMPLEMENTATION_MAX_SHADER_TEXTURES>; using ShaderTextureArray = std::array<T, gl::IMPLEMENTATION_MAX_SHADER_TEXTURES>;
// We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
// deleted while this program is in use.
vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
}; };
} // namespace rx } // namespace rx
......
...@@ -208,12 +208,6 @@ RendererVk::~RendererVk() ...@@ -208,12 +208,6 @@ RendererVk::~RendererVk()
} }
} }
for (auto &descriptorSetLayout : mGraphicsDescriptorSetLayouts)
{
descriptorSetLayout.reset();
}
mGraphicsPipelineLayout.reset();
mPipelineLayoutCache.destroy(mDevice); mPipelineLayoutCache.destroy(mDevice);
mDescriptorSetLayoutCache.destroy(mDevice); mDescriptorSetLayoutCache.destroy(mDevice);
...@@ -449,9 +443,6 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -449,9 +443,6 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps, mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps,
&mNativeCaps.compressedTextureFormats); &mNativeCaps.compressedTextureFormats);
// Initialize the pipeline layout for GL programs.
ANGLE_TRY(initGraphicsPipelineLayout());
return vk::NoError(); return vk::NoError();
} }
...@@ -843,51 +834,6 @@ vk::Error RendererVk::flush(const gl::Context *context, ...@@ -843,51 +834,6 @@ vk::Error RendererVk::flush(const gl::Context *context,
return vk::NoError(); return vk::NoError();
} }
const vk::PipelineLayout &RendererVk::getGraphicsPipelineLayout() const
{
return mGraphicsPipelineLayout.get();
}
const vk::DescriptorSetLayout &RendererVk::getGraphicsDescriptorSetLayout(uint32_t setIndex) const
{
return mGraphicsDescriptorSetLayouts[setIndex].get();
}
vk::Error RendererVk::initGraphicsPipelineLayout()
{
ASSERT(!mGraphicsPipelineLayout.valid());
// Create two descriptor set layouts: one for default uniform info, and one for textures.
vk::DescriptorSetLayoutDesc uniformsSetDesc;
uniformsSetDesc.update(kVertexUniformsBindingIndex, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
1);
uniformsSetDesc.update(kFragmentUniformsBindingIndex, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
1);
ANGLE_TRY(mDescriptorSetLayoutCache.getDescriptorSetLayout(mDevice, uniformsSetDesc,
&mGraphicsDescriptorSetLayouts[0]));
const uint32_t maxTextures = getMaxActiveTextures();
vk::DescriptorSetLayoutDesc texturesSetDesc;
for (uint32_t textureIndex = 0; textureIndex < maxTextures; ++textureIndex)
{
// TODO(jmadll): Sampler arrays. http://anglebug.com/2462
texturesSetDesc.update(textureIndex, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1);
}
ANGLE_TRY(mDescriptorSetLayoutCache.getDescriptorSetLayout(mDevice, texturesSetDesc,
&mGraphicsDescriptorSetLayouts[1]));
vk::PipelineLayoutDesc pipelineLayoutDesc;
pipelineLayoutDesc.updateDescriptorSetLayout(kUniformsDescriptorSetIndex, uniformsSetDesc);
pipelineLayoutDesc.updateDescriptorSetLayout(kTextureDescriptorSetIndex, texturesSetDesc);
ANGLE_TRY(mPipelineLayoutCache.getPipelineLayout(
mDevice, pipelineLayoutDesc, mGraphicsDescriptorSetLayouts, &mGraphicsPipelineLayout));
return vk::NoError();
}
vk::Error RendererVk::getInternalPushConstantPipelineLayout( vk::Error RendererVk::getInternalPushConstantPipelineLayout(
const vk::PipelineLayout **pipelineLayoutOut) const vk::PipelineLayout **pipelineLayoutOut)
{ {
...@@ -924,7 +870,6 @@ Serial RendererVk::issueShaderSerial() ...@@ -924,7 +870,6 @@ Serial RendererVk::issueShaderSerial()
vk::Error RendererVk::getAppPipeline(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,
const vk::PipelineLayout &pipelineLayout,
vk::PipelineAndSerial **pipelineOut) vk::PipelineAndSerial **pipelineOut)
{ {
ASSERT(programVk->getVertexModuleSerial() == ASSERT(programVk->getVertexModuleSerial() ==
...@@ -936,6 +881,8 @@ vk::Error RendererVk::getAppPipeline(const ProgramVk *programVk, ...@@ -936,6 +881,8 @@ vk::Error RendererVk::getAppPipeline(const ProgramVk *programVk,
vk::RenderPass *compatibleRenderPass = nullptr; vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass)); ANGLE_TRY(getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass));
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
return mPipelineCache.getPipeline(mDevice, *compatibleRenderPass, pipelineLayout, return mPipelineCache.getPipeline(mDevice, *compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, programVk->getLinkedVertexModule(), activeAttribLocationsMask, programVk->getLinkedVertexModule(),
programVk->getLinkedFragmentModule(), desc, pipelineOut); programVk->getLinkedFragmentModule(), desc, pipelineOut);
...@@ -962,6 +909,22 @@ vk::Error RendererVk::getInternalPipeline(const vk::ShaderAndSerial &vertexShade ...@@ -962,6 +909,22 @@ vk::Error RendererVk::getInternalPipeline(const vk::ShaderAndSerial &vertexShade
fragmentShader.get(), pipelineDesc, pipelineOut); fragmentShader.get(), pipelineDesc, pipelineOut);
} }
vk::Error RendererVk::getDescriptorSetLayout(
const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
{
return mDescriptorSetLayoutCache.getDescriptorSetLayout(mDevice, desc, descriptorSetLayoutOut);
}
vk::Error RendererVk::getPipelineLayout(
const vk::PipelineLayoutDesc &desc,
const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut)
{
return mPipelineLayoutCache.getPipelineLayout(mDevice, desc, descriptorSetLayouts,
pipelineLayoutOut);
}
vk::ShaderLibrary *RendererVk::getShaderLibrary() vk::ShaderLibrary *RendererVk::getShaderLibrary()
{ {
return &mShaderLibrary; return &mShaderLibrary;
......
...@@ -108,7 +108,6 @@ class RendererVk : angle::NonCopyable ...@@ -108,7 +108,6 @@ class RendererVk : angle::NonCopyable
vk::Error getAppPipeline(const ProgramVk *programVk, vk::Error getAppPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc, const vk::PipelineDesc &desc,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
const vk::PipelineLayout &pipelineLayout,
vk::PipelineAndSerial **pipelineOut); vk::PipelineAndSerial **pipelineOut);
// For getting a vk::Pipeline for an internal draw call. Use an explicit RenderPass. // For getting a vk::Pipeline for an internal draw call. Use an explicit RenderPass.
...@@ -119,14 +118,20 @@ class RendererVk : angle::NonCopyable ...@@ -119,14 +118,20 @@ class RendererVk : angle::NonCopyable
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut); vk::PipelineAndSerial **pipelineOut);
// Queries the descriptor set layout cache. Creates the layout if not present.
vk::Error getDescriptorSetLayout(
const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
// Queries the pipeline layout cache. Creates the layout if not present.
vk::Error getPipelineLayout(const vk::PipelineLayoutDesc &desc,
const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut);
// 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.
vk::CommandGraph *getCommandGraph(); vk::CommandGraph *getCommandGraph();
// TODO(jmadill): Use PipelineLayout cache. http://anglebug.com/2462
const vk::PipelineLayout &getGraphicsPipelineLayout() const;
const vk::DescriptorSetLayout &getGraphicsDescriptorSetLayout(uint32_t setIndex) const;
// Used in internal shaders. // Used in internal shaders.
// TODO(jmadill): Use PipelineLayout cache. http://anglebug.com/2462 // TODO(jmadill): Use PipelineLayout cache. http://anglebug.com/2462
vk::Error getInternalPushConstantPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut); vk::Error getInternalPushConstantPipelineLayout(const vk::PipelineLayout **pipelineLayoutOut);
...@@ -143,7 +148,6 @@ class RendererVk : angle::NonCopyable ...@@ -143,7 +148,6 @@ class RendererVk : angle::NonCopyable
vk::Error checkInFlightCommands(); vk::Error checkInFlightCommands();
void freeAllInFlightResources(); void freeAllInFlightResources();
vk::Error flushCommandGraph(const gl::Context *context, vk::CommandBuffer *commandBatch); vk::Error flushCommandGraph(const gl::Context *context, vk::CommandBuffer *commandBatch);
vk::Error initGraphicsPipelineLayout();
mutable bool mCapsInitialized; mutable bool mCapsInitialized;
mutable gl::Caps mNativeCaps; mutable gl::Caps mNativeCaps;
...@@ -196,10 +200,6 @@ class RendererVk : angle::NonCopyable ...@@ -196,10 +200,6 @@ class RendererVk : angle::NonCopyable
// DescriptorSetLayouts are also managed in a cache. // DescriptorSetLayouts are also managed in a cache.
DescriptorSetLayoutCache mDescriptorSetLayoutCache; DescriptorSetLayoutCache mDescriptorSetLayoutCache;
// TODO(jmadill): Only use the pipeline layout cache. http://anglebug.com/2462
vk::BindingPointer<vk::PipelineLayout> mGraphicsPipelineLayout;
vk::DescriptorSetLayoutPointerArray mGraphicsDescriptorSetLayouts;
// Used for internal shaders. // Used for internal shaders.
// TODO(jmadill): Use PipelineLayout cache. http://anglebug.com/2462 // TODO(jmadill): Use PipelineLayout cache. http://anglebug.com/2462
vk::PipelineLayout mInternalPushConstantPipelineLayout; vk::PipelineLayout mInternalPushConstantPipelineLayout;
......
...@@ -83,9 +83,13 @@ class DynamicBuffer : angle::NonCopyable ...@@ -83,9 +83,13 @@ class DynamicBuffer : angle::NonCopyable
std::vector<BufferAndMemory> mRetainedBuffers; std::vector<BufferAndMemory> mRetainedBuffers;
}; };
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool // Uses DescriptorPool to allocate descriptor sets as needed. If a descriptor pool becomes full, we
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and // allocate new pools internally as needed. RendererVk takes care of the lifetime of the discarded
// leave the renderer take care of the life time of the pools that become unused. // pools. Note that we used a fixed layout for descriptor pools in ANGLE. Uniform buffers must
// use set zero and combined Image Samplers must use set 1. We conservatively count each new set
// using the maximum number of descriptor sets and buffers with each allocation. Currently: 2
// (Vertex/Fragment) uniform buffers and 64 (MAX_ACTIVE_TEXTURES) image/samplers.
class DynamicDescriptorPool final : angle::NonCopyable class DynamicDescriptorPool final : angle::NonCopyable
{ {
public: public:
......
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