QRhiTexture Class

Texture resource. More...

Header: #include <QRhiTexture>
CMake: find_package(Qt6 REQUIRED COMPONENTS Gui)
target_link_libraries(mytarget PRIVATE Qt6::Gui)
qmake: QT += gui
Since: Qt 6.6
Inherits: QRhiResource

Public Types

struct NativeTexture
enum Flag { RenderTarget, CubeMap, MipMapped, sRGB, UsedAsTransferSource, …, OneDimensional }
flags Flags
enum Format { UnknownFormat, RGBA8, BGRA8, R8, RG8, …, ASTC_12x12 }

Public Functions

int arrayRangeLength() const
int arrayRangeStart() const
int arraySize() const
virtual bool create() = 0
virtual bool createFrom(QRhiTexture::NativeTexture src)
int depth() const
QRhiTexture::Flags flags() const
QRhiTexture::Format format() const
virtual QRhiTexture::NativeTexture nativeTexture()
QSize pixelSize() const
int sampleCount() const
void setArrayRange(int startIndex, int count)
void setArraySize(int arraySize)
void setDepth(int depth)
void setFlags(QRhiTexture::Flags f)
void setFormat(QRhiTexture::Format fmt)
virtual void setNativeLayout(int layout)
void setPixelSize(const QSize &sz)
void setSampleCount(int s)

Reimplemented Public Functions

virtual QRhiResource::Type resourceType() const override

Detailed Description

A QRhiTexture encapsulates a native texture object, such as a VkImage or MTLTexture.

A QRhiTexture instance is always created by calling the QRhi's newTexture() function. This creates no native graphics resources. To do that, call create() after setting the appropriate options, such as the format and size, although in most cases these are already set based on the arguments passed to newTexture().

Setting the flags correctly is essential, otherwise various errors can occur depending on the underlying QRhi backend and graphics API. For example, when a texture will be rendered into from a render pass via QRhiTextureRenderTarget, the texture must be created with the RenderTarget flag set. Similarly, when the texture is going to be read back, the UsedAsTransferSource flag must be set upfront. Mipmapped textures must have the MipMapped flag set. And so on. It is not possible to change the flags once create() has succeeded. To release the existing and create a new native texture object with the changed settings, call the setters and call create() again. This then might be a potentially expensive operation.

Example usage

To create a 2D texture with a size of 512x512 pixels and set its contents to all green:

 QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
 if (!texture->create()) { error(); }
 QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
 QImage image(512, 512, QImage::Format_RGBA8888);
 image.fill(Qt::green);
 batch->uploadTexture(texture, image);
 // ...
 commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call

Common patterns

A call to create() destroys any existing native resources if create() was successfully called before. If those native resources are still in use by an in-flight frame (i.e., there's a chance they are still read by the GPU), the destroying of those resources is deferred automatically. Thus a very common and convenient pattern to safely change the size of an already existing texture is the following. In practice this drops and creates a whole new native texture resource underneath, so it is not necessarily a cheap operation, but is more convenient and still faster than the alternatives, because by not destroying the texture object itself, all references to it stay valid in other data structures (e.g., in any QShaderResourceBinding the QRhiTexture is referenced from).

 // determine newSize, e.g. based on the swapchain's output size or other factors
 if (texture->pixelSize() != newSize) {
     texture->setPixelSize(newSize);
     if (!texture->create()) { error(); }
 }
 // continue using texture, fill it with new data

Note: This is a RHI API with limited compatibility guarantees, see QRhi for details.

See also QRhiResourceUpdateBatch, QRhi, and QRhiTextureRenderTarget.

Member Type Documentation

enum QRhiTexture::Flag
flags QRhiTexture::Flags

Flag values to specify how the texture is going to be used. Not honoring the flags set before create() and attempting to use the texture in ways that was not declared upfront can lead to unspecified behavior or decreased performance depending on the backend and the underlying graphics API.

ConstantValueDescription
QRhiTexture::RenderTarget1 << 0The texture going to be used in combination with QRhiTextureRenderTarget.
QRhiTexture::CubeMap1 << 2The texture is a cubemap. Such textures have 6 layers, one for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures cannot be multisample.
QRhiTexture::MipMapped1 << 3The texture has mipmaps. The appropriate mip count is calculated automatically and can also be retrieved via QRhi::mipLevelsForSize(). The images for the mip levels have to be provided in the texture uploaded or generated via QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have mipmaps.
QRhiTexture::sRGB1 << 4Use an sRGB format.
QRhiTexture::UsedAsTransferSource1 << 5The texture is used as the source of a texture copy or readback, meaning the texture is given as the source in QRhiResourceUpdateBatch::copyTexture() or QRhiResourceUpdateBatch::readBackTexture().
QRhiTexture::UsedWithGenerateMips1 << 6The texture is going to be used with QRhiResourceUpdateBatch::generateMips().
QRhiTexture::UsedWithLoadStore1 << 7The texture is going to be used with image load/store operations, for example, in a compute shader.
QRhiTexture::UsedAsCompressedAtlas1 << 8The texture has a compressed format and the dimensions of subresource uploads may not match the texture size.
QRhiTexture::ExternalOES1 << 9The texture should use the GL_TEXTURE_EXTERNAL_OES target with OpenGL. This flag is ignored with other graphics APIs.
QRhiTexture::ThreeDimensional1 << 10The texture is a 3D texture. Such textures should be created with the QRhi::newTexture() overload taking a depth in addition to width and height. A 3D texture can have mipmaps but cannot be multisample. When rendering into, or uploading data to a 3D texture, the layer specified in the render target's color attachment or the upload description refers to a single slice in range [0..depth-1]. The underlying graphics API may not support 3D textures at run time. Support is indicated by the QRhi::ThreeDimensionalTextures feature.
QRhiTexture::TextureRectangleGL1 << 11The texture should use the GL_TEXTURE_RECTANGLE target with OpenGL. This flag is ignored with other graphics APIs. Just like ExternalOES, this flag is useful when working with platform APIs where native OpenGL texture objects received from the platform are wrapped in a QRhiTexture, and the platform can only provide textures for a non-2D texture target.
QRhiTexture::TextureArray1 << 12The texture is a texture array, i.e. a single texture object that is a homogeneous array of 2D textures. Texture arrays are created with QRhi::newTextureArray(). The underlying graphics API may not support texture array objects at run time. Support is indicated by the QRhi::TextureArrays feature. When rendering into, or uploading data to a texture array, the layer specified in the render target's color attachment or the upload description selects a single element in the array.
QRhiTexture::OneDimensional1 << 13The texture is a 1D texture. Such textures can be created by passing a 0 height and depth to QRhi::newTexture(). Note that there can be limitations on one dimensional textures depending on the underlying graphics API. For example, rendering to them or using them with mipmap-based filtering may be unsupported. This is indicated by the QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps feature flags.

The Flags type is a typedef for QFlags<Flag>. It stores an OR combination of Flag values.

enum QRhiTexture::Format

Specifies the texture format. See also QRhi::isTextureFormatSupported() and note that flags() can modify the format when QRhiTexture::sRGB is set.

ConstantValueDescription
QRhiTexture::UnknownFormat0Not a valid format. This cannot be passed to setFormat().
QRhiTexture::RGBA81Four component, unsigned normalized 8 bit per component. Always supported.
QRhiTexture::BGRA82Four component, unsigned normalized 8 bit per component.
QRhiTexture::R83One component, unsigned normalized 8 bit.
QRhiTexture::RG84Two components, unsigned normalized 8 bit.
QRhiTexture::R165One component, unsigned normalized 16 bit.
QRhiTexture::RG166Two component, unsigned normalized 16 bit.
QRhiTexture::RED_OR_ALPHA87Either same as R8, or is a similar format with the component swizzled to alpha, depending on RedOrAlpha8IsRed.
QRhiTexture::RGBA16F8Four components, 16-bit float per component.
QRhiTexture::RGBA32F9Four components, 32-bit float per component.
QRhiTexture::R16F10One component, 16-bit float.
QRhiTexture::R32F11One component, 32-bit float.
QRhiTexture::RGB10A212Four components, unsigned normalized 10 bit R, G, and B, 2-bit alpha. This is a packed format so native endianness applies. Note that there is no BGR10A2. This is because RGB10A2 maps to DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is the only universally supported RGB30 option. The corresponding QImage formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
QRhiTexture::D161316-bit depth (normalized unsigned integer)
QRhiTexture::D241424-bit depth (normalized unsigned integer)
QRhiTexture::D24S81524-bit depth (normalized unsigned integer), 8 bit stencil
QRhiTexture::D32F1632-bit depth (32-bit float)
QRhiTexture::BC117 
QRhiTexture::BC218 
QRhiTexture::BC319 
QRhiTexture::BC420 
QRhiTexture::BC521 
QRhiTexture::BC6H22 
QRhiTexture::BC723 
QRhiTexture::ETC2_RGB824 
QRhiTexture::ETC2_RGB8A125 
QRhiTexture::ETC2_RGBA826 
QRhiTexture::ASTC_4x427 
QRhiTexture::ASTC_5x428 
QRhiTexture::ASTC_5x529 
QRhiTexture::ASTC_6x530 
QRhiTexture::ASTC_6x631 
QRhiTexture::ASTC_8x532 
QRhiTexture::ASTC_8x633 
QRhiTexture::ASTC_8x834 
QRhiTexture::ASTC_10x535 
QRhiTexture::ASTC_10x636 
QRhiTexture::ASTC_10x837 
QRhiTexture::ASTC_10x1038 
QRhiTexture::ASTC_12x1039 
QRhiTexture::ASTC_12x1240 

Member Function Documentation

int QRhiTexture::arrayRangeLength() const

Returns the exposed array range size when setArrayRange() was called.

See also setArrayRange().

int QRhiTexture::arrayRangeStart() const

Returns the first array layer when setArrayRange() was called.

See also setArrayRange().

int QRhiTexture::arraySize() const

Returns the texture array size.

See also setArraySize().

[pure virtual] bool QRhiTexture::create()

Creates the corresponding native graphics resources. If there are already resources present due to an earlier create() with no corresponding destroy(), then destroy() is called implicitly first.

Returns true when successful, false when a graphics operation failed. Regardless of the return value, calling destroy() is always safe.

[virtual] bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)

Similar to create(), except that no new native textures are created. Instead, the native texture resources specified by src is used.

This allows importing an existing native texture object (which must belong to the same device or sharing context, depending on the graphics API) from an external graphics engine.

Returns true if the specified existing native texture object has been successfully wrapped as a non-owning QRhiTexture.

Note: format(), pixelSize(), sampleCount(), and flags() must still be set correctly. Passing incorrect sizes and other values to QRhi::newTexture() and then following it with a createFrom() expecting that the native texture object alone is sufficient to deduce such values is wrong and will lead to problems.

Note: QRhiTexture does not take ownership of the texture object. destroy() does not free the object or any associated memory.

The opposite of this operation, exposing a QRhiTexture-created native texture object to a foreign engine, is possible via nativeTexture().

Note: When importing a 3D texture, or a texture array object, or, with OpenGL ES, an external texture, it is then especially important to set the corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via setFlags() before calling this function.

int QRhiTexture::depth() const

Returns the depth for 3D textures.

See also setDepth().

QRhiTexture::Flags QRhiTexture::flags() const

Returns the texture flags.

See also setFlags().

QRhiTexture::Format QRhiTexture::format() const

Returns the texture format.

See also setFormat().

[virtual] QRhiTexture::NativeTexture QRhiTexture::nativeTexture()

Returns the underlying native resources for this texture. The returned value will be empty if exposing the underlying native resources is not supported by the backend.

See also createFrom().

QSize QRhiTexture::pixelSize() const

Returns the size in pixels.

See also setPixelSize().

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

Reimplements: QRhiResource::resourceType() const.

Returns the resource type.

int QRhiTexture::sampleCount() const

Returns the sample count. 1 means no multisample antialiasing.

See also setSampleCount().

void QRhiTexture::setArrayRange(int startIndex, int count)

Normally all array layers are exposed and it is up to the shader to select the layer via the third coordinate passed to the texture() GLSL function when sampling the sampler2DArray. When QRhi::TextureArrayRange is reported as supported, calling setArrayRange() before create() or createFrom() requests selecting only the specified range, count elements starting from startIndex. The shader logic can then be written with this in mind.

See also QRhi::TextureArrayRange.

void QRhiTexture::setArraySize(int arraySize)

Sets the texture arraySize.

See also arraySize().

void QRhiTexture::setDepth(int depth)

Sets the depth for a 3D texture.

See also depth().

void QRhiTexture::setFlags(QRhiTexture::Flags f)

Sets the texture flags to f.

See also flags().

void QRhiTexture::setFormat(QRhiTexture::Format fmt)

Sets the requested texture format to fmt.

Note: The value set is only taken into account upon the next call to create(), i.e. when the underlying graphics resource are (re)created. Setting a new value is futile otherwise and must be avoided since it can lead to inconsistent state.

See also format().

[virtual] void QRhiTexture::setNativeLayout(int layout)

With some graphics APIs, such as Vulkan, integrating custom rendering code that uses the graphics API directly needs special care when it comes to image layouts. This function allows communicating the expected layout the image backing the QRhiTexture is in after the native rendering commands.

For example, consider rendering into a QRhiTexture's VkImage directly with Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and QRhiCommandBuffer::endExternal(), followed by using the image for texture sampling in a QRhi-based render pass. To avoid potentially incorrect image layout transitions, this function can be used to indicate what the image layout will be once the commands recorded in said code block complete.

Calling this function makes sense only after QRhiCommandBuffer::endExternal() and before a subsequent QRhiCommandBuffer::beginPass().

This function has no effect with QRhi backends where the underlying graphics API does not expose a concept of image layouts.

Note: With Vulkan layout is a VkImageLayout. With Direct 3D 12 layout is a value composed of the bits from D3D12_RESOURCE_STATES.

void QRhiTexture::setPixelSize(const QSize &sz)

Sets the texture size, specified in pixels, to sz.

Note: The value set is only taken into account upon the next call to create(), i.e. when the underlying graphics resource are (re)created. Setting a new value is futile otherwise and must be avoided since it can lead to inconsistent state. The same applies to all other setters as well.

See also pixelSize().

void QRhiTexture::setSampleCount(int s)

Sets the sample count to s.

See also sampleCount().