Reduce memory requirements for vkCmdBindDescriptorSets.
Split MVKCmdBindDescriptorSetsStatic into separate subclasses,
depending on use of dynamic offsets, and make them template classes
based on descriptor set count.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h
index bf75742..ec12615 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h
@@ -120,10 +120,49 @@
#pragma mark -
-#pragma mark MVKCmdBindDescriptorSets
+#pragma mark MVKCmdBindDescriptorSetsStatic
-/** Vulkan command to bind descriptor sets. */
-class MVKCmdBindDescriptorSets : public MVKCommand {
+/**
+ * Vulkan command to bind descriptor sets without dynamic offsets.
+ * Template class to balance vector pre-allocations between very common low counts and fewer larger counts.
+ */
+template <size_t N>
+class MVKCmdBindDescriptorSetsStatic : public MVKCommand {
+
+public:
+ VkResult setContent(MVKCommandBuffer* cmdBuff,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t setCount,
+ const VkDescriptorSet* pDescriptorSets);
+
+ void encode(MVKCommandEncoder* cmdEncoder) override;
+
+protected:
+ MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
+
+ MVKVectorInline<MVKDescriptorSet*, N> _descriptorSets;
+ MVKPipelineLayout* _pipelineLayout;
+ VkPipelineBindPoint _pipelineBindPoint;
+ uint32_t _firstSet;
+};
+
+// Concrete template class implementations.
+typedef MVKCmdBindDescriptorSetsStatic<1> MVKCmdBindDescriptorSetsStatic1;
+typedef MVKCmdBindDescriptorSetsStatic<4> MVKCmdBindDescriptorSetsStatic4;
+typedef MVKCmdBindDescriptorSetsStatic<8> MVKCmdBindDescriptorSetsStaticMulti;
+
+
+#pragma mark -
+#pragma mark MVKCmdBindDescriptorSetsDynamic
+
+/**
+ * Vulkan command to bind descriptor sets with dynamic offsets.
+ * Template class to balance vector pre-allocations between very common low counts and fewer larger counts.
+ */
+template <size_t N>
+class MVKCmdBindDescriptorSetsDynamic : public MVKCmdBindDescriptorSetsStatic<N> {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
@@ -140,13 +179,13 @@
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
- VkPipelineBindPoint _pipelineBindPoint;
- MVKPipelineLayout* _pipelineLayout;
- MVKVectorInline<MVKDescriptorSet*, 8> _descriptorSets;
- MVKVectorInline<uint32_t, 8> _dynamicOffsets;
- uint32_t _firstSet;
+ MVKVectorInline<uint32_t, N> _dynamicOffsets;
};
+// Concrete template class implementations.
+typedef MVKCmdBindDescriptorSetsDynamic<4> MVKCmdBindDescriptorSetsDynamic4;
+typedef MVKCmdBindDescriptorSetsDynamic<8> MVKCmdBindDescriptorSetsDynamicMulti;
+
#pragma mark -
#pragma mark MVKCmdPushConstants
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
index 50252ad..1658a52 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
@@ -182,16 +182,15 @@
#pragma mark -
-#pragma mark MVKCmdBindDescriptorSets
+#pragma mark MVKCmdBindDescriptorSetsStatic
-VkResult MVKCmdBindDescriptorSets::setContent(MVKCommandBuffer* cmdBuff,
- VkPipelineBindPoint pipelineBindPoint,
- VkPipelineLayout layout,
- uint32_t firstSet,
- uint32_t setCount,
- const VkDescriptorSet* pDescriptorSets,
- uint32_t dynamicOffsetCount,
- const uint32_t* pDynamicOffsets) {
+template <size_t N>
+VkResult MVKCmdBindDescriptorSetsStatic<N>::setContent(MVKCommandBuffer* cmdBuff,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t setCount,
+ const VkDescriptorSet* pDescriptorSets) {
_pipelineBindPoint = pipelineBindPoint;
_pipelineLayout = (MVKPipelineLayout*)layout;
_firstSet = firstSet;
@@ -203,6 +202,35 @@
_descriptorSets.push_back((MVKDescriptorSet*)pDescriptorSets[dsIdx]);
}
+ return VK_SUCCESS;
+}
+
+template <size_t N>
+void MVKCmdBindDescriptorSetsStatic<N>::encode(MVKCommandEncoder* cmdEncoder) {
+ _pipelineLayout->bindDescriptorSets(cmdEncoder, _descriptorSets, _firstSet, nullptr);
+}
+
+template class MVKCmdBindDescriptorSetsStatic<1>;
+template class MVKCmdBindDescriptorSetsStatic<4>;
+template class MVKCmdBindDescriptorSetsStatic<8>;
+
+
+#pragma mark -
+#pragma mark MVKCmdBindDescriptorSetsDynamic
+
+template <size_t N>
+VkResult MVKCmdBindDescriptorSetsDynamic<N>::setContent(MVKCommandBuffer* cmdBuff,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t setCount,
+ const VkDescriptorSet* pDescriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t* pDynamicOffsets) {
+
+ MVKCmdBindDescriptorSetsStatic<N>::setContent(cmdBuff, pipelineBindPoint, layout,
+ firstSet, setCount, pDescriptorSets);
+
// Add the dynamic offsets
_dynamicOffsets.clear(); // Clear for reuse
_dynamicOffsets.reserve(dynamicOffsetCount);
@@ -213,10 +241,14 @@
return VK_SUCCESS;
}
-void MVKCmdBindDescriptorSets::encode(MVKCommandEncoder* cmdEncoder) {
- _pipelineLayout->bindDescriptorSets(cmdEncoder, _descriptorSets, _firstSet, _dynamicOffsets);
+template <size_t N>
+void MVKCmdBindDescriptorSetsDynamic<N>::encode(MVKCommandEncoder* cmdEncoder) {
+ MVKCmdBindDescriptorSetsStatic<N>::_pipelineLayout->bindDescriptorSets(cmdEncoder, MVKCmdBindDescriptorSetsStatic<N>::_descriptorSets, MVKCmdBindDescriptorSetsStatic<N>::_firstSet, &_dynamicOffsets);
}
+template class MVKCmdBindDescriptorSetsDynamic<4>;
+template class MVKCmdBindDescriptorSetsDynamic<8>;
+
#pragma mark -
#pragma mark MVKCmdPushConstants
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def
index f48bd92..815ed97 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandTypePools.def
@@ -58,7 +58,8 @@
MVK_CMD_TYPE_POOL(NextSubpass)
MVK_CMD_TYPE_POOL(EndRenderPass)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(ExecuteCommands, 1)
-MVK_CMD_TYPE_POOL(BindDescriptorSets)
+MVK_CMD_TYPE_POOLS_FROM_TWO_THRESHOLDS(BindDescriptorSetsStatic, 1, 4)
+MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(BindDescriptorSetsDynamic, 4)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetViewport, 1)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetScissor, 1)
MVK_CMD_TYPE_POOL(SetLineWidth)
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
index 2d53f1a..c19f2eb 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h
@@ -89,7 +89,7 @@
MVKDescriptorSet* descSet,
uint32_t descStartIndex,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex);
/** Encodes this binding layout and the specified descriptor on the specified command encoder immediately. */
@@ -148,7 +148,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) = 0;
/**
@@ -202,7 +202,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
@@ -280,7 +280,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
@@ -319,7 +319,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
@@ -391,7 +391,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex);
void write(MVKDescriptorSet* mvkDescSet,
@@ -433,7 +433,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
@@ -473,7 +473,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
@@ -511,7 +511,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) override;
void write(MVKDescriptorSet* mvkDescSet,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
index a5cb26b..3179cc2 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm
@@ -83,7 +83,7 @@
MVKDescriptorSet* descSet,
uint32_t descStartIndex,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
// Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding.
@@ -93,7 +93,7 @@
for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) {
MVKDescriptor* mvkDesc = descSet->getDescriptor(descStartIndex + descIdx);
mvkDesc->bind(cmdEncoder, _info.descriptorType, descIdx, _applyToStage,
- mtlIdxs, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIdxs, pDynamicOffsets, pDynamicOffsetIndex);
}
return descCnt;
}
@@ -476,7 +476,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
MVKMTLBufferBinding bb;
NSUInteger bufferDynamicOffset = 0;
@@ -485,8 +485,10 @@
// 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:
- bufferDynamicOffset = dynamicOffsets[*pDynamicOffsetIndex];
- (*pDynamicOffsetIndex)++; // Move on to next dynamic offset (and feedback to caller)
+ if (pDynamicOffsets) {
+ bufferDynamicOffset = (*pDynamicOffsets)[*pDynamicOffsetIndex];
+ (*pDynamicOffsetIndex)++; // Move on to next dynamic offset (and feedback to caller)
+ }
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
if (_mvkBuffer) {
@@ -581,7 +583,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
MVKMTLBufferBinding bb;
@@ -678,7 +680,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
MVKMTLTextureBinding tb;
MVKMTLBufferBinding bb;
@@ -796,7 +798,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
MVKMTLSamplerStateBinding sb;
switch (descriptorType) {
@@ -914,12 +916,12 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER: {
MVKSamplerDescriptorMixin::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, pDynamicOffsets, pDynamicOffsetIndex);
break;
}
@@ -983,14 +985,14 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
MVKImageDescriptor::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, pDynamicOffsets, pDynamicOffsetIndex);
MVKSamplerDescriptorMixin::bind(cmdEncoder, descriptorType, descriptorIndex, stages,
- mtlIndexes, dynamicOffsets, pDynamicOffsetIndex);
+ mtlIndexes, pDynamicOffsets, pDynamicOffsetIndex);
break;
}
@@ -1057,7 +1059,7 @@
uint32_t descriptorIndex,
bool stages[],
MVKShaderResourceBinding& mtlIndexes,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
MVKMTLTextureBinding tb;
MVKMTLBufferBinding bb;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index 51756a3..a5cbe57 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -46,7 +46,7 @@
void bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
MVKDescriptorSet* descSet,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index 45d5ba5..59c2902 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -38,7 +38,7 @@
void MVKDescriptorSetLayout::bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
MVKDescriptorSet* descSet,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
- MVKVector<uint32_t>& dynamicOffsets,
+ MVKVector<uint32_t>* pDynamicOffsets,
uint32_t* pDynamicOffsetIndex) {
if (_isPushDescriptorLayout) return;
@@ -46,7 +46,7 @@
uint32_t bindCnt = (uint32_t)_bindings.size();
for (uint32_t descIdx = 0, bindIdx = 0; bindIdx < bindCnt; bindIdx++) {
descIdx += _bindings[bindIdx].bind(cmdEncoder, descSet, descIdx,
- dslMTLRezIdxOffsets, dynamicOffsets,
+ dslMTLRezIdxOffsets, pDynamicOffsets,
pDynamicOffsetIndex);
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
index 431f02f..3221299 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
@@ -56,7 +56,7 @@
void bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
MVKVector<MVKDescriptorSet*>& descriptorSets,
uint32_t firstSet,
- MVKVector<uint32_t>& dynamicOffsets);
+ MVKVector<uint32_t>* pDynamicOffsets);
/** Updates a descriptor set in a command encoder. */
void pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index c67ab8c..d270906 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -40,7 +40,7 @@
void MVKPipelineLayout::bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
MVKVector<MVKDescriptorSet*>& descriptorSets,
uint32_t firstSet,
- MVKVector<uint32_t>& dynamicOffsets) {
+ MVKVector<uint32_t>* pDynamicOffsets) {
clearConfigurationResult();
uint32_t pDynamicOffsetIndex = 0;
uint32_t dsCnt = (uint32_t)descriptorSets.size();
@@ -50,7 +50,7 @@
MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[dslIdx];
dsl->bindDescriptorSet(cmdEncoder, descSet,
_dslMTLResourceIndexOffsets[dslIdx],
- dynamicOffsets, &pDynamicOffsetIndex);
+ pDynamicOffsets, &pDynamicOffsetIndex);
setConfigurationResult(dsl->getConfigurationResult());
}
}
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index 9254cf4..6428509 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -1449,8 +1449,13 @@
const uint32_t* pDynamicOffsets) {
MVKTraceVulkanCallStart();
- MVKAddCmd(BindDescriptorSets, commandBuffer, pipelineBindPoint, layout,
- firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+ if (dynamicOffsetCount) {
+ MVKAddCmdFromThreshold(BindDescriptorSetsDynamic, setCount, 4, commandBuffer, pipelineBindPoint, layout,
+ firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+ } else {
+ MVKAddCmdFromTwoThresholds(BindDescriptorSetsStatic, setCount, 1, 4, commandBuffer, pipelineBindPoint, layout,
+ firstSet, setCount, pDescriptorSets);
+ }
MVKTraceVulkanCallEnd();
}