QRhiBuffer Class

버텍스, 인덱스 또는 균일(상수) 버퍼 리소스. 더 보기...

헤더: #include <rhi/qrhi.h>
CMake: find_package(Qt6 REQUIRED COMPONENTS Gui)
target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
qmake: QT += gui-private
이후: Qt 6.6
상속합니다: QRhiResource

공용 형

struct NativeBuffer
enum Type { Immutable, Static, Dynamic }
enum UsageFlag { VertexBuffer, IndexBuffer, UniformBuffer, StorageBuffer }
flags UsageFlags

공용 함수

virtual char *beginFullDynamicBufferUpdateForCurrentFrame()
virtual bool create() = 0
virtual void endFullDynamicBufferUpdateForCurrentFrame()
virtual QRhiBuffer::NativeBuffer nativeBuffer()
void setSize(quint32 sz)
void setType(QRhiBuffer::Type t)
void setUsage(QRhiBuffer::UsageFlags u)
quint32 size() const
QRhiBuffer::Type type() const
QRhiBuffer::UsageFlags usage() const

재구현된 공용 함수

virtual QRhiResource::Type resourceType() const override

상세 설명

참고: 호환성이 제한적으로 보장되는 RHI API이며, 자세한 내용은 QRhi 을 참조하세요.

QRhiBuffer는 0개, 하나 또는 그 이상의 네이티브 버퍼 객체(예: VkBuffer 또는 MTLBuffer)를 캡슐화합니다. 일부 그래픽 API 및 백엔드에서는 특정 유형의 버퍼가 네이티브 버퍼 객체를 전혀 사용하지 않을 수 있지만(예: 균일 버퍼 객체를 사용하지 않는 경우 OpenGL), 이는 QRhiBuffer API 사용자에게 투명하게 표시됩니다. 마찬가지로, 일부 버퍼 유형은 GPU 파이프라인을 지연시키지 않고 프레임당 콘텐츠를 효율적으로 업데이트하기 위해 그 아래에 두세 개의 네이티브 버퍼를 사용할 수 있다는 사실도 애플리케이션과 라이브러리에는 대부분 보이지 않습니다.

QRhiBuffer 인스턴스는 항상 the QRhi's newBuffer() function 을 호출하여 생성됩니다. 이렇게 하면 네이티브 그래픽 리소스가 생성되지 않습니다. 이렇게 하려면 유형, 사용 플래그, 크기 등 적절한 옵션을 설정한 후 create()를 호출하면 되지만 대부분의 경우 newBuffer()에 전달된 인수를 기반으로 이미 설정되어 있습니다.

사용 예

GLSL 유니폼 블록에 단일 mat4 멤버가 포함된 셰이더에 대한 유니폼 버퍼를 생성하고 내용을 업데이트합니다:

QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
if (!ubuf->create()) { error(); }
QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
QMatrix4x4 mvp;
// ... set up the modelview-projection matrix
batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
// ...
commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call

버텍스 데이터로 버퍼를 생성하는 예제입니다:

const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
if (!vbuf->create()) { error(); }
QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
batch->uploadStaticBuffer(vbuf, vertices);
// ...
commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call

인덱스 버퍼:

static const quint16 indices[] = { 0, 1, 2 };
QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
if (!ibuf->create()) { error(); }
QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
batch->uploadStaticBuffer(ibuf, indices);
// ...
commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call

일반적인 패턴

create()를 호출하면 이전에 create()를 성공적으로 호출한 경우 기존 네이티브 리소스가 모두 소멸됩니다. 해당 네이티브 리소스가 인플라이트 프레임에서 여전히 사용 중인 경우(즉, GPU에서 여전히 읽고 있을 가능성이 있는 경우) 해당 리소스의 소멸은 자동으로 연기됩니다. 따라서 이미 초기화된 버퍼의 크기를 안전하게 늘리는 매우 일반적이고 편리한 패턴은 다음과 같습니다. 실제로는 이렇게 하면 그 아래에 완전히 새로운 기본 리소스 집합이 삭제되고 생성되므로 반드시 저렴한 작업은 아니지만, buf 객체 자체를 파괴하지 않기 때문에 다른 데이터 구조(예: QRhiBuffer가 참조되는 QRhiShaderResourceBinding )에서도 모든 참조가 유효하게 유지되므로 다른 대안보다 더 편리하고 여전히 빠릅니다.

if (buf->size() < newSize) {
    buf->setSize(newSize);
    if (!buf->create()) { error(); }
}
// continue using buf, fill it with new data

균일 버퍼로 작업할 때 효율성을 위해 여러 드로우 호출에 대한 데이터를 단일 버퍼로 결합해야 하는 경우가 있습니다. 일부 그래픽 API의 경우 균일 버퍼의 오프셋을 256바이트에 맞춰 정렬해야 한다는 점에 유의하세요. 이는 QRhiShaderResourceBindingsetShaderResources()에 전달된 동적 오프셋에 모두 적용됩니다. ubufAlignment () 및 ubufAligned() 함수를 사용하여 이식 가능한 코드를 작성하세요. 예를 들어 다음은 동일한 파이프라인과 지오메트리를 사용하지만 바인딩 지점 0에 노출된 균일한 버퍼에 다른 데이터를 사용하여 여러 개의 (N) 드로우 호출을 발행하는 개요입니다. 여기서는 uniformBufferWithDynamicOffset()을 통해 버퍼가 노출되어 QRhiCommandBuffer::DynamicOffset 목록을 setShaderResources()에 전달할 수 있다고 가정합니다.

const int N = 2;
const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
if (!ubuf->create()) { error(); }
QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
for (int i = 0; i < N; ++i) {
    batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
    batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
}
// ...
// beginPass(), set pipeline, etc., and then:
for (int i = 0; i < N; ++i) {
    QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
    cb->setShaderResources(srb, 1, dynOfs);
    cb->draw(36);
}

QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer참조하세요 .

멤버 유형 문서

enum QRhiBuffer::Type

버퍼 리소스의 스토리지 유형을 지정합니다.

Constant설명
QRhiBuffer::Immutable0최초 업로드 이후에는 데이터가 변경되지 않을 것으로 예상됨을 나타냅니다. 내부적으로 이러한 버퍼 리소스는 일반적으로 장치 로컬(GPU) 메모리에 배치됩니다(해당되는 경우 시스템에서). 새 데이터를 업로드할 수 있지만 비용이 많이 들 수 있습니다. 업로드는 일반적으로 호스트가 볼 수 있는 별도의 스테이징 버퍼로 복사하여 이루어지며, 이 버퍼에서 GPU 버퍼 간 복사본이 실제 GPU 전용 버퍼로 발행됩니다.
QRhiBuffer::Static1데이터가 드물게 변경될 것으로 예상됨을 나타냅니다. 일반적으로 해당되는 경우 디바이스 로컬(GPU) 메모리에 배치됩니다. 호스트가 볼 수 있는 스테이징 버퍼가 업로드에 사용되는 백엔드에서는 이 유형의 스테이징 버퍼가 불변과 달리 유지되므로 후속 업로드 시 성능 저하가 발생하지 않습니다. 잦은 업데이트, 특히 연속된 프레임의 업데이트는 피해야 합니다.
QRhiBuffer::Dynamic2데이터가 자주 변경될 것으로 예상됨을 나타냅니다. 큰 버퍼에는 권장되지 않습니다. 일반적으로 그래픽 파이프라인을 중단시키지 않고 변경할 수 있도록 호스트 가시 메모리를 2개 복사본으로 백업합니다. 이중 버퍼링은 애플리케이션에 투명하게 관리되며 여기서는 어떤 형태로든 API에 노출되지 않습니다. 이는 권장되는 유형이며, 일부 백엔드에서는 UniformBuffer 사용이 가능한 유일한 버퍼 유형입니다.

열거형 QRhiBuffer::UsageFlag
플래그 QRhiBuffer::UsageFlags

버퍼의 사용 방법을 지정하는 플래그 값입니다.

Constant설명
QRhiBuffer::VertexBuffer1 << 0버텍스 버퍼. setVertexInput ()에서 QRhiBuffer 을 사용할 수 있습니다.
QRhiBuffer::IndexBuffer1 << 1인덱스 버퍼. setVertexInput ()에서 QRhiBuffer 을 사용할 수 있습니다.
QRhiBuffer::UniformBuffer1 << 2균일 버퍼(상수 버퍼라고도 함). 이를 통해 QRhiBufferUniformBuffer 과 함께 사용할 수 있습니다. NonDynamicUniformBuffers 이 지원되지 않는 것으로 보고되면 이 사용법은 동적 유형과 결합할 수만 있습니다.
QRhiBuffer::StorageBuffer1 << 3저장소 버퍼. QRhiBufferBufferLoad, BufferStore 또는 BufferLoadStore 과 함께 사용할 수 있습니다. 이 사용법은 불변 또는 정적 유형과만 결합할 수 있으며 Compute feature 이 지원되는 것으로 보고된 경우에만 사용할 수 있습니다.

UsageFlags 유형은 QFlags<UsageFlag>에 대한 typedef입니다. UsageFlag 값의 OR 조합을 저장합니다.

멤버 함수 문서

[virtual] char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()

호스트 가시 버퍼 데이터가 있는 메모리 블록에 대한 포인터를 반환합니다.

이는 전체 내용(또는 적어도 현재 프레임에서 셰이더가 읽는 모든 영역)이 매 프레임마다 변경되고 QRhiResourceUpdateBatch 기반 업데이트 메커니즘은 관련된 데이터 복사량으로 인해 너무 무거워 보이는 중대형 동적 균일 버퍼에 대한 지름길입니다.

이 함수를 호출한 후에는 이 버퍼에 의존하는 모든 렌더링 또는 계산 패스를 기록하기 전에 endFullDynamicUniformBufferUpdateForCurrentFrame() 호출이 뒤따라야 합니다.

경고: 이 메서드를 통한 데이터 업데이트는 QRhiResourceUpdateBatch 기반 업데이트 및 읽기백과 호환되지 않습니다. 동일한 버퍼에 대해 두 업데이트 모델을 결합하려고 할 때 예기치 않은 동작이 발생할 수 있습니다. 마찬가지로 이 직접 방식으로 업데이트된 데이터는 백엔드에 따라 readBackBuffer operations 에 표시되지 않을 수 있습니다.

경고: 이 방법을 통해 버퍼 데이터를 업데이트할 때는 매 프레임마다 업데이트를 수행해야 하며, 그렇지 않으면 리소스를 이중 또는 삼중으로 버퍼링하는 백엔드에서 예기치 않은 동작이 발생할 수 있습니다.

경고: 일부 백엔드는 이 함수를 호출할 때 버퍼의 이전 내용이 손실되는 전략을 선택할 수 있으므로 이 접근 방식에서는 부분 업데이트가 불가능합니다. 현재 준비 중인 프레임에서 셰이더가 읽는 모든 영역에 데이터를 기록해야 합니다.

경고: 이 함수는 프레임을 녹화할 때만 호출할 수 있으므로 QRhi::beginFrame()와 QRhi::endFrame() 사이에서만 호출할 수 있습니다.

경고: 이 함수는 동적 버퍼에서만 호출할 수 있습니다.

[pure virtual] bool QRhiBuffer::create()

해당 네이티브 그래픽 리소스를 생성합니다. 해당하는 destroy()가 없는 이전 create()로 인해 이미 리소스가 있는 경우 destroy()가 암시적으로 먼저 호출됩니다.

성공하면 true, 그래픽 작업이 실패하면 false 을 반환합니다. 반환 값에 관계없이 destroy()를 호출하는 것은 항상 안전합니다.

[virtual] void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()

beginFullDynamicBufferUpdateForCurrentFrame()에서 반환된 메모리 블록에서 버퍼 데이터의 전체 내용이 업데이트되었을 때 호출됩니다.

[virtual] QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()

이 버퍼의 기본 네이티브 리소스를 반환합니다. 백엔드에서 기본 네이티브 리소스 노출이 지원되지 않는 경우 반환된 값은 비어 있습니다.

type() 및 사용 중인 QRhi 백엔드에 따라 여러 네이티브 버퍼 객체가 QRhiBuffer 를 지원할 수 있습니다. 이 경우 반환된 구조체의 객체 배열에 모든 객체가 반환되며, 슬롯 카운트는 네이티브 버퍼 객체의 수를 지정합니다. recording a frame , QRhi::currentFrameSlot()을 사용하여 기록 중인 프레임 내에서 QRhiQRhiBuffer 에서 읽거나 쓰는 작업에 어떤 네이티브 버퍼를 사용하는지 확인할 수 있습니다.

경우에 따라 QRhiBuffer 은 네이티브 버퍼 객체에 의해 전혀 지원되지 않을 수 있습니다. 이 경우 슬롯 카운트가 0으로 설정되고 유효한 네이티브 객체가 반환되지 않습니다. 이는 오류가 아니며 특정 백엔드가 특정 유형 또는 용도의 QRhiBuffers에 대해 네이티브 버퍼를 사용하지 않는 경우 완벽하게 유효합니다.

참고: QRhi 백엔드는 다양한 버퍼 업데이트 전략을 사용할 수 있다는 점에 유의하세요. 이미지 데이터를 업로드하면 항상 명령 버퍼에 버퍼 대 이미지(또는 이와 유사한) 복사 명령을 기록하는 텍스처와 달리 버퍼, 특히 동적 및 UniformBuffer 버퍼는 여러 가지 방식으로 작동할 수 있습니다. 예를 들어, 사용 유형이 UniformBufferQRhiBuffer 은 특정 백엔드 및 그래픽 API에서 균일한 버퍼를 사용하거나 지원하지 않는 경우 기본 버퍼 객체에 의해 전혀 뒷받침되지 않을 수도 있습니다. 또한 데이터가 버퍼에 기록되는 방식과 사용되는 백업 메모리 유형에도 차이가 있습니다. 호스트 가시 메모리로 지원되는 버퍼의 경우 이 함수를 호출하면 반환된 모든 기본 버퍼에 대해 보류 중인 호스트 쓰기가 실행됩니다.

QRhi::currentFrameSlot() 및 QRhi::FramesInFlight참조하세요 .

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

재구현합니다: QRhiResource::resourceType() const.

리소스 타입을 리턴합니다.

void QRhiBuffer::setSize(quint32 sz)

버퍼의 크기를 바이트 단위로 설정합니다. 크기는 일반적으로 QRhi::newBuffer()에서 지정되므로 이 함수는 크기를 변경해야 하는 경우에만 사용됩니다. 다른 설정자와 마찬가지로 create()를 호출할 때만 크기가 적용되며, 이미 생성된 버퍼의 경우 이전 기본 리소스를 해제하고 내부에서 새 리소스를 생성해야 합니다.

백엔드는 정렬 요구 사항을 충족하기 위해 sz 보다 큰 버퍼를 할당하도록 선택할 수 있습니다. 이는 애플리케이션에서 숨겨지며 size()는 항상 sz 에서 요청된 크기를 보고합니다.

size()도 참조하세요 .

void QRhiBuffer::setType(QRhiBuffer::Type t)

버퍼의 유형을 t 로 설정합니다.

type()도 참조하세요 .

void QRhiBuffer::setUsage(QRhiBuffer::UsageFlags u)

버퍼의 사용 플래그를 u 로 설정합니다.

usage()도 참조하세요 .

quint32 QRhiBuffer::size() const

버퍼의 크기를 바이트 단위로 반환합니다.

이 값은 항상 setSize() 또는 QRhi::newBuffer()에 전달된 값입니다. 기본 그래픽 API에서 요구하는 경우 내부적으로 기본 버퍼가 더 클 수 있습니다.

setSize()도 참조하세요 .

QRhiBuffer::Type QRhiBuffer::type() const

버퍼 유형을 반환합니다.

setType()도 참조하세요 .

QRhiBuffer::UsageFlags QRhiBuffer::usage() const

버퍼의 사용 플래그를 반환합니다.

setUsage()도 참조하세요 .

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.