Merge pull request #239 from cdavis5e/desc-update-template

Support the VK_KHR_descriptor_update_template extension.
This commit is contained in:
Bill Hollings 2018-09-04 15:55:14 -04:00 committed by GitHub
commit 4fcd64c017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 405 additions and 53 deletions

View File

@ -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<MVKCmdPushDescriptorSetWithTemplate>* 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);

View File

@ -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<MVKCmdPushDescriptorSetWithTemplate>* pool)
: MVKCommand::MVKCommand((MVKCommandTypePool<MVKCommand>*)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);
}

View File

@ -133,6 +133,8 @@ public:
MVKCommandTypePool<MVKCmdPushDescriptorSet> _cmdPushDescriptorSetPool;
MVKCommandTypePool<MVKCmdPushDescriptorSetWithTemplate> _cmdPushSetWithTemplatePool;
#pragma mark Command resources

View File

@ -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.

View File

@ -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<typename DescriptorAction>
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<VkDescriptorUpdateTemplateEntryKHR> _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.

View File

@ -173,13 +173,18 @@ void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder,
}
}
template<typename T>
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<VkDescriptorBufferInfo>(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<VkDescriptorImageInfo>(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<MVKBufferView*>(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<VkDescriptorImageInfo>(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<VkDescriptorImageInfo>(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<VkWriteDescriptorSet>& 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<VkDescriptorImageInfo>(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<VkDescriptorImageInfo>(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<VkDescriptorImageInfo>(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<VkDescriptorBufferInfo>(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<VkBufferView>(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<typename DescriptorAction>
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<VkWriteDescriptorSet>(const VkWriteDescriptorSet* pDescriptorAction,
const VkDescriptorImageInfo* pImageInfo,
const VkDescriptorBufferInfo* pBufferInfo,
const VkBufferView* pTexelBufferView);
size_t stride, const void *pData);
template void MVKDescriptorSet::writeDescriptorSets<VkCopyDescriptorSet>(const VkCopyDescriptorSet* pDescriptorAction,
const VkDescriptorImageInfo* pImageInfo,
const VkDescriptorBufferInfo* pBufferInfo,
const VkBufferView* pTexelBufferView);
size_t stride, const void *pData);
template void MVKDescriptorSet::writeDescriptorSets<VkDescriptorUpdateTemplateEntryKHR>(
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);
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -55,6 +55,12 @@ public:
std::vector<VkWriteDescriptorSet>& 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);

View File

@ -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();

View File

@ -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.
@ -69,7 +70,8 @@ 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)
{}
bool MVKExtensionList::isEnabled(const char* extnName) const {

View File

@ -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;
};

View File

@ -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