Commit 8c3988c5 by Jamie Madill Committed by Commit Bot

Vulkan: Use one pipeline layout for all Programs.

This simplifies the pipeline state object caching. We will not need to use any extra bits to cache based on program properties - instead all programs will be compatible. The pipeline layout strucutre is described in the design docs. It currently only has two bind groups: the first for default uniforms, and the second for Textures. In the future we might re-organize this to handle driver uniforms, dynamic push constants, and/or program uniform buffers with ES 3.0. Instead of storing only the Textures that are required by a Program, we reserve space for the maximum possible Texture units. We might have to revisit this very simple design in the future to support texture arrays, which are handled specially in Vulkan. Bug: angleproject:2163 Change-Id: I3e1656c2c73045aed56838a5f1267b246a623362 Reviewed-on: https://chromium-review.googlesource.com/837943Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent bed35d76
...@@ -628,6 +628,12 @@ class Range ...@@ -628,6 +628,12 @@ class Range
T low() const { return mLow; } T low() const { return mLow; }
T high() const { return mHigh; } T high() const { return mHigh; }
void invalidate()
{
mLow = std::numeric_limits<T>::max();
mHigh = std::numeric_limits<T>::min();
}
private: private:
T mLow; T mLow;
T mHigh; T mHigh;
......
...@@ -259,10 +259,8 @@ gl::Error ContextVk::initPipeline(const gl::Context *context) ...@@ -259,10 +259,8 @@ gl::Error ContextVk::initPipeline(const gl::Context *context)
VkDevice device = mRenderer->getDevice(); VkDevice device = mRenderer->getDevice();
const auto &state = mState.getState(); const auto &state = mState.getState();
const gl::Program *programGL = state.getProgram();
const gl::VertexArray *vao = state.getVertexArray(); const gl::VertexArray *vao = state.getVertexArray();
const gl::Framebuffer *drawFBO = state.getDrawFramebuffer(); const gl::Framebuffer *drawFBO = state.getDrawFramebuffer();
ProgramVk *programVk = vk::GetImpl(programGL);
FramebufferVk *vkFBO = vk::GetImpl(drawFBO); FramebufferVk *vkFBO = vk::GetImpl(drawFBO);
VertexArrayVk *vkVAO = vk::GetImpl(vao); VertexArrayVk *vkVAO = vk::GetImpl(vao);
...@@ -288,7 +286,7 @@ gl::Error ContextVk::initPipeline(const gl::Context *context) ...@@ -288,7 +286,7 @@ gl::Error ContextVk::initPipeline(const gl::Context *context)
ANGLE_TRY(mRenderer->getCompatibleRenderPass(desc, &renderPass)); ANGLE_TRY(mRenderer->getCompatibleRenderPass(desc, &renderPass));
ASSERT(renderPass && renderPass->valid()); ASSERT(renderPass && renderPass->valid());
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout(); const vk::PipelineLayout &pipelineLayout = mRenderer->getGraphicsPipelineLayout();
ASSERT(pipelineLayout.valid()); ASSERT(pipelineLayout.valid());
mCurrentPipelineInfo.layout = pipelineLayout.getHandle(); mCurrentPipelineInfo.layout = pipelineLayout.getHandle();
...@@ -395,14 +393,14 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -395,14 +393,14 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
// Bind the graphics descriptor sets. // Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers. // TODO(jmadill): Handle multiple command buffers.
const auto &descriptorSets = programVk->getDescriptorSets(); const auto &descriptorSets = programVk->getDescriptorSets();
uint32_t firstSet = programVk->getDescriptorSetOffset(); const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange();
uint32_t setCount = static_cast<uint32_t>(descriptorSets.size()); if (!usedRange.empty())
if (!descriptorSets.empty() && ((setCount - firstSet) > 0))
{ {
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout(); ASSERT(!descriptorSets.empty());
const vk::PipelineLayout &pipelineLayout = mRenderer->getGraphicsPipelineLayout();
(*commandBuffer) (*commandBuffer)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, firstSet, ->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, usedRange.low(),
setCount - firstSet, &descriptorSets[firstSet], 0, nullptr); usedRange.length(), &descriptorSets[usedRange.low()], 0, nullptr);
} }
return gl::NoError(); return gl::NoError();
......
...@@ -139,8 +139,9 @@ ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() ...@@ -139,8 +139,9 @@ ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
} }
ProgramVk::ProgramVk(const gl::ProgramState &state) ProgramVk::ProgramVk(const gl::ProgramState &state)
: ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSetOffset(0), mDirtyTextures(true) : ProgramImpl(state), mDefaultUniformBlocks(), mUsedDescriptorSetRange(), mDirtyTextures(true)
{ {
mUsedDescriptorSetRange.invalidate();
} }
ProgramVk::~ProgramVk() ProgramVk::~ProgramVk()
...@@ -164,18 +165,12 @@ void ProgramVk::reset(VkDevice device) ...@@ -164,18 +165,12 @@ void ProgramVk::reset(VkDevice device)
mEmptyUniformBlockStorage.memory.destroy(device); mEmptyUniformBlockStorage.memory.destroy(device);
mEmptyUniformBlockStorage.buffer.destroy(device); mEmptyUniformBlockStorage.buffer.destroy(device);
for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{
descriptorSetLayout.destroy(device);
}
mLinkedFragmentModule.destroy(device); mLinkedFragmentModule.destroy(device);
mLinkedVertexModule.destroy(device); mLinkedVertexModule.destroy(device);
mPipelineLayout.destroy(device);
// 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();
mDescriptorSetOffset = 0; mUsedDescriptorSetRange.invalidate();
mDirtyTextures = false; mDirtyTextures = false;
} }
...@@ -246,10 +241,16 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -246,10 +241,16 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo)); ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
} }
ANGLE_TRY(initPipelineLayout(contextVk));
ANGLE_TRY(initDescriptorSets(contextVk)); ANGLE_TRY(initDescriptorSets(contextVk));
ANGLE_TRY(initDefaultUniformBlocks(glContext)); ANGLE_TRY(initDefaultUniformBlocks(glContext));
if (!mState.getSamplerUniformRange().empty())
{
// Ensure the descriptor set range includes the textures at position 1.
mUsedDescriptorSetRange.extend(1);
mDirtyTextures = true;
}
return true; return true;
} }
...@@ -358,11 +359,9 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) ...@@ -358,11 +359,9 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
} }
ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk)); ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
}
else // Ensure the descriptor set range includes the uniform buffers at position 0.
{ mUsedDescriptorSetRange.extend(0);
// If the program has no uniforms, note this in the offset.
mDescriptorSetOffset = 1;
} }
return gl::NoError(); return gl::NoError();
...@@ -553,145 +552,27 @@ const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const ...@@ -553,145 +552,27 @@ const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
return mLinkedFragmentModule; return mLinkedFragmentModule;
} }
const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
{
return mPipelineLayout;
}
vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
{
ASSERT(!mPipelineLayout.valid());
VkDevice device = context->getDevice();
// Create two descriptor set layouts: one for default uniform info, and one for textures.
// Skip one or both if there are no uniforms.
VkDescriptorSetLayoutBinding uniformBindings[2];
uint32_t blockCount = 0;
{
auto &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
layoutBinding.pImmutableSamplers = nullptr;
blockCount++;
}
{
auto &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
layoutBinding.pImmutableSamplers = nullptr;
blockCount++;
}
{
VkDescriptorSetLayoutCreateInfo uniformInfo;
uniformInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
uniformInfo.pNext = nullptr;
uniformInfo.flags = 0;
uniformInfo.bindingCount = blockCount;
uniformInfo.pBindings = uniformBindings;
vk::DescriptorSetLayout uniformLayout;
ANGLE_TRY(uniformLayout.init(device, uniformInfo));
mDescriptorSetLayouts.push_back(std::move(uniformLayout));
}
const auto &samplerBindings = mState.getSamplerBindings();
if (!samplerBindings.empty())
{
std::vector<VkDescriptorSetLayoutBinding> textureBindings;
uint32_t textureCount = 0;
const auto &uniforms = mState.getUniforms();
for (unsigned int uniformIndex : mState.getSamplerUniformRange())
{
const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
unsigned int samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformIndex);
const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
ASSERT(!samplerBinding.unreferenced);
VkDescriptorSetLayoutBinding layoutBinding;
uint32_t elementCount = samplerUniform.getBasicTypeElementCount();
layoutBinding.binding = textureCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
layoutBinding.descriptorCount = elementCount;
layoutBinding.stageFlags = 0;
if (samplerUniform.vertexStaticUse)
{
layoutBinding.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
}
if (samplerUniform.fragmentStaticUse)
{
layoutBinding.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
layoutBinding.pImmutableSamplers = nullptr;
textureCount += elementCount;
textureBindings.push_back(layoutBinding);
}
VkDescriptorSetLayoutCreateInfo textureInfo;
textureInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
textureInfo.pNext = nullptr;
textureInfo.flags = 0;
textureInfo.bindingCount = static_cast<uint32_t>(textureBindings.size());
textureInfo.pBindings = textureBindings.data();
vk::DescriptorSetLayout textureLayout;
ANGLE_TRY(textureLayout.init(device, textureInfo));
mDescriptorSetLayouts.push_back(std::move(textureLayout));
mDirtyTextures = true;
}
VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.setLayoutCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
createInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
createInfo.pushConstantRangeCount = 0;
createInfo.pPushConstantRanges = nullptr;
ANGLE_TRY(mPipelineLayout.init(device, createInfo));
return vk::NoError();
}
vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk) vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
{ {
ASSERT(mDescriptorSets.empty()); ASSERT(mDescriptorSets.empty());
RendererVk *renderer = contextVk->getRenderer();
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
// Write out to a new a descriptor set. // Write out to a new a descriptor set.
// TODO(jmadill): Handle descriptor set lifetime. // TODO(jmadill): Handle descriptor set lifetime.
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool(); vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
uint32_t descriptorSetCount = static_cast<uint32_t>(mDescriptorSetLayouts.size()); const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
VkDescriptorSetAllocateInfo allocInfo; VkDescriptorSetAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr; allocInfo.pNext = nullptr;
allocInfo.descriptorPool = descriptorPool->getHandle(); allocInfo.descriptorPool = descriptorPool->getHandle();
allocInfo.descriptorSetCount = descriptorSetCount; allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr(); allocInfo.pSetLayouts = descriptorSetLayouts[0].ptr();
mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE); mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0])); ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
...@@ -721,7 +602,7 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk) ...@@ -721,7 +602,7 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
return vk::NoError(); return vk::NoError();
} }
ASSERT(mDescriptorSetOffset == 0); ASSERT(mUsedDescriptorSetRange.contains(0));
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
...@@ -790,9 +671,9 @@ const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const ...@@ -790,9 +671,9 @@ const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
return mDescriptorSets; return mDescriptorSets;
} }
uint32_t ProgramVk::getDescriptorSetOffset() const const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
{ {
return mDescriptorSetOffset; return mUsedDescriptorSetRange;
} }
void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk) void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
...@@ -802,7 +683,8 @@ void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk) ...@@ -802,7 +683,8 @@ void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
return; return;
} }
VkDescriptorSet descriptorSet = mDescriptorSets.back(); ASSERT(mUsedDescriptorSetRange.contains(1));
VkDescriptorSet descriptorSet = mDescriptorSets[1];
// TODO(jmadill): Don't hard-code the texture limit. // TODO(jmadill): Don't hard-code the texture limit.
ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo; ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
......
...@@ -101,7 +101,6 @@ class ProgramVk : public ProgramImpl ...@@ -101,7 +101,6 @@ class ProgramVk : public ProgramImpl
const vk::ShaderModule &getLinkedVertexModule() const; const vk::ShaderModule &getLinkedVertexModule() const;
const vk::ShaderModule &getLinkedFragmentModule() const; const vk::ShaderModule &getLinkedFragmentModule() const;
const vk::PipelineLayout &getPipelineLayout() const;
vk::Error updateUniforms(ContextVk *contextVk); vk::Error updateUniforms(ContextVk *contextVk);
...@@ -111,14 +110,15 @@ class ProgramVk : public ProgramImpl ...@@ -111,14 +110,15 @@ class ProgramVk : public ProgramImpl
// However, it's valid to leave them in an undefined, unbound state, if they are never used. // However, it's valid to leave them in an undefined, unbound state, if they are never used.
// This means when we want to ignore a descriptor set index, we need to pass in an offset // This means when we want to ignore a descriptor set index, we need to pass in an offset
// parameter to BindDescriptorSets, which is an offset into the getDescriptorSets array. // parameter to BindDescriptorSets, which is an offset into the getDescriptorSets array.
uint32_t getDescriptorSetOffset() const; // This allows us to skip binding blank descriptor sets when the Program doesn't use Uniforms
// or Textures.
const gl::RangeUI &getUsedDescriptorSetRange() const;
void updateTexturesDescriptorSet(ContextVk *contextVk); void updateTexturesDescriptorSet(ContextVk *contextVk);
void invalidateTextures(); void invalidateTextures();
private: private:
void reset(VkDevice device); void reset(VkDevice device);
vk::Error initPipelineLayout(ContextVk *context);
vk::Error initDescriptorSets(ContextVk *contextVk); vk::Error initDescriptorSets(ContextVk *contextVk);
gl::Error initDefaultUniformBlocks(const gl::Context *glContext); gl::Error initDefaultUniformBlocks(const gl::Context *glContext);
vk::Error updateDefaultUniformsDescriptorSet(ContextVk *contextVk); vk::Error updateDefaultUniformsDescriptorSet(ContextVk *contextVk);
...@@ -128,8 +128,6 @@ class ProgramVk : public ProgramImpl ...@@ -128,8 +128,6 @@ class ProgramVk : public ProgramImpl
vk::ShaderModule mLinkedVertexModule; vk::ShaderModule mLinkedVertexModule;
vk::ShaderModule mLinkedFragmentModule; vk::ShaderModule mLinkedFragmentModule;
vk::PipelineLayout mPipelineLayout;
std::vector<vk::DescriptorSetLayout> mDescriptorSetLayouts;
// State for the default uniform blocks. // State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable struct DefaultUniformBlock final : private angle::NonCopyable
...@@ -157,7 +155,7 @@ class ProgramVk : public ProgramImpl ...@@ -157,7 +155,7 @@ class ProgramVk : public ProgramImpl
// Descriptor sets for uniform blocks and textures for this program. // Descriptor sets for uniform blocks and textures for this program.
std::vector<VkDescriptorSet> mDescriptorSets; std::vector<VkDescriptorSet> mDescriptorSets;
uint32_t mDescriptorSetOffset; gl::RangeUI mUsedDescriptorSetRange;
bool mDirtyTextures; bool mDirtyTextures;
template <typename T> template <typename T>
......
...@@ -231,6 +231,13 @@ RendererVk::~RendererVk() ...@@ -231,6 +231,13 @@ RendererVk::~RendererVk()
} }
} }
for (auto &descriptorSetLayout : mGraphicsDescriptorSetLayouts)
{
descriptorSetLayout.destroy(mDevice);
}
mGraphicsPipelineLayout.destroy(mDevice);
mRenderPassCache.destroy(mDevice); mRenderPassCache.destroy(mDevice);
if (mGlslangWrapper) if (mGlslangWrapper)
...@@ -462,6 +469,9 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -462,6 +469,9 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
// Initialize the format table. // Initialize the format table.
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps); mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps);
// Initialize the pipeline layout for GL programs.
ANGLE_TRY(initGraphicsPipelineLayout());
return vk::NoError(); return vk::NoError();
} }
...@@ -961,4 +971,102 @@ vk::Error RendererVk::flush(const gl::Context *context, ...@@ -961,4 +971,102 @@ vk::Error RendererVk::flush(const gl::Context *context,
return vk::NoError(); return vk::NoError();
} }
const vk::PipelineLayout &RendererVk::getGraphicsPipelineLayout() const
{
return mGraphicsPipelineLayout;
}
const std::vector<vk::DescriptorSetLayout> &RendererVk::getGraphicsDescriptorSetLayouts() const
{
return mGraphicsDescriptorSetLayouts;
}
vk::Error RendererVk::initGraphicsPipelineLayout()
{
ASSERT(!mGraphicsPipelineLayout.valid());
// Create two descriptor set layouts: one for default uniform info, and one for textures.
// Skip one or both if there are no uniforms.
VkDescriptorSetLayoutBinding uniformBindings[2];
uint32_t blockCount = 0;
{
auto &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
layoutBinding.pImmutableSamplers = nullptr;
blockCount++;
}
{
auto &layoutBinding = uniformBindings[blockCount];
layoutBinding.binding = blockCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
layoutBinding.pImmutableSamplers = nullptr;
blockCount++;
}
{
VkDescriptorSetLayoutCreateInfo uniformInfo;
uniformInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
uniformInfo.pNext = nullptr;
uniformInfo.flags = 0;
uniformInfo.bindingCount = blockCount;
uniformInfo.pBindings = uniformBindings;
vk::DescriptorSetLayout uniformLayout;
ANGLE_TRY(uniformLayout.init(mDevice, uniformInfo));
mGraphicsDescriptorSetLayouts.push_back(std::move(uniformLayout));
}
std::array<VkDescriptorSetLayoutBinding, gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES>
textureBindings;
// TODO(jmadill): This approach might not work well for texture arrays.
for (uint32_t textureIndex = 0; textureIndex < gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES;
++textureIndex)
{
VkDescriptorSetLayoutBinding &layoutBinding = textureBindings[textureIndex];
layoutBinding.binding = textureIndex;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
layoutBinding.pImmutableSamplers = nullptr;
}
{
VkDescriptorSetLayoutCreateInfo textureInfo;
textureInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
textureInfo.pNext = nullptr;
textureInfo.flags = 0;
textureInfo.bindingCount = static_cast<uint32_t>(textureBindings.size());
textureInfo.pBindings = textureBindings.data();
vk::DescriptorSetLayout textureLayout;
ANGLE_TRY(textureLayout.init(mDevice, textureInfo));
mGraphicsDescriptorSetLayouts.push_back(std::move(textureLayout));
}
VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.setLayoutCount = static_cast<uint32_t>(mGraphicsDescriptorSetLayouts.size());
createInfo.pSetLayouts = mGraphicsDescriptorSetLayouts[0].ptr();
createInfo.pushConstantRangeCount = 0;
createInfo.pPushConstantRanges = nullptr;
ANGLE_TRY(mGraphicsPipelineLayout.init(mDevice, createInfo));
return vk::NoError();
}
} // namespace rx } // namespace rx
...@@ -144,6 +144,9 @@ class RendererVk : angle::NonCopyable ...@@ -144,6 +144,9 @@ class RendererVk : angle::NonCopyable
// TODO(jmadill): Keep in ContextVk to enable threaded rendering. // TODO(jmadill): Keep in ContextVk to enable threaded rendering.
vk::CommandBufferNode *allocateCommandNode(); vk::CommandBufferNode *allocateCommandNode();
const vk::PipelineLayout &getGraphicsPipelineLayout() const;
const std::vector<vk::DescriptorSetLayout> &getGraphicsDescriptorSetLayouts() const;
private: private:
vk::Error initializeDevice(uint32_t queueFamilyIndex); vk::Error initializeDevice(uint32_t queueFamilyIndex);
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
...@@ -156,6 +159,7 @@ class RendererVk : angle::NonCopyable ...@@ -156,6 +159,7 @@ class RendererVk : angle::NonCopyable
void freeAllInFlightResources(); void freeAllInFlightResources();
vk::Error flushCommandGraph(const gl::Context *context, vk::CommandBuffer *commandBatch); vk::Error flushCommandGraph(const gl::Context *context, vk::CommandBuffer *commandBatch);
void resetCommandGraph(); void resetCommandGraph();
vk::Error initGraphicsPipelineLayout();
mutable bool mCapsInitialized; mutable bool mCapsInitialized;
mutable gl::Caps mNativeCaps; mutable gl::Caps mNativeCaps;
...@@ -197,6 +201,11 @@ class RendererVk : angle::NonCopyable ...@@ -197,6 +201,11 @@ class RendererVk : angle::NonCopyable
RenderPassCache mRenderPassCache; RenderPassCache mRenderPassCache;
std::vector<vk::CommandBufferNode *> mOpenCommandGraph; std::vector<vk::CommandBufferNode *> mOpenCommandGraph;
// ANGLE uses a single pipeline layout for all GL programs. It is owned here in the Renderer.
// See the design doc for an overview of the pipeline layout structure.
vk::PipelineLayout mGraphicsPipelineLayout;
std::vector<vk::DescriptorSetLayout> mGraphicsDescriptorSetLayouts;
}; };
} // 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