rhi: Make per-frame flags per-pass where appropriate

ExternalContentsInPass becomes a per-pass flag now. Why is this
beneficial? Because while Qt Quick has no choice for its render
pass, not being able to guess if the application wants to do some
native rendering in there, Quick 3D's render passes, all the ones
that are under Quick3D's control, do not have native rendering
from the application in them, and so using secondary command
buffers with Vulkan is not necessary.

Introduce something similar for compute and OpenGL. By knowing that
none of the resources used in a pass are used with a compute pass
(e.g. because we know that there are no compute passes at all) a small
amount of time can be saved by skipping tracking buffers and textures
because the only purpose of said tracking is to generate barriers that
are relevant only to compute.

Change-Id: I0eceb4774d87803c73a39db527f5707a9f4d75c1
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
bb10
Laszlo Agocs 2020-09-30 14:08:53 +02:00
parent 3080194ae4
commit d92b0e18c1
14 changed files with 199 additions and 127 deletions

View File

@ -614,11 +614,6 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
/*!
\enum QRhi::BeginFrameFlag
Flag values for QRhi::beginFrame()
\value ExternalContentsInPass Specifies that one or more render or compute
passes in this frame will call QRhiCommandBuffer::beginExternal(). Some
backends, Vulkan in particular, will fail if this flag is not set and
beginExternal() is still called.
*/
/*!
@ -4090,6 +4085,26 @@ QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
\value IndexUInt32 Unsigned 32-bit (quint32)
*/
/*!
\enum QRhiCommandBuffer::BeginPassFlag
Flag values for QRhi::beginPass()
\value ExternalContent Specifies that there will be a call to
QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in
particular, will fail if this flag is not set and beginExternal() is still
called.
\value DoNotTrackResourcesForCompute Specifies that there is no need to
track resources used in this pass if the only purpose of such tracking is
to generate barriers for compute. Implies that there are no compute passes
in the frame. This is an optimization hint that may be taken into account
by certain backends, OpenGL in particular, allowing them to skip certain
operations. When this flag is set for a render pass in a frame, calling
\l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame
may lead to unexpected behavior, depending on the resource dependencies
between the render and compute passes.
*/
/*!
\typedef QRhiCommandBuffer::DynamicOffset
@ -5135,9 +5150,10 @@ void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
BeginPassFlags flags)
{
m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates);
m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags);
}
/*!
@ -5466,9 +5482,9 @@ void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
\note Compute is only available when the \l{QRhi::Compute}{Compute} feature
is reported as supported.
*/
void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates)
void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
{
m_rhi->beginComputePass(this, resourceUpdates);
m_rhi->beginComputePass(this, resourceUpdates, flags);
}
/*!
@ -5543,10 +5559,10 @@ const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
enqueue commands to the current pass' command buffer by calling graphics
API functions directly.
\note This is only available when the intent was declared up front in
beginFrame(). Therefore this function must only be called when the frame
was started with specifying QRhi::ExternalContentsInPass in the flags
passed to QRhi::beginFrame().
\note This is only available when the intent was declared upfront in
beginPass() or beginComputePass(). Therefore this function must only be
called when the pass recording was started with specifying
QRhiCommandBuffer::ExternalContent.
With Vulkan or Metal one can query the native command buffer or encoder
objects via nativeHandles() and enqueue commands to them. With OpenGL or
@ -5993,9 +6009,7 @@ QRhiSwapChain *QRhi::newSwapChain()
A frame consists of resource updates and one or more render and compute
passes.
\a flags can indicate certain special cases. For example, the fact that
QRhiCommandBuffer::beginExternal() will be called within this new frame
must be declared up front by setting the ExternalContentsInPass flag.
\a flags can indicate certain special cases.
The high level pattern of rendering into a QWindow using a swapchain:

View File

@ -1331,6 +1331,12 @@ public:
IndexUInt32
};
enum BeginPassFlag {
ExternalContent = 0x01,
DoNotTrackResourcesForCompute = 0x02
};
Q_DECLARE_FLAGS(BeginPassFlags, BeginPassFlag)
QRhiResource::Type resourceType() const override;
void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
@ -1338,7 +1344,8 @@ public:
void beginPass(QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates = nullptr);
QRhiResourceUpdateBatch *resourceUpdates = nullptr,
BeginPassFlags flags = {});
void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
@ -1371,7 +1378,7 @@ public:
void debugMarkEnd();
void debugMarkMsg(const QByteArray &msg);
void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr, BeginPassFlags flags = {});
void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
void setComputePipeline(QRhiComputePipeline *ps);
void dispatch(int x, int y, int z);
@ -1384,6 +1391,8 @@ protected:
QRhiCommandBuffer(QRhiImplementation *rhi);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiCommandBuffer::BeginPassFlags)
struct Q_GUI_EXPORT QRhiReadbackResult
{
std::function<void()> completed = nullptr;
@ -1484,7 +1493,6 @@ public:
};
enum BeginFrameFlag {
ExternalContentsInPass = 0x01
};
Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
@ -1510,7 +1518,7 @@ public:
static QRhi *create(Implementation impl,
QRhiInitParams *params,
Flags flags = Flags(),
Flags flags = {},
QRhiNativeHandles *importDevice = nullptr);
Implementation backend() const;
@ -1531,13 +1539,13 @@ public:
QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
int sampleCount = 1,
QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags(),
QRhiRenderBuffer::Flags flags = {},
QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat);
QRhiTexture *newTexture(QRhiTexture::Format format,
const QSize &pixelSize,
int sampleCount = 1,
QRhiTexture::Flags flags = QRhiTexture::Flags());
QRhiTexture::Flags flags = {});
QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
QRhiSampler::Filter minFilter,
@ -1547,16 +1555,16 @@ public:
QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags());
QRhiTextureRenderTarget::Flags flags = {});
QRhiSwapChain *newSwapChain();
FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = BeginFrameFlags());
FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = EndFrameFlags());
FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = {});
FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = {});
bool isRecordingFrame() const;
int currentFrameSlot() const;
FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = BeginFrameFlags());
FrameOpResult endOffscreenFrame(EndFrameFlags flags = EndFrameFlags());
FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = {});
FrameOpResult endOffscreenFrame(EndFrameFlags flags = {});
QRhi::FrameOpResult finish();
@ -1576,7 +1584,7 @@ public:
QMatrix4x4 clipSpaceCorrMatrix() const;
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const;
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const;
bool isFeatureSupported(QRhi::Feature feature) const;
int resourceLimit(ResourceLimit limit) const;

View File

@ -109,7 +109,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) = 0;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) = 0;
virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -140,7 +141,9 @@ public:
virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
virtual void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
virtual void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) = 0;
virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;

View File

@ -1711,7 +1711,8 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags)
{
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::NoPass);
@ -1822,7 +1823,9 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
enqueueResourceUpdates(cb, resourceUpdates);
}
void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags)
{
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::NoPass);

View File

@ -606,7 +606,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -638,7 +639,9 @@ public:
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;

View File

@ -1103,44 +1103,46 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
hasDynamicOffsetInSrb = true;
break;
case QRhiShaderResourceBinding::SampledTexture:
for (int elem = 0; elem < b->u.stex.count; ++elem) {
trackedRegisterTexture(&passResTracker,
QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex),
QRhiPassResourceTracker::TexSample,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
if (cbD->passNeedsResourceTracking) {
for (int elem = 0; elem < b->u.stex.count; ++elem) {
trackedRegisterTexture(&passResTracker,
QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex),
QRhiPassResourceTracker::TexSample,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
}
}
break;
case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore:
case QRhiShaderResourceBinding::ImageLoadStore:
{
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex);
QRhiPassResourceTracker::TextureAccess access;
if (b->type == QRhiShaderResourceBinding::ImageLoad)
access = QRhiPassResourceTracker::TexStorageLoad;
else if (b->type == QRhiShaderResourceBinding::ImageStore)
access = QRhiPassResourceTracker::TexStorageStore;
else
access = QRhiPassResourceTracker::TexStorageLoadStore;
trackedRegisterTexture(&passResTracker, texD, access,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
}
if (cbD->passNeedsResourceTracking) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex);
QRhiPassResourceTracker::TextureAccess access;
if (b->type == QRhiShaderResourceBinding::ImageLoad)
access = QRhiPassResourceTracker::TexStorageLoad;
else if (b->type == QRhiShaderResourceBinding::ImageStore)
access = QRhiPassResourceTracker::TexStorageStore;
else
access = QRhiPassResourceTracker::TexStorageLoadStore;
trackedRegisterTexture(&passResTracker, texD, access,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
}
break;
case QRhiShaderResourceBinding::BufferLoad:
case QRhiShaderResourceBinding::BufferStore:
case QRhiShaderResourceBinding::BufferLoadStore:
{
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf);
QRhiPassResourceTracker::BufferAccess access;
if (b->type == QRhiShaderResourceBinding::BufferLoad)
access = QRhiPassResourceTracker::BufStorageLoad;
else if (b->type == QRhiShaderResourceBinding::BufferStore)
access = QRhiPassResourceTracker::BufStorageStore;
else
access = QRhiPassResourceTracker::BufStorageLoadStore;
trackedRegisterBuffer(&passResTracker, bufD, access,
QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage));
}
if (cbD->passNeedsResourceTracking) {
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf);
QRhiPassResourceTracker::BufferAccess access;
if (b->type == QRhiShaderResourceBinding::BufferLoad)
access = QRhiPassResourceTracker::BufStorageLoad;
else if (b->type == QRhiShaderResourceBinding::BufferStore)
access = QRhiPassResourceTracker::BufStorageStore;
else
access = QRhiPassResourceTracker::BufStorageLoadStore;
trackedRegisterBuffer(&passResTracker, bufD, access,
QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage));
}
break;
default:
break;
@ -1206,8 +1208,10 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb,
cmd.args.bindVertexBuffer.binding = startBinding + i;
cbD->commands.append(cmd);
trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput,
QRhiPassResourceTracker::BufVertexInputStage);
if (cbD->passNeedsResourceTracking) {
trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput,
QRhiPassResourceTracker::BufVertexInputStage);
}
}
if (indexBuf) {
@ -1221,8 +1225,10 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb,
cmd.args.bindIndexBuffer.type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
cbD->commands.append(cmd);
trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead,
QRhiPassResourceTracker::BufVertexInputStage);
if (cbD->passNeedsResourceTracking) {
trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead,
QRhiPassResourceTracker::BufVertexInputStage);
}
}
}
@ -1416,10 +1422,8 @@ void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
enqueueBindFramebuffer(cbD->currentTarget, cbD);
}
QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags)
{
Q_UNUSED(flags);
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
if (!ensureContext(swapChainD->surface))
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
@ -1465,9 +1469,8 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
return QRhi::FrameOpSuccess;
}
QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags)
{
Q_UNUSED(flags);
if (!ensureContext())
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
@ -2593,6 +2596,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::BarriersForPass:
{
if (!caps.compute)
break;
GLbitfield barriers = 0;
QRhiPassResourceTracker &tracker(cbD->passResTrackers[cmd.args.barriersForPass.trackerIndex]);
// we only care about after-write, not any other accesses, and
@ -2612,7 +2617,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
if (textureAccessIsWrite(accessBeforePass))
barriers |= GL_ALL_BARRIER_BITS;
}
if (barriers && caps.compute)
if (barriers)
f->glMemoryBarrier(barriers);
}
break;
@ -3127,12 +3132,12 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
const QRhiColorAttachment &colorAtt(*it);
QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture());
QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
if (texD) {
if (texD && cbD->passNeedsResourceTracking) {
trackedRegisterTexture(&passResTracker, texD,
QRhiPassResourceTracker::TexColorOutput,
QRhiPassResourceTracker::TexColorOutputStage);
}
if (resolveTexD) {
if (resolveTexD && cbD->passNeedsResourceTracking) {
trackedRegisterTexture(&passResTracker, resolveTexD,
QRhiPassResourceTracker::TexColorOutput,
QRhiPassResourceTracker::TexColorOutputStage);
@ -3140,7 +3145,7 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
// renderbuffers cannot be written in shaders (no image store) so
// they do not matter here
}
if (rtTex->m_desc.depthTexture()) {
if (rtTex->m_desc.depthTexture() && cbD->passNeedsResourceTracking) {
trackedRegisterTexture(&passResTracker, QRHI_RES(QGles2Texture, rtTex->m_desc.depthTexture()),
QRhiPassResourceTracker::TexDepthOutput,
QRhiPassResourceTracker::TexDepthOutputStage);
@ -3172,7 +3177,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass);
@ -3203,6 +3209,7 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
cbD->commands.append(clearCmd);
cbD->recordingPass = QGles2CommandBuffer::RenderPass;
cbD->passNeedsResourceTracking = !flags.testFlag(QRhiCommandBuffer::DoNotTrackResourcesForCompute);
cbD->currentTarget = rt;
cbD->resetCachedState();
@ -3249,7 +3256,9 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
enqueueResourceUpdates(cb, resourceUpdates);
}
void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags)
{
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass);

View File

@ -519,6 +519,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
int currentPassResTrackerIndex;
PassType recordingPass;
bool passNeedsResourceTracking;
QRhiRenderTarget *currentTarget;
QRhiGraphicsPipeline *currentGraphicsPipeline;
QRhiComputePipeline *currentComputePipeline;
@ -611,6 +612,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
}
void resetState() {
recordingPass = NoPass;
passNeedsResourceTracking = true;
currentTarget = nullptr;
resetCommands();
resetCachedState();
@ -741,7 +743,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -773,7 +776,9 @@ public:
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;

View File

@ -1898,7 +1898,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::NoPass);
@ -2013,7 +2014,9 @@ void QRhiMetal::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
enqueueResourceUpdates(cb, resourceUpdates);
}
void QRhiMetal::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
void QRhiMetal::beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::NoPass);

View File

@ -379,7 +379,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -411,7 +412,9 @@ public:
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;

View File

@ -522,11 +522,13 @@ void QRhiNull::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
Q_UNUSED(rt);
Q_UNUSED(colorClearValue);
Q_UNUSED(depthStencilClearValue);
Q_UNUSED(flags);
if (resourceUpdates)
resourceUpdate(cb, resourceUpdates);
}
@ -537,8 +539,11 @@ void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceU
resourceUpdate(cb, resourceUpdates);
}
void QRhiNull::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
void QRhiNull::beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
Q_UNUSED(flags);
if (resourceUpdates)
resourceUpdate(cb, resourceUpdates);
}

View File

@ -237,7 +237,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -269,7 +270,9 @@ public:
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;

View File

@ -1624,7 +1624,7 @@ void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain)
// NB! surface and similar must remain intact
}
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags)
{
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
const int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0;
@ -1724,7 +1724,6 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
}
swapChainD->cbWrapper.cb = frame.cmdBuf;
swapChainD->cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass);
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
swapChainD->rtWrapper.d.fb = image.fb;
@ -1971,7 +1970,7 @@ void QRhiVulkan::waitCommandCompletion(int frameSlot)
}
}
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags)
{
QRhi::FrameOpResult cbres = startPrimaryCommandBuffer(&ofr.cbWrapper.cb);
if (cbres != QRhi::FrameOpSuccess)
@ -1990,8 +1989,6 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi
if (swapchains.count() > 1)
waitCommandCompletion(currentFrameSlot);
ofr.cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass);
prepareNewFrame(&ofr.cbWrapper);
ofr.active = true;
@ -2209,7 +2206,8 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates)
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
@ -2245,6 +2243,7 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
}
cbD->recordingPass = QVkCommandBuffer::RenderPass;
cbD->passUsesSecondaryCb = flags.testFlag(QRhiCommandBuffer::ExternalContent);
cbD->currentTarget = rt;
// No copy operations or image layout transitions allowed after this point
@ -2282,10 +2281,11 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
cmd.cmd = QVkCommandBuffer::Command::BeginRenderPass;
cmd.args.beginRenderPass.desc = rpBeginInfo;
cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count();
cmd.args.beginRenderPass.useSecondaryCb = cbD->passUsesSecondaryCb;
cbD->pools.clearValue.append(cvs.constData(), cvs.count());
cbD->commands.append(cmd);
if (cbD->useSecondaryCb)
if (cbD->passUsesSecondaryCb)
cbD->secondaryCbs.append(startSecondaryCommandBuffer(rtD));
}
@ -2294,7 +2294,7 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
cbD->secondaryCbs.removeLast();
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
@ -2312,7 +2312,9 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc
enqueueResourceUpdates(cbD, resourceUpdates);
}
void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
@ -2323,10 +2325,11 @@ void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch
enqueueTransitionPassResources(cbD);
cbD->recordingPass = QVkCommandBuffer::ComputePass;
cbD->passUsesSecondaryCb = flags.testFlag(QRhiCommandBuffer::ExternalContent);
cbD->computePassState.reset();
if (cbD->useSecondaryCb)
if (cbD->passUsesSecondaryCb)
cbD->secondaryCbs.append(startSecondaryCommandBuffer());
}
@ -2335,7 +2338,7 @@ void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
cbD->secondaryCbs.removeLast();
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
@ -2356,7 +2359,7 @@ void QRhiVulkan::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
if (cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_COMPUTE, psD->pipeline);
} else {
QVkCommandBuffer::Command cmd;
@ -2485,7 +2488,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
}
}
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
if (!imageBarriers.isEmpty()) {
df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
@ -3697,7 +3700,8 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
case QVkCommandBuffer::Command::BeginRenderPass:
cmd.args.beginRenderPass.desc.pClearValues = cbD->pools.clearValue.constData() + cmd.args.beginRenderPass.clearValueIndex;
df->vkCmdBeginRenderPass(cbD->cb, &cmd.args.beginRenderPass.desc,
cbD->useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE);
cmd.args.beginRenderPass.useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
: VK_SUBPASS_CONTENTS_INLINE);
break;
case QVkCommandBuffer::Command::EndRenderPass:
df->vkCmdEndRenderPass(cbD->cb);
@ -4227,7 +4231,7 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_GRAPHICS, psD->pipeline);
} else {
QVkCommandBuffer::Command cmd;
@ -4435,7 +4439,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
}
}
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindDescriptorSets(cbD->secondaryCbs.last(),
gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
gfxPsD ? gfxPsD->layout : compPsD->layout,
@ -4509,7 +4513,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
QRhiPassResourceTracker::BufVertexInputStage);
}
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindVertexBuffers(cbD->secondaryCbs.last(), uint32_t(startBinding),
uint32_t(bufs.count()), bufs.constData(), ofs.constData());
} else {
@ -4545,7 +4549,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
cbD->currentIndexOffset = indexOffset;
cbD->currentIndexFormat = type;
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindIndexBuffer(cbD->secondaryCbs.last(), vkindexbuf, indexOffset, type);
} else {
QVkCommandBuffer::Command cmd;
@ -4583,7 +4587,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
vp->minDepth = viewport.minDepth();
vp->maxDepth = viewport.maxDepth();
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdSetViewport(cbD->secondaryCbs.last(), 0, 1, vp);
} else {
cmd.cmd = QVkCommandBuffer::Command::SetViewport;
@ -4596,7 +4600,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
s->offset.y = int32_t(y);
s->extent.width = uint32_t(w);
s->extent.height = uint32_t(h);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
} else {
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
@ -4624,7 +4628,7 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
s->extent.width = uint32_t(w);
s->extent.height = uint32_t(h);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
} else {
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
@ -4637,7 +4641,7 @@ void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
float constants[] = { float(c.redF()), float(c.greenF()), float(c.blueF()), float(c.alphaF()) };
df->vkCmdSetBlendConstants(cbD->secondaryCbs.last(), constants);
} else {
@ -4656,7 +4660,7 @@ void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdSetStencilReference(cbD->secondaryCbs.last(), VK_STENCIL_FRONT_AND_BACK, refValue);
} else {
QVkCommandBuffer::Command cmd;
@ -4672,7 +4676,7 @@ void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdDraw(cbD->secondaryCbs.last(), vertexCount, instanceCount, firstVertex, firstInstance);
} else {
QVkCommandBuffer::Command cmd;
@ -4691,7 +4695,7 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
if (cbD->useSecondaryCb) {
if (cbD->passUsesSecondaryCb) {
df->vkCmdDrawIndexed(cbD->secondaryCbs.last(), indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
} else {
@ -4716,7 +4720,7 @@ void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
marker.pMarkerName = name.constData();
vkCmdDebugMarkerBegin(cbD->secondaryCbs.last(), &marker);
} else {
@ -4735,7 +4739,7 @@ void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
return;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
vkCmdDebugMarkerEnd(cbD->secondaryCbs.last());
} else {
QVkCommandBuffer::Command cmd;
@ -4754,7 +4758,7 @@ void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
marker.pMarkerName = msg.constData();
vkCmdDebugMarkerInsert(cbD->secondaryCbs.last(), &marker);
} else {
@ -4812,9 +4816,9 @@ void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb)
if (cbD->inExternal)
return;
if (!cbD->useSecondaryCb) {
if (!cbD->passUsesSecondaryCb) {
qWarning("beginExternal() within a pass is only supported with secondary command buffers. "
"This can be enabled by passing QRhi::ExternalContentsInPass to beginFrame().");
"This can be enabled by passing QRhiCommandBuffer::ExternalContent to beginPass().");
return;
}
@ -6615,10 +6619,14 @@ const QRhiNativeHandles *QVkCommandBuffer::nativeHandles()
// secondary command buffer (typically the one started by beginExternal(),
// in case we are between beginExternal - endExternal inside a pass).
if (useSecondaryCb && !secondaryCbs.isEmpty())
nativeHandlesStruct.commandBuffer = secondaryCbs.last();
else
if (recordingPass == QVkCommandBuffer::NoPass) {
nativeHandlesStruct.commandBuffer = cb;
} else {
if (passUsesSecondaryCb && !secondaryCbs.isEmpty())
nativeHandlesStruct.commandBuffer = secondaryCbs.last();
else
nativeHandlesStruct.commandBuffer = cb;
}
return &nativeHandlesStruct;
}

View File

@ -329,7 +329,6 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
const QRhiNativeHandles *nativeHandles();
VkCommandBuffer cb = VK_NULL_HANDLE; // primary
bool useSecondaryCb = false;
QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
enum PassType {
@ -340,6 +339,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
void resetState() {
recordingPass = NoPass;
passUsesSecondaryCb = false;
currentTarget = nullptr;
secondaryCbs.clear();
@ -365,6 +365,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
}
PassType recordingPass;
bool passUsesSecondaryCb;
QRhiRenderTarget *currentTarget;
QRhiGraphicsPipeline *currentGraphicsPipeline;
QRhiComputePipeline *currentComputePipeline;
@ -468,6 +469,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
struct {
VkRenderPassBeginInfo desc;
int clearValueIndex;
bool useSecondaryCb;
} beginRenderPass;
struct {
} endRenderPass;
@ -694,7 +696,8 @@ public:
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
@ -726,7 +729,9 @@ public:
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginComputePass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;

View File

@ -2751,8 +2751,8 @@ void tst_QRhi::finishWithinSwapchainFrame()
QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)));
QVERIFY(vbuf->create());
// exercise begin/endExternal() just a little bit, hence ExternalContentsInPass
QVERIFY(rhi->beginFrame(swapChain.data(), QRhi::ExternalContentsInPass) == QRhi::FrameOpSuccess);
// exercise begin/endExternal() just a little bit, note ExternalContent for beginPass()
QVERIFY(rhi->beginFrame(swapChain.data()) == QRhi::FrameOpSuccess);
QRhiCommandBuffer *cb = swapChain->currentFrameCommandBuffer();
QRhiRenderTarget *rt = swapChain->currentFrameRenderTarget();
const QSize outputSize = swapChain->currentPixelSize();
@ -2763,7 +2763,7 @@ void tst_QRhi::finishWithinSwapchainFrame()
QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch();
updates->uploadStaticBuffer(vbuf.data(), vertices);
cb->beginPass(rt, Qt::blue, { 1.0f, 0 }, updates);
cb->beginPass(rt, Qt::blue, { 1.0f, 0 }, updates, QRhiCommandBuffer::ExternalContent);
// just have some commands, do not bother with draw calls
cb->setGraphicsPipeline(pipeline.data());