Commit 026f7d07 by Nicolas Capens Committed by Nicolas Capens

Store binding information in the pipeline layout

Descriptor set layout binding information needed by the pipeline layout has to persist after the descriptor set layout object has been destroyed. The spec states: "VkDescriptorSetLayout objects may be accessed by commands that operate on descriptor sets allocated using that layout, and those descriptor sets must not be updated with vkUpdateDescriptorSets after the descriptor set layout has been destroyed. Otherwise, a VkDescriptorSetLayout object passed as a parameter to create another object is not further accessed by that object after the duration of the command it is passed into." Bug: b/154522740 Change-Id: Ia6349383139ae0fceac328a685b06e2ec253a589 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/44328 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent c7d5ec39
...@@ -1105,12 +1105,12 @@ public: ...@@ -1105,12 +1105,12 @@ public:
{ {
ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (setNumber < vk::MAX_BOUND_DESCRIPTOR_SETS)); ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (setNumber < vk::MAX_BOUND_DESCRIPTOR_SETS));
auto &pipelineState = executionState.pipelineState[pipelineBindPoint]; auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
auto dynamicBindingBaseIndex = pipelineLayout->getDynamicOffsetBaseIndex(setNumber);
ASSERT_OR_RETURN(dynamicBindingBaseIndex + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
pipelineState.descriptorSets[setNumber] = descriptorSet->data; pipelineState.descriptorSets[setNumber] = descriptorSet->data;
for(uint32_t i = 0; i < dynamicOffsetCount; i++) for(uint32_t i = 0; i < dynamicOffsetCount; i++)
{ {
auto dynamicBindingBaseIndex = pipelineLayout->getDynamicOffsetIndex(setNumber, 0);
ASSERT_OR_RETURN(dynamicBindingBaseIndex + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
pipelineState.descriptorDynamicOffsets[dynamicBindingBaseIndex + i] = dynamicOffsets[i]; pipelineState.descriptorDynamicOffsets[dynamicBindingBaseIndex + i] = dynamicOffsets[i];
} }
} }
......
...@@ -188,6 +188,12 @@ uint32_t DescriptorSetLayout::getBindingOffset(uint32_t bindingNumber) const ...@@ -188,6 +188,12 @@ uint32_t DescriptorSetLayout::getBindingOffset(uint32_t bindingNumber) const
return bindings[bindingNumber].offset; return bindings[bindingNumber].offset;
} }
uint32_t DescriptorSetLayout::getDescriptorCount(uint32_t bindingNumber) const
{
ASSERT(bindingNumber < bindingsArraySize);
return bindings[bindingNumber].descriptorCount;
}
uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
{ {
uint32_t count = 0; uint32_t count = 0;
......
...@@ -110,21 +110,28 @@ public: ...@@ -110,21 +110,28 @@ public:
size_t getDescriptorSetAllocationSize() const; size_t getDescriptorSetAllocationSize() const;
// Returns the byte offset from the base address of the descriptor set for // Returns the byte offset from the base address of the descriptor set for
// the given binding. // the given binding number.
uint32_t getBindingOffset(uint32_t bindingNumber) const; uint32_t getBindingOffset(uint32_t bindingNumber) const;
// Returns the number of descriptors for the given binding number.
uint32_t getDescriptorCount(uint32_t bindingNumber) const;
// Returns the number of descriptors across all bindings that are dynamic. // Returns the number of descriptors across all bindings that are dynamic.
uint32_t getDynamicDescriptorCount() const; uint32_t getDynamicDescriptorCount() const;
// Returns the relative index into the pipeline's dynamic offsets array for // Returns the relative index into the pipeline's dynamic offsets array for
// the given binding. This index should be added to the base index // the given binding number. This index should be added to the base index
// returned by PipelineLayout::getDynamicOffsetBase() to produce the // returned by PipelineLayout::getDynamicOffsetBase() to produce the
// starting index for dynamic descriptors. // starting index for dynamic descriptors.
uint32_t getDynamicOffsetIndex(uint32_t bindingNumber) const; uint32_t getDynamicOffsetIndex(uint32_t bindingNumber) const;
// Returns the descriptor type for the given binding. // Returns the descriptor type for the given binding number.
VkDescriptorType getDescriptorType(uint32_t bindingNumber) const; VkDescriptorType getDescriptorType(uint32_t bindingNumber) const;
// Returns the number of entries in the direct-indexed array of bindings.
// It equals the highest binding number + 1.
uint32_t getBindingsArraySize() const { return bindingsArraySize; }
private: private:
uint8_t *getDescriptorPointer(DescriptorSet *descriptorSet, uint32_t bindingNumber, uint32_t arrayElement, uint32_t count, size_t *typeSize) const; uint8_t *getDescriptorPointer(DescriptorSet *descriptorSet, uint32_t bindingNumber, uint32_t arrayElement, uint32_t count, size_t *typeSize) const;
size_t getDescriptorSetDataSize() const; size_t getDescriptorSetDataSize() const;
......
...@@ -26,42 +26,51 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, vo ...@@ -26,42 +26,51 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, vo
, descriptorSetCount(pCreateInfo->setLayoutCount) , descriptorSetCount(pCreateInfo->setLayoutCount)
, pushConstantRangeCount(pCreateInfo->pushConstantRangeCount) , pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
{ {
char *hostMem = reinterpret_cast<char *>(mem); Binding *bindingStorage = reinterpret_cast<Binding *>(mem);
uint32_t dynamicOffsetIndex = 0;
size_t setLayoutsSize = pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *);
descriptorSetLayouts = reinterpret_cast<const DescriptorSetLayout **>(hostMem);
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++) for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
{ {
descriptorSetLayouts[i] = vk::Cast(pCreateInfo->pSetLayouts[i]); const vk::DescriptorSetLayout *setLayout = vk::Cast(pCreateInfo->pSetLayouts[i]);
uint32_t bindingsArraySize = setLayout->getBindingsArraySize();
descriptorSets[i].bindings = bindingStorage;
bindingStorage += bindingsArraySize;
descriptorSets[i].dynamicDescriptorCount = setLayout->getDynamicDescriptorCount();
descriptorSets[i].bindingCount = bindingsArraySize;
for(uint32_t j = 0; j < bindingsArraySize; j++)
{
descriptorSets[i].bindings[j].descriptorType = setLayout->getDescriptorType(j);
descriptorSets[i].bindings[j].offset = setLayout->getBindingOffset(j);
descriptorSets[i].bindings[j].dynamicOffsetIndex = dynamicOffsetIndex;
if(DescriptorSetLayout::IsDescriptorDynamic(descriptorSets[i].bindings[j].descriptorType))
{
dynamicOffsetIndex += setLayout->getDescriptorCount(j);
}
}
} }
hostMem += setLayoutsSize;
size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange); size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(hostMem); pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(bindingStorage);
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize); memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
hostMem += pushConstantRangesSize;
dynamicOffsetBaseIndices = reinterpret_cast<uint32_t *>(hostMem);
uint32_t dynamicOffsetBase = 0;
for(uint32_t i = 0; i < descriptorSetCount; i++)
{
uint32_t dynamicDescriptorCount = descriptorSetLayouts[i]->getDynamicDescriptorCount();
ASSERT_OR_RETURN((dynamicOffsetBase + dynamicDescriptorCount) <= MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
dynamicOffsetBaseIndices[i] = dynamicOffsetBase;
dynamicOffsetBase += dynamicDescriptorCount;
}
} }
void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator) void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
{ {
vk::deallocate(descriptorSetLayouts, pAllocator); // pushConstantRanges are in the same allocation vk::deallocate(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
} }
size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo) size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo)
{ {
return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *)) + // descriptorSetLayouts[] uint32_t bindingsCount = 0;
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) + // pushConstantRanges[] for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
(pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBaseIndices[] {
bindingsCount += vk::Cast(pCreateInfo->pSetLayouts[i])->getBindingsArraySize();
}
return bindingsCount * sizeof(Binding) + // descriptorSets[]
pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange); // pushConstantRanges[]
} }
size_t PipelineLayout::getDescriptorSetCount() const size_t PipelineLayout::getDescriptorSetCount() const
...@@ -71,27 +80,26 @@ size_t PipelineLayout::getDescriptorSetCount() const ...@@ -71,27 +80,26 @@ size_t PipelineLayout::getDescriptorSetCount() const
uint32_t PipelineLayout::getDynamicDescriptorCount(uint32_t setNumber) const uint32_t PipelineLayout::getDynamicDescriptorCount(uint32_t setNumber) const
{ {
return getDescriptorSetLayout(setNumber)->getDynamicDescriptorCount(); ASSERT(setNumber < descriptorSetCount);
} return descriptorSets[setNumber].dynamicDescriptorCount;
uint32_t PipelineLayout::getDynamicOffsetBaseIndex(uint32_t setNumber) const
{
return dynamicOffsetBaseIndices[setNumber];
} }
uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const
{ {
return getDynamicOffsetBaseIndex(setNumber) + getDescriptorSetLayout(setNumber)->getDynamicOffsetIndex(bindingNumber); ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].dynamicOffsetIndex;
} }
uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const
{ {
return getDescriptorSetLayout(setNumber)->getBindingOffset(bindingNumber); ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].offset;
} }
VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const
{ {
return getDescriptorSetLayout(setNumber)->getDescriptorType(bindingNumber); ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].descriptorType;
} }
uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const
...@@ -104,10 +112,4 @@ bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNum ...@@ -104,10 +112,4 @@ bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNum
return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber)); return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
} }
DescriptorSetLayout const *PipelineLayout::getDescriptorSetLayout(size_t descriptorSet) const
{
ASSERT(descriptorSet < descriptorSetCount);
return descriptorSetLayouts[descriptorSet];
}
} // namespace vk } // namespace vk
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#ifndef VK_PIPELINE_LAYOUT_HPP_ #ifndef VK_PIPELINE_LAYOUT_HPP_
#define VK_PIPELINE_LAYOUT_HPP_ #define VK_PIPELINE_LAYOUT_HPP_
#include "VkConfig.h"
#include "VkDescriptorSetLayout.hpp" #include "VkDescriptorSetLayout.hpp"
namespace vk { namespace vk {
...@@ -31,8 +32,7 @@ public: ...@@ -31,8 +32,7 @@ public:
uint32_t getDynamicDescriptorCount(uint32_t setNumber) const; uint32_t getDynamicDescriptorCount(uint32_t setNumber) const;
// Returns the index into the pipeline's dynamic offsets array for // Returns the index into the pipeline's dynamic offsets array for
// the given descriptor set (and binding number). // the given descriptor set and binding number.
uint32_t getDynamicOffsetBaseIndex(uint32_t setNumber) const;
uint32_t getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const; uint32_t getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const;
uint32_t getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const; uint32_t getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const;
...@@ -43,13 +43,25 @@ public: ...@@ -43,13 +43,25 @@ public:
const uint32_t identifier; const uint32_t identifier;
private: private:
DescriptorSetLayout const *getDescriptorSetLayout(size_t descriptorSet) const; struct Binding
{
VkDescriptorType descriptorType;
uint32_t offset; // Offset in bytes in the descriptor set data.
uint32_t dynamicOffsetIndex; // TODO(b/154914395): Debug only.
};
struct DescriptorSet
{
Binding *bindings;
uint32_t dynamicDescriptorCount;
uint32_t bindingCount;
};
DescriptorSet descriptorSets[MAX_BOUND_DESCRIPTOR_SETS];
const uint32_t descriptorSetCount = 0; const uint32_t descriptorSetCount = 0;
const DescriptorSetLayout **descriptorSetLayouts = nullptr;
const uint32_t pushConstantRangeCount = 0; const uint32_t pushConstantRangeCount = 0;
VkPushConstantRange *pushConstantRanges = nullptr; VkPushConstantRange *pushConstantRanges = nullptr;
uint32_t *dynamicOffsetBaseIndices = nullptr; // Base index per descriptor set for dynamic buffer offsets.
}; };
static inline PipelineLayout *Cast(VkPipelineLayout object) static inline PipelineLayout *Cast(VkPipelineLayout object)
......
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