From 63c6e4d8c421f1ba40ec740c131edf2b6a24f0f0 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Thu, 30 Aug 2018 12:06:01 -0500 Subject: [PATCH 1/2] Support the VK_KHR_descriptor_update_template extension. --- MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h | 34 +++ MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm | 71 +++++++ MoltenVK/MoltenVK/Commands/MVKCommandPool.h | 2 + MoltenVK/MoltenVK/Commands/MVKCommandPool.mm | 3 +- .../MoltenVK/GPUObjects/MVKDescriptorSet.h | 58 ++++- .../MoltenVK/GPUObjects/MVKDescriptorSet.mm | 198 ++++++++++++++---- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 6 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 11 + MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm | 4 + MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h | 6 + MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 13 ++ MoltenVK/MoltenVK/Layers/MVKExtensions.cpp | 2 + MoltenVK/MoltenVK/Layers/MVKExtensions.h | 1 + MoltenVK/MoltenVK/Vulkan/vulkan.mm | 47 +++++ 14 files changed, 404 insertions(+), 52 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h index f9fd523a..a6002f7a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h @@ -25,6 +25,7 @@ class MVKCommandBuffer; class MVKPipeline; class MVKPipelineLayout; class MVKDescriptorSet; +class MVKDescriptorUpdateTemplate; #pragma mark - @@ -160,6 +161,32 @@ private: }; +#pragma mark - +#pragma mark MVKCmdPushDescriptorSetWithTemplate + +/** Vulkan command to update a descriptor set from a template. */ +class MVKCmdPushDescriptorSetWithTemplate : public MVKCommand { + +public: + void setContent(VkDescriptorUpdateTemplateKHR descUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); + + void encode(MVKCommandEncoder* cmdEncoder) override; + + MVKCmdPushDescriptorSetWithTemplate(MVKCommandTypePool* pool); + + ~MVKCmdPushDescriptorSetWithTemplate() override; + +private: + MVKDescriptorUpdateTemplate* _descUpdateTemplate; + MVKPipelineLayout* _pipelineLayout; + uint32_t _set; + void* _pData; +}; + + #pragma mark - #pragma mark Command creation functions @@ -205,3 +232,10 @@ void mvkCmdPushDescriptorSet(MVKCommandBuffer* cmdBuff, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); + +/** Adds commands to the specified command buffer that update the specified descriptor set from the given template. */ +void mvkCmdPushDescriptorSetWithTemplate(MVKCommandBuffer* cmdBuff, + VkDescriptorUpdateTemplateKHR descUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm index d21af9ff..57d1ac83 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm @@ -237,6 +237,67 @@ void MVKCmdPushDescriptorSet::clearDescriptorWrites() { } +#pragma mark - +#pragma mark MVKCmdPushDescriptorSetWithTemplate + +void MVKCmdPushDescriptorSetWithTemplate::setContent(VkDescriptorUpdateTemplateKHR descUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData) { + _descUpdateTemplate = (MVKDescriptorUpdateTemplate*)descUpdateTemplate; + _pipelineLayout = (MVKPipelineLayout*)layout; + _set = set; + if (_pData) delete[] (char*)_pData; + // Work out how big the memory block in pData is. + const VkDescriptorUpdateTemplateEntryKHR* pEntry = + _descUpdateTemplate->getEntry(_descUpdateTemplate->getNumberOfEntries()-1); + size_t size = pEntry->offset; + // If we were given a stride, use that; otherwise, assume only one info + // struct of the appropriate type. + if (pEntry->stride) + size += pEntry->stride * pEntry->descriptorCount; + else switch (pEntry->descriptorType) { + + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + size += sizeof(VkDescriptorBufferInfo); + break; + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + size += sizeof(VkDescriptorImageInfo); + break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + size += sizeof(VkBufferView); + break; + + default: + break; + } + _pData = new char[size]; + memcpy(_pData, pData, size); +} + +void MVKCmdPushDescriptorSetWithTemplate::encode(MVKCommandEncoder* cmdEncoder) { + _pipelineLayout->pushDescriptorSet(cmdEncoder, _descUpdateTemplate, _set, _pData); +} + +MVKCmdPushDescriptorSetWithTemplate::MVKCmdPushDescriptorSetWithTemplate( + MVKCommandTypePool* pool) + : MVKCommand::MVKCommand((MVKCommandTypePool*)pool) {} + +MVKCmdPushDescriptorSetWithTemplate::~MVKCmdPushDescriptorSetWithTemplate() { + if (_pData) delete[] (char*)_pData; +} + + #pragma mark - #pragma mark Command creation functions @@ -300,3 +361,13 @@ void mvkCmdPushDescriptorSet(MVKCommandBuffer* cmdBuff, cmd->setContent(pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites); cmdBuff->addCommand(cmd); } + +void mvkCmdPushDescriptorSetWithTemplate(MVKCommandBuffer* cmdBuff, + VkDescriptorUpdateTemplateKHR descUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData) { + MVKCmdPushDescriptorSetWithTemplate* cmd = cmdBuff->_commandPool->_cmdPushSetWithTemplatePool.acquireObject(); + cmd->setContent(descUpdateTemplate, layout, set, pData); + cmdBuff->addCommand(cmd); +} diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h index 52db2654..3bf9ce75 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h @@ -133,6 +133,8 @@ public: MVKCommandTypePool _cmdPushDescriptorSetPool; + MVKCommandTypePool _cmdPushSetWithTemplatePool; + #pragma mark Command resources diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm index e12ba783..8623c5c3 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm @@ -119,7 +119,8 @@ MVKCommandPool::MVKCommandPool(MVKDevice* device, _cmdPushConstantsPool(this, true), _cmdDispatchPool(this, true), _cmdDispatchIndirectPool(this, true), - _cmdPushDescriptorSetPool(this, true) + _cmdPushDescriptorSetPool(this, true), + _cmdPushSetWithTemplatePool(this, true) {} // TODO: Destroying a command pool implicitly destroys all command buffers and commands created from it. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h index 4e8a4ccf..4c9e41cb 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h @@ -82,10 +82,10 @@ public: void push(MVKCommandEncoder* cmdEncoder, uint32_t& dstArrayElement, uint32_t& descriptorCount, + uint32_t& descriptorsPushed, VkDescriptorType descriptorType, - const VkDescriptorImageInfo*& pImageInfo, - const VkDescriptorBufferInfo*& pBufferInfo, - const VkBufferView*& pTexelBufferView, + size_t stride, + const void* pData, MVKShaderResourceBinding& dslMTLRezIdxOffsets); /** Populates the specified shader converter context, at the specified descriptor set binding. */ @@ -135,6 +135,13 @@ public: MVKShaderResourceBinding& dslMTLRezIdxOffsets); + /** Encodes this descriptor set layout and the updates from the given template on the specified command encoder immediately. */ + void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + MVKDescriptorUpdateTemplate* descUpdateTemplates, + const void* pData, + MVKShaderResourceBinding& dslMTLRezIdxOffsets); + + /** Populates the specified shader converter context, at the specified DSL index. */ void populateShaderConverterContext(SPIRVToMSLConverterContext& context, MVKShaderResourceBinding& dslMTLRezIdxOffsets, @@ -189,9 +196,8 @@ public: uint32_t writeBindings(uint32_t srcStartIndex, uint32_t dstStartIndex, uint32_t count, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView); + size_t stride, + const void* pData); /** * Updates the specified content arrays from the internal element bindings. @@ -216,6 +222,7 @@ public: uint32_t readBindings(uint32_t srcStartIndex, uint32_t dstStartIndex, uint32_t count, + VkDescriptorType& descType, VkDescriptorImageInfo* pImageInfo, VkDescriptorBufferInfo* pBufferInfo, VkBufferView* pTexelBufferView); @@ -254,15 +261,15 @@ public: /** Updates the resource bindings in this instance from the specified content. */ template void writeDescriptorSets(const DescriptorAction* pDescriptorAction, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView); + size_t stride, + const void* pData); /** * Reads the resource bindings defined in the specified content * from this instance into the specified collection of bindings. */ void readDescriptorSets(const VkCopyDescriptorSet* pDescriptorCopies, + VkDescriptorType& descType, VkDescriptorImageInfo* pImageInfo, VkDescriptorBufferInfo* pBufferInfo, VkBufferView* pTexelBufferView); @@ -311,6 +318,34 @@ protected: }; +#pragma mark - +#pragma mark MVKDescriptorUpdateTemplate + +/** Represents a Vulkan descriptor update template. */ +class MVKDescriptorUpdateTemplate : public MVKConfigurableObject { + +public: + + /** Get the nth update template entry. */ + const VkDescriptorUpdateTemplateEntryKHR* getEntry(uint32_t n) const; + + /** Get the total number of entries. */ + uint32_t getNumberOfEntries() const; + + /** Get the type of this template. */ + VkDescriptorUpdateTemplateTypeKHR getType() const; + + /** Constructs an instance for the specified device. */ + MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo); + + /** Destructor. */ + ~MVKDescriptorUpdateTemplate() override = default; + +private: + VkDescriptorUpdateTemplateTypeKHR _type; + std::vector _entries; +}; + #pragma mark - #pragma mark Support functions @@ -320,6 +355,11 @@ void mvkUpdateDescriptorSets(uint32_t writeCount, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies); +/** Updates the resource bindings in the given descriptor set from the specified template. */ +void mvkUpdateDescriptorSetWithTemplate(VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplateKHR updateTemplate, + const void* pData); + /** * If the shader stage binding has a binding defined for the specified stage, populates * the context at the descriptor set binding from the shader stage resource binding. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm index f47f4ff2..bd431537 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm @@ -173,13 +173,18 @@ void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder, } } +template +static const T& get(const void* pData, size_t stride, uint32_t index) { + return *(T*)((const char*)pData + stride * index); +} + void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, uint32_t& dstArrayElement, uint32_t& descriptorCount, + uint32_t& descriptorsPushed, VkDescriptorType descriptorType, - const VkDescriptorImageInfo*& pImageInfo, - const VkDescriptorBufferInfo*& pBufferInfo, - const VkBufferView*& pTexelBufferView, + size_t stride, + const void* pData, MVKShaderResourceBinding& dslMTLRezIdxOffsets) { MVKMTLBufferBinding bb; MVKMTLTextureBinding tb; @@ -196,9 +201,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, descriptorCount = 0; else { descriptorCount -= _info.descriptorCount; - pImageInfo += _info.descriptorCount; - pBufferInfo += _info.descriptorCount; - pTexelBufferView += _info.descriptorCount; + descriptorsPushed = _info.descriptorCount; } return; } @@ -215,7 +218,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: { - const VkDescriptorBufferInfo& bufferInfo = pBufferInfo[rezIdx - dstArrayElement]; + const auto& bufferInfo = get(pData, stride, rezIdx - dstArrayElement); MVKBuffer* buffer = (MVKBuffer*)bufferInfo.buffer; bb.mtlBuffer = buffer->getMTLBuffer(); bb.offset = bufferInfo.offset; @@ -237,7 +240,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { - const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement]; + const auto& imageInfo = get(pData, stride, rezIdx - dstArrayElement); MVKImageView* imageView = (MVKImageView*)imageInfo.imageView; tb.mtlTexture = imageView->getMTLTexture(); if (_applyToVertexStage) { @@ -257,7 +260,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { - MVKBufferView* bufferView = (MVKBufferView*)pTexelBufferView[rezIdx - dstArrayElement]; + auto* bufferView = get(pData, stride, rezIdx - dstArrayElement); tb.mtlTexture = bufferView->getMTLTexture(); if (_applyToVertexStage) { tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx; @@ -277,7 +280,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, case VK_DESCRIPTOR_TYPE_SAMPLER: { MVKSampler* sampler; if (_immutableSamplers.empty()) - sampler = (MVKSampler*)pImageInfo[rezIdx - dstArrayElement].sampler; + sampler = (MVKSampler*)get(pData, stride, rezIdx - dstArrayElement).sampler; else sampler = _immutableSamplers[rezIdx]; sb.mtlSamplerState = sampler->getMTLSamplerState(); @@ -297,7 +300,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, } case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { - const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement]; + const auto& imageInfo = get(pData, stride, rezIdx - dstArrayElement); MVKImageView* imageView = (MVKImageView*)imageInfo.imageView; MVKSampler* sampler = _immutableSamplers.empty() ? (MVKSampler*)imageInfo.sampler : _immutableSamplers[rezIdx]; tb.mtlTexture = imageView->getMTLTexture(); @@ -333,9 +336,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, descriptorCount = 0; else { descriptorCount -= _info.descriptorCount; - pImageInfo += _info.descriptorCount; - pBufferInfo += _info.descriptorCount; - pTexelBufferView += _info.descriptorCount; + descriptorsPushed = _info.descriptorCount; } } @@ -475,6 +476,41 @@ void MVKDescriptorSetLayout::bindDescriptorSet(MVKCommandEncoder* cmdEncoder, } } +static const void* getWriteParameters(VkDescriptorType type, const VkDescriptorImageInfo* pImageInfo, + const VkDescriptorBufferInfo* pBufferInfo, const VkBufferView* pTexelBufferView, + size_t& stride) { + const void* pData; + switch (type) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + pData = pBufferInfo; + stride = sizeof(VkDescriptorBufferInfo); + break; + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + pData = pImageInfo; + stride = sizeof(VkDescriptorImageInfo); + break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + pData = pTexelBufferView; + stride = sizeof(MVKBufferView*); + break; + + default: + pData = nullptr; + stride = 0; + } + return pData; +} + void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, vector& descriptorWrites, MVKShaderResourceBinding& dslMTLRezIdxOffsets) { @@ -490,9 +526,42 @@ void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, // Note: This will result in us walking off the end of the array // in case there are too many updates... but that's ill-defined anyway. for (; descriptorCount; bindIdx++) { + size_t stride; + const void* pData = getWriteParameters(descWrite.descriptorType, pImageInfo, + pBufferInfo, pTexelBufferView, stride); + uint32_t descriptorsPushed = 0; _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount, - descWrite.descriptorType, pImageInfo, pBufferInfo, - pTexelBufferView, dslMTLRezIdxOffsets); + descriptorsPushed, descWrite.descriptorType, + stride, pData, dslMTLRezIdxOffsets); + pBufferInfo += descriptorsPushed; + pImageInfo += descriptorsPushed; + pTexelBufferView += descriptorsPushed; + } + } +} + +void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + MVKDescriptorUpdateTemplate* descUpdateTemplate, + const void* pData, + MVKShaderResourceBinding& dslMTLRezIdxOffsets) { + + if (!_isPushDescriptorLayout || + descUpdateTemplate->getType() != VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) + return; + for (uint32_t i = 0; i < descUpdateTemplate->getNumberOfEntries(); i++) { + const VkDescriptorUpdateTemplateEntryKHR* pEntry = descUpdateTemplate->getEntry(i); + uint32_t bindIdx = pEntry->dstBinding; + uint32_t dstArrayElement = pEntry->dstArrayElement; + uint32_t descriptorCount = pEntry->descriptorCount; + const void* pCurData = (const char*)pData + pEntry->offset; + // Note: This will result in us walking off the end of the array + // in case there are too many updates... but that's ill-defined anyway. + for (; descriptorCount; bindIdx++) { + uint32_t descriptorsPushed = 0; + _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount, + descriptorsPushed, pEntry->descriptorType, + pEntry->stride, pCurData, dslMTLRezIdxOffsets); + pCurData = (const char*)pCurData + pEntry->stride * descriptorsPushed; } } } @@ -524,9 +593,8 @@ MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device, uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, uint32_t dstStartIndex, uint32_t count, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) { + size_t stride, + const void* pData) { uint32_t dstCnt = MIN(count, _pBindingLayout->_info.descriptorCount - dstStartIndex); @@ -534,7 +602,7 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, case VK_DESCRIPTOR_TYPE_SAMPLER: for (uint32_t i = 0; i < dstCnt; i++) { uint32_t dstIdx = dstStartIndex + i; - const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i]; + const auto* pImgInfo = &get(pData, stride, srcStartIndex + i); _imageBindings[dstIdx] = *pImgInfo; if (_hasDynamicSamplers) { _mtlSamplers[dstIdx] = ((MVKSampler*)pImgInfo->sampler)->getMTLSamplerState(); @@ -545,7 +613,7 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: for (uint32_t i = 0; i < dstCnt; i++) { uint32_t dstIdx = dstStartIndex + i; - const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i]; + const auto* pImgInfo = &get(pData, stride, srcStartIndex + i); _imageBindings[dstIdx] = *pImgInfo; _mtlTextures[dstIdx] = ((MVKImageView*)pImgInfo->imageView)->getMTLTexture(); if (_hasDynamicSamplers) { @@ -559,7 +627,7 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: for (uint32_t i = 0; i < dstCnt; i++) { uint32_t dstIdx = dstStartIndex + i; - const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i]; + const auto* pImgInfo = &get(pData, stride, srcStartIndex + i); _imageBindings[dstIdx] = *pImgInfo; _mtlTextures[dstIdx] = ((MVKImageView*)pImgInfo->imageView)->getMTLTexture(); } @@ -571,7 +639,7 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: for (uint32_t i = 0; i < dstCnt; i++) { uint32_t dstIdx = dstStartIndex + i; - const VkDescriptorBufferInfo* pBuffInfo = &pBufferInfo[srcStartIndex + i]; + const auto* pBuffInfo = &get(pData, stride, srcStartIndex + i); _bufferBindings[dstIdx] = *pBuffInfo; MVKBuffer* mtlBuff = (MVKBuffer*)pBuffInfo->buffer; _mtlBuffers[dstIdx] = mtlBuff->getMTLBuffer(); @@ -583,7 +651,7 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: for (uint32_t i = 0; i < dstCnt; i++) { uint32_t dstIdx = dstStartIndex + i; - const VkBufferView* pBuffView = &pTexelBufferView[srcStartIndex + i]; + const auto* pBuffView = &get(pData, stride, srcStartIndex + i); _texelBufferBindings[dstIdx] = *pBuffView; _mtlTextures[dstIdx] = ((MVKBufferView*)*pBuffView)->getMTLTexture(); } @@ -598,12 +666,14 @@ uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex, uint32_t MVKDescriptorBinding::readBindings(uint32_t srcStartIndex, uint32_t dstStartIndex, uint32_t count, + VkDescriptorType& descType, VkDescriptorImageInfo* pImageInfo, VkDescriptorBufferInfo* pBufferInfo, VkBufferView* pTexelBufferView) { uint32_t srcCnt = MIN(count, _pBindingLayout->_info.descriptorCount - srcStartIndex); + descType = _pBindingLayout->_info.descriptorType; switch (_pBindingLayout->_info.descriptorType) { case VK_DESCRIPTOR_TYPE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: @@ -714,9 +784,7 @@ void MVKDescriptorBinding::initMTLSamplers(MVKDescriptorSetLayoutBinding* pBindi template void MVKDescriptorSet::writeDescriptorSets(const DescriptorAction* pDescriptorAction, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) { + size_t stride, const void* pData) { uint32_t dstStartIdx = pDescriptorAction->dstArrayElement; uint32_t binding = pDescriptorAction->dstBinding; uint32_t origCnt = pDescriptorAction->descriptorCount; @@ -731,7 +799,7 @@ void MVKDescriptorSet::writeDescriptorSets(const DescriptorAction* pDescriptorAc uint32_t srcStartIdx = origCnt - remainCnt; remainCnt = mvkDescBind->writeBindings(srcStartIdx, dstStartIdx, remainCnt, - pImageInfo, pBufferInfo, pTexelBufferView); + stride, pData); binding++; // If not consumed, move to next consecutive binding point mvkDescBind = getBinding(binding); @@ -739,17 +807,17 @@ void MVKDescriptorSet::writeDescriptorSets(const DescriptorAction* pDescriptorAc } } -// Create concrete implementations of the two variations of the writeDescriptorSets() function. +// Create concrete implementations of the three variations of the writeDescriptorSets() function. template void MVKDescriptorSet::writeDescriptorSets(const VkWriteDescriptorSet* pDescriptorAction, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView); + size_t stride, const void *pData); template void MVKDescriptorSet::writeDescriptorSets(const VkCopyDescriptorSet* pDescriptorAction, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView); + size_t stride, const void *pData); +template void MVKDescriptorSet::writeDescriptorSets( + const VkDescriptorUpdateTemplateEntryKHR* pDescriptorAction, + size_t stride, const void *pData); void MVKDescriptorSet::readDescriptorSets(const VkCopyDescriptorSet* pDescriptorCopy, + VkDescriptorType& descType, VkDescriptorImageInfo* pImageInfo, VkDescriptorBufferInfo* pBufferInfo, VkBufferView* pTexelBufferView) { @@ -766,7 +834,7 @@ void MVKDescriptorSet::readDescriptorSets(const VkCopyDescriptorSet* pDescriptor // MVKLogDebug("Reading MVKDescriptorBinding with binding point %d.", binding); uint32_t dstStartIdx = origCnt - remainCnt; - remainCnt = mvkDescBind->readBindings(srcStartIdx, dstStartIdx, remainCnt, + remainCnt = mvkDescBind->readBindings(srcStartIdx, dstStartIdx, remainCnt, descType, pImageInfo, pBufferInfo, pTexelBufferView); binding++; // If not consumed, move to next consecutive binding point @@ -851,6 +919,29 @@ MVKDescriptorPool::~MVKDescriptorPool() { } +#pragma mark - +#pragma mark MVKDescriptorUpdateTemplate + +const VkDescriptorUpdateTemplateEntryKHR* MVKDescriptorUpdateTemplate::getEntry(uint32_t n) const { + return &_entries[n]; +} + +uint32_t MVKDescriptorUpdateTemplate::getNumberOfEntries() const { + return (uint32_t)_entries.size(); +} + +VkDescriptorUpdateTemplateTypeKHR MVKDescriptorUpdateTemplate::getType() const { + return _type; +} + +MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo) : + MVKConfigurableObject(), _type(pCreateInfo->templateType) { + + for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; i++) + _entries.push_back(pCreateInfo->pDescriptorUpdateEntries[i]); +} + + #pragma mark - #pragma mark Support functions @@ -863,11 +954,12 @@ void mvkUpdateDescriptorSets(uint32_t writeCount, // Perform the write updates for (uint32_t i = 0; i < writeCount; i++) { const VkWriteDescriptorSet* pDescWrite = &pDescriptorWrites[i]; + size_t stride; + const void* pData = getWriteParameters(pDescWrite->descriptorType, pDescWrite->pImageInfo, + pDescWrite->pBufferInfo, pDescWrite->pTexelBufferView, + stride); MVKDescriptorSet* dstSet = (MVKDescriptorSet*)pDescWrite->dstSet; - dstSet->writeDescriptorSets(pDescWrite, - pDescWrite->pImageInfo, - pDescWrite->pBufferInfo, - pDescWrite->pTexelBufferView); + dstSet->writeDescriptorSets(pDescWrite, stride, pData); } // Perform the copy updates by reading bindings from one set and writing to other set. @@ -875,15 +967,37 @@ void mvkUpdateDescriptorSets(uint32_t writeCount, const VkCopyDescriptorSet* pDescCopy = &pDescriptorCopies[i]; uint32_t descCnt = pDescCopy->descriptorCount; + VkDescriptorType descType; VkDescriptorImageInfo imgInfos[descCnt]; VkDescriptorBufferInfo buffInfos[descCnt]; VkBufferView texelBuffInfos[descCnt]; MVKDescriptorSet* srcSet = (MVKDescriptorSet*)pDescCopy->srcSet; - srcSet->readDescriptorSets(pDescCopy, imgInfos, buffInfos, texelBuffInfos); + srcSet->readDescriptorSets(pDescCopy, descType, imgInfos, buffInfos, texelBuffInfos); MVKDescriptorSet* dstSet = (MVKDescriptorSet*)pDescCopy->dstSet; - dstSet->writeDescriptorSets(pDescCopy, imgInfos, buffInfos, texelBuffInfos); + size_t stride; + const void* pData = getWriteParameters(descType, imgInfos, buffInfos, texelBuffInfos, stride); + dstSet->writeDescriptorSets(pDescCopy, stride, pData); + } +} + +/** Updates the resource bindings in the given descriptor set from the specified template. */ +void mvkUpdateDescriptorSetWithTemplate(VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplateKHR updateTemplate, + const void* pData) { + + MVKDescriptorSet* dstSet = (MVKDescriptorSet*)descriptorSet; + MVKDescriptorUpdateTemplate* pTemplate = (MVKDescriptorUpdateTemplate*)updateTemplate; + + if (pTemplate->getType() != VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR) + return; + + // Perform the updates + for (uint32_t i = 0; i < pTemplate->getNumberOfEntries(); i++) { + const VkDescriptorUpdateTemplateEntryKHR* pEntry = pTemplate->getEntry(i); + const void* pCurData = (const char*)pData + pEntry->offset; + dstSet->writeDescriptorSets(pEntry, pEntry->stride, pCurData); } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index bf19fc84..bc243c0f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -53,6 +53,7 @@ class MVKPipeline; class MVKSampler; class MVKDescriptorSetLayout; class MVKDescriptorPool; +class MVKDescriptorUpdateTemplate; class MVKFramebuffer; class MVKRenderPass; class MVKCommandPool; @@ -397,6 +398,11 @@ public: void destroyDescriptorPool(MVKDescriptorPool* mvkDP, const VkAllocationCallbacks* pAllocator); + MVKDescriptorUpdateTemplate* createDescriptorUpdateTemplate(const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator); + void destroyDescriptorUpdateTemplate(MVKDescriptorUpdateTemplate* mvkDUT, + const VkAllocationCallbacks* pAllocator); + MVKFramebuffer* createFramebuffer(const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator); void destroyFramebuffer(MVKFramebuffer* mvkFB, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 905a95f0..a2b66c0f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1362,6 +1362,17 @@ void MVKDevice::destroyDescriptorPool(MVKDescriptorPool* mvkDP, mvkDP->destroy(); } +MVKDescriptorUpdateTemplate* MVKDevice::createDescriptorUpdateTemplate( + const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator) { + return new MVKDescriptorUpdateTemplate(this, pCreateInfo); +} + +void MVKDevice::destroyDescriptorUpdateTemplate(MVKDescriptorUpdateTemplate* mvkDUT, + const VkAllocationCallbacks* pAllocator) { + mvkDUT->destroy(); +} + MVKFramebuffer* MVKDevice::createFramebuffer(const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { return new MVKFramebuffer(this, pCreateInfo); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index c9761c01..efa4f12f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -296,6 +296,10 @@ void MVKInstance::initProcAddrs() { ADD_PROC_ADDR(vkGetPhysicalDeviceMemoryProperties2KHR); ADD_PROC_ADDR(vkGetPhysicalDeviceSparseImageFormatProperties2KHR); ADD_PROC_ADDR(vkCmdPushDescriptorSetKHR); + ADD_PROC_ADDR(vkCmdPushDescriptorSetWithTemplateKHR); + ADD_PROC_ADDR(vkCreateDescriptorUpdateTemplateKHR); + ADD_PROC_ADDR(vkDestroyDescriptorUpdateTemplateKHR); + ADD_PROC_ADDR(vkUpdateDescriptorSetWithTemplateKHR); ADD_PROC_ADDR(vkGetMoltenVKConfigurationMVK); ADD_PROC_ADDR(vkSetMoltenVKConfigurationMVK); ADD_PROC_ADDR(vkGetPhysicalDeviceMetalFeaturesMVK); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h index 4cd6391c..951b1530 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h @@ -55,6 +55,12 @@ public: std::vector& descriptorWrites, uint32_t set); + /** Updates a descriptor set from a template in a command encoder. */ + void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + MVKDescriptorUpdateTemplate* descriptorUpdateTemplate, + uint32_t set, + const void* pData); + /** Constructs an instance for the specified device. */ MVKPipelineLayout(MVKDevice* device, const VkPipelineLayoutCreateInfo* pCreateInfo); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 151b840d..e93d2921 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -65,6 +65,19 @@ void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexOffsets.computeStage.bufferIndex); } +void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + MVKDescriptorUpdateTemplate* descUpdateTemplate, + uint32_t set, + const void* pData) { + + _descriptorSetLayouts[set].pushDescriptorSet(cmdEncoder, descUpdateTemplate, + pData, + _dslMTLResourceIndexOffsets[set]); + cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexOffsets.vertexStage.bufferIndex); + cmdEncoder->getPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexOffsets.fragmentStage.bufferIndex); + cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexOffsets.computeStage.bufferIndex); +} + void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConverterContext& context) { context.resourceBindings.clear(); diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp index f66b76a7..213d8af8 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp @@ -52,6 +52,7 @@ MVK_MAKE_VK_EXT_PROPS(AMD_NEGATIVE_VIEWPORT_HEIGHT); MVK_MAKE_VK_EXT_PROPS(KHR_SHADER_DRAW_PARAMETERS); MVK_MAKE_VK_EXT_PROPS(KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2); MVK_MAKE_VK_EXT_PROPS(KHR_PUSH_DESCRIPTOR); +MVK_MAKE_VK_EXT_PROPS(KHR_DESCRIPTOR_UPDATE_TEMPLATE); // Calls the constructor for a MVKExtension member variable, using the member name and the // portion of the extension name, as uppercase, used in the MVK_MAKE_VK_EXT_PROPS() macro above. @@ -70,6 +71,7 @@ MVKExtensionList::MVKExtensionList(bool enableForPlatform) : MVKExt_CONSTRUCT(vk_KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS), MVKExt_CONSTRUCT(vk_KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2), MVKExt_CONSTRUCT(vk_KHR_push_descriptor, KHR_PUSH_DESCRIPTOR) + MVKExt_CONSTRUCT(vk_KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE) {} bool MVKExtensionList::isEnabled(const char* extnName) const { diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.h b/MoltenVK/MoltenVK/Layers/MVKExtensions.h index 1b2a2e2a..479d71cf 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.h +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.h @@ -49,6 +49,7 @@ struct MVKExtensionList { MVKExtension vk_KHR_shader_draw_parameters; MVKExtension vk_KHR_get_physical_device_properties2; MVKExtension vk_KHR_push_descriptor; + MVKExtension vk_KHR_descriptor_update_template; }; MVKExtension extensionArray; }; diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index db0e6f3a..211c92d4 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -1692,6 +1692,53 @@ MVK_PUBLIC_SYMBOL void vkCmdPushDescriptorSetKHR( mvkCmdPushDescriptorSet(cmdBuff, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites); } +MVK_PUBLIC_SYMBOL void vkCmdPushDescriptorSetWithTemplateKHR( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData) { + + MVKCommandBuffer* cmdBuff = MVKCommandBuffer::getMVKCommandBuffer(commandBuffer); + mvkCmdPushDescriptorSetWithTemplate(cmdBuff, descriptorUpdateTemplate, layout, set, pData); +} + + +#pragma mark - +#pragma mark VK_KHR_descriptor_update_template extension + +MVK_PUBLIC_SYMBOL VkResult vkCreateDescriptorUpdateTemplateKHR( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate) { + + MVKDevice* mvkDev = MVKDevice::getMVKDevice(device); + auto *mvkDUT = mvkDev->createDescriptorUpdateTemplate(pCreateInfo, + pAllocator); + *pDescriptorUpdateTemplate = (VkDescriptorUpdateTemplateKHR)mvkDUT; + return mvkDUT->getConfigurationResult(); +} + +MVK_PUBLIC_SYMBOL void vkDestroyDescriptorUpdateTemplateKHR( + VkDevice device, + VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator) { + + if (!descriptorUpdateTemplate) { return; } + MVKDevice* mvkDev = MVKDevice::getMVKDevice(device); + mvkDev->destroyDescriptorUpdateTemplate((MVKDescriptorUpdateTemplate*)descriptorUpdateTemplate, pAllocator); +} + +MVK_PUBLIC_SYMBOL void vkUpdateDescriptorSetWithTemplateKHR( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, + const void* pData) { + + mvkUpdateDescriptorSetWithTemplate(descriptorSet, descriptorUpdateTemplate, pData); +} + #pragma mark - #pragma mark Loader and Layer ICD interface extension From d557b51433d9621389bf08268fb9dac5ad8b2184 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Sun, 2 Sep 2018 22:23:52 -0500 Subject: [PATCH 2/2] Fix a silly omission that breaks the build. --- MoltenVK/MoltenVK/Layers/MVKExtensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp index 213d8af8..d7e2942e 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp @@ -70,7 +70,7 @@ MVKExtensionList::MVKExtensionList(bool enableForPlatform) : MVKExt_CONSTRUCT(vk_AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT), MVKExt_CONSTRUCT(vk_KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS), MVKExt_CONSTRUCT(vk_KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2), - MVKExt_CONSTRUCT(vk_KHR_push_descriptor, KHR_PUSH_DESCRIPTOR) + MVKExt_CONSTRUCT(vk_KHR_push_descriptor, KHR_PUSH_DESCRIPTOR), MVKExt_CONSTRUCT(vk_KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE) {}