QRhi Class
2D/3D 그래픽 API 추상화 가속화. 더 보기...
| 헤더: | #include <rhi/qrhi.h> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS GuiPrivate) target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate) |
| qmake: | QT += gui-private |
| 다음과 같이: | Qt 6.6부터 |
- 상속된 멤버를 포함한 모든 멤버 목록
- QRhi는 3D 렌더링의 일부입니다.
공개 유형
(since 6.10) | AdapterList |
| enum | BeginFrameFlag { } |
| flags | BeginFrameFlags |
| enum | EndFrameFlag { SkipPresent } |
| flags | EndFrameFlags |
| enum | Feature { MultisampleTexture, MultisampleRenderBuffer, DebugMarkers, Timestamps, Instancing, …, ShaderDrawParameters } |
| enum | Flag { EnableDebugMarkers, EnableTimestamps, PreferSoftwareRenderer, EnablePipelineCacheDataSave, SuppressSmokeTestWarnings } |
| flags | Flags |
| enum | FrameOpResult { FrameOpSuccess, FrameOpError, FrameOpSwapChainOutOfDate, FrameOpDeviceLost } |
| enum | Implementation { Null, Vulkan, OpenGLES2, D3D11, D3D12, Metal } |
| enum | ResourceLimit { TextureSizeMin, TextureSizeMax, MaxColorAttachments, FramesInFlight, MaxAsyncReadbackFrames, …, ShadingRateImageTileSize } |
공개 함수
| ~QRhi() | |
| void | addCleanupCallback(const QRhi::CleanupCallback &callback) |
| void | addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback) |
| QRhi::Implementation | backend() const |
| const char * | backendName() const |
| QRhi::FrameOpResult | beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {}) |
| QRhi::FrameOpResult | beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags = {}) |
| QMatrix4x4 | clipSpaceCorrMatrix() const |
| int | currentFrameSlot() const |
| QRhiDriverInfo | driverInfo() const |
| QRhi::FrameOpResult | endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {}) |
| QRhi::FrameOpResult | endOffscreenFrame(QRhi::EndFrameFlags flags = {}) |
| QRhi::FrameOpResult | finish() |
| bool | isClipDepthZeroToOne() const |
| bool | isDeviceLost() const |
| bool | isFeatureSupported(QRhi::Feature feature) const |
| bool | isRecordingFrame() const |
| bool | isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const |
| bool | isYUpInFramebuffer() const |
| bool | isYUpInNDC() const |
| bool | makeThreadLocalNativeContextCurrent() |
| const QRhiNativeHandles * | nativeHandles() |
| QRhiBuffer * | newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size) |
| QRhiComputePipeline * | newComputePipeline() |
| QRhiGraphicsPipeline * | newGraphicsPipeline() |
| QRhiRenderBuffer * | newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat) |
| QRhiSampler * | newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW = QRhiSampler::Repeat) |
| QRhiShaderResourceBindings * | newShaderResourceBindings() |
(since 6.9) QRhiShadingRateMap * | newShadingRateMap() |
| QRhiSwapChain * | newSwapChain() |
| QRhiTexture * | newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {}) |
| QRhiTexture * | newTexture(QRhiTexture::Format format, int width, int height, int depth, int sampleCount = 1, QRhiTexture::Flags flags = {}) |
| QRhiTexture * | newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {}) |
| QRhiTextureRenderTarget * | newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = {}) |
| QRhiResourceUpdateBatch * | nextResourceUpdateBatch() |
| QByteArray | pipelineCacheData() |
| void | releaseCachedResources() |
| void | removeCleanupCallback(const void *key) |
| int | resourceLimit(QRhi::ResourceLimit limit) const |
| void | setPipelineCacheData(const QByteArray &data) |
(since 6.9) void | setQueueSubmitParams(QRhiNativeHandles *params) |
| QRhiStats | statistics() const |
| QList<int> | supportedSampleCounts() const |
(since 6.9) QList<QSize> | supportedShadingRates(int sampleCount) const |
| QThread * | thread() const |
| int | ubufAligned(int v) const |
| int | ubufAlignment() const |
정적 공용 멤버
| const char * | backendName(QRhi::Implementation impl) |
| QRhi * | create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter) |
| QRhi * | create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = nullptr) |
(since 6.10) QRhi::AdapterList | enumerateAdapters(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles = nullptr) |
| int | mipLevelsForSize(const QSize &size) |
| bool | probe(QRhi::Implementation impl, QRhiInitParams *params) |
| QSize | sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) |
| QRhiSwapChainProxyData | updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window) |
관련 비멤버
(since 6.7) | QRhiShaderResourceBindingSet |
상세 설명
Qt 렌더링 하드웨어 인터페이스는 OpenGL, OpenGL ES, Direct3D, Metal 및 Vulkan과 같은 하드웨어 가속 그래픽 API를 추상화한 것입니다.
경고: Qt GUI 모듈의 QRhi 클래스계열 ( QShader 및 QShaderDescription 포함)은 제한된 호환성만 보장합니다. 이 클래스들에 대해서는 소스 또는 바이너리 호환성이 보장되지 않으므로, 해당 API는 애플리케이션이 개발된 Qt 버전에서만 작동이 보장됩니다. 다만, 소스 비호환 변경 사항은 최소한으로 유지되도록 노력하며, 마이너 릴리스(6.7, 6.8 등)에서만 이루어질 예정입니다. 애플리케이션에서 이러한 클래스를 사용하려면 (CMake를 사용하는 경우) Qt::GuiPrivate 에 링크하고, rhi 접두사가 붙은 헤더 파일(예: #include <rhi/qrhi.h>)을 포함해야 합니다.
각 QRhi 인스턴스는 특정 그래픽 API용 백엔드를 기반으로 합니다. 백엔드 선택은 런타임 시 결정되며, QRhi 인스턴스를 생성하는 애플리케이션이나 라이브러리의 재량에 달려 있습니다. 일부 백엔드(OpenGL, Vulkan, Null)는 여러 플랫폼에서 사용할 수 있는 반면, 특정 플랫폼에 고유한 API는 해당 플랫폼에서 실행할 때만 사용할 수 있습니다(macOS/iOS의 Metal, Windows의 Direct3D).
현재 사용 가능한 백엔드는 다음과 같습니다:
- OpenGL 2.1 / OpenGL ES 2.0 이상. 멀티샘플 프레임버퍼나 컴퓨트 셰이더를 활성화하는 등, 일부 확장 기능 및 최신 핵심 사양 기능이 지원되는 경우 이를 활용합니다. 코어 프로파일 컨텍스트에서의 작동도 지원됩니다. 필요한 경우, 애플리케이션은 런타임에 feature flags 을 조회하여 QRhi를 뒷받침하는 OpenGL 컨텍스트에서 지원되지 않는 기능을 확인할 수 있습니다. OpenGL 백엔드는 QOpenGLContext, QOpenGLFunctions 및 Qt GUI 모듈의 관련 크로스 플랫폼 인프라를 기반으로 구축됩니다.
- Direct3D 11.2 이상(DXGI 1.3 이상 포함), Shader Model 5.0 이상 사용. D3D 런타임이 11.2 기능이나 셰이더 모델 5.0을 지원하지 않는 경우, 가속 그래픽 장치를 사용한 초기화는 실패하지만 소프트웨어 어댑터를 사용하는 것은 여전히 가능합니다.
- Windows 10 버전 1703 이상에서 Direct3D 12를 사용하며, 셰이더 모델 5.0 이상을 지원해야 합니다. Qt는 ID3D12Device2가 있어야 하므로, 최소 Windows 10 버전 1703 이상이 필요합니다. D3D12 장치는 기본적으로 최소 기능 수준
D3D_FEATURE_LEVEL_11_0로 지정되어 생성됩니다. - Metal 1.2 이상.
- Vulkan 1.0 이상이며, 선택적으로 일부 Vulkan 1.1 수준의 기능을 활용할 수 있습니다.
- Null: 그래픽 호출을 전혀 수행하지 않는 "더미" 백엔드입니다.
Qt 애플리케이션 및 라이브러리에서 셰이더 코드를 한 번만 작성할 수 있도록 하기 위해, 모든 셰이더는 단일 언어로 작성된 후 SPIR-V로 컴파일되어야 합니다. 그런 다음 이를 기반으로 다양한 셰이딩 언어용 버전이 리플렉션 정보(입력, 출력, 셰이더 리소스)와 함께 생성됩니다. 이후 이 결과물은 쉽고 효율적으로 직렬화할 수 있는 ` QShader ` 인스턴스로 압축됩니다. 이러한 셰이더를 생성하는 컴파일러와 도구는 QRhi 및 ` Qt GUI ` 모듈에 포함되지 않지만, 해당 셰이더를 사용하는 핵심 클래스인 ` QShader ` 및 ` QShaderDescription`는 포함되어 있습니다. 컴파일 및 변환을 수행하는 API와 도구는 Qt의 ` Shader Tools ` 모듈에 포함되어 있습니다.
QRhi를 사용하여 QWindow 에서 가속화된 3D 렌더링을 수행하는 이식성 있는 크로스 플랫폼 애플리케이션을 만드는 입문용 예제는 RHI Window 예제를 참조하십시오.
API 개요
창 관련 설정이 필요 없는 짧지만 완전한 예제를 통해 API를 간략히 살펴보도록 하겠습니다. 다음은 화면 밖에서 20프레임을 렌더링한 후, GPU에서 텍스처 내용을 다시 읽어와 생성된 이미지를 파일로 저장하는, 실행 가능한 완전한 크로스 플랫폼 애플리케이션입니다. 화면 상에서 렌더링하고, 이에 따라 QWindow 및 스왑체인(swapchain)을 설정해야 하는 예제는 RHI Window Example을 참조하십시오.
간결성을 위해 QRhi의 초기화는 플랫폼에 따라 수행됩니다. 이 샘플 코드는 Windows에서는 Direct 3D 12를, macOS 및 iOS에서는 Metal을, 그 외의 경우 Vulkan을 선택합니다. 이 애플리케이션은 OpenGL과 Direct 3D 11을 전혀 사용하지 않지만, 몇 줄의 코드를 추가하면 해당 기능에 대한 지원을 도입할 수 있습니다.
#include <QGuiApplication>
#include <QImage>
#include <QFile>
#include <rhi/qrhi.h>
int main(int argc, char**argv)
{
QGuiApplication app(argc, argv);
#if QT_CONFIG(vulkan)
QVulkanInstance inst;
#endif
std::unique_ptr<QRhi> rhi;
#if defined(Q_OS_WIN)
QRhiD3D12InitParams params;
rhi.reset(QRhi::create(QRhi::D3D12, ¶ms));
#elif QT_CONFIG(metal)
QRhiMetalInitParams params;
rhi.reset(QRhi::create(QRhi::Metal, ¶ms));
#elif QT_CONFIG(vulkan)
inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
if (inst.create()) {
QRhiVulkanInitParams params;
params.inst = &inst;
rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms));
} else {
qFatal("Failed to create Vulkan instance");
}
#endif
if (rhi)
qDebug() << rhi->backendName() << rhi->driverInfo();
else
qFatal("Failed to initialize RHI");
float rotation = 0.0f;
float opacity = 1.0f;
int opacityDir = 1;
std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8,
QSize(1280, 720),
1,
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
tex->create();
std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() }));
std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rp.get());
rt->create();
QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix();
viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
viewProjection.translate(0, 0,-4);
static float vertexData[] = { // Y축이 위, 시계 반대 방향
0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f,-0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
};
std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable,
QRhiBuffer::VertexBuffer,
sizeof(vertexData)));
vbuf->create();
std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic,
QRhiBuffer::UniformBuffer,
64 + 4));
ubuf->create();
std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
srb->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0,
QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
ubuf.get())
});
srb->create();
std::unique_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline());
QRhiGraphicsPipeline::TargetBlendpremulAlphaBlend;
premulAlphaBlend.enable = true;
ps->setTargetBlends({ premulAlphaBlend });
static auto getShader = [](const QString&name) {
QFile f(name);
return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
};
ps->setShaderStages({
{ QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },
{ QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) }
});
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({
{ 5 * sizeof(float) }
});
inputLayout.setAttributes({
{ 0, 0, QRhiVertexInputAttribute::Float2, 0 },
{ 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
});
ps->setVertexInputLayout(inputLayout);
ps->setShaderResourceBindings(srb.get());
ps->setRenderPassDescriptor(rp.get());
ps->create();
QRhiCommandBuffer*cb;
for (int frame = 0; frame < 20;++frame) {
rhi->beginOffscreenFrame(&cb);
QRhiResourceUpdateBatch*u = rhi->nextResourceUpdateBatch();
if (frame== 0)
u->uploadStaticBuffer(vbuf.get(), vertexData);
QMatrix4x4 mvp = viewProjection;
mvp.rotate(rotation, 0, 1, 0);
u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData());
rotation+= 5.0f;
u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity);
opacity+= opacityDir * 0.2f;
if (opacity < 0.0f|| opacity > 1.0f) {
opacityDir*=-1;
opacity = qBound(0.0f, opacity, 1.0f);
}
cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u);
cb->setGraphicsPipeline(ps.get());
cb->setViewport({ 0, 0, 1280, 720 });
cb->setShaderResources();
const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0);
cb->setVertexInput(0, 1, &vbufBinding);
cb->draw(3);
QRhiReadbackResult readbackResult;
u = rhi->nextResourceUpdateBatch();
u->readBackTexture({ tex.get() }, &readbackResult);
cb->endPass(u);
rhi->endOffscreenFrame();
QImage image(reinterpret_cast<const uchar*>(readbackResult.data.constData()),
readbackResult.pixelSize.width(),
readbackResult.pixelSize.height(),
QImage::Format_RGBA8888_Premultiplied);
if (rhi->isYUpInFramebuffer())
image.flip();
image.save(QString::asprintf("frame%d.png", frame));
}
return 0;
}이 프로그램을 실행하면 20개의 PNG 이미지(frame0.png - frame19.png)가 생성됩니다. 이 이미지들에는 녹색 배경 위에 불투명도가 변화하는 회전하는 삼각형이 포함되어 있습니다.
버텍스 셰이더와 프래그먼트 셰이더는 처리되어 .qsb 파일로 패키징되어야 합니다. Vulkan과 호환되는 GLSL 소스 코드는 다음과 같습니다:
color.vert
#version 440
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 v_color;
layout(std140, binding = 0) uniform buf {
mat4 mvp;
float opacity;
};
void main()
{
v_color = color;
gl_Position = mvp * position;
}color.frag
#version 440
layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
mat4 mvp;
float opacity;
};
void main()
{
fragColor = vec4(v_color * opacity, opacity);
}이러한 셰이더를 여러 대상(SPIR-V, HLSL, MSL, GLSL)으로 수동으로 컴파일 및 트랜스파일하고, 애플리케이션이 실행 시에 로드하는 ` .qsb ` 파일을 생성하려면 ` qsb --qt6 color.vert -o color.vert.qsb ` 및 ` qsb --qt6 color.frag -o color.frag.qsb`을 실행하십시오. 또는 Qt의 ` Shader Tools ` 모듈은 CMake용 빌드 시스템 통합 기능인 ` qt_add_shaders() ` CMake 함수를 제공하며, 이를 통해 빌드 시에 동일한 결과를 얻을 수 있습니다.
보안 고려 사항
QRhi 및 QShader 와 같은 관련 클래스가 처리하는 모든 데이터는 신뢰할 수 있는 콘텐츠로 간주됩니다.
경고: 애플리케이션 개발자는 애플리케이션의 일부가 아니며 개발자의 통제 범위를 벗어난 사용자 제공 콘텐츠의 사용을 허용하기 전에, 그로 인해 발생할 수 있는 잠재적 영향을 신중하게 고려해야 합니다. (여기에는 모든 버텍스/인덱스 데이터, 셰이더, 파이프라인 및 드로우 콜 매개변수 등이 포함됩니다.)
설계 기본 원칙
QRhi는 직접 인스턴스화할 수 없습니다. 대신 create() 함수를 사용하십시오. 그래픽 장치를 해제하려면 QRhi 인스턴스를 일반적인 방법으로 삭제하십시오.
리소스
QRhiResource 에서 파생된 클래스(예: QRhiBuffer, QRhiTexture 등)의 인스턴스는 0개, 1개 또는 그 이상의 네이티브 그래픽 리소스를 캡슐화합니다. 이러한 클래스의 인스턴스는 항상 QRhi의 new 함수(예: newBuffer(), newTexture(), newTextureRenderTarget(), newSwapChain())를 통해 생성됩니다.
QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
if (!vbuf->create()) { error(); }
// ...
delete vbuf;- newBuffer()과 같은 함수에서 반환된 값은 항상 호출자가 소유합니다.
- QRhiResource 의 서브클래스 인스턴스를 생성하는 것만으로는 네이티브 리소스가 할당되거나 초기화되지 않습니다. 이는 서브클래스의
create()함수(예: QRhiBuffer::create() 또는 QRhiTexture::create())를 호출할 때만 수행됩니다. - 단, QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(), QRhiSwapChain::newCompatibleRenderPassDescriptor(), QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor()는 예외입니다. 이 메서드들에는
create()작업이 없으며, 반환된 객체는 즉시 활성화됩니다. - 리소스 객체 자체는 불변으로 취급됩니다. 리소스에 대해 create()이 호출된 후에는, 기본이 되는 네이티브 리소스가 해제되고
create()가 다시 호출되지 않는 한, QRhiTexture::setPixelSize()과 같은 세터를 통해 매개변수를 변경해도 아무런 효과가 없습니다. 리소스 재사용에 대한 자세한 내용은 아래 섹션을 참조하십시오. - 기본이 되는 네이티브 리소스는 QRhiResource 의 소멸자나 QRhiResource::destroy() 호출을 통해 해제되도록 스케줄링됩니다. 백엔드는 종종 해제 요청을 큐에 넣고 실행을 미정된 시점으로 연기하는데, 이는 애플리케이션에서는 보이지 않습니다. 이렇게 하면 애플리케이션은 처리 중인 프레임에서 여전히 사용 중일 수 있는 네이티브 리소스의 해제에 대해 걱정할 필요가 없습니다.
- 단, 이것이 QRhiResource 가 프레임 내부(즉, beginFrame() - endFrame() 구간)에서 자유롭게 destroy()되거나 삭제될 수 있음을 의미하지는 않습니다. 일반적인 규칙에 따라, 참조되고 있는 모든 QRhiResource 객체는 endFrame() 호출을 통해 프레임이 제출될 때까지 변경되어서는 안 됩니다. 이를 용이하게 하기 위해 QRhiResource::deleteLater()가 편의 기능으로 제공됩니다.
명령 버퍼 및 지연된 명령 실행
기본이 되는 그래픽 API의 설계 및 기능과 관계없이, 모든 QRhi 백엔드는 어느 정도 수준의 명령 버퍼를 구현합니다. QRhiCommandBuffer 의 어떤 함수도 네이티브 바인드 또는 드로우 명령(예: glDrawElements)을 직접 발행하지 않습니다. 명령은 항상 네이티브 큐이거나 QRhi 백엔드가 제공하는 큐에 기록됩니다. 명령 버퍼는 제출되며, 따라서 QRhi::endFrame() 또는 QRhi::finish()이 호출될 때만 실행이 시작됩니다.
이러한 지연 실행 특성은 일부 유형의 객체에 영향을 미칩니다. 예를 들어, 호스트가 볼 수 있는 메모리를 백엔드로 사용하는 동적 버퍼에 프레임 내에서 여러 번 쓰기를 수행하면, 동적 버퍼 업데이트가 드로우 호출에 비해 언제 기록되었는지에 관계없이 해당 프레임의 명령 버퍼에 있는 모든 드로우 호출에서 모든 쓰기 결과를 볼 수 있게 됩니다.
또한, QRhiResource 하위 클래스의 인스턴스는 어떤 방식으로든 참조되는 프레임 내에서 불변으로 취급되어야 합니다. 다음 프레임에 대한 명령어 기록을 시작하기 전에 모든 리소스를 미리 생성해야 합니다. 프레임 내에서 ` QRhiResource ` 인스턴스를 재사용하는 것(` create() `를 호출한 후 동일한 ` beginFrame - endFrame ` 섹션에서 다시 참조하는 방식)은 백엔드에 따라 예기치 않은 결과를 초래할 수 있으므로 피해야 합니다.
일반적인 규칙으로, 참조된 모든 QRhiResource 객체는 endFrame()를 호출하여 프레임이 제출될 때까지 유효한 상태로 유지되어야 하며 수정되어서는 안 됩니다. 반면, destroy()를 호출하거나 QRhiResource 를 삭제하는 것은 프레임이 제출된 후에는 기본 네이티브 리소스의 상태(GPU에서 여전히 사용 중일 수 있지만, 이는 내부적으로 처리됨)와 관계없이 항상 안전합니다.
OpenGL과 같은 API와 달리, 업로드 및 복사 유형의 명령은 드로우 명령과 혼합하여 사용할 수 없습니다. 일반적인 렌더러는 다음과 유사한 순서로 작동합니다:
- 리소스 (재)생성
- 프레임 시작
- 업로드 및 복사 명령 기록/발행
- 렌더 패스 기록 시작
- 드로우 콜 기록
- 렌더 패스 종료
- 프레임 종료
복사 유형의 작업 기록은 ` QRhiResourceUpdateBatch`를 통해 이루어집니다. 이러한 작업은 일반적으로 ` beginPass()`에서 커밋됩니다.
OpenGL용으로 설계된 레거시 렌더링 엔진을 사용할 때, QRhi로 마이그레이션하는 과정에는 종종 단일 render 단계(복사 및 업로드, 버퍼 지우기, 드로우 콜 호출 등을 모두 혼합하여 수행하는)에서 명확하게 분리된, 두 단계의 prepare - render 구조로 재설계하는 과정을 수반합니다. 이 구조에서 render 단계는 렌더 패스를 시작하고 드로우 콜을 기록하는 역할만 수행하며, 모든 리소스 생성 및 업데이트, 업로드, 복사 작업의 큐잉은 그 이전 단계인 prepare 단계에서 미리 이루어집니다.
현재 QRhi에서는 커맨드 버퍼를 자유롭게 생성하고 제출할 수 없습니다. 향후, 특히 컴퓨트(compute) 지원이 도입될 경우 이 제한이 어느 정도 완화될 수 있겠지만, 명확하게 정의된 ` frame-start ` 및 ` frame-end ` 포인트 모델과 전용 “프레임(frame)” 명령 버퍼를 결합한 방식(이 경우 ` frame-end `은 프레젠테이션을 의미함)은 Qt의 다양한 UI 기술에 가장 잘 부합하므로 앞으로도 주요 운영 방식으로 유지될 것입니다.
스레딩
QRhi 인스턴스와 관련 리소스는 어떤 스레드에서든 생성 및 사용할 수 있지만, 모든 사용은 해당 단일 스레드로만 제한되어야 합니다. 애플리케이션 내에서 여러 QWindow에 렌더링할 때, 각 창마다 전용 스레드와 QRhi 인스턴스를 갖는 것이 종종 권장됩니다. 이는 여러 창에 프레젠테이션을 수행할 때 발생하는 예기치 않은 스로틀링 문제를 방지할 수 있기 때문입니다. 개념적으로 이는 OpenGL을 직접 사용할 때 Qt Quick 의 씬 그래프 스레드 기반 렌더 루프가 작동하는 방식과 동일합니다. 즉, 창마다 하나의 스레드, 스레드마다 하나의 ` QOpenGLContext `가 할당되는 방식입니다. QRhi로 전환할 때 ` QOpenGLContext `는 `QRhi`로 대체되므로 마이그레이션이 간단합니다.
QRhiGles2NativeHandles 를 통해 전달된 OpenGL 컨텍스트와 같이 외부에서 생성된 네이티브 객체의 경우, 다른 스레드에서 이를 오용하지 않도록 보장하는 것은 애플리케이션의 책임입니다.
리소스는 QRhi 인스턴스 간에 공유할 수 없습니다. 이는 QRhi가 대부분의 큐, 명령 버퍼 및 리소스 동기화 관련 작업을 숨기고 이에 대한 API를 제공하지 않기 때문에 의도된 선택입니다. 그러나 여러 스레드에서 그래픽 리소스를 안전하고 효율적으로 동시 사용하는 것은 이러한 개념과 밀접하게 관련되어 있으므로, 현재로서는 범위를 벗어난 주제이지만 향후 도입될 수도 있습니다.
참고: Metal백엔드는 렌더링 스레드에서 오토릴리즈 풀이 사용 가능해야 하며, 이상적으로는 렌더 루프의 각 반복을 감싸야 합니다. 메인(GUI) 스레드에서 렌더링할 때는 QRhi 사용자가 별도의 조치를 취할 필요가 없지만, 별도의 전용 렌더링 스레드를 사용할 때는 이 점이 중요해집니다.
리소스 동기화
QRhi는 리소스 배리어 또는 이미지 레이아웃 전환을 위한 API를 제공하지 않습니다. 이러한 동기화는 해당되는 경우(예: Vulkan) 백엔드에서 필요에 따라 리소스 사용량을 추적함으로써 암시적으로 수행됩니다. 버퍼 및 이미지 배리어는 렌더링 또는 컴퓨트 패스 전에 애플리케이션에 투명하게 삽입됩니다.
참고: 렌더링 또는 컴퓨트 패스 내의리소스는 해당 패스 동안 단일 용도로만 바인딩되어야 합니다. 예를 들어, 버퍼는 정점, 인덱스, 유니폼 또는 스토리지 버퍼로 사용될 수 있지만, 단일 패스 내에서 이들의 조합으로 사용될 수는 없습니다. 그러나 버퍼가 생성 시 두 가지 용도로 모두 선언되었다고 가정할 경우, 컴퓨트 패스에서는 스토리지 버퍼로 사용하고 렌더 패스에서는 정점 버퍼로 사용하는 것은 전혀 문제가 없습니다.
참고: 텍스처의 경우 특정 상황에서 이 규칙이 완화됩니다. 동일한 텍스처의 두 하위 리소스(일반적으로 서로 다른 두 미프 레벨)를 서로 다른 액세스(하나는 로드용, 다른 하나는 저장용)에 사용하는 것이 동일한 패스 내에서도 지원되기 때문입니다.
리소스 재사용
사용자 관점에서 볼 때, ` QRhiResource `는 ` QRhiResource::destroy()`를 호출한 직후부터 재사용할 수 있습니다. 스왑체인(swapchains)을 제외하고, 이미 생성된 객체에 대해 ` create() `를 호출하면 암시적으로 ` destroy()`가 수행됩니다. 이는 서로 다른 매개변수를 사용하여 ` QRhiResource ` 인스턴스를 재사용할 수 있는 편리한 단축키 역할을 하며, 그 밑에는 새로운 네이티브 그래픽스 객체가 사용됩니다.
동일한 객체를 재사용하는 것이 중요한 이유는 일부 객체가 다른 객체를 참조하기 때문입니다. 예를 들어, ` QRhiShaderResourceBindings `는 ` QRhiBuffer`, ` QRhiTexture`, ` QRhiSampler ` 인스턴스를 참조할 수 있습니다. 이후 프레임에서 이러한 버퍼 중 하나의 크기를 조정하거나 샘플러 매개변수를 변경해야 하는 경우, ` QRhiBuffer ` 또는 ` QRhiSampler `를 완전히 삭제하고 새로 생성하면 이전 인스턴스에 대한 모든 참조가 무효화됩니다. QRhiBuffer::setSize() 또는 이와 유사한 메서드를 통해 적절한 매개변수만 변경한 다음 QRhiBuffer::create()를 호출하면, 모든 것이 예상대로 작동하며 QRhiShaderResourceBindings 을 전혀 건드릴 필요가 없습니다. 비록 내부적으로는 QRhiBuffer 가 이제 완전히 새로운 네이티브 버퍼로 뒷받침될 가능성이 높더라도 말입니다.
QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
ubuf->create();
QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
srb->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
});
srb->create();
// ...
// now in a later frame we need to grow the buffer to a larger size
ubuf->setSize(512);
ubuf->create(); // same as ubuf->destroy(); ubuf->create();
// srb needs no changes whatsoever, any references in it to ubuf
// stay valid. When it comes to internal details, such as that
// ubuf may now be backed by a completely different native buffer
// resource, that is is recognized and handled automatically by the
// next setShaderResources().QRhiTextureRenderTarget 동일한 계약(contract)을 제공합니다. 즉, 렌더 타겟 객체가 생성된 이후 관련 텍스처나 렌더버퍼 중 하나가 ( create() 를 호출하여) 재구성된 경우에도 QRhiCommandBuffer::beginPass()를 호출하는 것은 안전합니다. 이를 통해 애플리케이션은 ` QRhiTexture `에 새로운 픽셀 크기를 설정하고 ` create()`를 호출하여 텍스처의 크기를 조정할 수 있으며, 이로 인해 내부적으로 완전히 새로운 네이티브 텍스처 리소스가 생성됩니다. 이때 ` QRhiTextureRenderTarget `를 업데이트할 필요는 없는데, 이는 `beginPass()`에서 암시적으로 처리되기 때문입니다.
풀링된 객체
리소스 외에도 QRhiResourceUpdateBatch 와 같은 풀링된 객체가 있습니다. 인스턴스는 nextResourceUpdateBatch()와 같은 next 함수를 통해 가져옵니다. 이 경우 호출자는 반환된 인스턴스를 소유하지 않습니다. 이 경우 유일하게 유효한 처리 방식은 QRhiResourceUpdateBatch 에 함수를 호출한 후, 이를 QRhiCommandBuffer::beginPass() 또는 QRhiCommandBuffer::endPass()에 전달하는 것입니다. 이 함수들은 배치(batch)를 풀로 반환하는 작업을 처리합니다. 또는 QRhiResourceUpdateBatch::release()를 호출하여 배치를 처리하지 않고 "취소"한 후 풀로 반환할 수도 있습니다.
따라서 일반적인 패턴은 다음과 같습니다:
QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
// ...
resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
if (!image.isNull()) {
resUpdates->uploadTexture(texture, image);
image = QImage();
}
// ...
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
// note the last argument
cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);스왑체인(Swapchain)의 특징
QRhiSwapChain 스왑체인의 독특한 특성으로 인해 몇 가지 특별한 의미 체계가 적용됩니다.
create()는 없으며, 대신 QRhiSwapChain::createOrResize()가 있습니다. 이 함수를 반복해서 호출하는 것은 QRhiSwapChain::destroy()를 호출한 후 QRhiSwapChain::createOrResize()를 호출하는 것과 동일하지 않습니다. 이는 스왑체인에서 버퍼 크기를 조정해야 할 경우, 무작정 버퍼를 파괴하고 처음부터 다시 생성하는 것보다 더 효율적인 방식으로 처리할 수 있는 방법이 종종 있기 때문입니다.- 활성 상태인 QRhiSwapChain 는 QWindow 의 기반이 되는 QPlatformWindow와 이에 연관된 네이티브 창 객체가 소멸되기 전에 destroy()을 호출하거나 객체를 소멸시켜 해제해야 합니다. 이 작업을 미루어서는 안 됩니다. 예를 들어, ` QWindow::close()`를 수신하는 과정에서 `QPlatformWindow`가 소멸되는 등 네이티브 윈도우가 더 이상 존재하지 않을 경우, 스왑 체인을 해제하는 데 문제가 발생할 수 있으며(Vulkan과 같은 일부 API에서는 명시적으로 금지되어 있음), 따라서 대상 QWindow 가 QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed 이벤트를 전송할 때마다 스왑 체인을 해제해야 합니다. QWindow 가 소멸되기 전에 이벤트가 도착하지 않는 경우( QCoreApplication::quit()를 사용할 때 발생할 수 있음), 이벤트 루프가 종료된 후 QWindow::handle()을 확인하고, 값이 null이 아닐 때(즉, 기본 네이티브 창이 여전히 존재할 때) 스왑 체인 해제를 호출해야 합니다.
소유권
일반적인 규칙은 소유권이 이전되지 않는다는 것입니다. 이미 존재하는 그래픽스 장치를 사용하여 QRhi를 생성한다고 해서 QRhi가 해당 장치 객체의 소유권을 갖는 것은 아닙니다. 마찬가지로, QRhi::nativeHandles() 또는 QRhiTexture::nativeTexture()를 통해 장치나 텍스처 객체를 “내보낼” 때도 소유권이 양도되지 않습니다. 무엇보다 중요한 점은, 구조체 내나 세터(setter)를 통해 포인터를 전달하더라도 소유권이 이전되지 않는다는 것입니다.
문제 해결 및 프로파일링
오류 보고
QRhi::create() 및 리소스 클래스의 create() 멤버 함수(예: QRhiBuffer::create())와 같은 함수는 반환 값(각각nullptr 또는 false)을 통해 실패를 나타냅니다. QShader 를 사용할 때, 함수에 전달된 데이터를 성공적으로 역직렬화할 수 없는 경우 QShader::fromSerialized()는 유효하지 않은 QShader 를 반환하며(이에 대해 isValid()는 false 를 반환합니다). 일부 함수, 특히 beginFrame()는 때때로 FrameOpSwapChainOutOfDate 와 같은 “소프트 오류”를 보고할 수도 있는데, 이는 복구 불가능한 오류를 나타내는 것이 아니라 “나중에 다시 시도해 보세요”라는 응답으로 간주되어야 합니다.
경고 및 오류는 qWarning()을 통해 언제든지 디버그 출력에 기록될 수 있습니다. 따라서 항상 애플리케이션의 출력을 확인하는 것이 좋습니다.
다음 로깅 범주를 통해 추가 디버그 메시지를 활성화할 수 있습니다. 이러한 범주의 메시지는 QLoggingCategory 또는 QT_LOGGING_RULES 환경 변수를 통해 명시적으로 활성화되지 않는 한 기본적으로 출력되지 않습니다. Qt Quick 와의 상호 운용성을 높이기 위해, QSG_INFO 환경 변수도 이러한 디버그 출력을 활성화합니다.
qt.rhi.general
또한, 애플리케이션은 성공적으로 초기화된 QRhi에서 QRhi backend name 및 graphics device information 를 조회할 수 있습니다. 원하는 경우, 이 정보는 프로덕션 빌드에서도 사용자에게 표시되거나 애플리케이션 로그에 저장될 수 있습니다.
렌더링 문제 조사
렌더링 결과가 예상과 다르거나 애플리케이션에 문제가 발생할 경우, 항상 네이티브 3D API의 디버그 및 유효성 검사 기능을 확인해 보십시오. QRhi 자체는 기본 레이어에 이미 존재하는 방대한 기능을 그대로 재현하는 것이 합리적이지 않으므로, 제한된 오류 검사 기능만 제공합니다.
- Vulkan의 경우, Vulkan 검증 레이어(Vulkan Validation Layers )를 제어하는 것은 QRhi의 범위에 속하지 않으며, 대신 QVulkanInstance 을 적절한 레이어로 구성하여 구현할 수 있습니다. 예를 들어, QVulkanInstance 에서 create()를 호출하기 전에
instance.setLayers({ "VK_LAYER_KHRONOS_validation" });를 호출하십시오. (이는 검증 레이어가 실제로 설치되어 있고 사용 가능한 상태, 예: Vulkan SDK에서 제공되는 경우를 전제로 합니다.) 기본적으로 QVulkanInstance 는 Vulkan 디버그 메시지를 qDebug 로 편리하게 리디렉션하므로, 검증 메시지가 다른 Qt 경고와 마찬가지로 출력됩니다. - Direct 3D 11 및 12의 경우, 해당 init params struct 에서
enableDebugLayer플래그를 토글하여 디버그 레이어가 활성화된 그래픽 장치를 요청할 수 있습니다. Direct 3D 12에서는 디버그 레이어가 메시지 콜백을 지원하는 한, Vulkan 유효성 검사 메시지와 마찬가지로 메시지가 qDebug 를 통해 출력됩니다. 그렇지 않은 경우, 그리고 Direct 3D 11의 경우에는 항상 메시지가 디버그 출력에 표시되며, 이는 Qt Creator 의 메시지 패널이나 DebugView와 같은 도구를 통해 확인할 수 있습니다. - Metal의 경우, Metal 유효성 검증을 제어하는 것은 QRhi의 범위를 벗어납니다. 대신 유효성 검사를 활성화하려면 환경 변수 `
METAL_DEVICE_WRAPPER_TYPE=1`을 설정하고 애플리케이션을 실행하거나, XCode 내에서 애플리케이션을 실행하십시오. 최신 XCode 및 macOS 버전에는 추가 설정 및 환경 변수가 있을 수도 있습니다. 예를 들어 이 페이지를 참조하십시오.
프레임 캡처 및 성능 프로파일링
내부적으로 3D API를 활용하면서 QRhi를 통해 창에 렌더링하는 Qt 애플리케이션은, 적어도 윈도우 및 그래픽 파이프라인의 관점에서 볼 때, 동일한 3D API를 사용하는 다른 (비-Qt) 애플리케이션과 다르지 않습니다. 즉, 게임과 같이 3D 그래픽을 다루는 애플리케이션을 디버깅하고 프로파일링하기 위한 도구와 기법은 이러한 Qt 애플리케이션에도 모두 적용됩니다.
Qt Quick 와 Qt Quick 3D 기반 프로젝트를 포함하여, QRhi를 사용하는 Qt 애플리케이션의 렌더링 내부 구조를 파악하는 데 도움이 되는 도구의 몇 가지 예는 다음과 같습니다:
- RenderDoc은 OpenGL, Vulkan, D3D11 또는 D3D12를 사용하는 애플리케이션의 경우, Windows 및 Linux 환경에서 프레임 캡처를 수행하고 기록된 명령어와 파이프라인 상태를 분석할 수 있게 해줍니다. 3D 씬의 일부가 예상대로 표시되지 않는 원인을 파악할 때, RenderDoc은 파이프라인 단계와 관련 상태를 확인하고 누락되거나 잘못된 값을 찾아내는 빠르고 효율적인 방법입니다. 또한 Qt 자체를 개발할 때도 활발히 사용되는 도구입니다.
- NVIDIA 기반 시스템의 경우, Nsight Graphics는 Windows 및 Linux에서 그래픽 디버거 도구를 제공합니다. 프레임 내 명령어와 파이프라인을 조사하는 것 외에도, 벤더별 도구를 사용하면 단순한 프레임 캡처로는 얻을 수 없는 타이밍 및 하드웨어 성능 정보를 확인할 수 있습니다.
- AMD 기반 시스템의 경우, Radeon GPU Profiler를 사용하여 애플리케이션의 렌더링 및 성능에 대한 더 깊은 통찰력을 얻을 수 있습니다.
- 실시간 성능 정보를 표시하는 오버레이 역시 매우 유용할 수 있으며, 더 신뢰할 수 있고 더 많은 정보를 제공하기 때문에 애플리케이션 자체에 단순한 초당 프레임 수(FPS) 카운터를 구현하는 것보다 종종 선호됩니다. 여러 벤더의 그래픽 하드웨어를 지원하는 PresentMon이 그 예입니다.
- QRhi는 Direct 3D 12를 지원하므로, Windows에서 DirectX 12 게임을 위한 성능 튜닝 및 디버깅 도구인 PIX를 사용하는 것도 하나의 방법입니다.
- macOS에서는 XCode Metal 디버거를 사용하여 프레임 캡처를 수행하고 분석하여 성능 세부 정보를 조사하고 셰이더를 디버깅할 수 있습니다. 또한 macOS 13에서는 환경 변수 `
MTL_HUD_ENABLED=1`를 설정하여 Metal 기반 창의 프레임 속도 및 기타 정보를 표시하는 오버레이를 활성화할 수도 있습니다.
모바일 및 임베디드 플랫폼의 경우, GPU 또는 SoC 공급업체에서 제공하는 벤더 및 플랫폼별 도구를 사용하여 OpenGL ES 또는 Vulkan을 활용하는 애플리케이션의 성능 프로파일링을 수행할 수 있습니다.
프레임을 캡처할 때, QRhi의 debug markers were enabled 및 사용 중인 그래픽 API가 이를 지원하는 한, 디버그 마커를 통해 객체와 명령어 그룹에 이름을 지정할 수 있다는 점을 기억하십시오. 명령어 스트림에 주석을 달려면 debugMarkBegin(), debugMarkEnd() 및/또는 debugMarkMsg()를 호출하십시오. 이는 여러 렌더링 패스가 포함된 대용량 프레임에서 특히 유용할 수 있습니다. 리소스 이름은 create()을 호출하기 전에 setName()을 호출하여 지정합니다.
애플리케이션 내에서 CPU 및 GPU 측의 기본적인 타이밍 측정을 수행하려면 QElapsedTimer 및 QRhiCommandBuffer::lastCompletedGpuTime()을 사용할 수 있습니다. 후자는 현재 특정 그래픽 API에서만 사용할 수 있으며, QRhi::EnableTimestamps 플래그를 통해 활성화해야 합니다.
리소스 누수 검사
QRhi 객체를 생성하여 만든 모든 버퍼, 텍스처 및 기타 리소스를 적절히 해제하지 않은 채로 QRhi 객체를 소멸시킬 경우, 애플리케이션이 디버그 빌드이거나 QT_RHI_LEAK_CHECK 환경 변수가 0이 아닌 값으로 설정된 경우 이에 대한 경고가 디버그 출력에 표시됩니다. 이는 애플리케이션 렌더링 로직 내 리소스 처리와 관련된 설계상의 문제를 발견할 수 있는 간단한 방법입니다. 다만 일부 플랫폼 및 기본 그래픽 API는 Qt가 직접 제어할 수 없는 자체적인 할당 및 리소스 누수 감지 기능을 수행할 수도 있다는 점에 유의하십시오. 예를 들어, Vulkan을 사용할 때 그래픽 메모리 할당을 소유한 리소스가 QRhi보다 먼저 소멸되지 않으면, 디버그 빌드에서 메모리 할당기가 실패한 어설션을 발생시킬 수 있습니다. 또한, Vulkan 유효성 검사 레이어가 활성화된 경우, 해제되지 않은 네이티브 그래픽 리소스에 대해 경고를 표시합니다. 마찬가지로, Direct 3D의 경우 애플리케이션이 QRhi와 그 리소스를 올바른 순서대로 파괴하지 않으면 해제되지 않은 COM 객체에 대한 경고가 출력될 수 있습니다.
관련 항목: RHI 창 예제, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture, QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget, QRhiGraphicsPipeline, QRhiComputePipeline 및 QRhiSwapChain.
멤버 유형 문서
[alias, since 6.10] QRhi::AdapterList
QVector 의 동의어 <QRhiAdapter *>.
이 typedef는 Qt 6.10에서 도입되었습니다.
enum QRhi::BeginFrameFlag
flags QRhi::BeginFrameFlags
QRhi::beginFrame()의 플래그 값
BeginFrameFlags 유형은 QFlags<BeginFrameFlag>에 대한 typedef입니다. 이 유형은 BeginFrameFlag 값들의 OR 조합을 저장합니다.
enum QRhi::EndFrameFlag
flags QRhi::EndFrameFlags
QRhi::endFrame()의 플래그 값
| 상수 | 값 | 설명 |
|---|---|---|
QRhi::SkipPresent | 1 << 0 | 현재 명령을 큐에 넣지 않거나 swapBuffers 호출을 수행하지 않도록 지정합니다. 이렇게 하면 이미지가 표시되지 않습니다. 이 플래그가 모두 설정된 여러 프레임을 생성하는 것은 권장되지 않습니다(예를 들어 벤치마킹 목적의 경우는 예외이지만, 프레임을 표시하지 않은 상태에서 명령어 완료를 기다릴 때 백엔드마다 동작 방식이 다를 수 있으므로 결과 간 비교가 불가능할 수 있다는 점을 유의하십시오). |
EndFrameFlags 유형은 QFlags<EndFrameFlag>에 대한 typedef입니다. 이 유형은 EndFrameFlag 값들의 OR 조합을 저장합니다.
enum QRhi::Feature
현재 사용 중인 백엔드에서 어떤 기능을 지원하는지 나타내는 플래그 값입니다.
| 상수 | 값 | 설명 |
|---|---|---|
QRhi::MultisampleTexture | 1 | 샘플 수가 1보다 큰 텍스처가 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL ES 3.1 이전 버전과 OpenGL 3.0 이전 버전에서는 지원되지 않습니다. |
QRhi::MultisampleRenderBuffer | 2 | 샘플 수가 1보다 큰 렌더 버퍼가 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL ES 2.0에서는 지원되지 않으며, 관련 확장 기능이 없는 한 OpenGL 2.x에서도 지원되지 않을 수 있습니다. |
QRhi::DebugMarkers | 3 | 디버그 마커 그룹(따라서 ` QRhiCommandBuffer::debugMarkBegin()`)이 지원됨을 나타냅니다. |
QRhi::Timestamps | 4 | 커맨드 버퍼 타임스탬프가 지원됨을 나타냅니다. QRhiCommandBuffer::lastCompletedGpuTime()과 관련이 있습니다. 이 기능은 Metal, Vulkan, Direct 3D 11 및 12, 그리고 버전 3.3 이상의 OpenGL 컨텍스트에서 지원될 것으로 예상됩니다. 그러나 이러한 API 중 일부에서는 타임스탬프 쿼리 지원이 기술적으로 선택 사항이므로, 해당 API의 모든 구현에서 이 기능이 항상 지원된다고 보장할 수는 없습니다. |
QRhi::Instancing | 5 | 인스턴스 드로잉이 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL ES 2.0 및 OpenGL 3.2 이하에서는 지원되지 않습니다. |
QRhi::CustomInstanceStepRate | 6 | 1 이외의 인스턴스 단계 비율이 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL에서는 항상 지원되지 않습니다. 또한, VK_EXT_vertex_attribute_divisor 없이 Vulkan 1.0을 실행하는 경우에도 이 기능에 대해 false로 보고됩니다. |
QRhi::PrimitiveRestart | 7 | 0xFFFF(IndexUInt16) 또는 0xFFFFFFFF(IndexUInt32) 인덱스 값이 발견될 때, 적어도 특정 프리미티브 토폴로지에 대해서는 프리미티브 조립 재시작이 활성화되어 있음을 나타냅니다. ` QRhi `는 모든 백엔드에서 이 기능을 활성화하려고 시도하지만, 경우에 따라 지원되지 않을 수 있습니다. 일부 API에서는 고정 인덱스를 사용하는 프리미티브 재시작이 항상 활성화되어 있으므로, 프리미티브 재시작을 동적으로 제어하는 것은 불가능합니다. 애플리케이션은 이 기능이 지원된다고 보고될 때마다, 토폴로지에 따라 앞서 언급한 인덱스 값 may 이 특별하게 처리된다고 가정해야 합니다. 이 기능이 지원된다고 보고되는 한, 모든 백엔드에서 프리미티브 재시작이 동일하게 작동하는 것이 보장되는 유일한 두 가지 토폴로지는 LineStrip 및 TriangleStrip 입니다. |
QRhi::NonDynamicUniformBuffers | 8 | UniformBuffer 을 사용하고 Immutable 또는 Static 유형으로 버퍼를 생성하는 것이 지원됨을 나타냅니다. 지원되지 않는 것으로 보고된 경우, 균일(상수) 버퍼는 Dynamic 형식으로 생성되어야 합니다. (어쨌든 권장되는 방식입니다) |
QRhi::NonFourAlignedEffectiveIndexBufferOffset | 9 | 4바이트 정렬되지 않은 유효 인덱스 버퍼 오프셋(indexOffset + firstIndex * indexComponentSize)이 지원됨을 나타냅니다. 지원되지 않는 경우, 정렬되지 않은 유효 오프셋을 사용하여 drawIndexed()을 호출하려고 하면 정의되지 않은 동작이 발생할 수 있습니다. 특히 Metal의 경우, 이 기능이 지원되지 않는 것으로 보고되므로 관련성이 높습니다. |
QRhi::NPOTTextureRepeat | 10 | 2의 거듭제곱 크기가 아닌 텍스처에 대해 Repeat 랩 모드 및 밉맵 필터링 모드가 지원됨을 나타냅니다. 실제로 이 값이 false일 수 있는 경우는 GL_OES_texture_npot 가 없는 OpenGL ES 2.0 구현체뿐입니다. |
QRhi::RedOrAlpha8IsRed | 11 | RED_OR_ALPHA8 형식이 단일 구성 요소 8비트 red 형식으로 매핑됨을 나타냅니다. 이는 OpenGL ES 또는 비코어 프로파일 컨텍스트를 사용할 때 OpenGL을 제외한 모든 백엔드에 해당합니다. 이 경우 GL_ALPHA, 즉 1개 컴포넌트의 8비트 alpha 형식이 대신 사용됩니다. 이 특수 텍스처 형식을 사용하면 텍스처 생성을 위한 단일 코드 경로를 유지할 수 있으며, 실제 형식 결정은 백엔드에 맡기고, 기능 플래그를 사용하여 텍스처 샘플링에 적합한 셰이더 변형을 선택할 수 있습니다. |
QRhi::ElementIndexUint | 12 | 인덱스 버퍼에서 32비트 부호 없는 정수 요소가 지원됨을 나타냅니다. 실제로는 필요한 확장 기능이 없는 일반 OpenGL ES 2.0 구현 환경에서 실행되는 경우를 제외하고는 모든 환경에서 이 설정이 적용됩니다. false인 경우, 인덱스 버퍼에서는 16비트 부호 없는 정수 요소만 지원됩니다. |
QRhi::Compute | 13 | 컴퓨트 셰이더, 이미지 로드/저장 및 스토리지 버퍼가 지원됨을 나타냅니다. OpenGL 4.3 이전 버전과 OpenGL ES 3.1 이전 버전은 컴퓨트 기능을 지원하지 않습니다. |
QRhi::WideLines | 14 | 폭이 1이 아닌 선이 지원됨을 나타냅니다. 지원되지 않는 것으로 보고될 경우, 그래픽 파이프라인 상태에 설정된 선 폭은 무시됩니다. 일부 백엔드(D3D11, D3D12, Metal)에서는 이 값이 항상 false일 수 있습니다. Vulkan의 경우, 이 값은 구현에 따라 다릅니다. OpenGL의 경우, 코어 프로파일 컨텍스트에서는 넓은 선이 지원되지 않습니다. |
QRhi::VertexShaderPointSize | 15 | 버텍스 셰이더에서 ` gl_PointSize `을 통해 설정된 래스터화 점의 크기가 고려됨을 나타냅니다. 지원되지 않는 것으로 보고될 경우, 크기가 1이 아닌 점을 그리는 것은 지원되지 않습니다. 이 경우에도 셰이더에서 ` gl_PointSize `을 설정하는 것은 유효하지만 무시됩니다. (예를 들어, HLSL을 생성할 때, 해당 할당 문은 생성된 코드에서 아무런 메시지 없이 생략됩니다) 일부 API(Metal, Vulkan)의 경우, 크기가 1일 때라도 자동으로 1로 기본 설정되지 않으므로, 점을 그릴 때마다 셰이더에서 점 크기를 명시적으로 설정해야 한다는 점에 유의하십시오. |
QRhi::BaseVertex | 16 | drawIndexed()가 vertexOffset 인수를 지원함을 나타냅니다. 지원되지 않는 것으로 보고된 경우, 인덱스 드로우에서 vertexOffset 값은 무시됩니다. 실제로 이 기능은 OpenGL 및 OpenGL ES 3.2 미만 버전과, iOS 시뮬레이터를 포함한 구형 iOS 기기의 Metal에서는 지원되지 않습니다. |
QRhi::BaseInstance | 17 | 인스턴스화된 드로우 명령이 firstInstance 인수를 지원함을 나타냅니다. 지원되지 않는 것으로 보고될 경우, firstInstance 값은 무시되고 인스턴스 ID는 0부터 시작합니다. 실제로 이 기능은 iOS 시뮬레이터를 포함한 구형 iOS 기기의 Metal 및 모든 버전의 OpenGL에서는 지원되지 않습니다. 후자의 경우, OpenGL ES가 기본 인스턴스가 포함된 드로우 호출을 전혀 지원하지 않기 때문입니다. 현재 QRhi 의 OpenGL 백엔드 역시 OpenGL(비-ES)에 대한 이 기능을 구현하지 않습니다. 이는 GLES로 인해 포터블 애플리케이션이 실제로 0이 아닌 기본 인스턴스에 의존할 수 없기 때문입니다. 애플리케이션에서 여전히 이를 사용하기로 선택한 경우, InstanceIndexIncludesBaseInstance 기능도 함께 고려해야 합니다. |
QRhi::TriangleFanTopology | 18 | QRhiGraphicsPipeline::setTopology()가 QRhiGraphicsPipeline::TriangleFan 를 지원함을 나타냅니다. 실제로 이 기능은 Metal 및 Direct 3D 11/12에서는 지원되지 않습니다. |
QRhi::ReadBackNonUniformBuffer | 19 | reading buffer contents 가 UniformBuffer와 다른 용도로 사용되는 QRhiBuffer 인스턴스에 대해 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL ES 2.0에서는 지원되지 않습니다. |
QRhi::ReadBackNonBaseMipLevel | 20 | 텍스처 내용을 다시 읽을 때 0 이외의 mip 레벨을 지정하는 것이 지원됨을 나타냅니다. 지원되지 않는 경우, QRhiReadbackDescription 에서 0이 아닌 레벨을 지정하면 모든 픽셀이 0인 이미지가 반환됩니다. 실제로 이 기능은 OpenGL ES 2.0에서는 지원되지 않습니다. |
QRhi::TexelFetch | 21 | 셰이더에서 texelFetch() 및 textureLod()를 사용할 수 있음을 나타냅니다. 실제로는 GLSL 100 es 및 130 이전 버전이 이러한 함수를 지원하지 않기 때문에, OpenGL ES 2.0 및 OpenGL 2.x 컨텍스트에서는 이 기능이 지원되지 않는 것으로 보고됩니다. |
QRhi::RenderToNonBaseMipLevel | 22 | QRhiTexture 를 색상 부착물로 사용하는 QRhiTextureRenderTarget 를 생성할 때 0 이외의 mip 레벨을 지정하는 것이 지원됨을 나타냅니다. 지원되지 않는 경우, 대상 mip 레벨이 0이 아닐 때마다 create() 호출이 실패합니다. 실제로 이 기능은 OpenGL ES 2.0에서는 지원되지 않습니다. |
QRhi::IntAttributes | 23 | 셰이더 파이프라인에 부호 있는 및 부호 없는 정수 유형의 입력 속성을 지정하는 것이 지원됨을 나타냅니다. 지원되지 않는 경우, ` QRhiGraphicsPipeline::create()` 함수는 성공하되 경고 메시지가 표시되며 대상 속성의 값은 올바르지 않게 됩니다. 실제로 이 기능은 OpenGL ES 2.0 및 OpenGL 2.x에서는 지원되지 않습니다. |
QRhi::ScreenSpaceDerivatives | 24 | dFdx(), dFdy(), fwidth()와 같은 함수가 셰이더에서 지원됨을 나타냅니다. 실제로 이 기능은 GL_OES_standard_derivatives 확장 기능이 없는 OpenGL ES 2.0에서는 지원되지 않습니다. |
QRhi::ReadBackAnyTextureFormat | 25 | QRhiTexture::Format 에 대해 텍스처 내용을 다시 읽어오는 기능이 정상적으로 작동할 것으로 예상됨을 나타냅니다. OpenGL 이외의 백엔드에서는 이 기능에 대해 true를 반환할 것으로 예상됩니다. false로 보고될 경우(일반적으로 OpenGL에서 발생함), QRhiTexture::RGBA8 및 QRhiTexture::BGRA8 형식만 다시 읽어오기가 보장됩니다. 또한, OpenGL ES는 제외되지만 OpenGL의 경우, 구성 요소당 1바이트 형식인 QRhiTexture::R8 및 QRhiTexture::RED_OR_ALPHA8 의 리드백도 지원됩니다. OpenGL에서는 구현체가 이를 지원하는 한 QRhiTexture::RGBA16F 및 RGBA32F와 같은 부동 소수점 형식의 리드백도 작동할 수 있지만, 이 플래그에서 알 수 있듯이 QRhi 는 이를 보장할 수 없습니다. |
QRhi::PipelineCacheDataLoadSave | 26 | pipelineCacheData() 및 setPipelineCacheData() 함수가 정상적으로 작동함을 나타냅니다. 지원되지 않는 경우, 해당 함수는 아무런 동작도 수행하지 않으며, 검색된 blob은 항상 비어 있으므로, 파이프라인 캐시 내용을 검색하고 이후 애플리케이션 실행 시 이를 다시 불러오는 것에서 어떠한 이점도 기대할 수 없습니다. |
QRhi::ImageDataStride | 27 | 텍스처 업로드 시 원시 이미지 데이터에 대한 사용자 정의 스트라이드(행 길이) 지정이 지원됨을 나타냅니다. 지원되지 않는 경우(기본 API가 GL_UNPACK_ROW_LENGTH를 지원하지 않는 OpenGL ES 2.0인 경우 등), QRhiTextureSubresourceUploadDescription::setDataStride()를 사용해서는 안 됩니다. |
QRhi::RenderBufferImport | 28 | QRhiRenderBuffer::createFrom()이 지원됨을 나타냅니다. 대부분의 그래픽 API에서는 QRhiRenderBuffer 가 QRhiTexture 와 마찬가지로 텍스처 객체를 내부적으로 캡슐화하므로 이 기능은 의미가 없습니다. 그러나 OpenGL의 경우, 렌더버퍼 객체는 API 내에서 별도의 객체 유형으로 존재하며, 특정 환경(예를 들어, 렌더버퍼 객체를 EGLImage 객체와 연관시키고자 하는 경우)에서는 기존 OpenGL 렌더버퍼 객체를 QRhiRenderBuffer 로 래핑할 수 있도록 허용하는 것이 중요합니다. |
QRhi::ThreeDimensionalTextures | 29 | 3D 텍스처가 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL 및 OpenGL ES 3.0 미만의 버전에서는 지원되지 않습니다. |
QRhi::RenderTo3DTextureSlice | 30 | 3D 텍스처의 슬라이스로의 렌더링이 지원됨을 나타냅니다. 이는 Vulkan 1.1 기능인 VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT에 의존하기 때문에 Vulkan 1.0에서는 지원되지 않을 수 있습니다. |
QRhi::TextureArrays | 31 | 텍스처 배열이 지원되며 ` QRhi::newTextureArray()`가 정상 작동함을 나타냅니다. 텍스처 배열이 지원되지 않더라도 텍스처 배열은 여전히 사용할 수 있다는 점에 유의하십시오. 이는 두 기능이 서로 독립적이기 때문입니다. |
QRhi::Tessellation | 32 | 테셀레이션 제어 및 평가 단계가 지원됨을 나타냅니다. 지원되는 것으로 보고될 경우, QRhiGraphicsPipeline 의 토폴로지는 Patches 로 설정할 수 있으며, 제어점의 수는 setPatchControlPointCount()를 통해 설정할 수 있고, 테셀레이션 제어 및 평가를 위한 셰이더는 QRhiShaderStage 목록에 지정할 수 있습니다. 테셀레이션 셰이더는 API 간 이식성 문제가 있습니다(예를 들어, 헐 셰이더의 구조상 GLSL/SPIR-V를 HLSL로 변환하는 것은 문제가 되는 반면, Metal은 다른 API들과 다소 다른 테셀레이션 파이프라인을 사용합니다). 따라서 기본 기능은 모든 기반 API에 구현되어 있음에도 불구하고 예상치 못한 문제가 여전히 발생할 수 있습니다. 특히 Direct 3D의 경우, qsb가 SPIR-V로부터 이를 생성할 수 없기 때문에 테셀레이션 제어 및 평가 단계를 위해 각각 수작업으로 작성된 HLSL 헐(hull) 및 도메인(domain) 셰이더를 각 퀀타이제이션 블록( QShader )에 삽입해야 합니다. 모든 백엔드에서 지원되지 않으므로 등고선(isoline) 테셀레이션은 피해야 합니다. 백엔드 간에 호환되는 최대 패치 제어점 수는 32개입니다. |
QRhi::GeometryShader | 33 | 지오메트리 셰이더 단계가 지원됨을 나타냅니다. 지원되는 경우, QRhiShaderStage 목록에서 지오메트리 셰이더를 지정할 수 있습니다. 지오메트리 셰이더는 QRhi 에서 실험적 기능으로 간주되며, 실행 시점에 구현이 이를 지원한다고 보고하는 경우에만 Vulkan, Direct 3D 11 및 12, OpenGL (3.2+), OpenGL ES (3.2+)에서 지원될 것으로 예상할 수 있습니다. Qt 6.11부터 지오메트리 셰이더는 자동으로 HLSL로 변환되므로, 더 이상 수동으로 작성한 HLSL 지오메트리 셰이더를 삽입할 필요가 없습니다(단, gl_in 및 gl_in[0].gl_Position과 같은 표현식은 지원되지 않으므로, 대신, 위치를 버텍스 셰이더의 출력 변수로 전달해야 합니다). Metal에서는 지오메트리 셰이더가 지원되지 않습니다. |
QRhi::TextureArrayRange | 34 | texture arrays 의 경우, 셰이더에 노출될 범위를 지정할 수 있음을 나타냅니다. 일반적으로 모든 배열 레이어가 노출되며, 레이어 선택은 셰이더 측에서 결정합니다( sampler2DArray 를 샘플링할 때 texture()에 전달되는 세 번째 좌표를 통해). 지원되는 경우, building 또는 importing 호출 전에 QRhiTexture::setArrayRangeStart() 및 QRhiTexture::setArrayRangeLength()를 호출하면 네이티브 텍스처에 효과가 적용되어 배열에서 지정된 범위만 선택하게 됩니다. 이는 가속화된 비디오 디코딩 및 Direct 3D 11을 다룰 때와 같은 특수한 경우에 필요합니다. D3D11_BIND_DECODER 와 D3D11_BIND_SHADER_RESOURCE 가 모두 적용된 텍스처 배열은 단일 배열 레이어만 선택된 경우에만 셰이더 리소스로 사용할 수 있기 때문입니다. 이 모든 내용은 텍스처가 QRhiShaderResourceBinding::SampledTexture 또는 QRhiShaderResourceBinding::Texture 셰이더 리소스로 사용될 때에만 적용되며, 이미지 로드/저장(image load/store)과는 호환되지 않는다는 점에 유의하십시오. 이 기능은 모든 그래픽 API에 잘 매핑되지 않기 때문에 일부 백엔드에서만 사용할 수 있으며, 어쨌든 특수한 경우를 지원하기 위한 목적으로만 제공됩니다. 실제로 이 기능은 Direct3D 11/12 및 Vulkan에서 지원될 것으로 예상됩니다. |
QRhi::NonFillPolygonMode | 35 | QRhiGraphicsPipeline 에서 기본값인 Fill 이외의 PolygonMode 설정이 지원됨을 나타냅니다. 모드를 Line으로 변경하는 일반적인 사용 사례는 와이어프레임 렌더링을 얻는 것입니다. 그러나 이는 OpenGL ES의 핵심 기능으로 제공되지 않으며, Vulkan에서는 선택 사항이고 일부 모바일 GPU에서는 이 기능을 제공하지 않을 수 있습니다. |
QRhi::OneDimensionalTextures | 36 | 1차원(1D) 텍스처가 지원됨을 나타냅니다. 실제로 이 기능은 OpenGL ES에서는 지원되지 않습니다. |
QRhi::OneDimensionalTextureMipmaps | 37 | 1차원 텍스처 밉맵 생성이 지원됨을 나타냅니다. 실제로 이 기능은 OneDimensionalTextures, Metal 및 Direct 3D 12에 대한 지원을 보고하지 않는 백엔드에서는 지원되지 않습니다. |
QRhi::HalfAttributes | 38 | 셰이더 파이프라인에 대해 반정밀도(16비트) 부동소수점 유형으로 입력 속성을 지정하는 것이 지원됨을 나타냅니다. 지원되지 않는 경우, ` QRhiGraphicsPipeline::create()` 함수는 성공하지만 경고 메시지가 표시되며 대상 속성의 값은 올바르지 않게 됩니다. 실제로 이 기능은 일부 OpenGL ES 2.0 및 OpenGL 2.x 구현체에서 지원되지 않습니다. Direct3D 11/12는 반정밀도 입력 속성을 지원하지만, half3 유형은 지원하지 않는다는 점에 유의하십시오. D3D 백엔드는 half3 속성을 half4로 전달합니다. 크로스 플랫폼 호환성을 보장하려면 half3 입력을 8바이트로 패딩해야 합니다. |
QRhi::RenderToOneDimensionalTexture | 39 | 1차원 텍스처 렌더 타깃이 지원됨을 나타냅니다. 실제로 OneDimensionalTextures 지원을 보고하지 않는 백엔드와 Metal에서는 이 기능이 지원되지 않습니다. |
QRhi::ThreeDimensionalTextureMipmaps | 40 | 3D 텍스처 밉맵 생성이 지원됨을 나타냅니다. 이는 일반적으로 Qt 6.10부터 모든 백엔드에서 지원됩니다. |
QRhi::MultiView | 41 | 멀티뷰(예: VK_KHR_multiview 참조)가 지원됨을 나타냅니다. OpenGL ES 2.0, Direct 3D 11 및 ` GL_OVR_multiview2 `가 없는 OpenGL(ES) 구현체에서는 이 기능이 지원되지 않습니다. Vulkan 1.1 이상 및 Direct 3D 12에서는 일반적으로 멀티뷰가 지원됩니다. 지원되는 것으로 보고될 경우, 텍스처 배열을 참조하고 ` multiViewCount `가 설정된 ` QRhiColorAttachment `를 사용하여 ` QRhiTextureRenderTarget `를 생성하면 멀티뷰 렌더링을 사용하는 렌더 패스를 기록할 수 있습니다. 또한, 해당 렌더 패스에서 사용되는 모든 QRhiGraphicsPipeline 는 the same view count set 를 가져야 합니다. 멀티뷰는 2D 텍스처 배열과 함께 사용할 때만 사용할 수 있다는 점에 유의하십시오. 개별 텍스처(예: 왼쪽 눈과 오른쪽 눈을 위한 두 개의 텍스처)로 렌더링을 최적화하는 데는 사용할 수 없습니다. 오히려 멀티뷰 렌더 패스의 대상은 항상 텍스처 배열이며, 각 뷰에 해당하는 레이어(배열 요소)로 자동으로 렌더링됩니다. 따라서 이 기능은 텍스처 배열(TextureArrays)도 포함합니다. 멀티뷰 렌더링은 테셀레이션이나 지오메트리 셰이더와 함께 사용할 수 없습니다. 멀티뷰 렌더링에 대한 자세한 내용은 QRhiColorAttachment::setMultiViewCount()을 참조하십시오. 이 열거형 값은 Qt 6.7에서 도입되었습니다. |
QRhi::TextureViewFormat | 42 | QRhiTexture 에 view format 를 설정하는 것이 유효함을 나타냅니다. 지원되는 것으로 보고될 경우, 읽기(샘플링) 또는 쓰기(렌더 타깃/이미지 로드-스토어) 뷰 모드를 설정하면 텍스처의 뷰 형식이 변경됩니다. 지원되지 않을 경우, 뷰 형식을 설정해도 아무런 효과가 없습니다. Qt 3D API 및 그 구현에서 포맷 호환성이나 리소스 뷰 규칙에 대해 알지 못하며 제어할 수도 없다는 점에 유의하십시오. 부적합하거나 호환되지 않는 포맷을 전달하면 오류나 정의되지 않은 동작이 발생할 수 있습니다. 이 기능은 주로 셰이더 쓰기 시 원치 않는 선형(linear)→sRGB 변환을 피하기 위해, sRGB 형식으로 생성된 텍스처로의 렌더링을 비-sRGB로 “캐스팅”할 수 있도록 제공하기 위한 것입니다. 다른 유형의 캐스팅은 기본 API에 따라 작동할 수도 있고 그렇지 않을 수도 있습니다. 현재 Vulkan 및 Direct 3D 12에서 구현되어 있습니다. D3D12의 경우, 이 기능은 CastingFullyTypedFormatSupported 가 지원될 때만 사용할 수 있습니다. 자세한 내용은 https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html를 참조하십시오(단, QRhi 는 텍스처에 대해 항상 완전한 타입 지정 형식을 사용한다는 점에 유의하십시오). 이 열거형 값은 Qt 6.8에서 도입되었습니다. |
QRhi::ResolveDepthStencil | 43 | 멀티샘플 깊이(multisample depth) 또는 깊이-스텐실(depth-stencil) 텍스처의 해상도 조정이 지원됨을 나타냅니다. 그렇지 않은 경우, ` setting a depth resolve texture `는 작동하지 않으므로 사용을 피해야 합니다. Direct 3D 11 및 12는 깊이/깊이-스텐실 형식의 해상도 조정을 지원하지 않으므로, 해당 버전에서는 이 기능이 절대 지원되지 않습니다. Vulkan 1.0에는 뎁스-스텐실 어태치먼트의 해상도 조정을 요청하는 API가 없습니다. 따라서 Vulkan의 경우 이 기능은 Vulkan 1.2 이상에서만 지원되며, 1.1 구현체에서는 적절한 확장 기능이 존재할 때만 지원됩니다. 이 기능은 OpenXR에서 제공하는 깊이 텍스처(XR_KHR_composition_layer_depth)로 렌더링하는 경우와 같이, 멀티샘플이 아닌 깊이 텍스처로 해결해야 하는 드문 상황을 위해 제공됩니다. 이 열거형 값은 Qt 6.8에서 도입되었습니다. |
QRhi::VariableRateShading | 44 | 드로우별(파이프라인별) 가변 속도 셰이딩이 지원됨을 나타냅니다. 지원되는 것으로 보고될 경우, ` QRhiCommandBuffer::setShadingRate()` 함수가 작동하며, 플래그에서 ` QRhiGraphicsPipeline::UsesShadingRate `를 선언한 ` QRhiGraphicsPipeline ` 객체에 대해 효과가 있습니다. QRhi::supportedShadingRates()를 호출하여 어떤 비율이 지원되는지 확인하십시오. (1x1은 항상 지원되며, 그 외 일반적인 값으로는 2x2, 1x2, 2x1, 2x4, 4x2, 4x4가 있습니다). 실행 시점에 사용되는 구현 및 GPU가 VRS를 지원하는 경우, 이 기능은 Direct 3D 12 및 Vulkan에서 지원될 것으로 예상됩니다. 이 열거형 값은 Qt 6.9에서 도입되었습니다. |
QRhi::VariableRateShadingMap | 45 | 셰이딩 비율을 이미지 기반으로 지정할 수 있음을 나타냅니다. 여기서 “이미지”는 반드시 텍스처일 필요는 없으며, 런타임 시의 기본 백엔드 및 그래픽 API에 따라 네이티브 3D API 객체일 수도 있습니다. 실제로 이 기능은 GPU가 VRS를 지원할 만큼 최신 사양이라면 Direct 3D 12, Vulkan 및 Metal에서 지원될 것으로 예상됩니다. D3D12/Vulkan 스타일의 이미지 기반 VRS가 지원되는지 확인하려면 대신 VariableRateShadingMapWithTexture를 사용하십시오. 이 기능이 지원되는 것으로 보고될 경우 두 가지 가능성이 있습니다. VariableRateShadingMapWithTexture도 true인 경우, QRhiShadingRateMap 는 QRhiTexture 인수를 받는 createFrom() 오버로드를 통해 QRhiTexture 객체를 사용합니다. VariableRateShadingMapWithTexture가 false인 경우, QRhiShadingRateMap 는 다른 유형의 네이티브 객체를 사용합니다(예: Metal의 경우 MTLRasterizationRateMap). 이 경우 NativeShadingRateMap을 인수로 받는 createFrom() 오버로드를 사용하십시오. 이 열거형 값은 Qt 6.9에서 도입되었습니다. |
QRhi::VariableRateShadingMapWithTexture | 46 | 일반 텍스처를 통해 셰이딩 속도의 이미지 기반 지정이 지원됨을 나타냅니다. 실제로는 Direct 3D 12 및 Vulkan에서 지원될 수 있습니다. 이 열거형 값은 Qt 6.9에서 도입되었습니다. |
QRhi::PerRenderTargetBlending | 47 | 렌더 타겟별 블렌딩이 지원됨을 나타냅니다. 즉, MRT 프레임버퍼 내의 서로 다른 렌더 타겟에 서로 다른 블렌딩 모드를 적용할 수 있습니다. 실제로는 OpenGL ES를 제외한 모든 환경에서 지원될 것으로 예상되며, OpenGL ES의 경우 GLES 3.2 구현에서만 사용할 수 있습니다. 이 열거형 값은 Qt 6.9에서 도입되었습니다. |
QRhi::SampleVariables | 48 | gl_SampleID, gl_SamplePosition, gl_SampleMaskIn 및 gl_SampleMask 변수가 프래그먼트 셰이더에서 사용할 수 있음을 나타냅니다. 실제로는 OpenGL ES를 제외한 모든 환경에서 지원될 것으로 예상되며, OpenGL ES에서는 GLES 3.2 구현에서만 사용할 수 있습니다. 이 열거형 값은 Qt 6.9에서 도입되었습니다. |
QRhi::InstanceIndexIncludesBaseInstance | 49 | gl_InstanceIndex 의 값에 기본 인스턴스(드로우 호출의 ` firstInstance ` 인자)가 포함됨을 나타냅니다. 이 기능이 지원되지 않지만 `BaseInstance`는 지원되는 경우, ` gl_InstanceIndex `는 기본값이 아닌 항상 0부터 시작함을 나타냅니다. 실제로 현재 Direct 3D 11 및 12의 경우 이러한 현상이 발생합니다. Vulkan 및 Metal의 경우 이 기능은 항상 지원되는 것으로 보고될 것으로 예상됩니다. 이 열거형 값은 Qt 6.11에서 도입되었습니다. |
QRhi::DepthClamp (since Qt 6.11) | 50 | 깊이 클램핑(depth clamping) 활성화가 지원됨을 나타냅니다. 지원되지 않는 것으로 보고되는 경우(OpenGL ES, 관련 확장 기능이 없는 OpenGL 3.2 이전 버전, iOS 시뮬레이터상의 Metal에서 해당됨), true 을 인수로 전달하여 QRhiGraphicsPipeline::setDepthClamp()를 호출해도 아무런 효과가 없습니다. |
QRhi::DrawIndirect (since Qt 6.12) | 51 | drawIndirect() 및 drawIndexedIndirect() 함수를 사용할 수 있음을 나타냅니다. 실제로는 OpenGL ES 3.1 미만을 제외한 모든 환경에서 지원될 것으로 예상됩니다. |
QRhi::DrawIndirectMulti (since Qt 6.12) | 52 | drawIndirect() 및 drawIndexedIndirect()에서 백엔드가 drawCount > 1을 네이티브로 지원함을 나타냅니다. 그렇지 않은 경우, RHI에 의해 CPU에서 여러 개의 드로우 호출이 발행됩니다. 실제로는 Vulkan 1.1 이상, OpenGL 4.3 이상 및 D3D12에서 지원될 것으로 예상됩니다. |
QRhi::ShaderDrawParameters (since Qt 6.12) | 53 | gl_BaseInstance, gl_BaseVertex 및 gl_DrawID 내장 변수를 셰이더에서 사용할 수 있음을 나타냅니다. 실제로는 Vulkan 1.1 이상 및 데스크톱용 OpenGL 4.6( GL_ARB_shader_draw_parameters)에서 지원될 것으로 예상됩니다. |
enum QRhi::Flag
flags QRhi::Flags
활성화할 특수 기능을 설명합니다.
| 상수 | 값 | 설명 |
|---|---|---|
QRhi::EnableDebugMarkers | 1 << 0 | 디버그 마커 그룹을 활성화합니다. 이 설정이 없으면 외부 GPU 디버깅 도구에서 디버그 그룹 및 사용자 정의 리소스 이름을 표시하는 등의 프레임 디버깅 기능을 사용할 수 없으며, QRhiCommandBuffer::debugMarkBegin()와 같은 함수는 아무 작업도 수행하지 않게 됩니다. 성능에 약간의 영향을 미칠 수 있으므로 프로덕션 빌드에서는 활성화하지 마십시오. QRhi::DebugMarkers 기능이 지원되는 것으로 보고되지 않은 경우에는 효과가 없습니다. |
QRhi::EnableTimestamps | 1 << 3 | GPU 타임스탬프 수집을 활성화합니다. 설정되지 않은 경우, ` QRhiCommandBuffer::lastCompletedGpuTime()`는 항상 0을 반환합니다. 기본 그래픽 API에 따라 소량의 추가 작업(예: 타임스탬프 쿼리)이 발생할 수 있으므로, 필요한 경우에만 이 기능을 활성화하십시오. ` QRhi::Timestamps ` 기능이 지원되지 않는 것으로 보고된 경우에는 효과가 없습니다. |
QRhi::PreferSoftwareRenderer | 1 << 1 | 백엔드가 CPU에서 소프트웨어 방식으로 렌더링하는 어댑터나 물리적 장치를 우선적으로 선택해야 함을 나타냅니다. 예를 들어, Direct3D의 경우 일반적으로 DXGI_ADAPTER_FLAG_SOFTWARE 를 지원하는 “Basic Render Driver” 어댑터가 있습니다. 이 플래그를 설정하면, 다른 백엔드 특정 수단에 의해 특정 어댑터가 강제 지정되지 않는 한, 백엔드가 다른 어떤 어댑터보다 해당 어댑터를 선택하도록 요청합니다. Vulkan의 경우, 이는 VK_PHYSICAL_DEVICE_TYPE_CPU 를 통해 물리적 장치를 우선적으로 선택하도록 매핑됩니다. 해당 옵션이 없거나 어댑터/장치가 소프트웨어 기반인지 판단할 수 없는 경우, 이 플래그는 무시됩니다. 또한 어댑터/장치를 열거하는 개념이나 수단이 없는 그래픽 API의 경우에도 이 플래그가 무시될 수 있습니다. |
QRhi::EnablePipelineCacheDataSave | 1 << 2 | 해당되는 경우 파이프라인 캐시 내용을 가져올 수 있도록 합니다. 이 플래그가 설정되지 않은 경우, ` pipelineCacheData()`는 항상 빈 블롭을 반환합니다. 파이프라인 캐시 내용의 가져오기 및 복원이 지원되지 않는 백엔드의 경우, 이 플래그는 효과가 없으며 직렬화된 캐시 데이터는 항상 비어 있습니다. 일부 백엔드에서는 관련 데이터 구조를 유지하는 데 상당한 비용이 소요되므로, 이 플래그는 선택적 활성화 메커니즘을 제공합니다. Vulkan의 경우 이 기능은 VkPipelineCache, vkGetPipelineCacheData 및 VkPipelineCacheCreateInfo::pInitialData에 직접 대응합니다. Direct3D 11의 경우 실제 파이프라인 캐시는 없지만, HLSL→DXBC 컴파일 결과가 저장되며 이 메커니즘을 통해 직렬화/역직렬화할 수 있습니다. 이를 통해 오프라인에서 미리 컴파일된 바이트코드 대신 HLSL 소스 코드가 포함된 셰이더의 경우, 향후 애플리케이션 실행 시 시간이 많이 소요되는 D3DCompile() 호출을 건너뛸 수 있습니다. HLSL 소스 컴파일이 많이 발생하는 경우, 이는 시작 및 로딩 시간을 대폭 단축시켜 줄 수 있습니다. OpenGL의 경우, 드라이버에서 지원하는 경우 셰이더 프로그램 바이너리를 가져와 로드함으로써 “파이프라인 캐시”를 시뮬레이션합니다. Qt OpenGL의 경우, 셰이더/프로그램 바이너리를 위한 추가적인 디스크 기반 캐싱 메커니즘이 있습니다. 프로그램 바이너리를 여러 캐시에 저장하는 것은 합리적이지 않으므로, 이 플래그가 설정되면 해당 캐시에 대한 쓰기 작업이 비활성화될 수 있습니다. |
QRhi::SuppressSmokeTestWarnings | 1 << 4 | 이 플래그가 관련이 있는 백엔드에서, 특정 비치명적 QRhi::create() 오류가 qWarning() 호출을 발생시키지 않도록 함을 나타냅니다. 예를 들어, D3D11의 경우 이 플래그를 전달하면 QRhi::create() 실패로 인해 나타나는 여러 경고 메시지가, 대신 일반적으로 사용되는 qt.rhi.general 로깅 범주 아래의 디버그 출력 범주로 분류됩니다. 이는 Qt Quick 와 같이 대체 로직을 지원하는 엔진에서 사용할 수 있습니다. 즉, 첫 번째 create() 호출이 실패했을 때 출력될 무조건적인 경고 메시지를 숨기기 위해, 다른 플래그 세트(예: PreferSoftwareRenderer)를 사용하여 create() 호출을 재시도하는 방식입니다. |
Flags 유형은 QFlags<Flag>에 대한 typedef입니다. 이 유형은 Flag 값들의 OR 조합을 저장합니다.
enum QRhi::FrameOpResult
소프트 오류가 발생할 수 있는 연산의 결과를 설명합니다.
| 상수 | 값 | 설명 |
|---|---|---|
QRhi::FrameOpSuccess | 0 | 성공 |
QRhi::FrameOpError | 1 | 명시되지 않은 오류 |
QRhi::FrameOpSwapChainOutOfDate | 2 | 스왑 체인이 내부적으로 일관성이 없는 상태입니다. 나중에 해당 작업(예: ` beginFrame()`)을 다시 시도하면 복구될 수 있습니다. |
QRhi::FrameOpDeviceLost | 3 | 그래픽스 장치가 손실되었습니다. 네이티브 그래픽스 리소스를 기반으로 하는 모든 객체를 해제하고 재초기화한 후, 해당 작업(예: beginFrame())을 다시 시도하면 복구될 수 있습니다. isDeviceLost()을 참조하십시오. |
enum QRhi::Implementation
QRhi 인스턴스에서 어떤 그래픽 API 전용 백엔드가 사용되는지 설명합니다.
| 상수 | 값 |
|---|---|
QRhi::Null | 0 |
QRhi::Vulkan | 1 |
QRhi::OpenGLES2 | 2 |
QRhi::D3D11 | 3 |
QRhi::D3D12 | 5 |
QRhi::Metal | 4 |
enum QRhi::ResourceLimit
쿼리할 리소스 제한을 설명합니다.
| 상수 | 값 | 설명 |
|---|---|---|
QRhi::TextureSizeMin | 1 | 최소 텍스처 너비 및 높이. 일반적으로 1입니다. 최소 텍스처 크기는 유연하게 처리되는데, 즉 크기가 비어 있는 텍스처를 생성하려고 시도하면 대신 최소 크기의 텍스처가 생성됩니다. |
QRhi::TextureSizeMax | 2 | 텍스처의 최대 너비와 높이입니다. 이는 그래픽 API에 따라 다르며, 경우에 따라 플랫폼이나 구현 방식에 따라 달라질 수도 있습니다. 일반적으로 값은 4096~16384 범위입니다. 이보다 큰 텍스처를 생성하려고 하면 실패할 것으로 예상됩니다. |
QRhi::MaxColorAttachments | 3 | 다중 렌더 타겟( QRhiTextureRenderTarget)이 지원되는 경우, 렌더 타겟당 허용되는 색상 어태치먼트의 최대 개수입니다. MRT가 지원되지 않을 경우 값은 1입니다. 그렇지 않은 경우 일반적으로 8이지만, OpenGL은 최소값으로 4만을 의무화하고 있으며 일부 OpenGL ES 구현체에서는 이 값만 제공한다는 점에 유의해야 합니다. |
QRhi::FramesInFlight | 4 | 백엔드가 "처리 중"으로 유지할 수 있는 프레임 수입니다. Vulkan이나 Metal과 같은 백엔드의 경우, 새로운 프레임을 시작할 때 CPU가 GPU보다 이미 N - 1 프레임 앞서 있는 것을 감지하면(프레임 번호 current - N 에서 제출된 명령 버퍼가 아직 완료되지 않았기 때문), QRhi 가 이를 차단할 책임이 있습니다. 값 N은 여기서 반환되는 값이며, 일반적으로 2입니다. 이는 그래픽 API를 통해 직접 렌더링을 수행하는 애플리케이션과 관련이 있을 수 있는데, 이러한 렌더링 코드는 QRhi 백엔드 자체와 마찬가지로 버퍼와 같은 리소스에 대해 이중(값이 2인 경우) 버퍼링을 수행하고자 할 수 있기 때문입니다. 현재 프레임 슬롯 인덱스(0, 1, …, N-1 순서로 증가하다가 다시 0으로 돌아가는 값)는 ` QRhi::currentFrameSlot()`에서 가져올 수 있습니다. 그래픽 API가 명령어 제출 과정에 대해 이러한 저수준 제어를 제공하지 않는 백엔드의 경우 이 값은 1입니다. 이 값이 1인 경우에도 파이프라인 처리가 여전히 발생할 수 있다는 점에 유의하십시오(예를 들어, D3D11과 같은 일부 백엔드는 파이프라인을 중단시키지 않는 균일 버퍼 업데이트 전략을 사용하는 등 이를 활성화하도록 설계되어 있습니다). 그러나 이는 QRhi 에 의해 제어되지 않으므로, API 상에서는 반영되지 않습니다. |
QRhi::MaxAsyncReadbackFrames | 5 | starting a new frame 가 호출되었을 때 비동기 텍스처 또는 버퍼 리드백이 완료될 것이 보장되는 submitted 프레임 수(리드백을 포함하는 프레임 포함). |
QRhi::MaxThreadGroupsPerDimension | 6 | 디스패치할 수 있는 컴퓨트 워크/스레드 그룹의 최대 수입니다. 실질적으로 QRhiCommandBuffer::dispatch()의 인자에 대한 최대값입니다. 일반적으로 65535입니다. |
QRhi::MaxThreadsPerThreadGroup | 7 | 단일 로컬 워크 그룹 내의 최대 호출 횟수, 즉 다른 용어로 표현하면 스레드 그룹 내의 최대 스레드 수입니다. 실질적으로 컴퓨트 셰이더 내의 local_size_x, local_size_y 및 local_size_z 의 곱에 대한 최대 값입니다. 일반적인 값은 128, 256, 512, 1024 또는 1536입니다. OpenGL ES와 Vulkan 모두 구현에 필요한 최소 한도로 128만을 명시하고 있으므로 주의해야 합니다. Vulkan에서는 드문 경우이지만, 모바일/임베디드 기기용 일부 OpenGL ES 3.1 구현체는 사양에서 요구하는 최소값만 지원하기도 합니다. |
QRhi::MaxThreadGroupX | 8 | X 차원에서의 워크/스레드 그룹의 최대 크기입니다. 실질적으로 컴퓨트 셰이더 내의 ` local_size_x `의 최대 값에 해당합니다. 일반적으로 256 또는 1024입니다. |
QRhi::MaxThreadGroupY | 9 | Y 차원에서의 워크/스레드 그룹의 최대 크기입니다. 실질적으로 컴퓨트 셰이더에서 ` local_size_y `의 최대 값에 해당합니다. 일반적으로 256 또는 1024입니다. |
QRhi::MaxThreadGroupZ | 10 | Z 차원에서의 워크/스레드 그룹의 최대 크기입니다. 실질적으로 컴퓨트 셰이더에서 ` local_size_z `의 최대 값에 해당합니다. 일반적으로 64 또는 256입니다. |
QRhi::TextureArraySizeMax | 11 | 텍스처 배열의 최대 크기입니다. 일반적으로 256~2048 범위입니다. 이보다 더 많은 요소를 사용하여 ` create a texture array `을 시도하면 실패할 가능성이 높습니다. |
QRhi::MaxUniformBufferRange | 12 | 유니폼 버퍼에서 셰이더로 한 번에 노출할 수 있는 바이트 수입니다. OpenGL ES 2.0 및 3.0 구현에서는 이 값이 3584바이트(4개 성분, 성분당 32비트 벡터 224개)까지 낮을 수 있습니다. 그 외의 경우 값은 일반적으로 16384(vec4 1024개) 또는 65536(vec4 4096개)입니다. |
QRhi::MaxVertexInputs | 13 | 버텍스 셰이더로 전달되는 입력 속성의 수입니다. QRhiVertexInputAttribute 내의 위치는 [0, MaxVertexInputs-1] 범위 내에 있어야 합니다. OpenGL ES 2.0에서는 이 값이 8까지 낮을 수 있습니다. 그 외의 경우, 일반적인 값은 16, 31 또는 32입니다. |
QRhi::MaxVertexOutputs | 14 | 버텍스 셰이더의 최대 출력 수(4성분 벡터 out 변수). OpenGL ES 2.0에서는 이 값이 8까지 낮을 수 있으며, OpenGL ES 3.0 및 일부 Metal 장치에서는 15까지 낮을 수 있습니다. 그 외의 경우, 일반적인 값은 32입니다. |
QRhi::ShadingRateImageTileSize | 15 | 셰이딩 레이트 텍스처의 타일 크기입니다. QRhi::VariableRateShadingMapWithTexture 기능이 지원되지 않는 경우 0입니다. 그렇지 않은 경우 16과 같은 값이 사용되며, 이는 예를 들어 16x16 타일 크기를 나타냅니다. (R8UI) 셰이딩 레이트 텍스처의 각 바이트는 16x16 픽셀 타일에 대한 셰이딩 레이트를 정의합니다. 자세한 내용은 QRhiShadingRateMap 를 참조하십시오. |
멤버 함수 설명서
[noexcept] QRhi::~QRhi()
소멸자. 백엔드를 소멸시키고 리소스를 해제합니다.
void QRhi::addCleanupCallback(const QRhi::CleanupCallback &callback)
QRhi 가 소멸될 때 호출되는 callback 를 등록합니다.
이 콜백은 그래픽 리소스가 여전히 사용 가능한 상태에서 실행되므로, 애플리케이션이 QRhi 에 속한 QRhiResource 인스턴스를 깔끔하게 해제할 수 있는 기회를 제공합니다. 이는 특히 cache 유형의 객체에 저장된 리소스의 수명 주기를 관리하는 데 유용하며, 이 경우 캐시에는 QRhiResources 또는 QRhiResources를 포함하는 객체가 저장됩니다.
~QRhi()도 참조하십시오 .
void QRhi::addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
QRhi 가 소멸될 때 호출될 콜백 함수 ` callback `를 등록합니다. 이 오버로드는 불투명한 포인터 ` key`를 인수로 받으며, 이 포인터는 주어진 콜백이 단 한 번만 등록(그리고 호출)되도록 보장하는 데 사용됩니다.
이 함수는 오버로드된 함수입니다.
removeCleanupCallback()도 참조하십시오 .
QRhi::Implementation QRhi::backend() const
이 QRhi 의 백엔드 유형을 반환합니다.
const char *QRhi::backendName() const
이 QRhi 에 대한 백엔드 유형을 문자열로 반환합니다.
[static] const char *QRhi::backendName(QRhi::Implementation impl)
백엔드 impl 의 친숙한 이름을 반환합니다. 일반적으로는 사용 중인 3D API의 이름입니다.
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {})
swapChain 의 다음 사용 가능한 버퍼를 대상으로 하는 새 프레임을 시작합니다.
프레임은 리소스 업데이트와 하나 이상의 렌더링 및 컴퓨팅 패스로 구성됩니다.
flags 특정 특수한 경우를 나타낼 수 있습니다.
스왑 체인을 사용하여 QWindow 에 렌더링하는 고수준 패턴은 다음과 같습니다.
- 스왑 체인을 생성합니다.
- 표면 크기가 이전과 다를 때마다 QRhiSwapChain::createOrResize()를 호출합니다.
- QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed 에서 QRhiSwapChain::destroy()을 호출합니다.
- 그런 다음 매 프레임마다:
beginFrame(sc); updates = nextResourceUpdateBatch(); updates->... QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer(); cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates); ... cb->endPass(); ... // more passes as necessary endFrame(sc);
성공 시 ` QRhi::FrameOpSuccess `을 반환하고, 실패 시 다른 ` QRhi::FrameOpResult ` 값을 반환합니다. 이 중 일부는 "나중에 다시 시도" 유형의 경미한 오류로 취급해야 합니다. ` QRhi::FrameOpSwapChainOutOfDate `가 반환되면, ` QRhiSwapChain::createOrResize()`를 호출하여 스왑 체인의 크기를 조정하거나 업데이트해야 합니다. 그런 다음 애플리케이션은 새로운 프레임을 생성하려고 시도해야 합니다. QRhi::FrameOpDeviceLost 는 그래픽 장치가 손실되었음을 의미하지만, QRhi 자체를 포함한 모든 리소스를 해제하고 모든 리소스를 다시 생성함으로써 복구될 수도 있습니다. 자세한 내용은 isDeviceLost()을 참조하십시오.
endFrame(), beginOffscreenFrame(), isDeviceLost()도 참조하십시오 .
QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags = {})
새로운 오프스크린 프레임을 시작합니다. ` cb`에 렌더링 명령을 기록하는 데 적합한 명령 버퍼를 제공합니다. ` flags `는 ` beginFrame()`와 마찬가지로 특정 특수한 경우를 나타내는 데 사용됩니다.
참고: *cb에 저장된 QRhiCommandBuffer 는 호출자가 소유하지 않습니다.
스왑체인 없이 렌더링하는 것도 가능합니다. 일반적인 사용 사례는 완전히 오프스크린 애플리케이션에서 사용하는 것으로, 예를 들어 창을 전혀 표시하지 않고 렌더링 및 다시 읽기를 통해 이미지 시퀀스를 생성하는 경우입니다.
온스크린 애플리케이션(즉, beginFrame, endFrame, beginOffscreenFrame, endOffscreenFrame, beginFrame 등)에서도 사용할 수 있습니다.
texture 이나 buffer 리드백이 예약된 경우, 오프스크린 프레임은 GPU가 이전 프레임을 처리하는 동안 CPU가 다른 프레임을 생성할 가능성을 차단합니다. 이로 인해 리드백이 예약되어 있다면, endOffscreenFrame()이 반환될 때 결과가 보장된다는 부수적인 효과가 있습니다. 스왑체인(swapchain)을 대상으로 하는 프레임의 경우 상황은 다릅니다. 스왑체인을 사용하면 GPU 활용도가 잠재적으로 높아지지만, endFrame()는 endOffscreenFrame()과 달리 리드백 결과가 해당 시점에 사용 가능함을 보장하지 않기 때문에, 애플리케이션에서 리드백 작업을 다룰 때는 더 세심한 주의가 필요합니다.
스왑체인 없이 프레임을 렌더링한 후 프레임 내용을 다시 읽어오는 코드의 기본 구조는 다음과 같을 수 있습니다:
QRhiReadbackResult rbResult;
QRhiCommandBuffer *cb;
rhi->beginOffscreenFrame(&cb);
cb->beginPass(rt, colorClear, dsClear);
// ...
u = nextResourceUpdateBatch();
u->readBackTexture(rb, &rbResult);
cb->endPass(u);
rhi->endOffscreenFrame();
// image data available in rbResultendOffscreenFrame() 및 beginFrame()도 참조하십시오 .
QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
활성화된 QRhi 백엔드와 관계없이, 애플리케이션이 OpenGL용 정점 데이터 및 투시 투영 행렬(예: QMatrix4x4::perspective()에 의해 생성된 것들)을 계속 사용할 수 있도록 하는 행렬을 반환합니다.
일반적인 렌더러에서, 단순히 ` mvp` 대신 ` this_matrix * mvp `을 사용하면, 런타임에 어떤 백엔드(그리고 그래픽 API)가 사용될지 고려하지 않고도 Y 축이 위쪽을 향하는 정점 데이터와 깊이 범위 0~1의 뷰포트를 사용할 수 있습니다. 이렇게 하면 isYUpInNDC() 및 isClipDepthZeroToOne()에 기반한 분기 처리를 피할 수 있습니다(비록 특정 고급 그래픽 기술을 구현할 때는 이러한 로직이 여전히 필요할 수 있지만).
Vulkan 관점에서 이 주제에 대한 논의는 이 페이지를 참조하십시오.
[static] QRhi *QRhi::create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
impl 로 지정된 그래픽 API에 대한 백엔드와 지정된 flags 를 갖는 새로운 QRhi 인스턴스를 반환합니다. 함수 실행에 실패하면 nullptr 를 반환합니다.
params must는 QRhiInitParams 의 백엔드별 하위 클래스(예: QRhiVulkanInitParams, QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams, QRhiGles2InitParams) 중 하나의 인스턴스를 가리켜야 합니다. QRhi 생성 예제는 해당 클래스를 참조하십시오.
QRhi 설계상 어떠한 대체 로직도 구현하지 않습니다. 지정된 API를 초기화할 수 없는 경우, create()는 실패하며 백엔드에서 디버그 출력에 경고 메시지가 표시됩니다. 그러나 QRhi 의 클라이언트(예: Qt Quick)는 플랫폼에 따라 요청된 것과 다른 API로 대체할 수 있는 추가 로직을 제공할 수 있습니다. 나중에 create()를 호출했을 때 초기화가 성공할지 여부를 단순히 테스트하려는 목적이라면, create() 대신 probe()를 사용하는 것이 바람직합니다. 일부 백엔드에서는 create()가 인프라의 전체 초기화를 수행하여 QRhi 인스턴스가 즉시 버려질 경우 자원이 낭비되는 반면, probing은 create()보다 더 가벼운 방식으로 구현될 수 있기 때문입니다.
importDevice QRhi 가 자체적으로 생성하지 않고, 이미 존재하는 그래픽 장치를 사용할 수 있게 해줍니다. null이 아닐 경우, 이 매개변수는 의 하위 클래스 중 하나인 , , , , 의 인스턴스를 가리켜야 합니다. 정확한 세부 사항과 의미는 백엔드 및 기본 그래픽 API에 따라 다릅니다. QRhiNativeHandles QRhiVulkanNativeHandles QRhiD3D11NativeHandles QRhiD3D12NativeHandles QRhiMetalNativeHandles QRhiGles2NativeHandles
adapter 에서 QRhiAdapter 를 지정하면, QRhiVulkanNativeHandles 를 통해 VkPhysicalDevice 를 전달하거나 QRhiD3D12NativeHandles 를 통해 어댑터 LUID를 전달하는 대신, 투명하고 API 간 호환이 가능한 대안을 제공합니다. adapter 의 소유권은 확보되지 않습니다. 이 접근 방식에 대한 자세한 내용은 enumerateAdapters()을 참조하십시오.
참고: importDevice 와 adapter 를 동시에 지정할 수는 없습니다.
probe()도 참조하십시오 .
[static] QRhi *QRhi::create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = nullptr)
create(impl, params, flags, importDevice, nullptr)와 동일합니다.
이것은 오버로드된 함수입니다.
int QRhi::currentFrameSlot() const
프레임을 기록하는 동안 현재 프레임 슬롯 인덱스를 반환합니다. 활성 프레임 외부에서 호출될 경우(즉, ` isRecordingFrame()`가 ` false` 상태일 때)는 반환값이 정의되지 않습니다.
Vulkan이나 Metal과 같은 백엔드의 경우, 새로운 프레임을 시작할 때마다 CPU가 GPU보다 FramesInFlight - 1 프레임 앞서 있는 것을 감지하면(프레임 번호 current - FramesInFlight 에서 제출된 명령 버퍼가 아직 완료되지 않았기 때문), QRhi 백엔드가 이를 차단해야 할 책임이 있습니다.
프레임 간에 변경되는 경향이 있는 리소스(예: 유형 QRhiBuffer::Dynamic 인 QRhiBuffer 을 뒷받침하는 네이티브 버퍼 객체)는 여러 버전이 존재하므로, 이전 프레임이 아직 처리 중인 동안 제출될 수 있는 각 프레임은 자체 사본을 사용하여 작동하며, 이로 인해 프레임을 준비할 때 파이프라인을 정지시킬 필요가 없습니다. (GPU에서 아직 사용 중일 수 있는 리소스의 내용은 건드리지 말아야 하지만, 단순히 이전 프레임이 끝날 때까지 항상 기다리기만 한다면 GPU 활용도가 떨어지고, 결과적으로 성능과 효율성도 저하될 것입니다.)
개념적으로 이는 일부 C++ 컨테이너 및 기타 유형에서 사용하는 ‘쓰기 시 복사(copy-on-write)’ 방식과 다소 유사합니다. 또한 OpenGL이나 Direct 3D 11 구현체가 특정 유형의 객체에 대해 내부적으로 수행하는 작업과도 유사할 수 있습니다.
실제로 이러한 이중(또는 삼중) 버퍼링 리소스는 Vulkan, Metal 및 이와 유사한 QRhi 백엔드에서, QRhiResource 뒤에 고정된 수의 네이티브 리소스(예: VkBuffer) slots 를 배치함으로써 구현됩니다. 이는 0, 1, …, FramesInFlight-1 순서로 진행되는 프레임 슬롯 인덱스를 통해 참조할 수 있으며, 이 인덱스는 주기가 끝나면 다시 처음부터 시작됩니다.
이 모든 과정은 QRhi 사용자에게는 투명하게 관리됩니다. 그러나 그래픽 API를 통해 직접 렌더링을 통합하는 애플리케이션의 경우, 자체 그래픽 리소스에 대해 유사한 이중 또는 삼중 버퍼링을 수행하고자 할 수 있습니다. 이는 처리 중인 프레임의 최대 개수( resourceLimit())를 통해 조회할 수 있으며, 현재 프레임(슬롯) 인덱스(이 함수가 반환)를 파악함으로써 가장 쉽게 달성할 수 있습니다.
isRecordingFrame(), beginFrame() 및 endFrame()도 참조하십시오 .
QRhiDriverInfo QRhi::driverInfo() const
성공적으로 초기화된 이 ` QRhi ` 인스턴스가 사용하는 그래픽 장치에 대한 메타데이터를 반환합니다.
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {})
swapChain 에서 마지막 beginFrame() 호출 시 시작된 프레임을 종료하고, 커밋하며, 표시합니다.
더블(또는 트리플) 버퍼링은 QRhiSwapChain 및 QRhi 에 의해 내부적으로 관리됩니다.
flags 선택적으로 이 메서드를 사용하여 동작을 특정 방식으로 변경할 수 있습니다. QRhi::SkipPresent 를 전달하면 Present 명령의 큐에 추가하거나 swapBuffers를 호출하는 과정을 건너뜁니다.
성공 시 QRhi::FrameOpSuccess 를 반환하고, 실패 시 다른 QRhi::FrameOpResult 값을 반환합니다. 이들 중 일부는 "나중에 다시 시도" 유형의 경미한 오류로 취급되어야 합니다. QRhi::FrameOpSwapChainOutOfDate 가 반환되면, QRhiSwapChain::createOrResize()를 호출하여 스왑 체인의 크기를 조정하거나 업데이트해야 합니다. 그런 다음 애플리케이션은 새로운 프레임을 생성하려고 시도해야 합니다. QRhi::FrameOpDeviceLost 는 그래픽 장치가 손실되었음을 의미하지만, QRhi 자체를 포함한 모든 리소스를 해제하고 모든 리소스를 다시 생성함으로써 복구될 수도 있습니다. 자세한 내용은 isDeviceLost()을 참조하십시오.
beginFrame() 및 isDeviceLost()도 참조하십시오 .
QRhi::FrameOpResult QRhi::endOffscreenFrame(QRhi::EndFrameFlags flags = {})
오프스크린 프레임을 종료하고, 제출하며, 필요한 경우 완료를 기다립니다.
endFrame()와 달리, 이 함수는 활성 버퍼 또는 텍스처 리드백이 있는 경우 GPU 측 작업이 완료될 때까지 차단되어 대기합니다.
flags 현재는 사용되지 않습니다.
beginOffscreenFrame()도 참조하십시오 .
[static, since 6.10] QRhi::AdapterList QRhi::enumerateAdapters(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles = nullptr)
현재 존재하는 어댑터(물리적 장치)의 목록을 반환하거나, 지정된 그래픽 API에서 해당 제어 기능이 지원되지 않는 경우 빈 목록을 반환합니다.
이러한 수준의 제어가 불가능한 백엔드의 경우, 반환되는 리스트는 항상 비어 있습니다. 따라서 빈 리스트는 시스템에 그래픽 장치가 없다는 것을 의미하는 것이 아니라, 사용할 장치를 선택하는 데 필요한 세밀한 제어 기능이 제공되지 않음을 나타냅니다.
Direct 3D 11, Direct 3D 12 및 Vulkan용 백엔드는 어댑터 열거를 완전히 지원할 것으로 예상됩니다. 그 외의 백엔드는 지원하지 않을 수 있습니다. 백엔드는 ` impl`로 지정됩니다. 이 함수에서 반환된 ` QRhiAdapter `는 반드시 동일한 ` impl`를 사용하는 ` create()` 호출에서만 사용되어야 합니다. 일부 기본 API는 추가적인 제한 사항을 가질 수 있으며, 특히 Vulkan의 경우 ` QRhiAdapter `가 ` QVulkanInstance `(`VkInstance`)로 지정됩니다.
호출자는 목록에 있는 QRhiAdapter 객체들을 소멸시켜야 합니다. info()를 조회하는 것 외에, 이 객체들의 유일한 용도는 create() 또는 Qt Quick 과 같은 상위 계층의 해당 함수에 전달되는 것입니다.
Vulkan을 위해 특별히 작성된 다음 코드 조각은 사용 가능한 물리적 장치를 열거하고, 선택한 장치에 대한 QRhi 생성을 요청하는 방법을 보여줍니다. 이는 실제로 QRhiVulkanNativeHandles 를 통해 VkPhysicalDevice 를 create()에 전달하는 것과 동일하지만, 애플리케이션 측에서 API에 특화된 코드를 덜 사용하게 됩니다:
QRhiVulkanInitParams initParams;
initParams.inst = &vulkanInstance;
QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
QRhiAdapter*chosenAdapter = nullptr;
for (QRhiAdapter*adapter: adapters) {
if (looksGood(adapter->info())) {
chosenAdapter = adapter;
break;
}
}
QRhi*rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
qDeleteAll(adapters);params 에 매개변수를 전달해야 하는 것은 일부 기본 그래픽 API의 설계 방식 때문입니다. 특히 Vulkan의 경우, QVulkanInstance 를 반드시 제공해야 하는데, 이 매개변수가 없으면 열거(enumeration)가 불가능하기 때문입니다. 백엔드별 params 의 다른 필드들은 이 함수에서 실제로 사용되지 않습니다.
nativeHandles 는 선택 사항입니다. 지정될 경우, create()와 마찬가지로 유효한 QRhiD3D11NativeHandles, QRhiD3D12NativeHandles 또는 QRhiVulkanNativeHandles 여야 합니다. 그러나 create()와 달리, (Vulkan의 경우) 물리적 장치 필드나 (D3D의 경우) 어댑터 LUID 필드만 사용되며, 그 외의 모든 필드는 무시됩니다. 이를 통해 결과를 특정 어댑터로 제한할 수 있습니다. 이 경우 반환되는 목록에는 1개 또는 0개의 요소가 포함됩니다.
앞서 제시된 코드 스니펫에서 looksGood() 함수 구현은 Windows의 어댑터 LUID나 Vulkan의 VkPhysicalDevice와 같이 실제 어댑터/물리적 장치의 식별 정보를 기반으로 한 플랫폼별 필터링을 수행할 수 없다는 점에 유의하십시오. 이는 QRhiDriverInfo 에 플랫폼별 데이터가 포함되어 있지 않기 때문입니다. 대신, ` nativeHandles `을 사용하여 `enumerateAdapters()` 내부에서 이미 필터링된 결과를 가져오십시오.
다음 두 코드 조각은 Direct 3D 12를 예로 들었으나, 실제로는 동등한 기능을 수행합니다:
// Qt 6.10부터 적용되는 enumerateAdapters 기반 접근 방식
QRhiD3D12InitParams initParams;
QRhiD3D12NativeHandles nativeHandles;
nativeHandles.adapterLuidLow = luid.LowPart; // 어딘가에서 LUID를 가져왔으므로, 이제 이를 Qt로 전달합니다.
nativeHandles.adapterLuidHigh = luid.HighPart;
QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
if (adapters.isEmpty()) { qWarning("요청한 어댑터를 찾을 수 없습니다"); }
QRhi*rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
qDeleteAll(adapters);// traditional approach, more lightweight
QRhiD3D12InitParams initParams;
QRhiD3D12NativeHandles nativeHandles;
nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
nativeHandles.adapterLuidHigh = luid.HighPart;
QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);이 함수는 Qt 6.10에서 도입되었습니다.
create()도 참조하십시오 .
QRhi::FrameOpResult QRhi::finish()
그래픽 큐(해당되는 경우)에 있는 모든 작업이 완료될 때까지 대기한 다음, 리드백 완료 및 리소스 해제 등 모든 지연된 작업을 실행합니다. 프레임 내부와 외부에서 호출할 수 있지만, 패스 내부에서는 호출할 수 없습니다. 프레임 내부에서 호출할 경우, 명령 버퍼에 있는 모든 작업을 제출하는 것을 의미합니다.
참고: 이 함수는가급적 사용하지 마십시오 . 이 함수가 필요할 수 있는 한 가지 경우는, 스왑체인 기반 프레임에서 큐에 등록된 리드백의 결과가 특정 시점에 필요하여 결과를 기다려야 하는 경우입니다.
bool QRhi::isClipDepthZeroToOne() const
기본 그래픽 API가 클립 공간에서 [0, 1] 깊이 범위를 사용하는 경우 true 을 반환합니다.
실제로는 OpenGL에서만 false 을 반환합니다. OpenGL은 투영 후 깊이 범위 [-1, 1]을 사용하기 때문입니다. (glDepthRange()로 제어되는 NDC-to-window 매핑과 혼동해서는 안 됩니다. 이 매핑은 QRhiViewport 에 의해 재정의되지 않는 한 [0, 1] 범위를 사용합니다.) 일부 OpenGL 버전에서는 glClipControl()을 사용하여 이를 변경할 수 있지만, QRhi 의 OpenGL 백엔드는 OpenGL ES 또는 4.5 미만의 OpenGL 버전에서는 해당 함수를 사용할 수 없기 때문에 이 함수를 사용하지 않습니다.
참고: ` clipSpaceCorrMatrix()`는 반환되는 행렬에 해당 조정을 포함합니다. 따라서 QRhi 의 많은 사용자는 투영 행렬에 clipSpaceCorrMatrix()을 미리 곱하는 것 외에는 별도의 조치가 필요하지 않습니다. 그러나 일부 그림자 매핑 기법과 같은 그래픽 기법은 셰이더 내에서 깊이 값을 처리하고 출력하는 과정을 포함합니다. 이러한 경우에는 이 함수의 값을 조회하여 적절히 반영해야 합니다.
bool QRhi::isDeviceLost() const
그래픽 장치가 손실된 경우 true를 반환합니다.
장치 손실은 백엔드 및 기본 네이티브 API에 따라 일반적으로 ` beginFrame()`, ` endFrame()` 또는 ` QRhiSwapChain::createOrResize()`에서 감지됩니다. 가장 일반적인 경우는 ` endFrame()`이며, 이는 프레젠테이션이 발생하는 지점이기 때문입니다. 일부 백엔드의 경우 ` QRhiSwapChain::createOrResize()`도 장치 손실로 인해 실패할 수 있습니다. 따라서 이 함수는 이전 작업에서 기기 손실이 감지되었는지 확인하는 일반적인 방법으로 제공됩니다.
장치가 손실된 경우, QRhi 를 통해 더 이상 작업을 수행해서는 안 됩니다. 대신, 모든 QRhi 리소스를 해제하고, 그 후 QRhi 를 파기해야 합니다. 그런 다음 새로운 QRhi 생성을 시도할 수 있습니다. 성공하면 모든 그래픽 리소스를 재초기화해야 합니다. 실패하면 나중에 반복해서 다시 시도하십시오.
간단한 애플리케이션의 경우 장치 손실을 무시할 수도 있지만, 일반적으로 사용되는 데스크톱 플랫폼에서는 그래픽 어댑터의 물리적 분리, 장치 또는 드라이버 비활성화, 그래픽 드라이버 제거 또는 업그레이드, 그래픽 장치 재설정을 유발하는 오류 등 다양한 이유로 인해 장치 손실이 발생할 수 있습니다. 이 중 일부는 완전히 정상적인 상황에서도 발생할 수 있습니다. 예를 들어, 그래픽 드라이버를 최신 버전으로 업그레이드하는 것은 Qt 애플리케이션이 실행 중일 때 언제든지 발생할 수 있는 일반적인 작업입니다. 사용자는 애플리케이션이 OpenGL이나 Direct3D와 같은 API를 적극적으로 사용하고 있는 경우에도 이러한 상황을 무사히 견뎌낼 수 있을 것으로 기대할 수 있습니다.
QRhi 을 기반으로 구축된 Qt 고유의 프레임워크(예: Qt Quick)는 장치 손실이 발생할 때 이를 처리하고 적절한 조치를 취할 것으로 기대할 수 있습니다. 텍스처나 버퍼와 같은 그래픽 리소스에 대한 데이터가 CPU 측에 여전히 남아 있다면, 그래픽 리소스를 원활하게 재초기화할 수 있으므로 이러한 이벤트는 애플리케이션 수준에서 전혀 감지되지 않을 수 있습니다. 그러나 QRhi 을 직접 사용하는 애플리케이션과 라이브러리는 장치 손실 상황을 스스로 확인하고 처리할 준비가 되어 있어야 합니다.
참고: OpenGL의 경우 , 애플리케이션은 ` QOpenGLContext`에서 ` QSurfaceFormat::ResetNotification `을 설정하여 컨텍스트 리셋 알림을 수신하도록 선택해야 할 수 있습니다. 이는 일반적으로 ` QRhiGles2InitParams::format`에서 해당 플래그를 활성화하여 수행됩니다. 그러나 이 플래그가 설정되지 않은 경우에도 일부 시스템에서는 컨텍스트 리셋 상황이 발생할 수 있다는 점을 유의하십시오.
bool QRhi::isFeatureSupported(QRhi::Feature feature) const
지정된 feature 가 지원되는 경우 true 를 반환합니다.
bool QRhi::isRecordingFrame() const
활성 프레임이 있을 때 true를 반환합니다. 즉, beginFrame() (또는 beginOffscreenFrame())가 호출되었으나, 이에 대응하는 endFrame() (또는 endOffscreenFrame())가 아직 호출되지 않은 경우를 의미합니다.
currentFrameSlot(), beginFrame() 및 endFrame()도 참조하십시오 .
bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const
flags 에 의해 수정된 지정된 텍스처 format 가 지원되는 경우 true 를 반환합니다.
이 쿼리는 비압축 및 압축 형식 모두에서 지원됩니다.
bool QRhi::isYUpInFramebuffer() const
기본 그래픽 API에서 프레임버퍼와 이미지의 Y축이 위쪽을 향하도록 설정되어 있는 경우 true 을 반환합니다.
실제로는 OpenGL에서만 이 함수가 ` true `를 반환합니다.
bool QRhi::isYUpInNDC() const
기본 그래픽 API의 정규화된 장치 좌표계에서 Y축이 위쪽을 향하는 경우 ` true `을 반환합니다.
실제로는 Vulkan에서만 false 를 반환합니다.
참고: ` clipSpaceCorrMatrix()`는 반환되는 행렬에 Y축이 위를 향하도록 하는 해당 보정 값을 포함합니다.
bool QRhi::makeThreadLocalNativeContextCurrent()
OpenGL의 경우, 이 함수를 호출하면 현재 스레드에서 OpenGL 컨텍스트가 활성 컨텍스트로 설정됩니다. 다른 백엔드에서는 이 함수가 아무런 효과를 발휘하지 않습니다.
이 함수를 호출하는 것은 일반적으로 Qt 프레임워크 코드에서, QRhi 가 OpenGL 백엔드를 사용하는 한, 애플리케이션에서 제공하는 외부 OpenGL 코드가 이전과 마찬가지로 OpenGL을 직접 사용했을 때와 동일하게 실행될 수 있도록 보장해야 할 때 관련이 있습니다.
QOpenGLContext::makeCurrent()와 마찬가지로 실패 시 false를 반환합니다. 작업이 실패한 경우, isDeviceLost()를 호출하여 컨텍스트 손실 상황이 발생했는지 확인할 수 있습니다. 이러한 확인은 QOpenGLContext::isValid()를 통해 확인하는 것과 동일합니다.
QOpenGLContext::makeCurrent() 및 QOpenGLContext::isValid()도 참조하십시오 .
[static] int QRhi::mipLevelsForSize(const QSize &size)
지정된 size 에 대한 미프 레벨 수를 반환합니다.
const QRhiNativeHandles *QRhi::nativeHandles()
백엔드에서 사용하는 장치, 컨텍스트 및 이와 유사한 개념에 대한 백엔드별 네이티브 객체 컬렉션에 대한 포인터를 반환합니다.
상황에 따라 QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiGles2NativeHandles 또는 QRhiMetalNativeHandles 로 형변환하십시오.
참고: 반환된 포인터나 네이티브 객체에 대한 소유권은 이전되지않습니다 .
QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
지정된 type, usage 및 size 값을 가진 새로운 버퍼를 반환합니다.
참고: 일부 usage 및 type 조합은 모든 백엔드에서 지원되지 않을 수 있습니다. UsageFlags 및 the feature flags 를 참조하십시오.
참고: 백엔드에 따라 size 보다 큰 버퍼를 할당할 수도 있습니다. 이는 애플리케이션에 대해 투명하게 수행되므로, size 의 값에 대한 특별한 제한은 없습니다. QRhiBuffer::size()는 항상 size 에서 요청된 값을 반환합니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiComputePipeline *QRhi::newComputePipeline()
새로운 컴퓨트 파이프라인 리소스를 반환합니다.
참고: 컴퓨트 기능은 Compute 기능이 지원되는 것으로 보고된 경우에만 사용할 수 있습니다.
참조: QRhiResource::destroy().
QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
새로운 그래픽 파이프라인 리소스를 반환합니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat)
지정된 type, pixelSize, sampleCount 및 flags 값을 가진 새로운 렌더 버퍼를 반환합니다.
backingFormatHint 가 QRhiTexture::UnknownFormat 이외의 텍스처 형식으로 설정된 경우, 백엔드에서 렌더 버퍼의 저장 백킹에 사용할 형식을 결정하는 데 이를 활용할 수 있습니다.
참고: backingFormatHint 는 일반적으로 멀티샘플링 및 부동 소수점 텍스처 형식이 관련될 때 중요해집니다. 멀티샘플 QRhiRenderBuffer 로 렌더링한 후 비-RGBA8 QRhiTexture 로 변환하는 경우(일부 그래픽 API에서), QRhiRenderBuffer 의 저장 백엔드는 이에 상응하는 비-RGBA8 형식을 사용하게 됩니다. 즉, QRhiTexture::RGBA32F 와 같은 형식을 전달하는 것이 중요한데, 이는 백엔드가 일반적으로 기본적으로 QRhiTexture::RGBA8 를 선택하기 때문이며, 이 경우 QRhiTextureRenderTarget 의 색상 어태치먼트에서 RGBA8->RGBA32F 멀티샘플 해상도를 설정하려고 시도할 때 나중에 오류가 발생하기 때문입니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW = QRhiSampler::Repeat)
지정된 확대 필터 magFilter, 축소 필터 minFilter, 밉매핑 모드 mipmapMode, 그리고 주소 지정(랩) 모드 addressU, addressV, addressW 을 가진 새로운 샘플러를 반환합니다.
참고: mipmapMode 를 None 이외의 값으로설정하면 , 모든 관련 미프 레벨에 대한 이미지가 texture uploads 를 통해 제공되거나, 이 샘플러와 함께 사용되는 텍스처에 대해 generateMips()를 호출하여 제공됨을 의미합니다. 관련된 모든 밉 레벨에 대한 데이터가 없는 텍스처로 이 샘플러를 사용하려고 하면 렌더링 오류가 발생하며, 정확한 동작은 사용 중인 그래픽 API에 따라 달라집니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
새로운 셰이더 리소스 바인딩 컬렉션 리소스를 반환합니다.
QRhiResource::destroy()도 참조하십시오 .
[since 6.9] QRhiShadingRateMap *QRhi::newShadingRateMap()
새로운 셰이딩 레이트 맵 객체를 반환합니다.
이 함수는 Qt 6.9에서 도입되었습니다.
QRhiSwapChain *QRhi::newSwapChain()
새로운 스왑체인을 반환합니다.
QRhiResource::destroy() 및 QRhiSwapChain::createOrResize()도 참조하십시오 .
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
지정된 format, pixelSize, sampleCount 및 flags 을 갖는 새로운 1D 또는 2D 텍스처를 반환합니다.
1차원 텍스처의 경우 flags 에 QRhiTexture::OneDimensional 가 설정되어 있어야 합니다. pixelSize 의 높이가 0인 경우, 이 함수는 이 플래그를 암시적으로 설정합니다.
참고: format 는 요청된 내부 및 외부 형식을 지정합니다. 즉, 텍스처로 업로드될 데이터는 호환되는 형식이어야 하며, 네이티브 텍스처는 내부적으로 이 형식을 사용할 수 있습니다(적어도 OpenGL의 경우 보장되지는 않음).
참고: 1차원 텍스처는 런타임에 OneDimensionalTextures 기능이 지원된다고 보고된 경우에만 작동합니다. 또한, 1차원 텍스처의 밉맵은 런타임에 OneDimensionalTextureMipmaps 기능이 보고된 경우에만 작동합니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, int width, int height, int depth, int sampleCount = 1, QRhiTexture::Flags flags = {})
지정된 format, width, height, depth, sampleCount 및 flags 을 갖는 새로운 1D, 2D 또는 3D 텍스처를 반환합니다.
이 오버로드는 ` depth`를 지정할 수 있으므로 3D 텍스처에 적합합니다. 3D 텍스처의 경우 flags 에서 ` QRhiTexture::ThreeDimensional `를 설정해야 하지만, 이 오버로드를 사용하면 ` depth `가 0보다 클 때마다 해당 플래그가 암시적으로 설정되므로 생략할 수 있습니다. 1D, 2D 및 큐브 텍스처의 경우 ` depth `를 0으로 설정해야 합니다.
1차원 텍스처의 경우 flags 에서 QRhiTexture::OneDimensional 가 설정되어 있어야 합니다. height 와 depth 가 모두 0인 경우, 이 오버로드는 이 플래그를 암시적으로 설정합니다.
참고: 3D 텍스처는 런타임에 ThreeDimensionalTextures 기능이 지원되는 것으로 보고될 때만 작동합니다.
참고: 1D 텍스처는 런타임에 OneDimensionalTextures 기능이 지원되는 것으로 보고될 때만 작동합니다. 또한, 1D 텍스처의 밉맵은 런타임에 OneDimensionalTextureMipmaps 기능이 보고될 때만 작동합니다.
이 함수는 오버로드된 함수입니다.
QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
지정된 format, arraySize, pixelSize, sampleCount 및 flags 를 갖는 새로운 1차원 또는 2차원 텍스처 배열을 반환합니다.
이 함수는 flags 에서 QRhiTexture::TextureArray 을 암시적으로 설정합니다.
1차원 텍스처 배열의 경우 flags 에서 QRhiTexture::OneDimensional 가 설정되어 있어야 합니다. pixelSize 의 높이가 0인 경우, 이 함수는 이 플래그를 암시적으로 설정합니다.
참고: 텍스처 배열과 텍스처의 배열을 혼동하지마십시오 . 이 함수로 생성된 QRhiTexture 는 셰이더 내의 1차원 또는 2차원 배열 샘플러와 함께 사용할 수 있습니다. 예: layout(binding = 1) uniform sampler2DArray texArr;. 텍스처 배열은 QRhiShaderResourceBinding::sampledTextures()를 통해 셰이더에 노출되고 개수가 1보다 큰 텍스처 목록을 의미하며, 셰이더 내에서 다음과 같이 선언됩니다: layout(binding = 1) uniform sampler2D textures[4];
참고: 이 기능은 런타임에 TextureArrays 기능이 지원된다고 보고된 경우에만 작동합니다.
참고: 1차원 텍스처는 런타임에 OneDimensionalTextures 기능이 지원된다고 보고된 경우에만 작동합니다. 또한, 1차원 텍스처의 밉맵은 런타임에 OneDimensionalTextureMipmaps 기능이 보고된 경우에만 작동합니다.
newTexture()도 참조하십시오 .
QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = {})
desc 에 지정된 색상 및 깊이/스텐실 어태치먼트를 가지며, 지정된 flags 를 갖는 새로운 텍스처 렌더 타겟을 반환합니다.
QRhiResource::destroy()도 참조하십시오 .
QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
복사 유형의 작업을 기록할 수 있는 사용 가능한 빈 배치 객체를 반환합니다.
참고: 반환값은 호출자가 소유하는 것이 아니므로 절대로 파기해서는 안 됩니다. 대신, 해당 배치 인스턴스를 ` QRhiCommandBuffer::beginPass()`, ` QRhiCommandBuffer::endPass()` 또는 ` QRhiCommandBuffer::resourceUpdate()`에 전달하거나, ` QRhiResourceUpdateBatch::release()`를 호출하여 재사용을 위해 풀로 반환해야 합니다.
참고: 배치 인스턴스는 자체적으로 데이터를 수집할 뿐, 어떠한 작업도 수행하지 않으므로 beginFrame() - endFrame() 외부에서도 호출할수 있습니다 .
녹화 중인 프레임에 묶여 있지 않기 때문에, 예를 들어 다음과 같은 순서도 유효합니다:
rhi->beginFrame(swapchain);
QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
u->uploadStaticBuffer(buf, data);
// ... do not commit the batch
rhi->endFrame();
// u stays valid (assuming buf stays valid as well)
rhi->beginFrame(swapchain);
swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
// ... draw with buf
rhi->endFrame();경고: QRhi 당최대 배치수는 64개입니다. 이 제한에 도달하면, 배치가 풀로 반환될 때까지 함수는 null을 반환합니다.
QByteArray QRhi::pipelineCacheData()
이 QRhi 의 수명 기간 동안 성공적으로 생성된 QRhiGraphicsPipeline 및 QRhiComputePipeline 에서 수집된 데이터가 포함된 이진 데이터 블롭을 반환합니다.
캐시 데이터를 저장한 후, 동일한 애플리케이션을 다시 실행할 때 이 데이터를 재로드하면 파이프라인 및 셰이더 생성 시간을 잠재적으로 단축할 수 있습니다. 캐시와 그 직렬화 버전에 정확히 어떤 내용이 포함되는지는 명시되어 있지 않으며, 항상 사용되는 백엔드에 따라 다르며, 경우에 따라 그래픽 API의 특정 구현에 따라 달라질 수도 있습니다.
PipelineCacheDataLoadSave 가 지원되지 않는 것으로 보고되면, 반환된 QByteArray 는 비어 있습니다.
create()를 호출할 때 EnablePipelineCacheDataSave 플래그가 지정되지 않은 경우, PipelineCacheDataLoadSave 기능이 지원되더라도 반환된 QByteArray 는 비어 있을 수 있습니다.
반환된 데이터가 비어 있지 않은 경우, 해당 데이터는 항상 Qt 버전 및 QRhi 백엔드에 따라 다릅니다. 또한, 경우에 따라 그래픽 장치 및 사용된 정확한 드라이버 버전에 대한 강한 의존성이 있을 수 있습니다. QRhi 는 적절한 헤더를 추가하고 데이터가 항상 setPipelineCacheData()로 안전하게 전달될 수 있도록 보장하므로, 다른 버전의 드라이버에서 실행된 데이터를 로드하려는 시도는 안전하고 원활하게 처리됩니다.
참고: releaseCachedResources()를 호출하면 백엔드에 따라 수집된 파이프라인 데이터가 지워질 수 있습니다. 이 경우, 이 함수를 다시 호출해도 데이터가 반환되지 않을 수 있습니다.
이 기능에 대한 자세한 내용은 EnablePipelineCacheDataSave 를 참조하십시오.
참고: 이 함수의 호출 횟수를최소화하십시오 . blob을 가져오는 작업은 항상 자원이 적게 소모되는 작업은 아니므로, 이 함수는 낮은 빈도로만 호출해야 하며, 이상적으로는 애플리케이션을 종료할 때와 같이 단 한 번만 호출하는 것이 좋습니다.
setPipelineCacheData(), create(), isFeatureSupported()도 참조하십시오 .
[static] bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
주어진 impl 및 params 에서 create() 호출이 성공할 것으로 예상될 경우 true를 반환합니다.
일부 백엔드의 경우, 이는 create()를 호출하고 반환 값을 확인한 다음, 결과로 생성된 QRhi 를 소멸시키는 것과 동일합니다.
다른 백엔드, 특히 Metal의 경우, 실패 시 디버그 출력을 경고로 어지럽히지 않고 더 가벼운 방식으로 테스트할 수 있도록 하는 특정 프로빙 구현이 있을 수 있습니다.
create()도 참조하십시오 .
void QRhi::releaseCachedResources()
백엔드 캐시에 저장된 리소스를 해제하려고 시도합니다. 여기에는 CPU 및 GPU 리소스가 모두 포함될 수 있습니다. 자동으로 재생성될 수 있는 메모리 및 리소스만 해당 범위에 포함됩니다. 예를 들어, 백엔드의 ` QRhiGraphicsPipeline ` 구현이 셰이더 컴파일 결과의 캐시를 유지하고 있는 경우, 이 함수를 호출하면 해당 캐시가 비워지므로 메모리 및 그래픽 리소스를 확보할 수 있습니다.
이 함수를 호출하는 것은 리소스가 제한된 환경에서, 즉 특정 시점에서 성능 저하를 감수하더라도 리소스 사용량을 최소화해야 할 필요가 있을 때 유용합니다.
void QRhi::removeCleanupCallback(const void *key)
key 를 통해 등록된 콜백을 해제합니다. key 를 통해 정리 콜백이 등록되지 않은 경우, 이 함수는 아무 작업도 수행하지 않습니다. 키 없이 등록된 콜백은 제거할 수 없습니다.
addCleanupCallback()도 참조하십시오 .
int QRhi::resourceLimit(QRhi::ResourceLimit limit) const
지정된 리소스 limit 의 값을 반환합니다.
이 값들은 초기화 시 백엔드에서 쿼리될 것으로 예상되므로, 이 함수를 호출하는 것은 부하가 적은 작업입니다.
void QRhi::setPipelineCacheData(const QByteArray &data)
해당되는 경우 data 를 파이프라인 캐시에 로드합니다.
PipelineCacheDataLoadSave 가 지원되지 않는 것으로 보고된 경우, 이 함수를 호출해도 안전하지만 아무런 효과도 없습니다.
pipelineCacheData()가 반환하는 blob은 항상 Qt 버전, QRhi 백엔드, 그리고 경우에 따라 그래픽 장치 및 특정 버전의 그래픽 드라이버에 따라 달라집니다. QRhi 는 적절한 헤더를 추가하고, 데이터가 항상 이 함수로 안전하게 전달될 수 있도록 보장하는 안전 장치를 처리합니다. 드라이버가 최신 버전으로 업그레이드되었거나, 데이터가 다른 QRhi 백엔드에서 생성된 경우와 같이 불일치가 발생하면 경고가 출력되며, data 는 안전하게 무시됩니다.
Vulkan의 경우, 이는 VkPipelineCache에 직접 매핑됩니다. 이 함수를 호출하면 data 에서 초기 데이터를 가져온 새로운 Vulkan 파이프라인 캐시 객체가 생성됩니다. 이후 생성되는 모든 QRhiGraphicsPipeline 및 QRhiComputePipeline 객체는 이 파이프라인 캐시 객체를 사용하므로, 파이프라인 생성 속도가 잠재적으로 빨라질 수 있습니다.
다른 API의 경우 실제 파이프라인 캐시는 없지만, 셰이더 컴파일 결과인 바이트코드(D3D)나 프로그램 바이너리(OpenGL)를 저장하는 캐시를 제공할 수 있습니다. 실행 시 소스 코드로부터 대량의 셰이더 컴파일을 수행하는 애플리케이션의 경우, 이 함수를 사용하여 이전 실행에서 “파이프라인 캐시”를 미리 채워두면 후속 실행 시 성능이 크게 향상될 수 있습니다.
참고: QRhi 는 data 가 파이프라인 및 셰이더 생성 성능에 영향을 미친다는 점을 보장할 수 없습니다. Vulkan과 같은 API의 경우, data 를 특정 목적으로 사용할지 아니면 무시할지는 드라이버에 따라 결정됩니다.
이 기능에 대한 자세한 내용은 EnablePipelineCacheDataSave 을 참조하십시오.
참고: QRhi 가 제공하는이 메커니즘은 드라이버 자체의 내부 캐싱 메커니즘(있는 경우)과는 독립적입니다. 즉, 그래픽 API 및 그 구현 방식에 따라 data 를 가져온 후 다시 불러오는 것의 정확한 효과는 예측할 수 없습니다. Qt가 제어할 수 없는 다른 캐싱 메커니즘이 이미 활성화된 경우, 성능 향상이 전혀 나타나지 않을 수도 있습니다.
참고: 이 함수의 호출 횟수를최소화하십시오 . 블롭을 로드하는 작업은 항상 비용이 적게 드는 것은 아니므로, 이 함수는 낮은 빈도로만 호출되어야 하며, 이상적으로는 애플리케이션을 시작할 때 한 번만 호출하는 것이 좋습니다.
경고: 직렬화된 파이프라인 캐시 데이터는 신뢰할 수 있는 콘텐츠로 간주됩니다. Qt는 data 에 포함된 헤더와 메타데이터를 철저하게 파싱하지만, 애플리케이션 개발자는 신뢰할 수 없는 출처의 데이터를 절대 전달하지 말아야 합니다.
pipelineCacheData() 및 isFeatureSupported()도 참조하십시오 .
[since 6.9] void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)
해당되는 백엔드 및 그래픽 API의 경우, 이 함수를 사용하면 그래픽 명령 큐에 다음에 제출될 명령에 추가 인수를 전달할 수 있습니다.
특히 Vulkan의 경우, 이를 통해 ` vkQueueSubmit() `가 신호를 보내고 대기할 Vulkan 세마포어 객체 목록을 전달할 수 있습니다. 이때 ` params `는 ` QRhiVulkanQueueSubmitParams`여야 합니다. 이는 애플리케이션의 사용자 정의 Vulkan 렌더링 또는 컴퓨팅 코드가 관리하는 `VkSemaphore`에 대한 신호 전송 및 대기가 필요한 네이티브 Vulkan 호출을 수행하는 경우와 같은 특정 고급 사용 사례에서 필수적입니다. 또한, 이를 통해 다음 ` vkQueuePresentKHR()`에서 대기할 추가 세마포어를 지정할 수도 있습니다.
참고: 이 함수는 endFrame(), endOffscreenFrame() 또는 finish()에서 수행되는 다음 큐 제출에만 영향을 미칩니다. present의 큐 등록은 endFrame()에서 이루어집니다.
다른 많은 백엔드에서는 이 함수의 구현이 아무 작업도 수행하지 않습니다.
이 함수는 Qt 6.9에서 도입되었습니다.
[static] QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
지정된 ` mipLevel`에 대한 텍스처 이미지 크기를 반환하며, 이 크기는 ` baseLevelSize`에 명시된 레벨 0 크기를 기준으로 계산됩니다.
QRhiStats QRhi::statistics() const
그래픽 리소스의 사용 시간 및 할당 현황에 대한 통계를 수집하여 반환합니다.
메모리 할당에 대한 데이터는 해당 작업이 Qt의 제어 하에 있는 일부 백엔드에서만 사용할 수 있습니다. 리소스 메모리 할당에 대한 하위 수준 제어가 없는 그래픽 API의 경우, 이 기능은 절대 지원되지 않으며 결과의 모든 관련 필드는 0으로 표시됩니다.
특히 Vulkan의 경우, 값은 항상 유효하며 기본 메모리 할당 라이브러리에서 조회됩니다. 이를 통해 활성 버퍼와 텍스처의 메모리 요구 사항을 파악할 수 있습니다.
Direct 3D 12의 경우도 마찬가지입니다. 메모리 할당기 라이브러리의 통계 정보 외에도, 여기서는 DXGI가 보고하는 바와 같이 메모리 할당기 라이브러리의 제어 범위를 벗어난 추가 리소스(스왑체인 버퍼, 디스크립터 힙 등)를 포함한 총 크기를 나타내는 ‘ totalUsageBytes ’ 필드도 결과에 포함됩니다.
이 값은 사용된 모든 유형의 메모리를 합산한 것입니다. (예: 디스크리트 GPU의 경우 비디오 메모리 + 시스템 메모리)
대부분의 백엔드에서는 그래픽 및 컴퓨트 파이프라인 생성(일반적으로 셰이더 컴파일이나 캐시 조회, 그리고 잠재적으로 비용이 많이 드는 처리가 포함됨)에 소요된 총 시간(밀리초 단위)과 같은 추가 데이터를 확인할 수 있습니다.
참고: 파이프라인 생성 같은 작업의 소요시간은 다양한 요인의 영향을 받을 수 있습니다. “파이프라인”이라는 개념과, 예를 들어 ` QRhiGraphicsPipeline::create()` 호출 시 내부적으로 정확히 어떤 일이 발생하는지는 그래픽 API와 그 구현체마다 크게 다르기 때문에, 서로 다른 백엔드 간의 결과를 비교해서는 안 됩니다.
참고: 또한 , 많은 드라이버는 셰이더, 프로그램, 파이프라인에 대해 다양한 캐싱 전략을 사용할 가능성이 높습니다. ( setPipelineCacheData()이나 OpenGL 전용 프로그램 바이너리 디스크 캐시와 같은 Qt 자체의 유사한 기능과는 별개로). 이러한 내부 동작은 API 클라이언트에게 투명하게 이루어지기 때문에, Qt와 QRhi 는 정확한 캐싱 전략, 지속성, 캐시된 데이터의 무효화 등에 대해 알 수도 없고 제어할 수도 없습니다. 파이프라인 생성 소요 시간과 같은 타이밍을 분석할 때는 드라이버 수준의 캐싱 메커니즘이 존재할 가능성과 그 비규격적인 동작을 염두에 두어야 합니다.
QList<int> QRhi::supportedSampleCounts() const
지원되는 샘플 수 목록을 반환합니다.
전형적인 예로는 (1, 2, 4, 8)이 있습니다.
일부 백엔드의 경우 지원되는 값 목록이 사전에 고정되어 있는 반면, 다른 백엔드의 경우 (물리적) 장치 속성을 통해 실행 시점에 지원되는 항목이 결정됩니다.
QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(), QRhiGraphicsPipeline::setSampleCount() 및 QRhiSwapChain::setSampleCount()도 참조하십시오 .
[since 6.9] QList<QSize> QRhi::supportedShadingRates(int sampleCount) const
지정된 sampleCount 에 대해 지원되는 가변 음영율 목록을 반환합니다.
1x1은 항상 지원됩니다.
이 함수는 Qt 6.9에서 도입되었습니다.
QThread *QRhi::thread() const
QRhi 가 initialized 된 스레드를 반환합니다.
int QRhi::ubufAligned(int v) const
ubufAlignment() 함수가 지정하는 균일한 버퍼 정렬에 맞춰 정렬된 값(일반적으로 오프셋) v 을 반환합니다.
int QRhi::ubufAlignment() const
바이트 단위로 표현된 균일 버퍼 오프셋 정렬의 최소값을 반환합니다. 일반적으로 이 값은 256입니다.
이 값에 정렬되지 않은 오프셋을 가진 유니폼 버퍼 영역을 바인딩하려고 하면, 백엔드 및 기본 그래픽 API에 따라 오류가 발생할 수 있습니다.
ubufAligned()도 참조하십시오 .
[static] QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
impl 로 지정된 백엔드 및 그래픽 API에 특화된 불투명 데이터를 포함하는 QRhiSwapChainProxyData 구조체를 생성하여 반환합니다. window 는 스왑체인(swapchain)이 대상으로 하는 그래픽 시스템( QWindow )입니다.
반환된 구조체는 ` QRhiSwapChain::setProxyData()`에 전달될 수 있습니다. 이는 스레드 기반 렌더링 시스템에서 의미가 있습니다. 이 정적 함수는 모든 ` QRhi ` 작업과 달리 메인(GUI) 스레드에서 호출된 후, ` QRhi ` 및 ` QRhiSwapChain `을 처리하는 스레드로 전송되어 스왑체인에 전달되는 방식으로 작동합니다. 이를 통해 메인 스레드에서만 안전하게 호출할 수 있는 네이티브 플랫폼 쿼리(예: NSView에서 CAMetalLayer 조회)를 수행한 후, 해당 데이터를 렌더링 스레드에 상주하는 QRhiSwapChain 로 전달할 수 있습니다. Metal 예제의 경우, 전용 렌더링 스레드에서 view.layer에 접근하면 Xcode 스레드 검사기에서 경고가 발생합니다. 데이터 프록시 메커니즘을 사용하면 이러한 문제를 피할 수 있습니다.
스레드가 관여하지 않는 경우, ` QRhiSwapChainProxyData `을 생성하여 전달할 필요가 없습니다. 백엔드는 필요한 모든 정보를 자체적으로 조회할 수 있도록 보장되며, 모든 것이 메인(GUI) 스레드에서 처리된다면 그것으로 충분합니다.
참고: ` impl `는 ` QRhi `가 생성될 때 사용된 것과 일치해야 합니다. 예를 들어, Apple이 아닌 플랫폼에서 ` QRhi::Metal `를 호출하면 유용한 데이터가 생성되지 않습니다.
관련 비회원
[alias, since 6.7] QRhiShaderResourceBindingSet
QRhiShaderResourceBindings 의 동의어.
이 typedef는 Qt 6.7에서 도입되었습니다.
© 2026 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.