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
auto d = descriptorDecorations.at(baseId);
ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
auto stride = static_cast<uint32_t>(setLayout->getBindingStride(d.Binding));
ptr.base += stride * GetConstScalarInt(indexIds[i]);
uint32_t descriptorSize = routine->pipelineLayout->getDescriptorSize(d.DescriptorSet, d.Binding);
ptr.base += descriptorSize * GetConstScalarInt(indexIds[i]);
}
else
{
......
......@@ -345,8 +345,7 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT
bool isCubeMap = imageType.definition.word(3) == spv::DimCube;
const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
auto descriptorType = routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base;
......@@ -409,8 +408,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQueryLevels(InsnIterator insn, Emi
auto imageId = Object::ID(insn.word(3));
const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
auto descriptorType = state->routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base;
Int mipLevels = 0;
......@@ -442,8 +440,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageQuerySamples(InsnIterator insn, Em
ASSERT(imageTy.definition.word(6 /* MS */) == 1);
const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
auto descriptorType = setLayout->getDescriptorType(d.Binding);
auto descriptorType = state->routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base;
Int sampleCount = 0;
......
......@@ -170,9 +170,7 @@ SpirvShader::EmitResult SpirvShader::EmitVariable(InsnIterator insn, EmitState *
ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0);
uint32_t arrayIndex = 0; // TODO(b/129523279)
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
uint32_t bindingOffset = static_cast<uint32_t>(setLayout->getBindingOffset(d.Binding, arrayIndex));
uint32_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding);
Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
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.
......@@ -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.Binding >= 0);
auto set = state->getPointer(id);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
int bindingOffset = static_cast<int>(setLayout->getBindingOffset(d.Binding, arrayIndex));
uint32_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding);
uint32_t descriptorSize = routine->pipelineLayout->getDescriptorSize(d.DescriptorSet, d.Binding);
uint32_t descriptorOffset = bindingOffset + descriptorSize * 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*
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 =
routine->pipelineLayout->getDynamicOffsetBase(d.DescriptorSet) +
setLayout->getDynamicDescriptorOffset(d.Binding) +
uint32_t dynamicOffsetIndex =
routine->pipelineLayout->getDynamicOffsetIndex(d.DescriptorSet, d.Binding) +
arrayIndex;
Int offset = routine->descriptorDynamicOffsets[dynamicBindingIndex];
Int offset = routine->descriptorDynamicOffsets[dynamicOffsetIndex];
Int robustnessSize = *Pointer<Int>(descriptor + OFFSET(vk::BufferDescriptor, robustnessSize));
return SIMD::Pointer(data + offset, Min(size, robustnessSize - offset));
}
else
......
......@@ -13,6 +13,7 @@
// limitations under the License.
#include "Reactor.hpp"
#include "Debug.hpp"
#include "Print.hpp"
......
......@@ -1087,11 +1087,11 @@ private:
class CmdBindDescriptorSet : public vk::CommandBuffer::Command
{
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)
: pipelineBindPoint(pipelineBindPoint)
, pipelineLayout(pipelineLayout)
, set(set)
, setNumber(setNumber)
, descriptorSet(descriptorSet)
, dynamicOffsetCount(dynamicOffsetCount)
{
......@@ -1103,26 +1103,26 @@ public:
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 dynamicOffsetBase = pipelineLayout->getDynamicOffsetBase(set);
ASSERT_OR_RETURN(dynamicOffsetBase + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
auto dynamicBindingBaseIndex = pipelineLayout->getDynamicOffsetBaseIndex(setNumber);
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++)
{
pipelineState.descriptorDynamicOffsets[dynamicOffsetBase + i] = dynamicOffsets[i];
pipelineState.descriptorDynamicOffsets[dynamicBindingBaseIndex + i] = dynamicOffsets[i];
}
}
std::string description() override { return "vkCmdBindDescriptorSet()"; }
private:
VkPipelineBindPoint pipelineBindPoint;
const vk::PipelineLayout *pipelineLayout;
uint32_t set;
vk::DescriptorSet *descriptorSet;
uint32_t dynamicOffsetCount;
const VkPipelineBindPoint pipelineBindPoint;
const vk::PipelineLayout *const pipelineLayout;
const uint32_t setNumber;
vk::DescriptorSet *const descriptorSet;
const uint32_t dynamicOffsetCount;
vk::DescriptorSet::DynamicOffsets dynamicOffsets;
};
......@@ -1568,9 +1568,7 @@ void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, co
for(uint32_t i = 0; i < descriptorSetCount; i++)
{
auto descriptorSetIndex = firstSet + i;
auto setLayout = layout->getDescriptorSetLayout(descriptorSetIndex);
auto numDynamicDescriptors = setLayout->getDynamicDescriptorCount();
uint32_t numDynamicDescriptors = layout->getDynamicDescriptorCount(descriptorSetIndex);
ASSERT(numDynamicDescriptors == 0 || pDynamicOffsets != nullptr);
ASSERT(dynamicOffsetCount >= numDynamicDescriptors);
......
......@@ -109,7 +109,7 @@ size_t DescriptorSetLayout::ComputeRequiredAllocationSize(const VkDescriptorSetL
immutableSamplerCount * sizeof(VkSampler);
}
size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
uint32_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
{
switch(type)
{
......@@ -117,22 +117,28 @@ size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
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_TEXEL_BUFFER:
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_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
return sizeof(BufferDescriptor);
return static_cast<uint32_t>(sizeof(BufferDescriptor));
default:
UNSUPPORTED("Unsupported Descriptor Type");
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
{
// vk::DescriptorSet has a header with a pointer to the layout.
......@@ -176,29 +182,10 @@ void DescriptorSetLayout::initialize(DescriptorSet *descriptorSet)
}
}
size_t DescriptorSetLayout::getBindingStride(uint32_t binding) 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
uint32_t DescriptorSetLayout::getBindingOffset(uint32_t bindingNumber) const
{
ASSERT(binding < bindingsArraySize);
return isDynamic(bindings[binding].descriptorType);
ASSERT(bindingNumber < bindingsArraySize);
return bindings[bindingNumber].offset;
}
uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
......@@ -206,7 +193,7 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
uint32_t count = 0;
for(size_t i = 0; i < bindingsArraySize; i++)
{
if(isDynamic(bindings[i].descriptorType))
if(IsDescriptorDynamic(bindings[i].descriptorType))
{
count += bindings[i].descriptorCount;
}
......@@ -215,15 +202,15 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorCount() const
return count;
}
uint32_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const
uint32_t DescriptorSetLayout::getDynamicOffsetIndex(uint32_t bindingNumber) const
{
ASSERT(binding < bindingsArraySize);
ASSERT(isDynamic(bindings[binding].descriptorType));
ASSERT(bindingNumber < bindingsArraySize);
ASSERT(IsDescriptorDynamic(bindings[bindingNumber].descriptorType));
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;
}
......@@ -232,17 +219,17 @@ uint32_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const
return index;
}
VkDescriptorType DescriptorSetLayout::getDescriptorType(uint32_t binding) const
VkDescriptorType DescriptorSetLayout::getDescriptorType(uint32_t bindingNumber) const
{
ASSERT(binding < bindingsArraySize);
return bindings[binding].descriptorType;
ASSERT(bindingNumber < bindingsArraySize);
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);
*typeSize = GetDescriptorSize(bindings[binding].descriptorType);
size_t byteOffset = bindings[binding].offset + (*typeSize * arrayElement);
ASSERT(bindingNumber < bindingsArraySize);
*typeSize = GetDescriptorSize(bindings[bindingNumber].descriptorType);
size_t byteOffset = bindings[bindingNumber].offset + (*typeSize * arrayElement);
ASSERT(((*typeSize * count) + byteOffset) <= getDescriptorSetDataSize()); // Make sure the operation will not go out of bounds
return &descriptorSet->data[byteOffset];
......@@ -261,7 +248,7 @@ void DescriptorSetLayout::WriteDescriptorSet(Device *device, DescriptorSet *dstS
ASSERT(binding.descriptorType == entry.descriptorType);
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.
......@@ -629,10 +616,10 @@ void DescriptorSetLayout::CopyDescriptorSet(const VkCopyDescriptorSet &descripto
ASSERT(dstLayout);
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;
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);
size_t writeSize = dstTypeSize * descriptorCopies.descriptorCount;
......
......@@ -21,6 +21,8 @@
#include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkSampler.hpp"
#include <cstdint>
namespace vk {
class DescriptorSet;
......@@ -93,7 +95,9 @@ public:
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 CopyDescriptorSet(const VkCopyDescriptorSet &descriptorCopies);
......@@ -106,33 +110,23 @@ public:
size_t getDescriptorSetAllocationSize() const;
// Returns the byte offset from the base address of the descriptor set for
// the given binding and array element within that binding.
size_t getBindingOffset(uint32_t binding, size_t arrayElement) const;
// Returns the stride of an array of descriptors
size_t getBindingStride(uint32_t binding) const;
// the given binding.
uint32_t getBindingOffset(uint32_t bindingNumber) const;
// Returns the number of descriptors across all bindings that are dynamic
// (see isBindingDynamic).
// Returns the number of descriptors across all bindings that are dynamic.
uint32_t getDynamicDescriptorCount() const;
// Returns the relative offset into the pipeline's dynamic offsets array for
// the given binding. This offset should be added to the base offset
// Returns the relative index into the pipeline's dynamic offsets array for
// the given binding. This index should be added to the base index
// returned by PipelineLayout::getDynamicOffsetBase() to produce the
// starting index for dynamic descriptors.
uint32_t getDynamicDescriptorOffset(uint32_t binding) 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;
uint32_t getDynamicOffsetIndex(uint32_t bindingNumber) const;
// Returns the descriptor type for the given binding.
VkDescriptorType getDescriptorType(uint32_t binding) const;
uint8_t *getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t *typeSize) const;
VkDescriptorType getDescriptorType(uint32_t bindingNumber) const;
private:
uint8_t *getDescriptorPointer(DescriptorSet *descriptorSet, uint32_t bindingNumber, uint32_t arrayElement, uint32_t count, size_t *typeSize) const;
size_t getDescriptorSetDataSize() const;
static bool isDynamic(VkDescriptorType type);
......
......@@ -16,6 +16,7 @@
#define VK_OBJECT_HPP_
#include "VkMemory.h"
#include "VkConfig.h"
#include "System/Memory.hpp"
......
......@@ -23,16 +23,16 @@ static std::atomic<uint32_t> layoutIdentifierSerial = { 1 }; // Start at 1. 0 i
PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem)
: identifier(layoutIdentifierSerial++)
, setLayoutCount(pCreateInfo->setLayoutCount)
, descriptorSetCount(pCreateInfo->setLayoutCount)
, pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
{
char *hostMem = reinterpret_cast<char *>(mem);
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++)
{
setLayouts[i] = vk::Cast(pCreateInfo->pSetLayouts[i]);
descriptorSetLayouts[i] = vk::Cast(pCreateInfo->pSetLayouts[i]);
}
hostMem += setLayoutsSize;
......@@ -41,44 +41,73 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, vo
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
hostMem += pushConstantRangesSize;
dynamicOffsetBases = reinterpret_cast<uint32_t *>(hostMem);
dynamicOffsetBaseIndices = reinterpret_cast<uint32_t *>(hostMem);
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);
dynamicOffsetBases[i] = dynamicOffsetBase;
dynamicOffsetBaseIndices[i] = dynamicOffsetBase;
dynamicOffsetBase += dynamicDescriptorCount;
}
}
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)
{
return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *)) +
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) +
(pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBases
return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout *)) + // descriptorSetLayouts[]
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) + // pushConstantRanges[]
(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 setLayouts[descriptorSet];
return getDescriptorSetLayout(setNumber)->getBindingOffset(bindingNumber);
}
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);
return dynamicOffsetBases[descriptorSet];
ASSERT(descriptorSet < descriptorSetCount);
return descriptorSetLayouts[descriptorSet];
}
} // namespace vk
......@@ -27,21 +27,29 @@ public:
static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo);
size_t getNumDescriptorSets() const;
DescriptorSetLayout const *getDescriptorSetLayout(size_t descriptorSet) const;
size_t getDescriptorSetCount() 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
// the given descriptor set.
uint32_t getDynamicOffsetBase(size_t descriptorSet) const;
uint32_t getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const;
VkDescriptorType getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const;
uint32_t getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const;
bool isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const;
const uint32_t identifier;
private:
uint32_t setLayoutCount = 0;
DescriptorSetLayout **setLayouts = nullptr;
uint32_t pushConstantRangeCount = 0;
DescriptorSetLayout const *getDescriptorSetLayout(size_t descriptorSet) const;
const uint32_t descriptorSetCount = 0;
const DescriptorSetLayout **descriptorSetLayouts = nullptr;
const uint32_t pushConstantRangeCount = 0;
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)
......
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