From 54f69c30e7f2e5938dd5b78e26a0785f93a65fb2 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Mon, 27 Aug 2018 12:37:01 -0500 Subject: [PATCH] Support the VK_KHR_push_descriptor extension. --- MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h | 37 ++++ MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm | 68 +++++++ MoltenVK/MoltenVK/Commands/MVKCommandPool.h | 2 + MoltenVK/MoltenVK/Commands/MVKCommandPool.mm | 3 +- .../MoltenVK/GPUObjects/MVKDescriptorSet.h | 20 ++ .../MoltenVK/GPUObjects/MVKDescriptorSet.mm | 191 ++++++++++++++++++ MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 14 ++ MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm | 1 + MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h | 5 + MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 11 + MoltenVK/MoltenVK/Loader/MVKLayers.mm | 5 + MoltenVK/MoltenVK/Vulkan/vulkan.mm | 16 ++ 12 files changed, 372 insertions(+), 1 deletion(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h index dfbd7403..f9fd523a 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.h @@ -131,6 +131,35 @@ private: }; +#pragma mark - +#pragma mark MVKCmdPushDescriptorSet + +/** Vulkan command to update a descriptor set. */ +class MVKCmdPushDescriptorSet : public MVKCommand { + +public: + void setContent(VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); + + void encode(MVKCommandEncoder* cmdEncoder) override; + + MVKCmdPushDescriptorSet(MVKCommandTypePool* pool); + + ~MVKCmdPushDescriptorSet() override; + +private: + void clearDescriptorWrites(); + + VkPipelineBindPoint _pipelineBindPoint; + MVKPipelineLayout* _pipelineLayout; + std::vector _descriptorWrites; + uint32_t _set; +}; + + #pragma mark - #pragma mark Command creation functions @@ -168,3 +197,11 @@ void mvkCmdPushConstants(MVKCommandBuffer* cmdBuff, uint32_t offset, uint32_t size, const void* pValues); + +/** Adds commands to the specified command buffer that update the specified descriptor set. */ +void mvkCmdPushDescriptorSet(MVKCommandBuffer* cmdBuff, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm index 8383d653..d21af9ff 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm @@ -179,6 +179,64 @@ MVKCmdPushConstants::MVKCmdPushConstants(MVKCommandTypePool : MVKCommand::MVKCommand((MVKCommandTypePool*)pool) {} +#pragma mark - +#pragma mark MVKCmdPushDescriptorSet + +void MVKCmdPushDescriptorSet::setContent(VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites) { + _pipelineBindPoint = pipelineBindPoint; + _pipelineLayout = (MVKPipelineLayout*)layout; + _set = set; + + // Add the descriptor writes + clearDescriptorWrites(); // Clear for reuse + _descriptorWrites.reserve(descriptorWriteCount); + for (uint32_t dwIdx = 0; dwIdx < descriptorWriteCount; dwIdx++) { + _descriptorWrites.push_back(pDescriptorWrites[dwIdx]); + VkWriteDescriptorSet& descWrite = _descriptorWrites.back(); + // Make a copy of the associated data. + if (descWrite.pImageInfo) { + auto* pNewImageInfo = new VkDescriptorImageInfo[descWrite.descriptorCount]; + std::copy_n(descWrite.pImageInfo, descWrite.descriptorCount, pNewImageInfo); + descWrite.pImageInfo = pNewImageInfo; + } + if (descWrite.pBufferInfo) { + auto* pNewBufferInfo = new VkDescriptorBufferInfo[descWrite.descriptorCount]; + std::copy_n(descWrite.pBufferInfo, descWrite.descriptorCount, pNewBufferInfo); + descWrite.pBufferInfo = pNewBufferInfo; + } + if (descWrite.pTexelBufferView) { + auto* pNewTexelBufferView = new VkBufferView[descWrite.descriptorCount]; + std::copy_n(descWrite.pTexelBufferView, descWrite.descriptorCount, pNewTexelBufferView); + descWrite.pTexelBufferView = pNewTexelBufferView; + } + } +} + +void MVKCmdPushDescriptorSet::encode(MVKCommandEncoder* cmdEncoder) { + _pipelineLayout->pushDescriptorSet(cmdEncoder, _descriptorWrites, _set); +} + +MVKCmdPushDescriptorSet::MVKCmdPushDescriptorSet(MVKCommandTypePool* pool) + : MVKCommand::MVKCommand((MVKCommandTypePool*)pool) {} + +MVKCmdPushDescriptorSet::~MVKCmdPushDescriptorSet() { + clearDescriptorWrites(); +} + +void MVKCmdPushDescriptorSet::clearDescriptorWrites() { + for (VkWriteDescriptorSet &descWrite : _descriptorWrites) { + if (descWrite.pImageInfo) delete[] descWrite.pImageInfo; + if (descWrite.pBufferInfo) delete[] descWrite.pBufferInfo; + if (descWrite.pTexelBufferView) delete[] descWrite.pTexelBufferView; + } + _descriptorWrites.clear(); +} + + #pragma mark - #pragma mark Command creation functions @@ -232,3 +290,13 @@ void mvkCmdPushConstants(MVKCommandBuffer* cmdBuff, cmdBuff->addCommand(cmd); } +void mvkCmdPushDescriptorSet(MVKCommandBuffer* cmdBuff, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites) { + MVKCmdPushDescriptorSet* cmd = cmdBuff->_commandPool->_cmdPushDescriptorSetPool.acquireObject(); + cmd->setContent(pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites); + cmdBuff->addCommand(cmd); +} diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h index 2037bee7..52db2654 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h @@ -131,6 +131,8 @@ public: MVKCommandTypePool _cmdDispatchIndirectPool; + MVKCommandTypePool _cmdPushDescriptorSetPool; + #pragma mark Command resources diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm index bf21b894..e12ba783 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm @@ -118,7 +118,8 @@ MVKCommandPool::MVKCommandPool(MVKDevice* device, _cmdCopyQueryPoolResultsPool(this, true), _cmdPushConstantsPool(this, true), _cmdDispatchPool(this, true), - _cmdDispatchIndirectPool(this, true) + _cmdDispatchIndirectPool(this, true), + _cmdPushDescriptorSetPool(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 d03ca573..4e8a4ccf 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h @@ -78,6 +78,16 @@ public: std::vector& dynamicOffsets, uint32_t* pDynamicOffsetIndex); + /** Encodes this binding layout and the specified descriptor binding on the specified command encoder immediately. */ + void push(MVKCommandEncoder* cmdEncoder, + uint32_t& dstArrayElement, + uint32_t& descriptorCount, + VkDescriptorType descriptorType, + const VkDescriptorImageInfo*& pImageInfo, + const VkDescriptorBufferInfo*& pBufferInfo, + const VkBufferView*& pTexelBufferView, + MVKShaderResourceBinding& dslMTLRezIdxOffsets); + /** Populates the specified shader converter context, at the specified descriptor set binding. */ void populateShaderConverterContext(SPIRVToMSLConverterContext& context, MVKShaderResourceBinding& dslMTLRezIdxOffsets, @@ -119,11 +129,20 @@ public: uint32_t* pDynamicOffsetIndex); + /** Encodes this descriptor set layout and the specified descriptor updates on the specified command encoder immediately. */ + void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + std::vector& descriptorWrites, + MVKShaderResourceBinding& dslMTLRezIdxOffsets); + + /** Populates the specified shader converter context, at the specified DSL index. */ void populateShaderConverterContext(SPIRVToMSLConverterContext& context, MVKShaderResourceBinding& dslMTLRezIdxOffsets, uint32_t dslIndex); + /** Returns true if this layout is for push descriptors only. */ + bool isPushDescriptorLayout() const { return _isPushDescriptorLayout; } + /** Constructs an instance for the specified device. */ MVKDescriptorSetLayout(MVKDevice* device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo); @@ -135,6 +154,7 @@ protected: std::vector _bindings; MVKShaderResourceBinding _mtlResourceCounts; + bool _isPushDescriptorLayout : 1; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm index 9b514f7d..d85e29ca 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm @@ -173,6 +173,172 @@ void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder, } } +void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, + uint32_t& dstArrayElement, + uint32_t& descriptorCount, + VkDescriptorType descriptorType, + const VkDescriptorImageInfo*& pImageInfo, + const VkDescriptorBufferInfo*& pBufferInfo, + const VkBufferView*& pTexelBufferView, + MVKShaderResourceBinding& dslMTLRezIdxOffsets) { + MVKMTLBufferBinding bb; + MVKMTLTextureBinding tb; + MVKMTLSamplerStateBinding sb; + + if (dstArrayElement >= _info.descriptorCount) { + dstArrayElement -= _info.descriptorCount; + return; + } + + if (descriptorType != _info.descriptorType) { + dstArrayElement = 0; + if (_info.descriptorCount > descriptorCount) + descriptorCount = 0; + else { + descriptorCount -= _info.descriptorCount; + pImageInfo += _info.descriptorCount; + pBufferInfo += _info.descriptorCount; + pTexelBufferView += _info.descriptorCount; + } + return; + } + + // Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding. + MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets; + + for (uint32_t rezIdx = dstArrayElement; + rezIdx < _info.descriptorCount && rezIdx - dstArrayElement < descriptorCount; + rezIdx++) { + switch (_info.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: { + const VkDescriptorBufferInfo& bufferInfo = pBufferInfo[rezIdx - dstArrayElement]; + MVKBuffer* buffer = (MVKBuffer*)bufferInfo.buffer; + bb.mtlBuffer = buffer->getMTLBuffer(); + bb.offset = bufferInfo.offset; + if (_applyToVertexStage) { + bb.index = mtlIdxs.vertexStage.bufferIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexBuffer(bb); + } + if (_applyToFragmentStage) { + bb.index = mtlIdxs.fragmentStage.bufferIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentBuffer(bb); + } + if (_applyToComputeStage) { + bb.index = mtlIdxs.computeStage.bufferIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindBuffer(bb); + } + break; + } + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { + const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement]; + MVKImageView* imageView = (MVKImageView*)imageInfo.imageView; + tb.mtlTexture = imageView->getMTLTexture(); + if (_applyToVertexStage) { + tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb); + } + if (_applyToFragmentStage) { + tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb); + } + if (_applyToComputeStage) { + tb.index = mtlIdxs.computeStage.textureIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindTexture(tb); + } + break; + } + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { + MVKBufferView* bufferView = (MVKBufferView*)pTexelBufferView[rezIdx - dstArrayElement]; + tb.mtlTexture = bufferView->getMTLTexture(); + if (_applyToVertexStage) { + tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb); + } + if (_applyToFragmentStage) { + tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb); + } + if (_applyToComputeStage) { + tb.index = mtlIdxs.computeStage.textureIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindTexture(tb); + } + break; + } + + case VK_DESCRIPTOR_TYPE_SAMPLER: { + MVKSampler* sampler; + if (_immutableSamplers.empty()) + sampler = (MVKSampler*)pImageInfo[rezIdx - dstArrayElement].sampler; + else + sampler = _immutableSamplers[rezIdx]; + sb.mtlSamplerState = sampler->getMTLSamplerState(); + if (_applyToVertexStage) { + sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb); + } + if (_applyToFragmentStage) { + sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb); + } + if (_applyToComputeStage) { + sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindSamplerState(sb); + } + break; + } + + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { + const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement]; + MVKImageView* imageView = (MVKImageView*)imageInfo.imageView; + MVKSampler* sampler = _immutableSamplers.empty() ? (MVKSampler*)imageInfo.sampler : _immutableSamplers[rezIdx]; + tb.mtlTexture = imageView->getMTLTexture(); + sb.mtlSamplerState = sampler->getMTLSamplerState(); + if (_applyToVertexStage) { + tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb); + sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb); + } + if (_applyToFragmentStage) { + tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb); + sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx; + cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb); + } + if (_applyToComputeStage) { + tb.index = mtlIdxs.computeStage.textureIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindTexture(tb); + sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx; + cmdEncoder->_computeResourcesState.bindSamplerState(sb); + } + break; + } + + default: + break; + } + } + + dstArrayElement = 0; + if (_info.descriptorCount > descriptorCount) + descriptorCount = 0; + else { + descriptorCount -= _info.descriptorCount; + pImageInfo += _info.descriptorCount; + pBufferInfo += _info.descriptorCount; + pTexelBufferView += _info.descriptorCount; + } +} + void MVKDescriptorSetLayoutBinding::populateShaderConverterContext(SPIRVToMSLConverterContext& context, MVKShaderResourceBinding& dslMTLRezIdxOffsets, uint32_t dslIndex) { @@ -300,6 +466,7 @@ void MVKDescriptorSetLayout::bindDescriptorSet(MVKCommandEncoder* cmdEncoder, vector& dynamicOffsets, uint32_t* pDynamicOffsetIndex) { + if (_isPushDescriptorLayout) return; uint32_t bindCnt = (uint32_t)_bindings.size(); for (uint32_t bindIdx = 0; bindIdx < bindCnt; bindIdx++) { _bindings[bindIdx].bind(cmdEncoder, descSet->_bindings[bindIdx], @@ -308,6 +475,28 @@ void MVKDescriptorSetLayout::bindDescriptorSet(MVKCommandEncoder* cmdEncoder, } } +void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + vector& descriptorWrites, + MVKShaderResourceBinding& dslMTLRezIdxOffsets) { + + if (!_isPushDescriptorLayout) return; + for (const VkWriteDescriptorSet& descWrite : descriptorWrites) { + uint32_t bindIdx = descWrite.dstBinding; + uint32_t dstArrayElement = descWrite.dstArrayElement; + uint32_t descriptorCount = descWrite.descriptorCount; + const VkDescriptorImageInfo* pImageInfo = descWrite.pImageInfo; + const VkDescriptorBufferInfo* pBufferInfo = descWrite.pBufferInfo; + const VkBufferView* pTexelBufferView = descWrite.pTexelBufferView; + // 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++) { + _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount, + descWrite.descriptorType, pImageInfo, pBufferInfo, + pTexelBufferView, dslMTLRezIdxOffsets); + } + } +} + void MVKDescriptorSetLayout::populateShaderConverterContext(SPIRVToMSLConverterContext& context, MVKShaderResourceBinding& dslMTLRezIdxOffsets, uint32_t dslIndex) { @@ -319,6 +508,7 @@ void MVKDescriptorSetLayout::populateShaderConverterContext(SPIRVToMSLConverterC MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) { + _isPushDescriptorLayout = (pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) != 0; // Create the descriptor bindings _bindings.reserve(pCreateInfo->bindingCount); for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { @@ -616,6 +806,7 @@ VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count, for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) { MVKDescriptorSetLayout* mvkDSL = (MVKDescriptorSetLayout*)pSetLayouts[dsIdx]; + if (mvkDSL->isPushDescriptorLayout()) continue; MVKDescriptorSet* mvkDescSet = new MVKDescriptorSet(_device, mvkDSL); _allocatedSets.push_front(mvkDescSet); pDescriptorSets[dsIdx] = (VkDescriptorSet)mvkDescSet; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 89411c40..ee5889c0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -77,6 +77,20 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2KHR* properties if (properties) { properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; properties->properties = _properties; + auto* next = (VkStructureType*)properties->pNext; + while (next) { + switch (*next) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: { + auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next; + pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources; + next = (VkStructureType*)pushDescProps->pNext; + break; + } + default: + next = *(VkStructureType**)(next+1); + break; + } + } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index df5b9ff9..61df8edc 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -249,6 +249,7 @@ void MVKInstance::initProcAddrs() { ADD_PROC_ADDR(vkGetPhysicalDeviceQueueFamilyProperties2KHR); ADD_PROC_ADDR(vkGetPhysicalDeviceMemoryProperties2KHR); ADD_PROC_ADDR(vkGetPhysicalDeviceSparseImageFormatProperties2KHR); + ADD_PROC_ADDR(vkCmdPushDescriptorSetKHR); 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 3772693b..4cd6391c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h @@ -50,6 +50,11 @@ public: /** Populates the specified shader converter context. */ void populateShaderConverterContext(SPIRVToMSLConverterContext& context); + /** Updates a descriptor set in a command encoder. */ + void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + std::vector& descriptorWrites, + uint32_t set); + /** 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 2efa06f9..151b840d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -54,6 +54,17 @@ void MVKPipelineLayout::bindDescriptorSets(MVKCommandEncoder* cmdEncoder, cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexOffsets.computeStage.bufferIndex); } +void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + vector& descriptorWrites, + uint32_t set) { + + _descriptorSetLayouts[set].pushDescriptorSet(cmdEncoder, descriptorWrites, + _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/Loader/MVKLayers.mm b/MoltenVK/MoltenVK/Loader/MVKLayers.mm index bc3b9e8b..42f331ea 100644 --- a/MoltenVK/MoltenVK/Loader/MVKLayers.mm +++ b/MoltenVK/MoltenVK/Loader/MVKLayers.mm @@ -107,6 +107,11 @@ MVKLayer::MVKLayer() { extTmplt.specVersion = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION; _extensions.push_back(extTmplt); + memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName)); + strcpy(extTmplt.extensionName, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + extTmplt.specVersion = VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION; + _extensions.push_back(extTmplt); + #if MVK_IOS memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName)); strcpy(extTmplt.extensionName, VK_MVK_IOS_SURFACE_EXTENSION_NAME); diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index a9434f3a..db0e6f3a 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -1677,6 +1677,22 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceSparseImageFormatProperties2KHR( } +#pragma mark - +#pragma mark VK_KHR_push_descriptor extension + +MVK_PUBLIC_SYMBOL void vkCmdPushDescriptorSetKHR( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites) { + + MVKCommandBuffer* cmdBuff = MVKCommandBuffer::getMVKCommandBuffer(commandBuffer); + mvkCmdPushDescriptorSet(cmdBuff, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites); +} + + #pragma mark - #pragma mark Loader and Layer ICD interface extension