Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Let SPIRV-Cross assign MSL resource indices. #1173

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
b.index = mvkDvc->getMetalBufferIndexForVertexAttributeBinding(startBinding + bindIdx);
b.mtlBuffer = mvkBuffer->getMTLBuffer();
b.offset = mvkBuffer->getMTLBufferOffset() + pOffsets[bindIdx];
b.isFixed = true;
_bindings.push_back(b);
}

Expand Down
14 changes: 14 additions & 0 deletions MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,19 @@
switch (pipelineBindPoint) {
case VK_PIPELINE_BIND_POINT_GRAPHICS:
_graphicsPipelineState.setPipeline(pipeline);
// New pipeline likely has different MSL index mappings
// Need to mark resources dirty
_graphicsResourcesState.markDirty();
_vertexPushConstants.markDirty();
_tessCtlPushConstants.markDirty();
_tessEvalPushConstants.markDirty();
_fragmentPushConstants.markDirty();
break;

case VK_PIPELINE_BIND_POINT_COMPUTE:
_computePipelineState.setPipeline(pipeline);
_computeResourcesState.markDirty();
_computePushConstants.markDirty();
break;

default:
Expand Down Expand Up @@ -458,9 +467,13 @@
_scissorState.encode(stage);
_depthBiasState.encode(stage);
_blendColorState.encode(stage);
_vertexPushConstants._pipeline = _graphicsPipelineState.getPipeline();
_vertexPushConstants.encode(stage);
_tessCtlPushConstants._pipeline = _graphicsPipelineState.getPipeline();
_tessCtlPushConstants.encode(stage);
_tessEvalPushConstants._pipeline = _graphicsPipelineState.getPipeline();
_tessEvalPushConstants.encode(stage);
_fragmentPushConstants._pipeline = _graphicsPipelineState.getPipeline();
_fragmentPushConstants.encode(stage);
_depthStencilState.encode(stage);
_stencilReferenceValueState.encode(stage);
Expand Down Expand Up @@ -512,6 +525,7 @@
void MVKCommandEncoder::finalizeDispatchState() {
_computePipelineState.encode(); // Must do first..it sets others
_computeResourcesState.encode();
_computePushConstants._pipeline = _computePipelineState.getPipeline();
_computePushConstants.encode();
}

Expand Down
20 changes: 15 additions & 5 deletions MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ class MVKPushConstantsCommandEncoderState : public MVKCommandEncoderState {
VkShaderStageFlagBits shaderStage)
: MVKCommandEncoderState(cmdEncoder), _shaderStage(shaderStage) {}

MVKPipeline *_pipeline;

protected:
void encodeImpl(uint32_t stage) override;
void resetImpl() override;
Expand Down Expand Up @@ -395,13 +397,20 @@ class MVKResourcesCommandEncoderState : public MVKCommandEncoderState {
// Template function that executes a lambda expression on each dirty element of
// a vector of bindings, and marks the bindings and the vector as no longer dirty.
template<class T, class V>
void encodeBinding(V& bindings,
void encodeBinding(MVKSmallVector<uint16_t>& mslIndices,
V& bindings,
bool& bindingsDirtyFlag,
std::function<void(MVKCommandEncoder* cmdEncoder, T& b)> mtlOperation) {
if (bindingsDirtyFlag) {
bindingsDirtyFlag = false;
for (auto& b : bindings) {
if (b.isDirty) {
for (auto b : bindings) {
if (!b.isFixed) {
if (b.index >= mslIndices.size()) {
continue;
}
b.index = mslIndices[b.index];
}
if (b.isDirty && b.index != (uint16_t)-1) {
mtlOperation(_cmdEncoder, b);
b.isDirty = false;
}
Expand Down Expand Up @@ -501,7 +510,8 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode
bool needVertexViewBuffer,
bool needFragmentViewBuffer);

void encodeBindings(MVKShaderStage stage,
void encodeBindings(MVKGraphicsPipeline *pipeline,
MVKShaderStage stage,
const char* pStageName,
bool fullImageViewSwizzle,
std::function<void(MVKCommandEncoder*, MVKMTLBufferBinding&)> bindBuffer,
Expand All @@ -512,6 +522,7 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode
/** Offset all buffers for vertex attribute bindings with zero divisors by the given number of strides. */
void offsetZeroDivisorVertexBuffers(MVKGraphicsStage stage, MVKGraphicsPipeline* pipeline, uint32_t firstInstance);

void markDirty() override;
#pragma mark Construction

/** Constructs this instance for the specified command encoder. */
Expand All @@ -520,7 +531,6 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode
protected:
void encodeImpl(uint32_t stage) override;
void resetImpl() override;
void markDirty() override;

ResourceBindings<8> _shaderStageResourceBindings[4];
};
Expand Down
62 changes: 39 additions & 23 deletions MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
Original file line number Diff line number Diff line change
Expand Up @@ -193,21 +193,31 @@
void MVKPushConstantsCommandEncoderState::encodeImpl(uint32_t stage) {
if (_pushConstants.empty() ) { return; }

_isDirty = true; // Stay dirty until I actually decide to make a change to the encoder
_isDirty = true; // Stay dirty until I actually decide to make a change to the encoder

int mvkStage = mvkShaderStageFromVkShaderStageFlagBits(_shaderStage);
if (_mtlBufferIndex >= _pipeline->_bufferMSLIndices[mvkStage].size()) {
return;
}
uint16_t index = _pipeline->_bufferMSLIndices[mvkStage][_mtlBufferIndex];
if (index == (uint16_t)-1) {
return;
}


switch (_shaderStage) {
case VK_SHADER_STAGE_VERTEX_BIT:
if (stage == kMVKGraphicsStageVertex) {
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl),
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
} else if (!isTessellating() && stage == kMVKGraphicsStageRasterization) {
_cmdEncoder->setVertexBytes(_cmdEncoder->_mtlRenderEncoder,
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
}
break;
Expand All @@ -216,7 +226,7 @@
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl),
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
}
break;
Expand All @@ -225,7 +235,7 @@
_cmdEncoder->setVertexBytes(_cmdEncoder->_mtlRenderEncoder,
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
}
break;
Expand All @@ -234,15 +244,15 @@
_cmdEncoder->setFragmentBytes(_cmdEncoder->_mtlRenderEncoder,
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
}
break;
case VK_SHADER_STAGE_COMPUTE_BIT:
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
_pushConstants.data(),
_pushConstants.size(),
_mtlBufferIndex);
index);
_isDirty = false; // Okay, I changed the encoder
break;
default:
Expand Down Expand Up @@ -569,20 +579,25 @@
_shaderStageResourceBindings[kMVKShaderStageFragment].viewRangeBufferBinding.isDirty = needFragmentViewBuffer;
}

void MVKGraphicsResourcesCommandEncoderState::encodeBindings(MVKShaderStage stage,
void MVKGraphicsResourcesCommandEncoderState::encodeBindings(MVKGraphicsPipeline *pipeline,
MVKShaderStage stage,
const char* pStageName,
bool fullImageViewSwizzle,
std::function<void(MVKCommandEncoder*, MVKMTLBufferBinding&)> bindBuffer,
std::function<void(MVKCommandEncoder*, MVKMTLBufferBinding&, const MVKArrayRef<uint32_t>&)> bindImplicitBuffer,
std::function<void(MVKCommandEncoder*, MVKMTLTextureBinding&)> bindTexture,
std::function<void(MVKCommandEncoder*, MVKMTLSamplerStateBinding&)> bindSampler) {
auto& shaderStage = _shaderStageResourceBindings[stage];
encodeBinding<MVKMTLBufferBinding>(shaderStage.bufferBindings, shaderStage.areBufferBindingsDirty, bindBuffer);
auto& bufferMSLIndices = pipeline->_bufferMSLIndices[stage];
auto& textureMSLIndices = pipeline->_textureMSLIndices[stage];
auto& samplerMSLIndices = pipeline->_samplerMSLIndices[stage];

encodeBinding<MVKMTLBufferBinding>(bufferMSLIndices, shaderStage.bufferBindings, shaderStage.areBufferBindingsDirty, bindBuffer);

if (shaderStage.swizzleBufferBinding.isDirty) {

for (auto& b : shaderStage.textureBindings) {
if (b.isDirty) { updateImplicitBuffer(shaderStage.swizzleConstants, b.index, b.swizzle); }
if (b.isDirty) { updateImplicitBuffer(shaderStage.swizzleConstants, textureMSLIndices[b.index], b.swizzle); }
}

bindImplicitBuffer(_cmdEncoder, shaderStage.swizzleBufferBinding, shaderStage.swizzleConstants.contents());
Expand All @@ -593,7 +608,7 @@

if (shaderStage.bufferSizeBufferBinding.isDirty) {
for (auto& b : shaderStage.bufferBindings) {
if (b.isDirty) { updateImplicitBuffer(shaderStage.bufferSizes, b.index, b.size); }
if (b.isDirty) { updateImplicitBuffer(shaderStage.bufferSizes, bufferMSLIndices[b.index], b.size); }
}

bindImplicitBuffer(_cmdEncoder, shaderStage.bufferSizeBufferBinding, shaderStage.bufferSizes.contents());
Expand All @@ -606,8 +621,8 @@
bindImplicitBuffer(_cmdEncoder, shaderStage.viewRangeBufferBinding, viewRange.contents());
}

encodeBinding<MVKMTLTextureBinding>(shaderStage.textureBindings, shaderStage.areTextureBindingsDirty, bindTexture);
encodeBinding<MVKMTLSamplerStateBinding>(shaderStage.samplerStateBindings, shaderStage.areSamplerStateBindingsDirty, bindSampler);
encodeBinding<MVKMTLTextureBinding>(textureMSLIndices, shaderStage.textureBindings, shaderStage.areTextureBindingsDirty, bindTexture);
encodeBinding<MVKMTLSamplerStateBinding>(samplerMSLIndices, shaderStage.samplerStateBindings, shaderStage.areSamplerStateBindingsDirty, bindSampler);
}

void MVKGraphicsResourcesCommandEncoderState::offsetZeroDivisorVertexBuffers(MVKGraphicsStage stage,
Expand All @@ -618,6 +633,7 @@
uint32_t mtlBuffIdx = pipeline->getMetalBufferIndexForVertexAttributeBinding(binding.first);
auto iter = std::find_if(shaderStage.bufferBindings.begin(), shaderStage.bufferBindings.end(), [mtlBuffIdx](const MVKMTLBufferBinding& b) { return b.index == mtlBuffIdx; });
if (!iter) { continue; }

switch (stage) {
case kMVKGraphicsStageVertex:
[_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl) setBufferOffset: iter->offset + firstInstance * binding.second
Expand Down Expand Up @@ -651,7 +667,7 @@
bool forTessellation = pipeline->isTessellationPipeline();

if (stage == kMVKGraphicsStageVertex) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
encodeBindings(pipeline, kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline)
cmdEncoder->setComputeBytes(cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl),
Expand Down Expand Up @@ -679,7 +695,7 @@
});

} else if (!forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
encodeBindings(pipeline, kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
[pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline) {
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,
Expand Down Expand Up @@ -720,7 +736,7 @@
}

if (stage == kMVKGraphicsStageTessControl) {
encodeBindings(kMVKShaderStageTessCtl, "tessellation control", fullImageViewSwizzle,
encodeBindings(pipeline, kMVKShaderStageTessCtl, "tessellation control", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline)
cmdEncoder->setComputeBytes(cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl),
Expand Down Expand Up @@ -750,7 +766,7 @@
}

if (forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageTessEval, "tessellation evaluation", fullImageViewSwizzle,
encodeBindings(pipeline, kMVKShaderStageTessEval, "tessellation evaluation", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline)
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,
Expand Down Expand Up @@ -780,7 +796,7 @@
}

if (stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageFragment, "fragment", fullImageViewSwizzle,
encodeBindings(pipeline, kMVKShaderStageFragment, "fragment", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline)
cmdEncoder->setFragmentBytes(cmdEncoder->_mtlRenderEncoder,
Expand Down Expand Up @@ -858,7 +874,7 @@

if (_resourceBindings.swizzleBufferBinding.isDirty) {
for (auto& b : _resourceBindings.textureBindings) {
if (b.isDirty) { updateImplicitBuffer(_resourceBindings.swizzleConstants, b.index, b.swizzle); }
if (b.isDirty) { updateImplicitBuffer(_resourceBindings.swizzleConstants, pipeline->_textureMSLIndices[kMVKShaderStageCompute][b.index], b.swizzle); }
}

_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
Expand All @@ -872,7 +888,7 @@

if (_resourceBindings.bufferSizeBufferBinding.isDirty) {
for (auto& b : _resourceBindings.bufferBindings) {
if (b.isDirty) { updateImplicitBuffer(_resourceBindings.bufferSizes, b.index, b.size); }
if (b.isDirty) { updateImplicitBuffer(_resourceBindings.bufferSizes, pipeline->_bufferMSLIndices[kMVKShaderStageCompute][b.index], b.size); }
}

_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
Expand All @@ -882,7 +898,7 @@

}

encodeBinding<MVKMTLBufferBinding>(_resourceBindings.bufferBindings, _resourceBindings.areBufferBindingsDirty,
encodeBinding<MVKMTLBufferBinding>(pipeline->_bufferMSLIndices[kMVKShaderStageCompute], _resourceBindings.bufferBindings, _resourceBindings.areBufferBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline) {
cmdEncoder->setComputeBytes(cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
Expand All @@ -896,13 +912,13 @@
}
});

encodeBinding<MVKMTLTextureBinding>(_resourceBindings.textureBindings, _resourceBindings.areTextureBindingsDirty,
encodeBinding<MVKMTLTextureBinding>(pipeline->_textureMSLIndices[kMVKShaderStageCompute], _resourceBindings.textureBindings, _resourceBindings.areTextureBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLTextureBinding& b)->void {
[cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setTexture: b.mtlTexture
atIndex: b.index];
});

encodeBinding<MVKMTLSamplerStateBinding>(_resourceBindings.samplerStateBindings, _resourceBindings.areSamplerStateBindingsDirty,
encodeBinding<MVKMTLSamplerStateBinding>(pipeline->_samplerMSLIndices[kMVKShaderStageCompute], _resourceBindings.samplerStateBindings, _resourceBindings.areSamplerStateBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLSamplerStateBinding& b)->void {
[cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setSamplerState: b.mtlSamplerState
atIndex: b.index];
Expand Down
3 changes: 3 additions & 0 deletions MoltenVK/MoltenVK/Commands/MVKMTLResourceBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ typedef struct {
uint32_t swizzle = 0;
uint16_t index = 0;
bool isDirty = true;
bool isFixed = false;
} MVKMTLTextureBinding;

/** Describes a MTLSamplerState resource binding. */
typedef struct {
union { id<MTLSamplerState> mtlSamplerState = nil; id<MTLSamplerState> mtlResource; }; // aliases
uint16_t index = 0;
bool isDirty = true;
bool isFixed = false;
} MVKMTLSamplerStateBinding;

/** Describes a MTLBuffer resource binding. */
Expand All @@ -51,6 +53,7 @@ typedef struct {
uint16_t index = 0;
bool isDirty = true;
bool isInline = false;
bool isFixed = false;
} MVKMTLBufferBinding;

/** Describes a MTLBuffer resource binding as used for an index buffer. */
Expand Down
8 changes: 8 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ class MVKPipeline : public MVKVulkanAPIDeviceObject {
/** Constructs an instance for the device. layout, and parent (which may be NULL). */
MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipelineLayout* layout, MVKPipeline* parent);


/** Resource remapping */
MVKSmallVector<uint16_t> _samplerMSLIndices[kMVKShaderStageMax];
MVKSmallVector<uint16_t> _textureMSLIndices[kMVKShaderStageMax];
MVKSmallVector<uint16_t> _bufferMSLIndices[kMVKShaderStageMax];

void populateMSLIndices(MVKShaderStage stage, const SPIRVToMSLConversionConfiguration& shaderContext);

protected:
void propagateDebugName() override {}

Expand Down
Loading