diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h index 65131c77..a9073f5d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h @@ -71,7 +71,7 @@ public: inline uint32_t getBinding() { return _info.binding; } /** Returns the number of descriptors in this layout. */ - inline uint32_t getDescriptorCount() { return _info.descriptorCount; } + inline uint32_t getDescriptorCount() { return (_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1 : _info.descriptorCount; } /** Returns the descriptor type of this layout. */ inline VkDescriptorType getDescriptorType() { return _info.descriptorType; } @@ -284,17 +284,19 @@ public: void write(MVKDescriptorSet* mvkDescSet, VkDescriptorType descriptorType, - uint32_t srcIndex, + uint32_t dstIndex, size_t stride, const void* pData) override; void read(MVKDescriptorSet* mvkDescSet, VkDescriptorType descriptorType, - uint32_t dstIndex, + uint32_t srcIndex, VkDescriptorImageInfo* pImageInfo, VkDescriptorBufferInfo* pBufferInfo, VkBufferView* pTexelBufferView, VkWriteDescriptorSetInlineUniformBlockEXT* inlineUniformBlock) override; + + void setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index) override; void reset() override; @@ -302,7 +304,6 @@ public: protected: id _mtlBuffer = nil; - uint32_t _dataSize = 0; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm index 140c31b2..f4338e26 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm @@ -89,13 +89,18 @@ uint32_t MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder, // Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding. MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets; - uint32_t descCnt = _info.descriptorCount; - for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { - MVKDescriptor* mvkDesc = descSet->getDescriptor(descStartIndex + descIdx); - mvkDesc->bind(cmdEncoder, _info.descriptorType, descIdx, _applyToStage, - mtlIdxs, dynamicOffsets, pDynamicOffsetIndex); + if (_info.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { + MVKDescriptor* mvkDesc = descSet->getDescriptor(descStartIndex); + mvkDesc->bind(cmdEncoder, _info.descriptorType, 0, _applyToStage, mtlIdxs, dynamicOffsets, pDynamicOffsetIndex); + return 1; + } else { + uint32_t descCnt = _info.descriptorCount; + for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { + MVKDescriptor* mvkDesc = descSet->getDescriptor(descStartIndex + descIdx); + mvkDesc->bind(cmdEncoder, _info.descriptorType, descIdx, _applyToStage, mtlIdxs, dynamicOffsets, pDynamicOffsetIndex); + } + return descCnt; } - return descCnt; } template @@ -167,13 +172,13 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, } case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: { - const auto& inlineUniformBlock = get(pData, stride, rezIdx - dstArrayElement); + const auto& inlineUniformBlock = *(VkWriteDescriptorSetInlineUniformBlockEXT*)pData; bb.mtlBytes = inlineUniformBlock.pData; bb.size = inlineUniformBlock.dataSize; bb.isInline = true; for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) { if (_applyToStage[i]) { - bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx; + bb.index = mtlIdxs.stages[i].bufferIndex; if (i == kMVKShaderStageCompute) { if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } } else { @@ -470,11 +475,15 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: pBindingIndexes->bufferIndex = pDescSetCounts->bufferIndex; pDescSetCounts->bufferIndex += pBinding->descriptorCount; break; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: + pBindingIndexes->bufferIndex = pDescSetCounts->bufferIndex; + pDescSetCounts->bufferIndex += 1; + break; + default: break; } @@ -605,18 +614,19 @@ void MVKInlineUniformBlockDescriptor::bind(MVKCommandEncoder* cmdEncoder, switch (descriptorType) { case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: { - bb.mtlBuffer = _mtlBuffer; - bb.size = _dataSize; - for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) { - if (stages[i]) { - bb.index = mtlIndexes.stages[i].bufferIndex + descriptorIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } - } - } + bb.mtlBytes = _mtlBuffer.contents; + bb.size = (uint32_t)_mtlBuffer.length; + bb.isInline = true; + for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) { + if (stages[i]) { + bb.index = mtlIndexes.stages[i].bufferIndex; + if (i == kMVKShaderStageCompute) { + if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } + } else { + if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } + } + } + } break; } @@ -626,25 +636,18 @@ void MVKInlineUniformBlockDescriptor::bind(MVKCommandEncoder* cmdEncoder, } void MVKInlineUniformBlockDescriptor::write(MVKDescriptorSet* mvkDescSet, - VkDescriptorType descriptorType, - uint32_t srcIndex, - size_t stride, - const void* pData) { + VkDescriptorType descriptorType, + uint32_t dstIndex, + size_t stride, + const void* pData) { switch (descriptorType) { case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: { - const auto& srcInlineUniformBlock = get(pData, stride, srcIndex); - _dataSize = srcInlineUniformBlock.dataSize; - - [_mtlBuffer release]; - if (srcInlineUniformBlock.dataSize > 0) { - MTLResourceOptions mtlBuffOpts = MTLResourceStorageModeShared | MTLResourceCPUCacheModeDefaultCache; - _mtlBuffer = [mvkDescSet->getMTLDevice() newBufferWithBytes: srcInlineUniformBlock.pData - length: srcInlineUniformBlock.dataSize - options:mtlBuffOpts]; // retained - } else { - _mtlBuffer = nil; - } - + const auto& pInlineUniformBlock = *(VkWriteDescriptorSetInlineUniformBlockEXT*)pData; + uint8_t* pDstData = (uint8_t*)_mtlBuffer.contents; + uint8_t* pSrcData = (uint8_t*)pInlineUniformBlock.pData; + if (pSrcData && pDstData) { + memcpy(pDstData + dstIndex, pSrcData, pInlineUniformBlock.dataSize); + } break; } @@ -654,23 +657,19 @@ void MVKInlineUniformBlockDescriptor::write(MVKDescriptorSet* mvkDescSet, } void MVKInlineUniformBlockDescriptor::read(MVKDescriptorSet* mvkDescSet, - VkDescriptorType descriptorType, - uint32_t dstIndex, - VkDescriptorImageInfo* pImageInfo, - VkDescriptorBufferInfo* pBufferInfo, - VkBufferView* pTexelBufferView, - VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock) { + VkDescriptorType descriptorType, + uint32_t srcIndex, + VkDescriptorImageInfo* pImageInfo, + VkDescriptorBufferInfo* pBufferInfo, + VkBufferView* pTexelBufferView, + VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock) { switch (descriptorType) { case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: { - auto& dstInlineUniformBlock = pInlineUniformBlock[dstIndex]; - void* pDstData = const_cast(dstInlineUniformBlock.pData); - void* pSrcData = _mtlBuffer.contents; + uint8_t* pDstData = (uint8_t*)pInlineUniformBlock->pData; + uint8_t* pSrcData = (uint8_t*)_mtlBuffer.contents; if (pSrcData && pDstData) { - memcpy(pDstData, pSrcData, _dataSize); - dstInlineUniformBlock.dataSize = _dataSize; - } else { - dstInlineUniformBlock.dataSize = 0; - } + memcpy(pDstData, pSrcData + srcIndex, pInlineUniformBlock->dataSize); + } break; } @@ -679,10 +678,14 @@ void MVKInlineUniformBlockDescriptor::read(MVKDescriptorSet* mvkDescSet, } } +void MVKInlineUniformBlockDescriptor::setLayout(MVKDescriptorSetLayoutBinding* dslBinding, uint32_t index) { + _mtlBuffer = [dslBinding->getMTLDevice() newBufferWithLength: dslBinding->getDescriptorCount() + options: MTLResourceStorageModeShared | MTLResourceCPUCacheModeDefaultCache]; // retained +} + void MVKInlineUniformBlockDescriptor::reset() { [_mtlBuffer release]; _mtlBuffer = nil; - _dataSize = 0; MVKDescriptor::reset(); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm index 32decbd3..b89782c1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm @@ -209,12 +209,17 @@ void MVKDescriptorSet::write(const DescriptorAction* pDescriptorAction, const void* pData) { VkDescriptorType descType = getDescriptorType(pDescriptorAction->dstBinding); - uint32_t dstStartIdx = _layout->getDescriptorIndex(pDescriptorAction->dstBinding, - pDescriptorAction->dstArrayElement); uint32_t descCnt = pDescriptorAction->descriptorCount; - for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { - _descriptors[dstStartIdx + descIdx]->write(this, descType, descIdx, stride, pData); - } + if (descType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { + uint32_t dstStartIdx = _layout->getDescriptorIndex(pDescriptorAction->dstBinding, 0); + _descriptors[dstStartIdx]->write(this, descType, pDescriptorAction->dstArrayElement, stride, pData); + } else { + uint32_t dstStartIdx = _layout->getDescriptorIndex(pDescriptorAction->dstBinding, + pDescriptorAction->dstArrayElement); + for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { + _descriptors[dstStartIdx + descIdx]->write(this, descType, descIdx, stride, pData); + } + } } // Create concrete implementations of the three variations of the write() function. @@ -232,13 +237,18 @@ void MVKDescriptorSet::read(const VkCopyDescriptorSet* pDescriptorCopy, VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock) { VkDescriptorType descType = getDescriptorType(pDescriptorCopy->srcBinding); - uint32_t srcStartIdx = _layout->getDescriptorIndex(pDescriptorCopy->srcBinding, - pDescriptorCopy->srcArrayElement); uint32_t descCnt = pDescriptorCopy->descriptorCount; - for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { - _descriptors[srcStartIdx + descIdx]->read(this, descType, descIdx, pImageInfo, pBufferInfo, - pTexelBufferView, pInlineUniformBlock); - } + if (descType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { + pInlineUniformBlock->dataSize = pDescriptorCopy->descriptorCount; + uint32_t srcStartIdx = _layout->getDescriptorIndex(pDescriptorCopy->srcBinding, 0); + _descriptors[srcStartIdx]->read(this, descType, pDescriptorCopy->srcArrayElement, pImageInfo, pBufferInfo, pTexelBufferView, pInlineUniformBlock); + } else { + uint32_t srcStartIdx = _layout->getDescriptorIndex(pDescriptorCopy->srcBinding, + pDescriptorCopy->srcArrayElement); + for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { + _descriptors[srcStartIdx + descIdx]->read(this, descType, descIdx, pImageInfo, pBufferInfo, pTexelBufferView, pInlineUniformBlock); + } + } } // If the descriptor pool fails to allocate a descriptor, record a configuration error @@ -249,15 +259,23 @@ MVKDescriptorSet::MVKDescriptorSet(MVKDescriptorSetLayout* layout, MVKDescriptor uint32_t bindCnt = (uint32_t)layout->_bindings.size(); for (uint32_t bindIdx = 0; bindIdx < bindCnt; bindIdx++) { MVKDescriptorSetLayoutBinding* mvkDSLBind = &layout->_bindings[bindIdx]; - uint32_t descCnt = mvkDSLBind->getDescriptorCount(); - for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { - MVKDescriptor* mvkDesc = nullptr; - setConfigurationResult(_pool->allocateDescriptor(mvkDSLBind->getDescriptorType(), &mvkDesc)); - if ( !wasConfigurationSuccessful() ) { break; } + MVKDescriptor* mvkDesc = nullptr; + if (mvkDSLBind->getDescriptorType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { + setConfigurationResult(_pool->allocateDescriptor(mvkDSLBind->getDescriptorType(), &mvkDesc)); + if ( !wasConfigurationSuccessful() ) { break; } - mvkDesc->setLayout(mvkDSLBind, descIdx); - _descriptors.push_back(mvkDesc); - } + mvkDesc->setLayout(mvkDSLBind, 0); + _descriptors.push_back(mvkDesc); + } else { + uint32_t descCnt = mvkDSLBind->getDescriptorCount(); + for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { + setConfigurationResult(_pool->allocateDescriptor(mvkDSLBind->getDescriptorType(), &mvkDesc)); + if ( !wasConfigurationSuccessful() ) { break; } + + mvkDesc->setLayout(mvkDSLBind, descIdx); + _descriptors.push_back(mvkDesc); + } + } if ( !wasConfigurationSuccessful() ) { break; } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 4aa6f0c9..d89a82cf 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -209,6 +209,15 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { portabilityProps->minVertexInputBindingStrideAlignment = 4; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT: { + auto* inlineUniformBlockProps = (VkPhysicalDeviceInlineUniformBlockPropertiesEXT*)next; + inlineUniformBlockProps->maxInlineUniformBlockSize = _metalFeatures.dynamicMTLBufferSize; + inlineUniformBlockProps->maxPerStageDescriptorInlineUniformBlocks = _properties.limits.maxPerStageDescriptorUniformBuffers; + inlineUniformBlockProps->maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks = _properties.limits.maxPerStageDescriptorUniformBuffers; + inlineUniformBlockProps->maxDescriptorSetInlineUniformBlocks = _properties.limits.maxDescriptorSetUniformBuffers; + inlineUniformBlockProps->maxDescriptorSetUpdateAfterBindInlineUniformBlocks = _properties.limits.maxDescriptorSetUniformBuffers; + break; + } default: break; }