Fix crash in vkDestroyPipelineLayout().
MVKPipelineLayout hold retained/released pointers to MVKDescriptorSetLayout,
instead of copies of MVKDescriptorSetLayout instances.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index ab8f920..3cdd3fb 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -24,6 +24,7 @@
- Revert to supporting host-coherent memory for linear images on macOS.
- Ensure Vulkan loader magic number is set every time before returning any dispatchable Vulkan handle.
- Fix crash when `VkDeviceCreateInfo` specifies queue families out of numerical order.
+- Fix crash in `vkDestroyPipelineLayout()`.
- Remove error logging on `VK_TIMEOUT` of `VkSemaphore` and `VkFence`.
- Consolidate the various linkable objects into a `MVKLinkableMixin` template base class.
- Use `MVKVector` whenever possible in MoltenVK, especially within render loop.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
index 30d48c2..020af29 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
@@ -102,10 +102,12 @@
/** Constructs an instance for the specified device. */
MVKPipelineLayout(MVKDevice* device, const VkPipelineLayoutCreateInfo* pCreateInfo);
+ ~MVKPipelineLayout() override;
+
protected:
void propogateDebugName() override {}
- MVKVectorInline<MVKDescriptorSetLayout, 8> _descriptorSetLayouts;
+ MVKVectorInline<MVKDescriptorSetLayout*, 8> _descriptorSetLayouts;
MVKVectorInline<MVKShaderResourceBinding, 8> _dslMTLResourceIndexOffsets;
MVKVectorInline<VkPushConstantRange, 8> _pushConstants;
MVKShaderResourceBinding _pushConstantsMTLResourceIndexes;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 265d922..1d1ae2d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -47,11 +47,11 @@
for (uint32_t dsIdx = 0; dsIdx < dsCnt; dsIdx++) {
MVKDescriptorSet* descSet = descriptorSets[dsIdx];
uint32_t dslIdx = firstSet + dsIdx;
- auto& dsl = _descriptorSetLayouts[dslIdx];
- dsl.bindDescriptorSet(cmdEncoder, descSet,
- _dslMTLResourceIndexOffsets[dslIdx],
- dynamicOffsets, &pDynamicOffsetIndex);
- setConfigurationResult(dsl.getConfigurationResult());
+ MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[dslIdx];
+ dsl->bindDescriptorSet(cmdEncoder, descSet,
+ _dslMTLResourceIndexOffsets[dslIdx],
+ dynamicOffsets, &pDynamicOffsetIndex);
+ setConfigurationResult(dsl->getConfigurationResult());
}
}
@@ -60,9 +60,9 @@
MVKVector<VkWriteDescriptorSet>& descriptorWrites,
uint32_t set) {
clearConfigurationResult();
- auto& dsl = _descriptorSetLayouts[set];
- dsl.pushDescriptorSet(cmdEncoder, descriptorWrites, _dslMTLResourceIndexOffsets[set]);
- setConfigurationResult(dsl.getConfigurationResult());
+ MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[set];
+ dsl->pushDescriptorSet(cmdEncoder, descriptorWrites, _dslMTLResourceIndexOffsets[set]);
+ setConfigurationResult(dsl->getConfigurationResult());
}
// A null cmdEncoder can be passed to perform a validation pass
@@ -71,9 +71,9 @@
uint32_t set,
const void* pData) {
clearConfigurationResult();
- auto& dsl = _descriptorSetLayouts[set];
- dsl.pushDescriptorSet(cmdEncoder, descUpdateTemplate, pData, _dslMTLResourceIndexOffsets[set]);
- setConfigurationResult(dsl.getConfigurationResult());
+ MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[set];
+ dsl->pushDescriptorSet(cmdEncoder, descUpdateTemplate, pData, _dslMTLResourceIndexOffsets[set]);
+ setConfigurationResult(dsl->getConfigurationResult());
}
void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context) {
@@ -82,9 +82,9 @@
// Add resource bindings defined in the descriptor set layouts
uint32_t dslCnt = (uint32_t)_descriptorSetLayouts.size();
for (uint32_t dslIdx = 0; dslIdx < dslCnt; dslIdx++) {
- _descriptorSetLayouts[dslIdx].populateShaderConverterContext(context,
- _dslMTLResourceIndexOffsets[dslIdx],
- dslIdx);
+ _descriptorSetLayouts[dslIdx]->populateShaderConverterContext(context,
+ _dslMTLResourceIndexOffsets[dslIdx],
+ dslIdx);
}
// Add any resource bindings used by push-constants
@@ -113,16 +113,16 @@
// with each DSL as it is added. The final accumulation of resource index offsets
// becomes the resource index offsets that will be used for push contants.
- // According to the Vulkan spec, VkDescriptorSetLayout is intended to be consumed when
- // passed to any Vulkan function, and may be safely destroyed by app immediately after.
- // In order for this pipeline layout to retain the content of a VkDescriptorSetLayout,
- // this pipeline holds onto copies of the MVKDescriptorSetLayout instances, so that the
- // originals created by the app can be safely destroyed.
+ // According to the Vulkan spec, VkDescriptorSetLayout is intended to be consumed when passed
+ // to any Vulkan function, and may be safely destroyed by app immediately after. In order for
+ // this pipeline layout to retain the VkDescriptorSetLayout, the MVKDescriptorSetLayout
+ // instance is retained, so that it will live on here after it has been destroyed by the API.
_descriptorSetLayouts.reserve(pCreateInfo->setLayoutCount);
for (uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++) {
MVKDescriptorSetLayout* pDescSetLayout = (MVKDescriptorSetLayout*)pCreateInfo->pSetLayouts[i];
- _descriptorSetLayouts.push_back(*pDescSetLayout);
+ pDescSetLayout->retain();
+ _descriptorSetLayouts.push_back(pDescSetLayout);
_dslMTLResourceIndexOffsets.push_back(_pushConstantsMTLResourceIndexes);
_pushConstantsMTLResourceIndexes += pDescSetLayout->_mtlResourceCounts;
}
@@ -150,6 +150,10 @@
}
}
+MVKPipelineLayout::~MVKPipelineLayout() {
+ for (auto dsl : _descriptorSetLayouts) { dsl->release(); }
+}
+
#pragma mark -
#pragma mark MVKPipeline