Merge pull request #305 from billhollings/master

Update shader caching for compatibility with texture swizzling.
This commit is contained in:
Bill Hollings 2018-10-19 15:50:32 -07:00 committed by GitHub
commit 79e4d75e1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 64 deletions

View File

@ -48,7 +48,7 @@ extern "C" {
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 0
#define MVK_VERSION_PATCH 24
#define MVK_VERSION_PATCH 25
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
@ -631,7 +631,7 @@ typedef uint32_t MVKMSLSPIRVHeader;
#endif // VK_NO_PROTOTYPES
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@ -58,6 +58,10 @@ typedef struct MVKShaderResourceBinding {
MVKShaderStageResourceBinding fragmentStage;
MVKShaderStageResourceBinding computeStage;
uint32_t getMaxBufferIndex();
uint32_t getMaxTextureIndex();
uint32_t getMaxSamplerIndex();
MVKShaderResourceBinding operator+ (const MVKShaderResourceBinding& rhs);
MVKShaderResourceBinding& operator+= (const MVKShaderResourceBinding& rhs);

View File

@ -46,6 +46,18 @@ MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::
#pragma mark MVKShaderResourceBinding
MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxBufferIndex() {
return max({vertexStage.bufferIndex, fragmentStage.bufferIndex, computeStage.bufferIndex});
}
MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxTextureIndex() {
return max({vertexStage.textureIndex, fragmentStage.textureIndex, computeStage.textureIndex});
}
MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxSamplerIndex() {
return max({vertexStage.samplerIndex, fragmentStage.samplerIndex, computeStage.samplerIndex});
}
MVK_PUBLIC_SYMBOL MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (const MVKShaderResourceBinding& rhs) {
MVKShaderResourceBinding rslt;
rslt.vertexStage = this->vertexStage + rhs.vertexStage;

View File

@ -75,18 +75,17 @@ public:
const MVKShaderAuxBufferBinding& getAuxBufferIndex() { return _auxBufferIndex; }
/** Returns the number of textures in this layout. This is used to calculate the size of the auxiliary buffer. */
uint32_t getNumTextures() { return _numTextures; }
uint32_t getMaxTextureIndex() { return _pushConstantsMTLResourceIndexes.getMaxTextureIndex(); }
/** Constructs an instance for the specified device. */
MVKPipelineLayout(MVKDevice* device, const VkPipelineLayoutCreateInfo* pCreateInfo);
private:
protected:
std::vector<MVKDescriptorSetLayout> _descriptorSetLayouts;
std::vector<MVKShaderResourceBinding> _dslMTLResourceIndexOffsets;
std::vector<VkPushConstantRange> _pushConstants;
MVKShaderResourceBinding _pushConstantsMTLResourceIndexOffsets;
MVKShaderResourceBinding _pushConstantsMTLResourceIndexes;
MVKShaderAuxBufferBinding _auxBufferIndex;
uint32_t _numTextures;
};
@ -108,6 +107,10 @@ public:
MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKBaseDeviceObject(device),
_pipelineCache(pipelineCache) {}
~MVKPipeline() override {
[_auxBuffer release];
};
protected:
MVKPipelineCache* _pipelineCache;
MVKShaderAuxBufferBinding _auxBufferIndex;

View File

@ -49,9 +49,9 @@ void MVKPipelineLayout::bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
_dslMTLResourceIndexOffsets[dslIdx],
dynamicOffsets, &pDynamicOffsetIndex);
}
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);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.vertexStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.fragmentStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.computeStage.bufferIndex);
}
void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
@ -60,9 +60,9 @@ void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
_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);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.vertexStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.fragmentStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.computeStage.bufferIndex);
}
void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
@ -73,9 +73,9 @@ void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
_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);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.vertexStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.fragmentStage.bufferIndex);
cmdEncoder->getPushConstants(VK_SHADER_STAGE_COMPUTE_BIT)->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.computeStage.bufferIndex);
}
void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConverterContext& context) {
@ -91,62 +91,26 @@ void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConverterContex
// Add any resource bindings used by push-constants
mvkPopulateShaderConverterContext(context,
_pushConstantsMTLResourceIndexOffsets.vertexStage,
_pushConstantsMTLResourceIndexes.vertexStage,
spv::ExecutionModelVertex,
kPushConstDescSet,
kPushConstBinding);
mvkPopulateShaderConverterContext(context,
_pushConstantsMTLResourceIndexOffsets.fragmentStage,
_pushConstantsMTLResourceIndexes.fragmentStage,
spv::ExecutionModelFragment,
kPushConstDescSet,
kPushConstBinding);
mvkPopulateShaderConverterContext(context,
_pushConstantsMTLResourceIndexOffsets.computeStage,
_pushConstantsMTLResourceIndexes.computeStage,
spv::ExecutionModelGLCompute,
kPushConstDescSet,
kPushConstBinding);
// Scan the resource bindings, looking for an unused buffer index.
// FIXME: If we ever encounter a device that supports more than 31 buffer
// bindings, we'll need to update this code.
unordered_map<uint32_t, uint32_t> freeBufferMasks;
freeBufferMasks[spv::ExecutionModelVertex] = freeBufferMasks[spv::ExecutionModelFragment] = freeBufferMasks[spv::ExecutionModelGLCompute] = (1 << _device->_pMetalFeatures->maxPerStageBufferCount) - 1;
_numTextures = 0;
for (auto& binding : context.resourceBindings) {
if (binding.descriptorSet == kPushConstDescSet && binding.binding == kPushConstBinding) {
// This is the special push constant buffer.
freeBufferMasks[binding.stage] &= ~(1 << binding.mslBuffer);
continue;
}
VkDescriptorType descriptorType = _descriptorSetLayouts[binding.descriptorSet]._bindings[binding.binding]._info.descriptorType;
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
// This buffer is being used.
freeBufferMasks[binding.stage] &= ~(1 << binding.mslBuffer);
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
// If it results in a texture binding, we need to account for it so
// we know how big to make the auxiliary buffer.
if (binding.mslTexture + 1 > _numTextures)
_numTextures = binding.mslTexture + 1;
break;
default:
break;
}
}
// Pick the lowest index that isn't used.
_auxBufferIndex.vertex = ffs(freeBufferMasks[spv::ExecutionModelVertex]) - 1;
_auxBufferIndex.fragment = ffs(freeBufferMasks[spv::ExecutionModelFragment]) - 1;
_auxBufferIndex.compute = ffs(freeBufferMasks[spv::ExecutionModelGLCompute]) - 1;
_auxBufferIndex.vertex = _pushConstantsMTLResourceIndexes.vertexStage.bufferIndex + 1;
_auxBufferIndex.fragment = _pushConstantsMTLResourceIndexes.fragmentStage.bufferIndex + 1;
_auxBufferIndex.compute = _pushConstantsMTLResourceIndexes.computeStage.bufferIndex + 1;
}
MVKPipelineLayout::MVKPipelineLayout(MVKDevice* device,
@ -167,8 +131,8 @@ MVKPipelineLayout::MVKPipelineLayout(MVKDevice* device,
for (uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++) {
MVKDescriptorSetLayout* pDescSetLayout = (MVKDescriptorSetLayout*)pCreateInfo->pSetLayouts[i];
_descriptorSetLayouts.push_back(*pDescSetLayout);
_dslMTLResourceIndexOffsets.push_back(_pushConstantsMTLResourceIndexOffsets);
_pushConstantsMTLResourceIndexOffsets += pDescSetLayout->_mtlResourceCounts;
_dslMTLResourceIndexOffsets.push_back(_pushConstantsMTLResourceIndexes);
_pushConstantsMTLResourceIndexes += pDescSetLayout->_mtlResourceCounts;
}
// Add push constants
@ -339,7 +303,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
initMVKShaderConverterContext(shaderContext, pCreateInfo);
auto* mvkLayout = (MVKPipelineLayout*)pCreateInfo->layout;
_auxBufferIndex = mvkLayout->getAuxBufferIndex();
uint32_t auxBufferSize = sizeof(uint32_t) * mvkLayout->getNumTextures();
uint32_t auxBufferSize = sizeof(uint32_t) * mvkLayout->getMaxTextureIndex();
// Retrieve the render subpass for which this pipeline is being constructed
MVKRenderPass* mvkRendPass = (MVKRenderPass*)pCreateInfo->renderPass;
@ -394,7 +358,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
}
if (_needsVertexAuxBuffer || _needsFragmentAuxBuffer) {
_auxBuffer = [_device->getMTLDevice() newBufferWithLength: auxBufferSize options: MTLResourceStorageModeShared];
_auxBuffer = [_device->getMTLDevice() newBufferWithLength: auxBufferSize options: MTLResourceStorageModeShared]; // retained
}
// Vertex attributes
@ -584,14 +548,14 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI
MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout;
layout->populateShaderConverterContext(shaderContext);
_auxBufferIndex = layout->getAuxBufferIndex();
uint32_t auxBufferSize = sizeof(uint32_t) * layout->getNumTextures();
uint32_t auxBufferSize = sizeof(uint32_t) * layout->getMaxTextureIndex();
shaderContext.options.auxBufferIndex = _auxBufferIndex.compute;
MVKShaderModule* mvkShdrMod = (MVKShaderModule*)pSS->module;
auto func = mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache);
_needsAuxBuffer = shaderContext.options.needsAuxBuffer;
if (_needsAuxBuffer) {
_auxBuffer = [_device->getMTLDevice() newBufferWithLength: auxBufferSize options: MTLResourceStorageModeShared];
_auxBuffer = [_device->getMTLDevice() newBufferWithLength: auxBufferSize options: MTLResourceStorageModeShared]; // retained
}
return func;
}
@ -661,9 +625,11 @@ namespace mvk {
opt.entryPointStage,
opt.mslVersion,
opt.texelBufferTextureWidth,
opt.auxBufferIndex,
opt.shouldFlipVertexY,
opt.isRenderingPoints,
opt.isRasterizationDisabled);
opt.isRasterizationDisabled,
opt.needsAuxBuffer);
}
template<class Archive>

View File

@ -42,6 +42,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverterOptions::matches(const SPIRVToMSLConve
if (entryPointStage != other.entryPointStage) { return false; }
if (mslVersion != other.mslVersion) { return false; }
if (texelBufferTextureWidth != other.texelBufferTextureWidth) { return false; }
if (auxBufferIndex != other.auxBufferIndex) { return false; }
if (!!shouldFlipVertexY != !!other.shouldFlipVertexY) { return false; }
if (!!isRenderingPoints != !!other.isRenderingPoints) { return false; }
if (entryPointName != other.entryPointName) { return false; }
@ -103,6 +104,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverterContext::matches(const SPIRVToMSLConve
MVK_PUBLIC_SYMBOL void SPIRVToMSLConverterContext::alignWith(const SPIRVToMSLConverterContext& srcContext) {
options.isRasterizationDisabled = srcContext.options.isRasterizationDisabled;
options.needsAuxBuffer = srcContext.options.needsAuxBuffer;
if (options.entryPointStage == spv::ExecutionModelVertex) {
for (auto& va : vertexAttributes) {