Commit a4844d82 authored by Laszlo Agocs's avatar Laszlo Agocs
Browse files

mtl: no need to redo res bindings upon pipeline change

...because we only really need to make sure arg changes are not skipped
upon a new pass, just changing the pipeline state has no effect on this.

Clarify the docs a bit as well.
parent b5b55be8
......@@ -951,7 +951,7 @@ public:
// Sometimes committing the updates is necessary without starting a render
// pass. Not often needed, updates should typically be passed to beginPass
// (or endPass, in case of readbacks) instead.
// (or endPass, in case of readbacks) instead. Cannot be called inside a pass.
void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
void beginPass(QRhiRenderTarget *rt,
......@@ -960,6 +960,13 @@ public:
QRhiResourceUpdateBatch *resourceUpdates = nullptr);
void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
// The set* and draw* functions can only be called inside a pass. Also,
// (with the exception of setGraphicsPipeline) they expect to have a
// pipeline set already on the command buffer. Otherwise, unspecified
// issues may arise, depending on the backend.
//
// Do not assume that any bindings or states persist between passes.
// When specified, srb can be different from ps' srb but the layouts must
// match. Basic tracking is included: no command is added to the cb when
// the pipeline or srb are the same as in the last call in the same frame;
......@@ -971,12 +978,8 @@ public:
void setGraphicsPipeline(QRhiGraphicsPipeline *ps,
QRhiShaderResourceBindings *srb = nullptr);
// The set* and draw* functions expect to have a pipeline set already on
// the command buffer. Otherwise, unspecified issues may arise, depending on
// the backend.
// Some level of smartness can be expected from most backends: superfluous
// vertex input or index buffer changes are ignored automatically.
// vertex input and index changes in the same pass are ignored automatically.
using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
void setVertexInput(int startBinding, const QVector<VertexInput> &bindings,
QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
......@@ -1000,6 +1003,7 @@ public:
quint32 firstInstance = 0);
// Ignored when DebugMarkers are not supported or EnableDebugMarkers is not set.
// debugMarkBegin/End can be called both inside and outside a pass.
void debugMarkBegin(const QByteArray &name);
void debugMarkEnd();
// With some backends debugMarkMsg is only supported inside a pass and is
......
......@@ -158,6 +158,7 @@ struct QMetalCommandBufferData
id<MTLCommandBuffer> cb;
id<MTLRenderCommandEncoder> currentPassEncoder;
MTLRenderPassDescriptor *currentPassRpDesc;
bool shaderResourceBindingsValid;
int currentFirstVertexBinding;
QRhiBatchedBindings<id<MTLBuffer> > currentVertexInputsBuffers;
QRhiBatchedBindings<NSUInteger> currentVertexInputOffsets;
......@@ -600,11 +601,10 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
[cbD->d->currentPassEncoder setDepthStencilState: psD->d->ds];
[cbD->d->currentPassEncoder setCullMode: psD->d->cullMode];
[cbD->d->currentPassEncoder setFrontFacingWinding: psD->d->winding];
}
// resource assignments will need to be redone both for vertex input and shader resources
cbD->resetPerPipelineState();
if (!cbD->d->shaderResourceBindingsValid)
resNeedsRebind = true;
}
if (resNeedsRebind || cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation) {
cbD->currentSrb = srb;
......@@ -612,6 +612,7 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
cbD->currentResSlot = resSlot;
enqueueShaderResourceBindings(srbD, cbD);
cbD->d->shaderResourceBindingsValid = true;
}
psD->lastActiveFrameSlot = currentFrameSlot;
......@@ -1341,6 +1342,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
cbD->d->currentPassEncoder = [cbD->d->cb renderCommandEncoderWithDescriptor: cbD->d->currentPassRpDesc];
cbD->resetPerPassState();
cbD->currentTarget = rt;
inPass = true;
}
......@@ -2608,11 +2611,12 @@ void QMetalCommandBuffer::resetState()
d->currentPassEncoder = nil;
d->currentPassRpDesc = nil;
resetPerPipelineState();
resetPerPassState();
}
void QMetalCommandBuffer::resetPerPipelineState()
void QMetalCommandBuffer::resetPerPassState()
{
d->shaderResourceBindingsValid = false;
d->currentFirstVertexBinding = -1;
d->currentVertexInputsBuffers.clear();
d->currentVertexInputOffsets.clear();
......
......@@ -235,7 +235,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
QRhiCommandBuffer::IndexFormat currentIndexFormat;
void resetState();
void resetPerPipelineState();
void resetPerPassState();
};
struct QMetalSwapChainData;
......
......@@ -6,7 +6,7 @@ should istexformatsupported should check srgb combinations
vk: image in wrong layout when beginFrame-endFrame without a pass in it
cbuffer alignment rules - some things fail to translate (to hlsl e.g. with structs), which is fine but how to mitigate
what does image copy do for compressed formats?
figure sg out for minimizing viewport/scissor cmds
reduce viewport/scissor/other state changes in a pass
vk: test FrameOpDeviceLost somehow
d3d device loss?
more what-if-resource-rebuilt cases
......@@ -45,7 +45,7 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done
vk, d3d, mtl: minimize vertex input changes
vk, d3d, mtl: minimize vertex input changes inside passes
mtl: cbuffers, textures, samplers set should be batched too
mtl: reduce set*
mtl: report readback temp buf
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment