Commit c7d5ec39 by Nicolas Capens Committed by Nicolas Capens

Don't expose individual descriptor set layouts to SPIR-V compilation

Shader compilation requires access to the pipeline layout, but not to each of its descriptor set layout interfaces. This change ensures that all information is queried only through the pipeline layout interface. This facilitates refactoring the pipeline layout object to contain all this information, instead of depending on the descriptor set layout objects to remain alive after pipeline layout creation. The Vulkan spec states that "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." Also consistently use "index" for values that index into an array, and "offset" for byte offsets. "descriptor" signifies an individual resource descriptor, while "binding" refers to the descriptor set binding which is an array (often of just one descriptor). Use "setNumber" and "bindingNumber" for the 32-bit identifiers used by SPIR-V, to distinguish them from the actual objects. Bug: b/154522740 Change-Id: If3f6e56b6769aae6ebbd49109e7dc1e78cf6558c Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/44188 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
parent ca9de964
...@@ -1236,9 +1236,8 @@ SIMD::Pointer SpirvShader::WalkAccessChain(Object::ID baseId, uint32_t numIndexe ...@@ -1236,9 +1236,8 @@ SIMD::Pointer SpirvShader::WalkAccessChain(Object::ID baseId, uint32_t numIndexe
auto d = descriptorDecorations.at(baseId); auto d = descriptorDecorations.at(baseId);
ASSERT(d.DescriptorSet >= 0); ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0); ASSERT(d.Binding >= 0);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet); uint32_t descriptorSize = routine->pipelineLayout->getDescriptorSize(d.DescriptorSet, d.Binding);
auto stride = static_cast<uint32_t>(setLayout->getBindingStride(d.Binding)); ptr.base += descriptorSize * GetConstScalarInt(indexIds[i]);
ptr.base += stride * GetConstScalarInt(indexIds[i]);
} }
else else
{ {
......
...@@ -345,8 +345,7 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT ...@@ -345,8 +345,7 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT
bool isCubeMap = imageType.definition.word(3) == spv::DimCube; bool isCubeMap = imageType.definition.word(3) == spv::DimCube;
const DescriptorDecorations &d = descriptorDecorations.at(imageId); const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet); auto descriptorType = routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base; Pointer<Byte> descriptor = state->getPointer(imageId).base;
...@@ -409,8 +408,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQueryLevels(InsnIterator insn, Emi ...@@ -409,8 +408,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQueryLevels(InsnIterator insn, Emi
auto imageId = Object::ID(insn.word(3)); auto imageId = Object::ID(insn.word(3));
const DescriptorDecorations &d = descriptorDecorations.at(imageId); const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet); auto descriptorType = state->routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base; Pointer<Byte> descriptor = state->getPointer(imageId).base;
Int mipLevels = 0; Int mipLevels = 0;
...@@ -442,8 +440,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQuerySamples(InsnIterator insn, Em ...@@ -442,8 +440,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQuerySamples(InsnIterator insn, Em
ASSERT(imageTy.definition.word(6 /* MS */) == 1); ASSERT(imageTy.definition.word(6 /* MS */) == 1);
const DescriptorDecorations &d = descriptorDecorations.at(imageId); const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet); auto descriptorType = state->routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base; Pointer<Byte> descriptor = state->getPointer(imageId).base;
Int sampleCount = 0; Int sampleCount = 0;
......
...@@ -170,9 +170,7 @@ SpirvShader::EmitResult SpirvShader::EmitVariable(InsnIterator insn, EmitState * ...@@ -170,9 +170,7 @@ SpirvShader::EmitResult SpirvShader::EmitVariable(InsnIterator insn, EmitState *
ASSERT(d.DescriptorSet >= 0); ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0); ASSERT(d.Binding >= 0);
uint32_t arrayIndex = 0; // TODO(b/129523279) uint32_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
uint32_t bindingOffset = static_cast<uint32_t>(setLayout->getBindingOffset(d.Binding, arrayIndex));
Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet* Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // vk::SampledImageDescriptor* Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // vk::SampledImageDescriptor*
auto size = 0; // Not required as this pointer is not directly used by SIMD::Read or SIMD::Write. auto size = 0; // Not required as this pointer is not directly used by SIMD::Read or SIMD::Write.
...@@ -390,22 +388,23 @@ SIMD::Pointer SpirvShader::GetPointerToData(Object::ID id, int arrayIndex, EmitS ...@@ -390,22 +388,23 @@ SIMD::Pointer SpirvShader::GetPointerToData(Object::ID id, int arrayIndex, EmitS
ASSERT(d.DescriptorSet >= 0 && d.DescriptorSet < vk::MAX_BOUND_DESCRIPTOR_SETS); ASSERT(d.DescriptorSet >= 0 && d.DescriptorSet < vk::MAX_BOUND_DESCRIPTOR_SETS);
ASSERT(d.Binding >= 0); ASSERT(d.Binding >= 0);
auto set = state->getPointer(id); uint32_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding);
uint32_t descriptorSize = routine->pipelineLayout->getDescriptorSize(d.DescriptorSet, d.Binding);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet); uint32_t descriptorOffset = bindingOffset + descriptorSize * arrayIndex;
int bindingOffset = static_cast<int>(setLayout->getBindingOffset(d.Binding, arrayIndex));
Pointer<Byte> descriptor = set.base + bindingOffset; // BufferDescriptor* auto set = state->getPointer(id);
Pointer<Byte> descriptor = set.base + descriptorOffset; // BufferDescriptor*
Pointer<Byte> data = *Pointer<Pointer<Byte>>(descriptor + OFFSET(vk::BufferDescriptor, ptr)); // void* Pointer<Byte> data = *Pointer<Pointer<Byte>>(descriptor + OFFSET(vk::BufferDescriptor, ptr)); // void*
Int size = *Pointer<Int>(descriptor + OFFSET(vk::BufferDescriptor, sizeInBytes)); Int size = *Pointer<Int>(descriptor + OFFSET(vk::BufferDescriptor, sizeInBytes));
if(setLayout->isBindingDynamic(d.Binding))
if(routine->pipelineLayout->isDescriptorDynamic(d.DescriptorSet, d.Binding))
{ {
uint32_t dynamicBindingIndex = uint32_t dynamicOffsetIndex =
routine->pipelineLayout->getDynamicOffsetBase(d.DescriptorSet) + routine->pipelineLayout->getDynamicOffsetIndex(d.DescriptorSet, d.Binding) +
setLayout->getDynamicDescriptorOffset(d.Binding) +
arrayIndex; arrayIndex;
Int offset = routine->descriptorDynamicOffsets[dynamicBindingIndex]; Int offset = routine->descriptorDynamicOffsets[dynamicOffsetIndex];
Int robustnessSize = *Pointer<Int>(descriptor + OFFSET(vk::BufferDescriptor, robustnessSize)); Int robustnessSize = *Pointer<Int>(descriptor + OFFSET(vk::BufferDescriptor, robustnessSize));
return SIMD::Pointer(data + offset, Min(size, robustnessSize - offset)); return SIMD::Pointer(data + offset, Min(size, robustnessSize - offset));
} }
else else
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "Reactor.hpp" #include "Reactor.hpp"
#include "Debug.hpp" #include "Debug.hpp"
#include "Print.hpp" #include "Print.hpp"
......
...@@ -1087,11 +1087,11 @@ private: ...@@ -1087,11 +1087,11 @@ private:
class CmdBindDescriptorSet : public vk::CommandBuffer::Command class CmdBindDescriptorSet : public vk::CommandBuffer::Command
{ {
public: public:
CmdBindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, const vk::PipelineLayout *pipelineLayout, uint32_t set, vk::DescriptorSet *descriptorSet, CmdBindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, const vk::PipelineLayout *pipelineLayout, uint32_t setNumber, vk::DescriptorSet *descriptorSet,
uint32_t dynamicOffsetCount, uint32_t const *dynamicOffsets) uint32_t dynamicOffsetCount, uint32_t const *dynamicOffsets)
: pipelineBindPoint(pipelineBindPoint) : pipelineBindPoint(pipelineBindPoint)
, pipelineLayout(pipelineLayout) , pipelineLayout(pipelineLayout)
, set(set) , setNumber(setNumber)
, descriptorSet(descriptorSet) , descriptorSet(descriptorSet)
, dynamicOffsetCount(dynamicOffsetCount) , dynamicOffsetCount(dynamicOffsetCount)
{ {
...@@ -1103,26 +1103,26 @@ public: ...@@ -1103,26 +1103,26 @@ public:
void play(vk::CommandBuffer::ExecutionState &executionState) override void play(vk::CommandBuffer::ExecutionState &executionState) override
{ {
ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < 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 dynamicOffsetBase = pipelineLayout->getDynamicOffsetBase(set); auto dynamicBindingBaseIndex = pipelineLayout->getDynamicOffsetBaseIndex(setNumber);
ASSERT_OR_RETURN(dynamicOffsetBase + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC); ASSERT_OR_RETURN(dynamicBindingBaseIndex + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
pipelineState.descriptorSets[set] = descriptorSet->data; pipelineState.descriptorSets[setNumber] = descriptorSet->data;
for(uint32_t i = 0; i < dynamicOffsetCount; i++) for(uint32_t i = 0; i < dynamicOffsetCount; i++)
{ {
pipelineState.descriptorDynamicOffsets[dynamicOffsetBase + i] = dynamicOffsets[i]; pipelineState.descriptorDynamicOffsets[dynamicBindingBaseIndex + i] = dynamicOffsets[i];
} }
} }
std::string description() override { return "vkCmdBindDescriptorSet()"; } std::string description() override { return "vkCmdBindDescriptorSet()"; }
private: private:
VkPipelineBindPoint pipelineBindPoint; const VkPipelineBindPoint pipelineBindPoint;
const vk::PipelineLayout *pipelineLayout; const vk::PipelineLayout *const pipelineLayout;
uint32_t set; const uint32_t setNumber;
vk::DescriptorSet *descriptorSet; vk::DescriptorSet *const descriptorSet;
uint32_t dynamicOffsetCount; const uint32_t dynamicOffsetCount;
vk::DescriptorSet::DynamicOffsets dynamicOffsets; vk::DescriptorSet::DynamicOffsets dynamicOffsets;
}; };
...@@ -1568,9 +1568,7 @@ void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, co ...@@ -1568,9 +1568,7 @@ void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, co
for(uint32_t i = 0; i < descriptorSetCount; i++) for(uint32_t i = 0; i < descriptorSetCount; i++)
{ {
auto descriptorSetIndex = firstSet + i; auto descriptorSetIndex = firstSet + i;
auto setLayout = layout->getDescriptorSetLayout(descriptorSetIndex); uint32_t numDynamicDescriptors = layout->getDynamicDescriptorCount(descriptorSetIndex);
auto numDynamicDescriptors = setLayout->getDynamicDescriptorCount();
ASSERT(numDynamicDescriptors == 0 || pDynamicOffsets != nullptr); ASSERT(numDynamicDescriptors == 0 || pDynamicOffsets != nullptr);
ASSERT(dynamicOffsetCount >= numDynamicDescriptors); ASSERT(dynamicOffsetCount >= numDynamicDescriptors);
......
...@@ -109,7 +109,7 @@ size_t DescriptorSetLayout::ComputeRequiredAllocationSize(const VkDescriptorSetL ...@@ -109,7 +109,7 @@ size_t DescriptorSetLayout::ComputeRequiredAllocationSize(const VkDescriptorSetL
immutableSamplerCount * sizeof(VkSampler); immutableSamplerCount * sizeof(VkSampler);
} }
size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type) uint32_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
{ {
switch(type) switch(type)
{ {
...@@ -117,22 +117,28 @@ size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type) ...@@ -117,22 +117,28 @@ size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
return sizeof(SampledImageDescriptor); return static_cast<uint32_t>(sizeof(SampledImageDescriptor));
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return sizeof(StorageImageDescriptor); return static_cast<uint32_t>(sizeof(StorageImageDescriptor));
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
return sizeof(BufferDescriptor); return static_cast<uint32_t>(sizeof(BufferDescriptor));
default: default:
UNSUPPORTED("Unsupported Descriptor Type"); UNSUPPORTED("Unsupported Descriptor Type");
return 0; return 0;
} }
} }
bool DescriptorSetLayout::IsDescriptorDynamic(VkDescriptorType type)
{
return type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
}
size_t DescriptorSetLayout::getDescriptorSetAllocationSize() const size_t DescriptorSetLayout::getDescriptorSetAllocationSize() const
{ {
// vk::DescriptorSet has a header with a pointer to the layout. // vk::DescriptorSet has a header with a pointer to the layout.
...@@ -176,29 +182,10 @@ void DescriptorSetLayout::initialize(DescriptorSet *descriptorSet) ...@@ -176,29 +182,10 @@ void DescriptorSetLayout::initialize(DescriptorSet *descriptorSet)
} }
} }
size_t DescriptorSetLayout::getBindingStride(uint32_t binding) const uint32_t DescriptorSetLayout::getBindingOffset(uint32_t bindingNumber) const
{
ASSERT(binding < bindingsArraySize);
return GetDescriptorSize(bindings[binding].descriptorType);
}
size_t DescriptorSetLayout::getBindingOffset(uint32_t binding, size_t arrayElement) const
{
ASSERT(binding < bindingsArraySize && arrayElement < bindings[binding].descriptorCount);
auto typeSize = GetDescriptorSize(bindings[binding].descriptorType);
return bindings[binding].offset + (typeSize * arrayElement);
}
bool DescriptorSetLayout::isDynamic(VkDescriptorType type)
{
return type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
}
bool DescriptorSetLayout::isBindingDynamic(uint32_t binding) const
{ {
ASSERT(binding < bindingsArraySize); ASSERT(bindingNumber < bindingsArraySize);
return isDynamic(bindings[binding].descriptorType); return bindings[bindingNumber].offset;
} }
uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
...@@ -206,7 +193,7 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const ...@@ -206,7 +193,7 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
uint32_t count = 0; uint32_t count = 0;
for(size_t i = 0; i < bindingsArraySize; i++) for(size_t i = 0; i < bindingsArraySize; i++)
{ {
if(isDynamic(bindings[i].descriptorType)) if(IsDescriptorDynamic(bindings[i].descriptorType))
{ {
count += bindings[i].descriptorCount; count += bindings[i].descriptorCount;
} }
...@@ -215,15 +202,15 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const ...@@ -215,15 +202,15 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
return count; return count;
} }
uint32_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const uint32_t DescriptorSetLayout::getDynamicOffsetIndex(uint32_t bindingNumber) const
{ {
ASSERT(binding < bindingsArraySize); ASSERT(bindingNumber < bindingsArraySize);
ASSERT(isDynamic(bindings[binding].descriptorType)); ASSERT(IsDescriptorDynamic(bindings[bindingNumber].descriptorType));
uint32_t index = 0; uint32_t index = 0;
for(uint32_t i = 0; i < binding; i++) for(uint32_t i = 0; i < bindingNumber; i++)
{ {
if(isDynamic(bindings[i].descriptorType)) if(IsDescriptorDynamic(bindings[i].descriptorType))
{ {
index += bindings[i].descriptorCount; index += bindings[i].descriptorCount;
} }
...@@ -232,17 +219,17 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const ...@@ -232,17 +219,17 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const
return index; return index;
} }
VkDescriptorType DescriptorSetLayout::getDescriptorType(uint32_t binding) const VkDescriptorType DescriptorSetLayout::getDescriptorType(uint32_t bindingNumber) const
{ {
ASSERT(binding < bindingsArraySize); ASSERT(bindingNumber < bindingsArraySize);
return bindings[binding].descriptorType; return bindings[bindingNumber].descriptorType;
} }
uint8_t *DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t *typeSize) const uint8_t *DescriptorSetLayout::getDescriptorPointer(DescriptorSet *descriptorSet, uint32_t bindingNumber, uint32_t arrayElement, uint32_t count, size_t *typeSize) const
{ {
ASSERT(binding < bindingsArraySize); ASSERT(bindingNumber < bindingsArraySize);
*typeSize = GetDescriptorSize(bindings[binding].descriptorType); *typeSize = GetDescriptorSize(bindings[bindingNumber].descriptorType);
size_t byteOffset = bindings[binding].offset + (*typeSize * arrayElement); size_t byteOffset = bindings[bindingNumber].offset + (*typeSize * arrayElement);
ASSERT(((*typeSize * count) + byteOffset) <= getDescriptorSetDataSize()); // Make sure the operation will not go out of bounds ASSERT(((*typeSize * count) + byteOffset) <= getDescriptorSetDataSize()); // Make sure the operation will not go out of bounds
return &descriptorSet->data[byteOffset]; return &descriptorSet->data[byteOffset];
...@@ -261,7 +248,7 @@ void DescriptorSetLayout::WriteDescriptorSet(Device *device, DescriptorSet *dstS ...@@ -261,7 +248,7 @@ void DescriptorSetLayout::WriteDescriptorSet(Device *device, DescriptorSet *dstS
ASSERT(binding.descriptorType == entry.descriptorType); ASSERT(binding.descriptorType == entry.descriptorType);
size_t typeSize = 0; size_t typeSize = 0;
uint8_t *memToWrite = dstLayout->getOffsetPointer(dstSet, entry.dstBinding, entry.dstArrayElement, entry.descriptorCount, &typeSize); uint8_t *memToWrite = dstLayout->getDescriptorPointer(dstSet, entry.dstBinding, entry.dstArrayElement, entry.descriptorCount, &typeSize);
ASSERT(reinterpret_cast<intptr_t>(memToWrite) % 16 == 0); // Each descriptor must be 16-byte aligned. ASSERT(reinterpret_cast<intptr_t>(memToWrite) % 16 == 0); // Each descriptor must be 16-byte aligned.
...@@ -629,10 +616,10 @@ void DescriptorSetLayout::CopyDescriptorSet(const VkCopyDescriptorSet &descripto ...@@ -629,10 +616,10 @@ void DescriptorSetLayout::CopyDescriptorSet(const VkCopyDescriptorSet &descripto
ASSERT(dstLayout); ASSERT(dstLayout);
size_t srcTypeSize = 0; size_t srcTypeSize = 0;
uint8_t *memToRead = srcLayout->getOffsetPointer(srcSet, descriptorCopies.srcBinding, descriptorCopies.srcArrayElement, descriptorCopies.descriptorCount, &srcTypeSize); uint8_t *memToRead = srcLayout->getDescriptorPointer(srcSet, descriptorCopies.srcBinding, descriptorCopies.srcArrayElement, descriptorCopies.descriptorCount, &srcTypeSize);
size_t dstTypeSize = 0; size_t dstTypeSize = 0;
uint8_t *memToWrite = dstLayout->getOffsetPointer(dstSet, descriptorCopies.dstBinding, descriptorCopies.dstArrayElement, descriptorCopies.descriptorCount, &dstTypeSize); uint8_t *memToWrite = dstLayout->getDescriptorPointer(dstSet, descriptorCopies.dstBinding, descriptorCopies.dstArrayElement, descriptorCopies.descriptorCount, &dstTypeSize);
ASSERT(srcTypeSize == dstTypeSize); ASSERT(srcTypeSize == dstTypeSize);
size_t writeSize = dstTypeSize * descriptorCopies.descriptorCount; size_t writeSize = dstTypeSize * descriptorCopies.descriptorCount;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "Vulkan/VkImageView.hpp" #include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkSampler.hpp" #include "Vulkan/VkSampler.hpp"
#include <cstdint>
namespace vk { namespace vk {
class DescriptorSet; class DescriptorSet;
...@@ -93,7 +95,9 @@ public: ...@@ -93,7 +95,9 @@ public:
static size_t ComputeRequiredAllocationSize(const VkDescriptorSetLayoutCreateInfo *pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkDescriptorSetLayoutCreateInfo *pCreateInfo);
static size_t GetDescriptorSize(VkDescriptorType type); static uint32_t GetDescriptorSize(VkDescriptorType type);
static bool IsDescriptorDynamic(VkDescriptorType type);
static void WriteDescriptorSet(Device *device, const VkWriteDescriptorSet &descriptorWrites); static void WriteDescriptorSet(Device *device, const VkWriteDescriptorSet &descriptorWrites);
static void CopyDescriptorSet(const VkCopyDescriptorSet &descriptorCopies); static void CopyDescriptorSet(const VkCopyDescriptorSet &descriptorCopies);
...@@ -106,33 +110,23 @@ public: ...@@ -106,33 +110,23 @@ 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 and array element within that binding. // the given binding.
size_t getBindingOffset(uint32_t binding, size_t arrayElement) const; uint32_t getBindingOffset(uint32_t bindingNumber) const;
// Returns the stride of an array of descriptors
size_t getBindingStride(uint32_t binding) const;
// Returns the number of descriptors across all bindings that are dynamic // Returns the number of descriptors across all bindings that are dynamic.
// (see isBindingDynamic).
uint32_t getDynamicDescriptorCount() const; uint32_t getDynamicDescriptorCount() const;
// Returns the relative offset into the pipeline's dynamic offsets array for // Returns the relative index into the pipeline's dynamic offsets array for
// the given binding. This offset should be added to the base offset // the given binding. 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 getDynamicDescriptorOffset(uint32_t binding) const; uint32_t getDynamicOffsetIndex(uint32_t bindingNumber) const;
// Returns true if the given binding is of type:
// VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or
// VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
bool isBindingDynamic(uint32_t binding) const;
// Returns the descriptor type for the given binding. // Returns the descriptor type for the given binding.
VkDescriptorType getDescriptorType(uint32_t binding) const; VkDescriptorType getDescriptorType(uint32_t bindingNumber) const;
uint8_t *getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t *typeSize) const;
private: private:
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;
static bool isDynamic(VkDescriptorType type); static bool isDynamic(VkDescriptorType type);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define VK_OBJECT_HPP_ #define VK_OBJECT_HPP_
#include "VkMemory.h" #include "VkMemory.h"
#include "VkConfig.h" #include "VkConfig.h"
#include "System/Memory.hpp" #include "System/Memory.hpp"
......
...@@ -23,16 +23,16 @@ static std::atomic<uint32_t> layoutIdentifierSerial = { 1 }; // Start at 1. 0 i ...@@ -23,16 +23,16 @@ static std::atomic<uint32_t> layoutIdentifierSerial = { 1 }; // Start at 1. 0 i
PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem) PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem)
: identifier(layoutIdentifierSerial++) : identifier(layoutIdentifierSerial++)
, setLayoutCount(pCreateInfo->setLayoutCount) , descriptorSetCount(pCreateInfo->setLayoutCount)
, pushConstantRangeCount(pCreateInfo->pushConstantRangeCount) , pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
{ {
char *hostMem = reinterpret_cast<char *>(mem); char *hostMem = reinterpret_cast<char *>(mem);
size_t setLayoutsSize = pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *); size_t setLayoutsSize = pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *);
setLayouts = reinterpret_cast<DescriptorSetLayout **>(hostMem); descriptorSetLayouts = reinterpret_cast<const DescriptorSetLayout **>(hostMem);
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++) for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
{ {
setLayouts[i] = vk::Cast(pCreateInfo->pSetLayouts[i]); descriptorSetLayouts[i] = vk::Cast(pCreateInfo->pSetLayouts[i]);
} }
hostMem += setLayoutsSize; hostMem += setLayoutsSize;
...@@ -41,44 +41,73 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, vo ...@@ -41,44 +41,73 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, vo
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize); memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
hostMem += pushConstantRangesSize; hostMem += pushConstantRangesSize;
dynamicOffsetBases = reinterpret_cast<uint32_t *>(hostMem); dynamicOffsetBaseIndices = reinterpret_cast<uint32_t *>(hostMem);
uint32_t dynamicOffsetBase = 0; uint32_t dynamicOffsetBase = 0;
for(uint32_t i = 0; i < setLayoutCount; i++) for(uint32_t i = 0; i < descriptorSetCount; i++)
{ {
uint32_t dynamicDescriptorCount = setLayouts[i]->getDynamicDescriptorCount(); uint32_t dynamicDescriptorCount = descriptorSetLayouts[i]->getDynamicDescriptorCount();
ASSERT_OR_RETURN((dynamicOffsetBase + dynamicDescriptorCount) <= MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC); ASSERT_OR_RETURN((dynamicOffsetBase + dynamicDescriptorCount) <= MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
dynamicOffsetBases[i] = dynamicOffsetBase; dynamicOffsetBaseIndices[i] = dynamicOffsetBase;
dynamicOffsetBase += dynamicDescriptorCount; dynamicOffsetBase += dynamicDescriptorCount;
} }
} }
void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator) void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
{ {
vk::deallocate(setLayouts, pAllocator); // pushConstantRanges are in the same allocation vk::deallocate(descriptorSetLayouts, 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 *)) + return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *)) + // descriptorSetLayouts[]
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) + (pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) + // pushConstantRanges[]
(pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBases (pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBaseIndices[]
} }
size_t PipelineLayout::getNumDescriptorSets() const size_t PipelineLayout::getDescriptorSetCount() const
{ {
return setLayoutCount; return descriptorSetCount;
} }
DescriptorSetLayout const *PipelineLayout::getDescriptorSetLayout(size_t descriptorSet) const uint32_t PipelineLayout::getDynamicDescriptorCount(uint32_t setNumber) const
{
return getDescriptorSetLayout(setNumber)->getDynamicDescriptorCount();
}
uint32_t PipelineLayout::getDynamicOffsetBaseIndex(uint32_t setNumber) const
{
return dynamicOffsetBaseIndices[setNumber];
}
uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const
{
return getDynamicOffsetBaseIndex(setNumber) + getDescriptorSetLayout(setNumber)->getDynamicOffsetIndex(bindingNumber);
}
uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const
{ {
ASSERT(descriptorSet < setLayoutCount); return getDescriptorSetLayout(setNumber)->getBindingOffset(bindingNumber);
return setLayouts[descriptorSet];
} }
uint32_t PipelineLayout::getDynamicOffsetBase(size_t descriptorSet) const VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const
{
return getDescriptorSetLayout(setNumber)->getDescriptorType(bindingNumber);
}
uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const
{
return DescriptorSetLayout::GetDescriptorSize(getDescriptorType(setNumber, bindingNumber));
}
bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const
{
return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
}
DescriptorSetLayout const *PipelineLayout::getDescriptorSetLayout(size_t descriptorSet) const
{ {
ASSERT(descriptorSet < setLayoutCount); ASSERT(descriptorSet < descriptorSetCount);
return dynamicOffsetBases[descriptorSet]; return descriptorSetLayouts[descriptorSet];
} }
} // namespace vk } // namespace vk
...@@ -27,21 +27,29 @@ public: ...@@ -27,21 +27,29 @@ public:
static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo);
size_t getNumDescriptorSets() const; size_t getDescriptorSetCount() const;
DescriptorSetLayout const *getDescriptorSetLayout(size_t descriptorSet) const; uint32_t getDynamicDescriptorCount(uint32_t setNumber) const;
// Returns the index into the pipeline's dynamic offsets array for
// the given descriptor set (and binding number).
uint32_t getDynamicOffsetBaseIndex(uint32_t setNumber) const;
uint32_t getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const;
// Returns the starting index into the pipeline's dynamic offsets array for uint32_t getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const;
// the given descriptor set. VkDescriptorType getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const;
uint32_t getDynamicOffsetBase(size_t descriptorSet) const; uint32_t getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const;
bool isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const;
const uint32_t identifier; const uint32_t identifier;
private: private:
uint32_t setLayoutCount = 0; DescriptorSetLayout const *getDescriptorSetLayout(size_t descriptorSet) const;
DescriptorSetLayout **setLayouts = nullptr;
uint32_t pushConstantRangeCount = 0; const uint32_t descriptorSetCount = 0;
const DescriptorSetLayout **descriptorSetLayouts = nullptr;
const uint32_t pushConstantRangeCount = 0;
VkPushConstantRange *pushConstantRanges = nullptr; VkPushConstantRange *pushConstantRanges = nullptr;
uint32_t *dynamicOffsetBases = nullptr; // Base offset per set layout. 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