QRhiCommandBuffer Class

Command buffer resource. More...

Header: #include <QRhiCommandBuffer>
qmake: QT += rhi
Inherits: QRhiResource

Public Types

typedef DynamicOffset
enum IndexFormat { IndexUInt16, IndexUInt32 }
typedef VertexInput

Public Functions

void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)
void beginExternal()
void beginPass(QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates = nullptr)
void debugMarkBegin(const QByteArray &name)
void debugMarkEnd()
void debugMarkMsg(const QByteArray &msg)
void dispatch(int x, int y, int z)
void draw(quint32 vertexCount, quint32 instanceCount = 1, quint32 firstVertex = 0, quint32 firstInstance = 0)
void drawIndexed(quint32 indexCount, quint32 instanceCount = 1, quint32 firstIndex = 0, qint32 vertexOffset = 0, quint32 firstInstance = 0)
void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)
void endExternal()
void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)
const QRhiNativeHandles *nativeHandles()
void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
void setBlendConstants(const QColor &c)
void setComputePipeline(QRhiComputePipeline *ps)
void setGraphicsPipeline(QRhiGraphicsPipeline *ps)
void setScissor(const QRhiScissor &scissor)
void setShaderResources(QRhiShaderResourceBindings *srb = nullptr, int dynamicOffsetCount = 0, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets = nullptr)
void setStencilRef(quint32 refValue)
void setVertexInput(int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0, QRhiCommandBuffer::IndexFormat indexFormat = IndexUInt16)
void setViewport(const QRhiViewport &viewport)

Reimplemented Public Functions

virtual QRhiResource::Type resourceType() const override

Additional Inherited Members

Detailed Description

Command buffer resource.

Not creatable by applications at the moment. The only ways to obtain a valid QRhiCommandBuffer are to get it from the targeted swapchain via QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering completely offscreen, initializing one via QRhi::beginOffscreenFrame().

Member Type Documentation

typedef QRhiCommandBuffer::DynamicOffset

Synonym for QPair<int, quint32>. The first entry is the binding, the second is the offset in the buffer.

enum QRhiCommandBuffer::IndexFormat

Specifies the index data type

ConstantValueDescription
QRhiCommandBuffer::IndexUInt160Unsigned 16-bit (quint16)
QRhiCommandBuffer::IndexUInt321Unsigned 32-bit (quint32)

typedef QRhiCommandBuffer::VertexInput

Synonym for QPair<QRhiBuffer *, quint32>. The second entry is an offset in the buffer specified by the first.

Property Documentation

Member Function Documentation

void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)

Records starting a new compute pass.

resourceUpdates, when not null, specifies a resource update batch that is to be committed and then released.

Note: Do not assume that any state or resource bindings persist between passes.

Note: A compute pass can record setComputePipeline(), setShaderResources(), and dispatch() calls, not graphics ones. General functionality, such as, debug markers and beginExternal() is available both in render and compute passes.

Note: Compute is only available when the Compute feature is reported as supported.

void QRhiCommandBuffer::beginExternal()

To be called when the application before the application is about to enqueue commands to the current pass' command buffer by calling graphics API functions directly.

With Vulkan or Metal one can query the native command buffer or encoder objects via nativeHandles() and enqueue commands to them. With OpenGL or Direct3D 11 the (device) context can be retrieved from QRhi::nativeHandles(). However, this must never be done without ensuring the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for wrapping any externally added command recording between beginExternal() and endExternal(). Conceptually this is the same as QPainter's beginNativePainting() and endNativePainting() functions.

For OpenGL in particular, this function has an additional task: it makes sure the context is made current on the current thread.

Note: Once beginExternal() is called, no other render pass specific functions (set* or draw*) must be called on the QRhiCommandBuffer until endExternal().

See also endExternal() and nativeHandles().

void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates = nullptr)

Records starting a new render pass targeting the render target rt.

resourceUpdates, when not null, specifies a resource update batch that is to be committed and then released.

The color and depth/stencil buffers of the render target are normally cleared. The clear values are specified in colorClearValue and depthStencilClearValue. The exception is when the render target was created with QRhiTextureRenderTarget::PreserveColorContents and/or QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are ignored then.

Note: Enabling preserved color or depth contents leads to decreased performance depending on the underlying hardware. Mobile GPUs with tiled architecture benefit from not having to reload the previous contents into the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as the depth buffer is less efficient than a QRhiRenderBuffer since using a depth texture triggers requiring writing the data out to it, while with renderbuffers this is not needed (as the API does not allow sampling or reading from a renderbuffer).

Note: Do not assume that any state or resource bindings persist between passes.

Note: The QRhiCommandBuffer's 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. Unspecified issues may arise otherwise, depending on the backend.

void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)

Records a named debug group on the command buffer. This is shown in graphics debugging tools such as RenderDoc and XCode. The end of the grouping is indicated by debugMarkEnd().

Note: Ignored when QRhi::DebugMarkers are not supported or QRhi::EnableDebugMarkers is not set.

Note: Can be called anywhere within the frame, both inside and outside of passes.

void QRhiCommandBuffer::debugMarkEnd()

Records the end of a debug group.

Note: Ignored when QRhi::DebugMarkers are not supported or QRhi::EnableDebugMarkers is not set.

Note: Can be called anywhere within the frame, both inside and outside of passes.

void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)

Inserts a debug message msg into the command stream.

Note: Ignored when QRhi::DebugMarkers are not supported or QRhi::EnableDebugMarkers is not set.

Note: With some backends debugMarkMsg() is only supported inside a pass and is ignored when called outside a pass. With others it is recorded anywhere within the frame.

void QRhiCommandBuffer::dispatch(int x, int y, int z)

Records dispatching compute work items, with x, y, and z specifying the number of local workgroups in the corresponding dimension.

Note: This function can only be called inside a compute pass, meaning between a beginComputePass() and endComputePass() call.

void QRhiCommandBuffer::draw(quint32 vertexCount, quint32 instanceCount = 1, quint32 firstVertex = 0, quint32 firstInstance = 0)

Records a non-indexed draw.

The number of vertices is specified in vertexCount. For instanced drawing set instanceCount to a value other than 1. firstVertex is the index of the first vertex to draw. firstInstance is the instance ID of the first instance to draw.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::drawIndexed(quint32 indexCount, quint32 instanceCount = 1, quint32 firstIndex = 0, qint32 vertexOffset = 0, quint32 firstInstance = 0)

Records an indexed draw.

The number of vertices is specified in indexCount. firstIndex is the base index. The effective offset in the index buffer is given by indexOffset + firstIndex * n where n is 2 or 4 depending on the index element type. indexOffset is specified in setVertexInput().

Note: The effective offset in the index buffer must be 4 byte aligned with some backends (for example, Metal). With these backends the NonFourAlignedEffectiveIndexBufferOffset feature will be reported as not-supported.

For instanced drawing set instanceCount to a value other than 1. firstInstance is the instance ID of the first instance to draw.

vertexOffset is added to the vertex index.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)

Records ending the current compute pass.

resourceUpdates, when not null, specifies a resource update batch that is to be committed and then released.

void QRhiCommandBuffer::endExternal()

To be called once the externally added commands are recorded to the command buffer or context.

Note: All QRhiCommandBuffer state must be assumed as invalid after calling this function. Pipelines, vertex and index buffers, and other state must be set again if more draw calls are recorded after the external commands.

See also beginExternal() and nativeHandles().

void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr)

Records ending the current render pass.

resourceUpdates, when not null, specifies a resource update batch that is to be committed and then released.

const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()

Returns a pointer to a backend-specific QRhiNativeHandles subclass, such as QRhiVulkanCommandBufferNativeHandles. The returned value is null when exposing the underlying native resources is not supported by, or not applicable to, the backend.

See also QRhiVulkanCommandBufferNativeHandles, QRhiMetalCommandBufferNativeHandles, beginExternal(), and endExternal().

[override virtual] QRhiResource::Type QRhiCommandBuffer::resourceType() const

Reimplemented from QRhiResource::resourceType().

Returns the resource type.

void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)

Sometimes committing resource 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.

Note: Cannot be called inside a pass.

void QRhiCommandBuffer::setBlendConstants(const QColor &c)

Records setting the active blend constants to c.

This can only be called when the bound pipeline has QRhiGraphicsPipeline::UsesBlendConstants set.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::setComputePipeline(QRhiComputePipeline *ps)

Records setting a new compute pipeline ps.

Note: This function must be called before recording setShaderResources() or dispatch() commands on the command buffer.

Note: QRhi will optimize out unnecessary invocations within a pass, so therefore overoptimizing to avoid calls to this function is not necessary on the applications' side.

Note: This function can only be called inside a compute pass, meaning between a beginComputePass() and endComputePass() call.

void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)

Records setting a new graphics pipeline ps.

Note: This function must be called before recording other set or draw commands on the command buffer.

Note: QRhi will optimize out unnecessary invocations within a pass, so therefore overoptimizing to avoid calls to this function is not necessary on the applications' side.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)

Records setting the active scissor rectangle specified in scissor.

This can only be called when the bound pipeline has UsesScissor set. When the flag is set on the active pipeline, this function must be called because scissor testing will get enabled and so a scissor rectangle must be provided.

Note: QRhi assumes OpenGL-style viewport coordinates, meaning x and y are bottom-left.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb = nullptr, int dynamicOffsetCount = 0, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets = nullptr)

Records binding a set of shader resources, such as, uniform buffers or textures, that are made visible to one or more shader stages.

srb can be null in which case the current graphics or compute pipeline's associated QRhiShaderResourceBindings is used. When srb is non-null, it must be layout-compatible, meaning the layout (number of bindings, the type and binding number of each binding) must fully match the QRhiShaderResourceBindings that was associated with the pipeline at the time of calling the pipeline's build().

There are cases when a seemingly unnecessary setShaderResources() call is mandatory: when rebuilding a resource referenced from srb, for example changing the size of a QRhiBuffer followed by a QRhiBuffer::build(), this is the place where associated native objects (such as descriptor sets in case of Vulkan) are updated to refer to the current native resources that back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from srb. In this case setShaderResources() must be called even if srb is the same as in the last call.

dynamicOffsets allows specifying buffer offsets for uniform buffers that were associated with srb via QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is different from providing the offset in the srb itself: dynamic offsets do not require building a new QRhiShaderResourceBindings for every different offset, can avoid writing the underlying descriptors (with backends where applicable), and so they may be more efficient. Each element of dynamicOffsets is a binding - offset pair. dynamicOffsetCount specifies the number of elements in dynamicOffsets.

Note: All offsets in dynamicOffsets must be byte aligned to the value returned from QRhi::ubufAlignment().

Note: QRhi will optimize out unnecessary invocations within a pass (taking the conditions described above into account), so therefore overoptimizing to avoid calls to this function is not necessary on the applications' side.

Note: This function can only be called inside a render or compute pass, meaning between a beginPass() and endPass(), or beginComputePass() and endComputePass().

void QRhiCommandBuffer::setStencilRef(quint32 refValue)

Records setting the active stencil reference value to refValue.

This can only be called when the bound pipeline has QRhiGraphicsPipeline::UsesStencilRef set.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0, QRhiCommandBuffer::IndexFormat indexFormat = IndexUInt16)

Records vertex input bindings.

The index buffer used by subsequent drawIndexed() commands is specified by indexBuf, indexOffset, and indexFormat. indexBuf can be set to null when indexed drawing is not needed.

Vertex buffer bindings are batched. startBinding specifies the first binding number. The recorded command then binds each buffer from bindings to the binding point startBinding + i where i is the index in bindings. Each element in bindings specifies a QRhiBuffer and an offset.

Superfluous vertex input and index changes in the same pass are ignored automatically with most backends and therefore applications do not need to overoptimize to avoid calls to this function.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

As a simple example, take a vertex shader with two inputs:


  layout(location = 0) in vec4 position;
  layout(location = 1) in vec3 color;

and assume we have the data available in interleaved format, using only 2 floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for this shader can then be created using the input layout:


  QRhiVertexInputLayout inputLayout;
  inputLayout.setBindings({
      { 5 * sizeof(float) }
  });
  inputLayout.setAttributes({
      { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
      { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
  });

Here there is one buffer binding (binding number 0), with two inputs referencing it. When recording the pass, once the pipeline is set, the vertex bindings can be specified simply like the following (using C++11 initializer syntax), assuming vbuf is the QRhiBuffer with all the interleaved position+color data:


  const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
  cb->setVertexInput(0, 1, &vbufBinding);

void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)

Records setting the active viewport rectangle specified in viewport.

With backends where the underlying graphics API has scissoring always enabled, this function also sets the scissor to match the viewport whenever the active QRhiGraphicsPipeline does not have UsesScissor set.

Note: QRhi assumes OpenGL-style viewport coordinates, meaning x and y are bottom-left.

Note: This function can only be called inside a render pass, meaning between a beginPass() and endPass() call.

Member Variable Documentation

Related Non-Members

Macro Documentation