Fixes 4 bugs in VK_EXT_inline_uniform_block:

descriptorCount measures bytes, array indices are offsets into the buffer,
missing isInline flag in bind, missing struct VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT.
This commit is contained in:
Alexander Meißner 2020-06-14 09:45:07 +02:00
parent 06747095c5
commit 4a09c7aa20
4 changed files with 107 additions and 76 deletions

View File

@ -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> _mtlBuffer = nil;
uint32_t _dataSize = 0;
};

View File

@ -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<typename T>
@ -167,13 +172,13 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
}
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: {
const auto& inlineUniformBlock = get<VkWriteDescriptorSetInlineUniformBlockEXT>(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<VkWriteDescriptorSetInlineUniformBlockEXT>(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<void*>(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();
}

View File

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

View File

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