diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 31b0bbde..babb789f 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -18,7 +18,11 @@ MoltenVK 1.0.34 Released TBD +- Allow zero offset and stride combo in VkVertexInputBindingDescription. +- Fix potential memory leak on synchronous command buffer submission. - Increase shader float constant accuracy beyond 6 digits of precision. +- MoltenVKShaderConverterTool support cs & csh for compute shader file extensions. +- `fetchDependencies`: Stop on first error. @@ -46,6 +50,7 @@ Released 2019/02/28 - Fix crash from use of MTLDevice registryID on early OS versions. - `fetchDependencies`: Fix issue loading from `Vulkan-Portability_repo_revision`. - `fetchDependencies`: Clean MoltenVK build to ensure using latest dependency libs. +- Update `VK_MVK_MOLTENVK_SPEC_VERSION` to 18. - Update to latest dependency libraries to support SDK 1.1.101. - Update to latest SPIRV-Cross version: - MSL: Implement 8-bit part of `VK_KHR_shader_float16_int8`. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index f2900ab3..84063271 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -839,16 +839,23 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor* for (uint32_t i = 0; i < vaCnt; i++) { const VkVertexInputAttributeDescription* pVKVA = &pVI->pVertexAttributeDescriptions[i]; if (shaderContext.isVertexAttributeLocationUsed(pVKVA->location)) { - // Vulkan allows offsets to exceed the buffer stride, but Metal doesn't. - const VkVertexInputBindingDescription* pVKVB = pVI->pVertexBindingDescriptions; - for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) { - if (pVKVB->binding == pVKVA->binding) { break; } - } - if (pVKVA->offset >= pVKVB->stride) { - setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute offsets must not exceed the vertex buffer stride.")); - return false; - } - MTLVertexAttributeDescriptor* vaDesc = plDesc.vertexDescriptor.attributes[pVKVA->location]; + + // Vulkan allows offsets to exceed the buffer stride, but Metal doesn't. + // Only check non-zero offsets, as it's common for both to be zero when step rate is instance. + if (pVKVA->offset > 0) { + const VkVertexInputBindingDescription* pVKVB = pVI->pVertexBindingDescriptions; + for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) { + if (pVKVB->binding == pVKVA->binding) { + if (pVKVA->offset >= pVKVB->stride) { + setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute offsets must not exceed the vertex buffer stride.")); + return false; + } + break; + } + } + } + + MTLVertexAttributeDescriptor* vaDesc = plDesc.vertexDescriptor.attributes[pVKVA->location]; vaDesc.format = mvkMTLVertexFormatFromVkFormat(pVKVA->format); vaDesc.bufferIndex = _device->getMetalBufferIndexForVertexAttributeBinding(pVKVA->binding); vaDesc.offset = pVKVA->offset; @@ -860,15 +867,16 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor* const VkVertexInputBindingDescription* pVKVB = &pVI->pVertexBindingDescriptions[i]; uint32_t vbIdx = _device->getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding); if (shaderContext.isVertexBufferUsed(vbIdx)) { - MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx]; - // Vulkan allows any stride, but Metal only allows multiples of 4. - // TODO: We should try to expand the buffer to the required alignment - // in that case. + + // Vulkan allows any stride, but Metal only allows multiples of 4. + // TODO: We should try to expand the buffer to the required alignment in that case. if ((pVKVB->stride % 4) != 0) { setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex buffer strides must be aligned to four bytes.")); return false; } - vbDesc.stride = (pVKVB->stride == 0) ? sizeof(simd::float4) : pVKVB->stride; // Vulkan allows zero stride but Metal doesn't. Default to float4 + + MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx]; + vbDesc.stride = (pVKVB->stride == 0) ? sizeof(simd::float4) : pVKVB->stride; // Vulkan allows zero stride but Metal doesn't. Default to float4 vbDesc.stepFunction = mvkMTLVertexStepFunctionFromVkVertexInputRate(pVKVB->inputRate); vbDesc.stepRate = 1; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm index 2b9f79d2..102d93a4 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -63,6 +63,10 @@ MVKQueueFamily::~MVKQueueFamily() { #pragma mark Queue submissions +// Execute the queue submission under an autorelease pool to ensure transient Metal objects are autoreleased. +// This is critical for apps that don't use standard OS autoreleasing runloop threading. +static inline void execute(MVKQueueSubmission* qSubmit) { @autoreleasepool { qSubmit->execute(); } } + // Executes the submmission, either immediately, or by dispatching to an execution queue. // Submissions to the execution queue are wrapped in a dedicated autorelease pool. // Relying on the dispatch queue to find time to drain the autorelease pool can @@ -72,9 +76,9 @@ VkResult MVKQueue::submit(MVKQueueSubmission* qSubmit) { VkResult rslt = qSubmit->_submissionResult; // Extract result before submission to avoid race condition with early destruction if (_execQueue) { - dispatch_async(_execQueue, ^{ @autoreleasepool { qSubmit->execute(); } } ); + dispatch_async(_execQueue, ^{ execute(qSubmit); } ); } else { - qSubmit->execute(); + execute(qSubmit); } return rslt; } diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverterTool/MoltenVKShaderConverterTool.cpp b/MoltenVKShaderConverter/MoltenVKShaderConverterTool/MoltenVKShaderConverterTool.cpp index a8980ad8..fd757083 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverterTool/MoltenVKShaderConverterTool.cpp +++ b/MoltenVKShaderConverter/MoltenVKShaderConverterTool/MoltenVKShaderConverterTool.cpp @@ -34,7 +34,7 @@ static const char* _defaultVertexShaderExtns = "vs vsh vert vertex"; static const char* _defaultFragShaderExtns = "fs fsh frag fragment"; // The default list of compute file extensions. -static const char* _defaultCompShaderExtns = "cp cmp comp compute kn kl krn kern kernel"; +static const char* _defaultCompShaderExtns = "cs csh cp cmp comp compute kn kl krn kern kernel"; // The default list of SPIR-V file extensions. static const char* _defaultSPIRVShaderExtns = "spv spirv";