Merge pull request #980 from mbechard/master
dynamicOffsets are supposed to be ordered by binding index
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
index e283a73..424a07f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
@@ -76,6 +76,13 @@
/** Returns the descriptor type of this layout. */
inline VkDescriptorType getDescriptorType() { return _info.descriptorType; }
+ /** If this descriptor is a dynamic buffer type, this returns the index within the dynamicOffsets array where the
+ first descriptor in this binding is located. It will start at 0 for this set, so this number should be incremented
+ by the number of dynamic offsets in previous sets given in vkCmdBindDescriptorSets */
+ inline uint32_t getDynamicOffsetIndex() { return _dynamicOffsetIndex; }
+
+ void setDynamicOffsetIndex(uint32_t i) { _dynamicOffsetIndex = i; }
+
/** Returns the immutable sampler at the index, or nullptr if immutable samplers are not used. */
MVKSampler* getImmutableSampler(uint32_t index);
@@ -89,7 +96,7 @@
uint32_t descStartIndex,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex);
+ uint32_t baseDynamicOffsetIndex);
/** Encodes this binding layout and the specified descriptor on the specified command encoder immediately. */
void push(MVKCommandEncoder* cmdEncoder,
@@ -126,6 +133,7 @@
MVKSmallVector<MVKSampler*> _immutableSamplers;
MVKShaderResourceBinding _mtlResourceIndexOffsets;
bool _applyToStage[kMVKShaderStageMax];
+ uint32_t _dynamicOffsetIndex;
};
@@ -149,7 +157,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) = 0;
+ uint32_t dynamicOffsetIndex) = 0;
/**
* Updates the internal binding from the specified content. The format of the content depends
@@ -205,7 +213,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -283,7 +291,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -324,7 +332,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -396,7 +404,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex);
+ uint32_t dynamicOffsetIndex);
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -438,7 +446,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -478,7 +486,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
@@ -516,7 +524,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) override;
+ uint32_t dynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
VkDescriptorType descriptorType,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
index 96dc03b..81e1387 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
@@ -84,7 +84,7 @@
uint32_t descStartIndex,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t baseDynamicOffsetIndex) {
// Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding.
MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets;
@@ -92,7 +92,8 @@
uint32_t descCnt = getDescriptorCount();
for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) {
MVKDescriptor* mvkDesc = descSet->getDescriptor(descStartIndex + descIdx);
- mvkDesc->bind(cmdEncoder, _info.descriptorType, descIdx, _applyToStage, mtlIdxs, dynamicOffsets, pDynamicOffsetIndex);
+ mvkDesc->bind(cmdEncoder, _info.descriptorType, descIdx, _applyToStage, mtlIdxs, dynamicOffsets,
+ baseDynamicOffsetIndex + _dynamicOffsetIndex + descIdx);
}
return descCnt;
}
@@ -360,7 +361,8 @@
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDevice* device,
MVKDescriptorSetLayout* layout,
- const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device), _layout(layout) {
+ const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device), _layout(layout),
+ _dynamicOffsetIndex(0) {
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
// Determine if this binding is used by this shader stage
@@ -390,7 +392,8 @@
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(const MVKDescriptorSetLayoutBinding& binding) :
MVKBaseDeviceObject(binding._device), _layout(binding._layout),
_info(binding._info), _immutableSamplers(binding._immutableSamplers),
- _mtlResourceIndexOffsets(binding._mtlResourceIndexOffsets) {
+ _mtlResourceIndexOffsets(binding._mtlResourceIndexOffsets),
+ _dynamicOffsetIndex(0) {
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
_applyToStage[i] = binding._applyToStage[i];
@@ -494,7 +497,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
MVKMTLBufferBinding bb;
NSUInteger bufferDynamicOffset = 0;
@@ -502,8 +505,8 @@
// After determining dynamic part of offset (zero otherwise), fall through to non-dynamic handling
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- if (dynamicOffsets.size > *pDynamicOffsetIndex) {
- bufferDynamicOffset = dynamicOffsets[(*pDynamicOffsetIndex)++]; // Move on to next dynamic offset (and feedback to caller)
+ if (dynamicOffsets.size > dynamicOffsetIndex) {
+ bufferDynamicOffset = dynamicOffsets[dynamicOffsetIndex];
}
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
@@ -603,7 +606,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
MVKMTLBufferBinding bb;
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
@@ -690,7 +693,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
@@ -809,7 +812,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
MVKMTLSamplerStateBinding sb;
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
@@ -927,11 +930,11 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER: {
MVKSamplerDescriptorMixin::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, dynamicOffsets, dynamicOffsetIndex);
break;
}
@@ -996,13 +999,13 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
MVKImageDescriptor::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, dynamicOffsets, dynamicOffsetIndex);
MVKSamplerDescriptorMixin::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, dynamicOffsets, dynamicOffsetIndex);
break;
}
@@ -1070,7 +1073,7 @@
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t dynamicOffsetIndex) {
MVKMTLTextureBinding tb;
MVKMTLBufferBinding bb;
switch (descriptorType) {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index 532c14f..3f1c0ca 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -43,12 +43,14 @@
/** Returns the debug report object type of this object. */
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT; }
+ inline uint32_t getDynamicDescriptorCount() { return _dynamicDescriptorCount; }
+
/** Encodes this descriptor set layout and the specified descriptor set on the specified command encoder. */
void bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
MVKDescriptorSet* descSet,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex);
+ uint32_t baseDynamicOffsetIndex);
/** Encodes this descriptor set layout and the specified descriptor updates on the specified command encoder immediately. */
@@ -90,6 +92,7 @@
std::unordered_map<uint32_t, uint32_t> _bindingToIndex;
MVKShaderResourceBinding _mtlResourceCounts;
uint32_t _descriptorCount;
+ uint32_t _dynamicDescriptorCount;
bool _isPushDescriptorLayout;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index de5a9f3..ed4896f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -39,7 +39,7 @@
MVKDescriptorSet* descSet,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
MVKArrayRef<uint32_t> dynamicOffsets,
- uint32_t* pDynamicOffsetIndex) {
+ uint32_t baseDynamicOffsetIndex) {
if (_isPushDescriptorLayout) return;
clearConfigurationResult();
@@ -47,7 +47,7 @@
for (uint32_t descIdx = 0, bindIdx = 0; bindIdx < bindCnt; bindIdx++) {
descIdx += _bindings[bindIdx].bind(cmdEncoder, descSet, descIdx,
dslMTLRezIdxOffsets, dynamicOffsets,
- pDynamicOffsetIndex);
+ baseDynamicOffsetIndex);
}
}
@@ -188,11 +188,37 @@
// Create the descriptor layout bindings
_descriptorCount = 0;
_bindings.reserve(pCreateInfo->bindingCount);
+ struct SortInfo
+ {
+ const VkDescriptorSetLayoutBinding* binding;
+ uint32_t index;
+ };
+ std::vector<SortInfo> dynamicBindings;
+
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
_bindings.emplace_back(_device, this, &pCreateInfo->pBindings[i]);
_descriptorCount += _bindings.back().getDescriptorCount();
_bindingToIndex[pCreateInfo->pBindings[i].binding] = i;
- }
+ if (pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
+ dynamicBindings.push_back(SortInfo{ &pCreateInfo->pBindings[i], i });
+ }
+ }
+
+ // Dynamic offsets are ordered by binding index when given to vkCmdBindDescriptorSets
+ // not by the order they are provided in the layout.
+ // So we want to sort by binding, and then count how many dynamic offsets the binding
+ // has so we can assign each binding it's first dynamic offset index
+ std::sort(dynamicBindings.begin(), dynamicBindings.end(),
+ [](const SortInfo &info1, const SortInfo &info2) {
+ return info1.binding->binding < info2.binding->binding; });
+
+ uint32_t curOffsetIndex = 0;
+ for (auto &i : dynamicBindings) {
+ _bindings[i.index].setDynamicOffsetIndex(curOffsetIndex);
+ curOffsetIndex += i.binding->descriptorCount;
+ }
+ _dynamicDescriptorCount = curOffsetIndex;
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 46dfa05..28227ba 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -42,7 +42,7 @@
uint32_t firstSet,
MVKArrayRef<uint32_t> dynamicOffsets) {
clearConfigurationResult();
- uint32_t pDynamicOffsetIndex = 0;
+ uint32_t baseDynamicOffsetIndex = 0;
size_t dsCnt = descriptorSets.size;
for (uint32_t dsIdx = 0; dsIdx < dsCnt; dsIdx++) {
MVKDescriptorSet* descSet = descriptorSets[dsIdx];
@@ -50,7 +50,8 @@
MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[dslIdx];
dsl->bindDescriptorSet(cmdEncoder, descSet,
_dslMTLResourceIndexOffsets[dslIdx],
- dynamicOffsets, &pDynamicOffsetIndex);
+ dynamicOffsets, baseDynamicOffsetIndex);
+ baseDynamicOffsetIndex += dsl->getDynamicDescriptorCount();
setConfigurationResult(dsl->getConfigurationResult());
}
}