QRhi Class
高速化された2D/3DグラフィックスAPIの抽象化。詳細...
Header: | #include <rhi/qrhi.h> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Gui) target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate) |
qmake: | QT += gui-private |
Since: | Qt 6.6 |
- 継承メンバを含む全メンバ一覧
- QRhiは、Rendering in 3D に含まれます。
パブリックタイプ
enum | BeginFrameFlag { } |
flags | BeginFrameFlags |
enum | EndFrameFlag { SkipPresent } |
flags | EndFrameFlags |
enum | Feature { MultisampleTexture, MultisampleRenderBuffer, DebugMarkers, Timestamps, Instancing, …, ResolveDepthStencil } |
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, …, MaxVertexOutputs } |
パブリック関数
~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() |
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 | runCleanup() |
void | setPipelineCacheData(const QByteArray &data) |
QRhiStats | statistics() const |
QList<int> | supportedSampleCounts() 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 = 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 Rendering Hardware Interface は、OpenGL、OpenGL ES、Direct3D、Metal、Vulkan などのハードウェアアクセラレーショングラフィックス API を抽象化したものです。
警告 QShader やQShaderDescription を含む Qt Gui モジュールの QRhi ファミリーのクラスは、限られた互換性しか保証していません。これらのクラスにはソース互換性もバイナリ互換性も保証されていません。つまり、APIはアプリケーションが開発されたQtのバージョンでのみ動作することが保証されています。しかし、ソース互換性のない変更は最小限にとどめることを目的としており、マイナーリリース(6.7、6.8など)でのみ行われます。これらのクラスをアプリケーションで使用するには、Qt::GuiPrivate
(CMakeを使用している場合)にリンクし、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機能またはShader Model 5.0をサポートしていない場合、アクセラレーショングラフィックスデバイスを使用した初期化は失敗しますが、ソフトウェアアダプターを使用することは可能です。
- Windows 10 のバージョン 1703 以降で、Shader Model 5.0 以降の Direct3D 12。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 Exampleを参照してください。
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 up, CCW 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::TargetBlend premulAlphaBlend; 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 = image.mirrored(); 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を直接インスタンス化することはできません。代わりに、create ()関数を使用してください。グラフィックス・デバイスを解放するには、QRhiインスタンスを普通に削除してください。
リソース
QRhiBuffer 、QRhiTexture など、QRhiResource から派生したクラスのインスタンスは、0 個、1 個、またはそれ以上のネイティブ・グラフィックス・リソースをカプセル化します。このようなクラスのインスタンスは常に、newBuffer ()、newTexture ()、newTextureRenderTarget ()、newSwapChain ()など、QRhiのnew
関数によって作成されます。
QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)); if (!vbuf->create()) { error(); } // ... delete vbuf;
- newBuffer() のような関数から返される値は、常に呼び出し元が所有します。
- QRhiResource サブクラスのインスタンスを作成するだけでは、ネイティブ・リソースの割り当てや初期化は行われません。これは、QRhiBuffer::create() やQRhiTexture::create() など、サブクラスの
create()
関数を呼び出すときにのみ行われます。 - 例外はQRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()、QRhiSwapChain::newCompatibleRenderPassDescriptor()、QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() です。これらには
create()
の操作はなく、返されたオブジェクトはすぐにアクティブになります。 - リソースオブジェクト自体は不変なものとして扱われます。いったんcreate() が呼び出されると、QRhiTexture::setPixelSize() などのセッターでパラメータを変更しても、その下にあるネイティブリソースが解放され、
create()
が再度呼び出されない限り、何の影響もありません。リソースの再利用については、以下のセクションを参照してください。 - 基盤となるネイティブ・リソースは、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
の2段階のセットアップが必要になることがよくあります。render
ステップでは、レンダーパスを開始し、描画コールを記録するだけで、すべてのリソースの作成と、更新、アップロード、コピーのキューイングは、prepare
ステップで事前に行われます。
QRhiでは今のところ、コマンドバッファを自由に作成したり送信したりすることはできません。これは将来、特に計算のサポートが導入されれば、ある程度は解除されるかもしれませんが、frame-start
とframe-end
のポイントが明確に定義され、frame-end
が提示を意味する、専用の「フレーム」コマンドバッファと組み合わされたモデルは、Qtの様々なUI技術に最も適しているため、今後も主要な操作方法であり続けるでしょう。
スレッド処理
QRhiインスタンスと関連リソースは、どのスレッドでも作成、使用できますが、使用はすべて1つのスレッドに限定する必要があります。アプリケーション内で複数のQWindowsにレンダリングする場合、各ウィンドウに専用のスレッドとQRhiインスタンスを持つことが推奨されます。QOpenGLContext これは、Qt Quickシーングラフのスレッド化されたレンダリングループがOpenGLで直接動作するときと同じです。QRhiに移行するときは、QOpenGLContext がQRhiに置き換えられ、移行が簡単になります。
QRhiGles2NativeHandles を介して渡されるOpenGLコンテキストなど、外部で作成されたネイティブ・オブジェクトに関しては、他のスレッドによって悪用されないようにするのはアプリケーション次第です。
リソースはQRhiインスタンス間で共有できません。これはQRhiがほとんどのキュー、コマンド・バッファ、リソース同期関連のタスクを隠蔽し、それらのためのAPIを提供しないため、意図的に選択されたものです。しかし、複数のスレッドからのグラフィックス・リソースの安全で効率的な同時使用は、これらの概念と関連しているため、現在のところスコープ外のトピックですが、将来的には導入される可能性があります。
注: Metalバックエンドは、レンダリングスレッドで自動解放プールが利用可能であることを必要とし、理想的にはレンダリングループの各反復をラップします。メイン(gui)スレッドでレンダリングする場合は、QRhiのユーザーによる操作は必要ありませんが、独立した専用のレンダリングスレッドを使用する場合は重要になります。
リソースの同期
QRhiはリソースバリアや画像レイアウトの遷移のためのAPIを公開していません。このような同期は、必要に応じてリソースの使用状況を追跡することにより、バックエンドによって暗黙的に行われます(たとえばVulkan)。バッファと画像のバリアは、アプリケーションに対して透過的に、レンダーまたは計算パスの前に挿入されます。
注: レンダーまたはコンピュートパス内のリソースは、そのパスの間、単一の用途にバインドされることが期待されます。例えば、バッファは頂点バッファ、インデックスバッファ、ユニフォームバッファ、ストレージバッファとして使用できますが、1つのパス内でこれらを組み合わせて使用することはできません。ただし、バッファが作成時に両方の用途を宣言していれば、たとえば、計算パスでバッファをストレージバッファとして使用し、レンダーパスで頂点バッファとして使用することはまったく問題ありません。
注: テクスチャは、同じパス内であっても、同じテクスチャの 2 つのサブ リソース(通常は 2 つの異なる mip レベル)を異なるアクセス(1 つはロード用、1 つはストア用)に使用することがサポートされているため、特定の ケースではこのルールが緩和されます。
リソースの再利用
ユーザーから見て、QRhiResource はQRhiResource::destroy() を呼び出した直後から再利用可能です。スワップチェーンを除き、すでに作成されたオブジェクトに対してcreate()
を呼び出すと、暗黙のうちにdestroy()
が実行されます。これは、QRhiResource インスタンスを、新しいネイティブ・グラフィックス・オブジェクトの下に、異なるパラメータで再利用するための便利なショートカットを提供します。
同じオブジェクトを再利用することの重要性は、オブジェクトの中には他のオブジェクトを参照するものがあるという事実にあります。たとえば、QRhiShaderResourceBindings は、QRhiBuffer 、QRhiTexture 、QRhiSampler インスタンスを参照することができます。例えば、QRhiSampler は、QRhiBuffer 、 、 のインスタンスを参照することができます。後のフレームでこれらのバッファのサイズを変更したり、サンプラーのパラメータを変更したりする必要がある場合、 や を破棄して新しく作成すると、古いインスタンスへの参照はすべて無効になります。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 レンダーターゲットの関連テクスチャまたはレンダーバッファの 1 つが、レンダーターゲットオブジェクトの作成以降に( を呼び出して)再構築された場合でも、 ()を呼び出すと安全です。これにより、アプリケーションは、 に新しいピクセルサイズを設定し、 ()を呼び出すことによってテクスチャのサイズを変更することができます。したがって、beginPass()で暗黙的に行われるため、 を更新することなく、その下にまったく新しいネイティブテクスチャリソースを作成します。create()
QRhiCommandBuffer::beginPass QRhiTexture create QRhiTextureRenderTarget
プールされたオブジェクト
リソースに加えて、QRhiResourceUpdateBatch のようなプールされたオブジェクトもあります。インスタンスは、nextResourceUpdateBatch() のようなnext
関数で取得されます。この場合、呼び出し元は返されたインスタンスを所有しません。ここでの唯一の有効な操作方法は、QRhiResourceUpdateBatch で関数を呼び出し、それをQRhiCommandBuffer::beginPass() やQRhiCommandBuffer::endPass() に渡すことである。これらの関数は、バッチをプールに戻す処理を行う。また、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);
スワップチェーン仕様
QRhiSwapChain は、スワップチェーン特有の性質により、いくつかの特殊なセマンティクスを備えている。
- これは、
create()
を持たず、QRhiSwapChain::createOrResize ()を持つ。この関数を繰り返し呼び出すことは、QRhiSwapChain::destroy ()の後にQRhiSwapChain::createOrResize ()を呼び出すことと同じではない。なぜなら、スワップチェーンは、バッファのサイズを変更する必要がある場合に、力ずくで破棄してゼロから再作成するよりも効率的な方法で処理する方法を備えていることが多いからである。 - アクティブなQRhiSwapChain は、destroy() を呼び出すか、オブジェクトを破棄することで、QWindow の基礎となる QPlatformWindow、つまり関連するネイティブ・ウィンドウ・オブジェクトが破棄される前に解放されなければなりません。スワップチェーンの解放は、例えば、QWindow::close ()の取得時に QPlatformWindow が破棄されるなどして、ネイティブウィンドウが存在しなくなった場合に問題となる可能性がある(Vulkan などの一部の API では明示的に禁止されている)ため、延期すべきではありません。したがって、スワップチェーンの解放は、対象となるQWindow がQPlatformSurfaceEvent::SurfaceAboutToBeDestroyed イベントを送信するたびに発生する必要があります。QWindow が破壊される前にイベントが到着しない場合(これはQCoreApplication::quit() を使用している場合に起こりえます)、イベントループが終了した後に QWindow::handle() をチェックし、null でない場合(つまり、基盤となるネイティブウィンドウがまだ存在している場合)にスワップチェーンの解放を呼び出します。
所有権
一般的なルールとして、所有権は移譲されません。すでに存在するグラフィック・デバイスでQRhiを作成しても、QRhiがデバイス・オブジェクトの所有権を取得するわけではありません。同様に、QRhi::nativeHandles ()やQRhiTexture::nativeTexture ()を使ってデバイスやテクスチャ・オブジェクトを「エクスポート」しても、所有権は譲渡されません。最も重要なことは、構造体やセッターでポインターを渡しても所有権は移らないということです。
トラブルシューティングとプロファイリング
エラー・レポート
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 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
フラグを切り替えることで、デバッグレイヤーを有効にしたグラフィックデバイスを要求できます。メッセージはデバッグ出力に表示され、Qt Creator のメッセージパネルやDebugView などのツールで見ることができます。 - Metalについては、Metal Validationの制御はQRhiの範囲外です。バリデーションを有効にするには、環境変数
METAL_DEVICE_WRAPPER_TYPE=1
を設定してアプリケーションを実行するか、XCode内でアプリケーションを実行します。また、最近のXCodeやmacOSのバージョンでは、さらなる設定や環境変数があるかもしれません。例えば、このページを参照してください。
フレームキャプチャとパフォーマンスプロファイリング
Qtアプリケーションは、QRhiを使ってウィンドウをレンダリングし、その下で3D APIに依存していますが、ウィンドウとグラフィックパイプラインの観点からは、少なくとも同じ3D APIを使用する他の(Qt以外の)アプリケーションと変わりません。つまり、ゲームなどの 3D グラフィックスを含むアプリケーションのデバッグやプロファイリングのためのツールやプラクティスは、すべて Qt アプリケーションにも適用できます。
QRhiを使用するQtアプリケーション(Qt QuickやQt Quick 3Dベースのプロジェクトも含む)のレンダリング内部を知ることができるツールの例をいくつか紹介します:
- RenderDocは、OpenGL、Vulkan、D3D11、または D3D12 を使用するアプリケーションのフレームキャプチャを取得し、記録されたコマンドとパイプラインの状態を Windows と Linux でイントロスペクトできます。3Dシーンのある部分が期待通りに表示されない原因を突き止めようとするとき、RenderDocはパイプラインステージと関連するステートをチェックし、欠落している値や不正確な値を発見するための高速で効率的な方法であることがよくあります。また、Qt 自体を開発する際にも積極的に使用されるツールです。
- NVIDIA ベースのシステムでは、Nsight Graphics がWindows と Linux 上でグラフィックデバッガツールを提供しています。フレームやパイプラインのコマンドを調べるだけでなく、ベンダー固有のツールでは、単純なフレームキャプチャでは得られないタイミングやハードウェアの性能情報を調べることができます。
- AMDベースのシステムの場合、Radeon GPU Profilerを使用することで、アプリケーションのレンダリングとそのパフォーマンスについてより深い洞察を得ることができます。
- QRhiはDirect 3D 12をサポートしているため、WindowsのDirectX 12ゲーム用のパフォーマンス・チューニングおよびデバッグ・ツールであるPIXを使用することも可能です。
- macOSでは、XCode Metalデバッガを使用して、フレームキャプチャを取得してイントロスペクトし、パフォーマンスの詳細を調査し、シェーダをデバッグできます。macOS 13では、環境変数
MTL_HUD_ENABLED=1
を設定することで、Metalベースのウィンドウのフレームレートやその他の情報を表示するオーバーレイを有効にすることもできます。
モバイルおよび組み込みプラットフォームでは、GPU または SoC のベンダーが提供する、OpenGL ES または Vulkan を使用するアプリケーションのパフォーマンスプロファイリングを実行するためのベンダーおよびプラットフォーム固有のツールが利用できる場合があります。
フレームをキャプチャするとき、debug markers were enabled for the QRhi と使用中のグラフィックス API がサポートしている限り、オブジェクトとコマンドのグループにデバッグマーカーで名前を付けることができることを覚えておいてください。コマンドストリームに注釈を付けるには、debugMarkBegin ()、debugMarkEnd ()、debugMarkMsg ()を呼び出します。これは、複数のレンダーパスがある大きなフレームで特に役立ちます。リソースの名前は、create() の前にsetName() を呼び出すことで指定します。
アプリケーション内でCPU側とGPU側の基本的なタイミング測定を行うには、QElapsedTimer とQRhiCommandBuffer::lastCompletedGpuTime() を使用できます。後者は、現時点では一部のグラフィックス API でのみ利用可能で、QRhi::EnableTimestamps フラグでオプトインする必要があります。
リソースリーク・チェック
QRhiオブジェクトから作成されたすべてのバッファ、テクスチャ、およびその他のリソースを適切に破棄せずにQRhiオブジェクトを破棄した場合、アプリケーションがデバッグビルドであるとき、または環境変数QT_RHI_LEAK_CHECK
がゼロ以外の値に設定されているときはいつでも、この問題に関する警告がデバッグ出力に出力されます。これは、アプリケーションのレンダリングロジック内のリソース処理に関する設計上の問題を発見する簡単な方法です。ただし、プラットフォームやグラフィックス API によっては、Qt が直接制御できない独自の割り当てやリソースリーク検出を行う場合があります。例えば、Vulkan を使用する場合、グラフィックスのメモリ割り当てを所有するリソースが QRhi の前に破棄されないと、メモリアロケータはデバッグビルドで失敗するアサーションを発生させる可能性があります。さらに、Vulkan検証レイヤーが有効な場合、解放されなかったネイティブグラフィックリソースに関する警告が発行されます。同様に、Direct 3Dでは、アプリケーションがQRhiとそのリソースを正しい順序で破棄しない場合、解放されていないCOMオブジェクトに関する警告が出力されることがあります。
RHI Window Example,QRhiCommandBuffer,QRhiResourceUpdateBatch,QRhiShaderResourceBindings,QShader,QRhiBuffer,QRhiTexture,QRhiRenderBuffer,QRhiSampler,QRhiTextureRenderTarget,QRhiGraphicsPipeline,QRhiComputePipeline, およびQRhiSwapChainも参照のこと 。
メンバー型ドキュメント
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より大きいテクスチャがサポートされていることを示します。実際には、この機能は3.1より古いOpenGL ESバージョンや3.0より古いOpenGLではサポートされません。 |
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の一部では、タイムスタンプクエリのサポートは技術的にオプションであるため、この機能がすべての実装で常にサポートされていることを保証することはできません。 |
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) または 0xFFFFFF (IndexUInt32) のインデックス値に遭遇したときにプリミティブのアセンブリを再起動することが、少なくとも特定のプリミティブトポロジに対して有効であることを示します。QRhi はすべてのバックエンドでこれを有効にしようとしますが、サポートされない場合もあります。プリミティブの再起動を動的に制御することは、いくつかのAPIでは固定インデックスでのプリミティブの再起動が常にオンになっているため、不可能である。アプリケーションは、この機能がサポートされていると報告された場合、トポロジーに応じて、上記のインデックス値(may )が特別に扱われることを想定しなければならない。この機能がサポートされていると報告されている限り、プリミティブ再開がバックエンド間で同じ動作をすることが保証されている唯一の2つのトポロジーは、LineStrip とTriangleStrip です。 |
QRhi::NonDynamicUniformBuffers | 8 | 使用法UniformBuffer 、型Immutable またはStatic を持つバッファの作成がサポートされていることを示す。サポートされていないと報告された場合、一様(定数)バッファはDynamic のように作成されなければなりません。 |
QRhi::NonFourAlignedEffectiveIndexBufferOffset | 9 | 4バイト・アライメントでない有効インデックス・バッファ・オフセット (indexOffset + firstIndex * indexComponentSize ) がサポートされていることを示す。サポートされていない場合、アライメントされていない有効オフセットでdrawIndexed() を発行しようとすると、特定できない動作になる可能性があります。特にメタルに関連し、サポートされていないと報告される。 |
QRhi::NPOTTextureRepeat | 10 | Repeat ラップモードとミップマップフィルタリングモードが、非2乗サイズのテクスチャに対してサポートされていることを示します。実際には、これはGL_OES_texture_npot のない OpenGL ES 2.0 実装でのみ偽となり得ます。 |
QRhi::RedOrAlpha8IsRed | 11 | RED_OR_ALPHA8 フォーマットが 1 コンポーネント 8 ビットred フォーマットにマップされることを示します。これは、OpenGL ESまたは非コアプロファイルコンテキストを使用する場合、OpenGLを除くすべてのバックエンドの場合です。そこでは、GL_ALPHA (1コンポーネント8ビットalpha フォーマット)が代わりに使用されます。特別なテクスチャフォーマットを使用することで、テクスチャを作成するための単一のコードパスを持つことができ、実際のフォーマットを決定するのはバックエンドに任せ、featureフラグはテクスチャをサンプリングするための適切なシェーダーバリアントを選択するために使用できます。 |
QRhi::ElementIndexUint | 12 | 32ビット符号なし整数要素がインデックスバッファでサポートされていることを示します。実際には、これは、必要な拡張のないプレーンな OpenGL ES 2.0 実装で実行される場合を除き、どこでも真です。falseの場合、インデックス・バッファでは16ビット符号なし要素のみがサポートされます。 |
QRhi::Compute | 13 | コンピュートシェーダー、イメージロード/ストア、ストレージバッファがサポートされていることを示します。4.3より古いOpenGLと3.1より古いOpenGL ESはコンピュート・サポートがありません。 |
QRhi::WideLines | 14 | 1以外の幅の線がサポートされていることを示します。サポートされていないと報告された場合、グラフィックス・パイプライン・ステートで設定された線幅は無視されます。これは、いくつかのバックエンド(D3D11、D3D12、Metal)では常に偽になります。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 Simulator を含む古い iOS デバイスの Metal ではサポートされません。 |
QRhi::BaseInstance | 17 | インスタンス描画コマンドがfirstInstance 引数をサポートしていることを示します。サポートされていないと報告された場合、firstInstance値は無視され、インスタンスIDは0から始まります。実際には、この機能はOpenGL、およびiOS Simulatorを含む古いiOSデバイス上のMetalではサポートされません。 |
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 レベルの指定がサポートされていることを示す。サポートされていない場合、create() は、ターゲット mip レベルが 0 でないときは常に失敗する。実際には、この機能はOpenGL ES 2.0ではサポートされません。 |
QRhi::IntAttributes | 23 | シェーダー・パイプラインに対して符号付き整数型および符号なし整数型の入力属性を指定することがサポートされていることを示します。サポートされていない場合、build() は成功しますが、警告メッセージが表示されるだけで、ターゲット属性の値は壊れてしまいます。実際には、この機能は 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 のリードバックもサポートされています。浮動小数点フォーマットQRhiTexture::RGBA16F とRGBA32Fのリードバックは、実装がこれらのサポートを提供する限り、OpenGLでも動作するかもしれませんが、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 ()が機能していることを示します。テクスチャ配列がサポートされていない場合でも、テクスチャ配列は2つの独立した機能であるため、利用可能であることに注意してください。 |
QRhi::Tessellation | 32 | テッセレーション制御および評価ステージがサポートされていることを示します。サポートされていると報告された場合、QRhiGraphicsPipeline のトポロジーはPatches に設定でき、制御点の数はsetPatchControlPointCount() で設定でき、テッセレーション制御と評価のためのシェーダーはQRhiShaderStage リストで指定できる。テッセレーションシェーダーは、API間の移植性に問題があり(例えば、GLSL/SPIR-VをHLSLに変換することは、ハルシェーダーがどのように構造化されているかに起因する問題があります。特にDirect 3Dの場合、手書きのHLSLハルシェーダーとドメインシェーダーは、それぞれテッセレーション制御と評価ステージのために、各QShader 。アイソラインテッセレーションは、すべてのバックエンドでサポートされないため、避けるべきであることに注意してください。バックエンド間で移植可能な最大パッチ制御ポイント数は32です。 |
QRhi::GeometryShader | 33 | ジオメトリシェーダステージがサポートされていることを示します。サポートされている場合、QRhiShaderStage リストでジオメトリシェーダを指定できます。ジオメトリ・シェーダは、QRhi では実験的な機能と見なされており、実装が実行時にサポートされていると報告することを前提として、Vulkan、Direct 3D、OpenGL(3.2+)、OpenGL ES(3.2+)でのみサポートされることが期待されます。ジオメトリーシェーダーにはAPI間の移植性の問題があるため、普遍的なソリューションを保証することはできません。Metalでサポートされることはないでしょう。Direct 3D では、手書きの HLSL ジオメトリシェーダを各QShader に注入してジオメトリステー ジに使用する必要がありますが、qsb では SPIR-V から生成できないためです。 |
QRhi::TextureArrayRange | 34 | texture arrays 、シェーダに公開する範囲を指定できることを示す。通常、すべての配列レイヤが公開され、レイヤを選択するかどうかはシェーダ次第です(sampler2DArray をサンプリングするときに texture() に渡される 3 番目の座標を介して)。サポートされている場合、ネイティブテクスチャbuilding またはimporting の前に QRhiTexture::setArrayRangeStart() と QRhiTexture::setArrayRangeLength() を呼び出すと効果があり、配列から指定された範囲のみを選択するようになります。これは、アクセラレイティッド・ビデオ・デコーディングや Direct 3D 11 で作業するときなど、特殊な場合に必要になります。なぜなら、D3D11_BIND_DECODER とD3D11_BIND_SHADER_RESOURCE の両方を持つテクスチャ配列は、単一の配列レイヤーが選択されている場合にのみ、シェーダ・リソースとして使用できるからです。これはすべて、テクスチャがQRhiShaderResourceBinding::SampledTexture またはQRhiShaderResourceBinding::Texture シェーダリソースとして使用される場合にのみ適用され、イメージロード/ストアとは互換性がないことに注意してください。この機能は、すべてのグラフィックスAPIにうまくマッピングされないため、一部のバックエンドでのみ利用可能であり、いずれにせよ特殊なケースのサポートを提供することを意図しているだけです。実際には、この機能はDirect3D 11/12とVulkanでサポートされることが期待できます。 |
QRhi::NonFillPolygonMode | 35 | デフォルトの Fill 以外の PolygonMode の設定がQRhiGraphicsPipeline でサポートされていることを示します。モードを Line に変更する一般的なユースケースは、ワイヤフレームレンダリングを得ることです。ただし、これは OpenGL ES のコア機能としては利用できず、Vulkan ではオプションです。 |
QRhi::OneDimensionalTextures | 36 | 1Dテクスチャがサポートされていることを示します。実際には、この機能は OpenGL ES ではサポートされません。 |
QRhi::OneDimensionalTextureMipmaps | 37 | 1Dテクスチャのミップマップの生成がサポートされていることを示します。実際には、OneDimensionalTextures、Metal、Direct 3D 12のサポートを報告しないバックエンドでは、この機能はサポートされません。 |
QRhi::HalfAttributes | 38 | シェーダパイプラインに対して半精度(16 ビット)浮動小数点型の入力アトリビュートを指定することがサポートされていることを示します。サポートされていない場合、build() は成功しますが、警告メッセージが表示されるだけで、ターゲットアトリビュートの値は壊れてしまいます。実際には、OpenGL ES 2.0やOpenGL 2.xの実装では、この機能はサポートされていません。Direct3D 11/12は半精度入力アトリビュートをサポートしていますが、half3タイプはサポートしていないことに注意してください。D3Dバックエンドはhalf3属性をhalf4として渡します。クロスプラットフォームの互換性を確保するために、half3入力は8バイトにパディングされるべきです。 |
QRhi::RenderToOneDimensionalTexture | 39 | 1Dテクスチャレンダーターゲットがサポートされていることを示します。実際には、OneDimensionalTextures や Metal のサポートを報告しないバックエンドでは、この機能はサポートされません。 |
QRhi::ThreeDimensionalTextureMipmaps | 40 | 3Dテクスチャのミップマップの生成がサポートされていることを示します。実際には、この機能は Direct 3D 12 ではサポートされません。 |
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 テクスチャ配列との組み合わせでのみ利用可能であることに注意してください。レンダリングを個々のテクスチャに最適化するために使用することはでき ません(たとえば、左目用と右目用の 2 つ)。むしろ、マルチビューレンダーパスのターゲットは常にテクスチャ配列であり、各ビューに対応するレイヤー(配列要素)に自動的にレンダリングされます。したがって、この機能はTextureArraysも意味します。マルチビューレンダリングは、テッセレーションやジオメトリシェーダとの組み合わせではサポートされていません。マルチビューレンダリングの詳細については、QRhiColorAttachment::setMultiViewCount() を参照してください。この enum 値は Qt 6.7 で導入されました。 |
QRhi::TextureViewFormat | 42 | QRhiTexture のview format の設定が有効であることを示します。サポートされていると報告された場合、読み込み(サンプリング)または書き込み(レンダーターゲット/イメージロードストア)ビューモードを設定すると、テクスチャの表示形式が変更されます。サポートされていない場合、ビューフォーマットを設定しても効果はありません。Qt は、基礎となる 3D API やその実装におけるフォーマットの互換性やリソースの表示ルールについて、何の知識もコントロールも持っていないことに注意してください。不適当な、互換性のないフォーマットを渡すと、エラーや仕様外の動作につながる可能性があります。これは主に、sRGBフォーマットで作成されたテクスチャへのレンダリングをnon-sRGBに「キャスト」して、シェーダ書き込み時の不要なlinear->sRGB変換を回避できるようにするために提供されています。他のタイプのキャスティングは、基礎となる API によって機能する場合としない場合があります。現在、Vulkan および Direct 3D 12 用に実装されています。D3D12 では、この機能はCastingFullyTypedFormatSupported がサポートされている場合にのみ利用可能です。https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.htmlを参照してください(また、QRhi は常にテクスチャに完全型付けフォーマットを使用することに注意してください)。この列挙値は Qt 6.8 で導入されました。 |
QRhi::ResolveDepthStencil | 43 | マルチサンプル深度または深度ステンシルテクスチャの解決がサポートされていることを示します。そうでない場合、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)にレンダリングする場合など、非マルチサンプルの深度テクスチャに解決することが必要になるまれなケースのために提供されます。この enum 値は Qt 6.8 で導入されました。 |
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() は常に空の blob を返します。パイプラインキャッシュの内容の取得と復元がサポートされていないバックエンドでは、このフラグは何の効果もなく、直列化されたキャッシュデータは常に空になります。関連するデータ構造を維持するコストは、いくつかのバックエンドで取るに足らないものではないため、フラグはオプトインのメカニズムを提供します。Vulkanでは、この機能はVkPipelineCache、vkGetPipelineCacheData、およびVkPipelineCacheCreateInfo::pInitialDataに直接マッピングされます。Direct3D 11 では実際のパイプラインキャッシュはありませんが、HLSL->DXBC のコンパイル結果は保存され、このメカニズムでシリアライズ/デシリアライズできます。これにより、オフラインでプリコンパイルされたバイトコードではなく、HLSLソースが付属しているシェーダの場合、アプリケーションの今後の実行で、時間のかかるD3DCompile()をスキップすることができます。これは、HLSLソースのコンパイルが大量に行われている場合に、起動時間とロード時間を大幅に向上させることができます。OpenGL では、"パイプラインキャッシュ "は、シェーダープログラムのバイナリを 取得してロードすることでシミュレートされます(ドライバでサポートされている場 合)。OpenGL では、Qt が提供するシェーダー/プログラム・バイナリのための、追加のディスクベースのキャッシング・メカニズムがあります。複数のキャッシュにプログラムバイナリを保存することは賢明ではないため、このフラグが設定されるたびに、それらへの書き込みが無効になる可能性があります。 |
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
どのグラフィックス API 固有のバックエンドがQRhi インスタンスで使用されるかを記述します。
定数 | 値 |
---|---|
QRhi::Null | 0 |
QRhi::Vulkan | 1 |
QRhi::OpenGLES2 | 2 |
QRhi::D3D11 | 3 |
QRhi::D3D12 | 5 |
QRhi::Metal | 4 |
enum QRhi::ResourceLimit
クエリするリソース制限を記述します。
定数 | 値 | 説明 |
---|---|---|
QRhi::TextureSizeMin | 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 の責任です。このようなレンダリングコードは、QRhi バックエンド自体と同様に、バッファなどのリソースに対してダブルバッファリング(値が 2 の場合)を実行したい場合があるためです。現在のフレームスロットインデックス(0、1、...、N-1 の順に折り返す値)は、QRhi::currentFrameSlot() から取得できます。この値は、グラフィックスAPIがコマンド送信プロセスに対してそのような低レベルの制御を提供しないバックエンドでは1である。QRhi この値が1であってもパイプライン化は起こるかもしれないことに注意する(D3D11のようないくつかのバックエンドは、例えば、パイプラインをストールさせないユニフォームバッファの更新戦略を使用することによって、これを有効にしようとするように設計されている)。 |
QRhi::MaxAsyncReadbackFrames | 5 | 非同期テクスチャまたはバッファのリードバックがstarting a new frame で完了することが保証されるsubmitted フレーム数(リードバックを含むフレームを含む)。 |
QRhi::MaxThreadGroupsPerDimension | 6 | ディスパッチ可能な計算ワーク/スレッドグループの最大数。事実上、QRhiCommandBuffer::dispatch ()の引数の最大値。通常は65535である。 |
QRhi::MaxThreadsPerThreadGroup | 7 | 1つのローカル作業グループ内の最大呼び出し数、または他の用語では、スレッドグループ内の最大スレッド数。実質的に、計算シェーダにおける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バイト(224個の4コンポーネント、各コンポーネントベクトルあたり32ビット)と低いかもしれません。それ以外の場所では、通常16384(1024 vec4s)または65536(4096 vec4s)です。 |
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である。 |
メンバ関数ドキュメント
[noexcept]
QRhi::~QRhi()
デストラクタ。バックエンドを破棄し、リソースを解放します。
void QRhi::addCleanupCallback(const QRhi::CleanupCallback &callback)
QRhi が破棄されたとき、またはrunCleanup() が呼び出されたときに呼び出されるcallback を登録します。
このコールバックは、グラフィックス・リソースがまだ利用可能な状態で実行されるため、アプリケーションがQRhi に属するQRhiResource インスタンスをきれいに解放する機会を提供します。これは、キャッシュが QRhiResources または QRhiResources を含むオブジェクトを保持するcache
タイプのオブジェクトに格納されたリソースの寿命を管理する場合に特に便利です。
runCleanup() および~QRhi()も参照してください 。
void QRhi::addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
これはオーバーロードされた関数です。
QRhi が破棄されたとき、またはrunCleanup() が呼び出されたときに呼び出されるようにcallback を登録します。このオーバーロードは、与えられたコールバックが一度だけ登録される(そして呼び出される)ことを保証するために使用される不透明なポインタ、key を取ります。
removeCleanupCallback()も参照 。
QRhi::Implementation QRhi::backend() const
このQRhi のバックエンド型を返します。
const char *QRhi::backendName() const
QRhi のバックエンド型を文字列で返します。
[static]
const char *QRhi::backendName(QRhi::Implementation impl)
バックエンドのフレンドリーな名前impl を返します。
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {})
swapChain の次に利用可能なバッファをターゲットとして新しいフレームを開始します。
フレームはリソースの更新と、1つ以上のレンダーパスとコンピュートパスで構成されます。
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 、...)での使用も可能ですが、並列性が低下するため、使用頻度は低くすべきです。
オフスクリーン・フレームは、GPU がまだ前のフレームを処理している間、 CPU に別のフレームを生成させない可能性があります。これには、リードバックがスケジューリングされている場合、endOffscreenFrame() が戻ってくれば結果が利用可能になることが保証されるという副作用があります。スワップチェーンをターゲットとするフレームの場合はそうではあり ません。そこでは 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 rbResult
endOffscreenFrame() および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 = nullptr)
impl で指定されたグラフィックス API のバックエンドを持つ新しいQRhi インスタンスを、指定されたflags で返します。関数が失敗した場合はnullptr
を返します。
params は、 、 、 、 、 のような、 のバックエンド固有のサブクラスのいずれかのインスタンスを指す必要があります。 を作成する例については、これらのクラスを参照してください。QRhiVulkanInitParams QRhiMetalInitParams QRhiD3D11InitParams QRhiD3D12InitParams QRhiGles2InitParams QRhiInitParams QRhi
QRhi 指定されたAPIを初期化できない場合、create()は失敗し、バックエンドのデバッグ出力に警告が表示されます。しかし、 のクライアント、例えばQt Quickは、プラットフォームに応じて、要求されたAPIとは異なるAPIにフォールバックするための追加ロジックを提供することができる。後でcreate()を呼び出したときに初期化が成功するかどうかをテストするだけであれば、create()の代わりに ()を使用することが望ましい。バックエンドによっては、インフラストラクチャの完全な初期化を実行するcreate()とは対照的に、より軽量な方法でプロービングを実装することができるため、 、そのインスタンスがすぐに捨てられてしまうと無駄になってしまうからである。QRhi probe QRhi
importDevice によって、 自身を作成することなく、すでに存在するグラフィック・デバイスを使用することができる。NULLでない場合、このパラメータは のサブクラスの1つのインスタンスを指す必要があります: , , , 。正確な詳細とセマンティクスは、バックランドとその下にあるグラフィックスAPIに依存します。QRhi QRhiNativeHandles QRhiVulkanNativeHandles QRhiD3D11NativeHandles QRhiD3D12NativeHandles QRhiMetalNativeHandles QRhiGles2NativeHandles
probe()も参照してください 。
int QRhi::currentFrameSlot() const
フレームの記録中に現在のフレームスロットインデックスを返します。アクティブなフレーム外で呼び出された場合(つまり、isRecordingFrame() がfalse
の場合)は不定。
Vulkan や Metal のようなバックエンドでは、新しいフレームを開始し、CPU が GPU よりもすでにFramesInFlight - 1
フレーム進んでいる(フレーム番号current
~FramesInFlight
で投入されたコマンドバッファがまだ完了していないため)ことがわかるたびにブロックするのは、QRhi バックエンドの責任です。
フレーム間で変更される傾向のあるリソース(たとえば、QRhiBuffer::Dynamic 型のQRhiBuffer をバッ クするネイティブバッファオブジェクトなど)は、複数のバージョンで存在します。そのため、前のフレームがまだ処理されている間に提出できる各フレームは、それ自身のコピーで動作します。(GPUでまだ使用中である可能性のあるリソースのコンテンツに触れるべきではありませんが、前のフレームが終了するのを常に待つだけでは、GPUの使用率が低下し、最終的にパフォーマンスと効率が低下します)。
概念的には、これはいくつかのC++コンテナや他の型が使用するコピーオンライト方式にいくらか似ています。また、OpenGLやDirect 3D 11の実装が、ある種のオブジェクトに対して内部的に実行するものと似ているかもしれません。
実際には、このようなダブル(またはトリプル)バッファリングリソースは、Vulkan、Metal、および類似のQRhi バックエンドで、固定数のネイティブリソース(VkBuffer など)slots
をQRhiResource の背後に持つことによって実現されます。これは、0、1、...、FramesInFlight-1 を実行するフレームスロットインデックスによってインデックス付けされ、ラップアラウンドすることができます。
これらはすべて、QRhi のユーザーに対して透過的に管理されます。 しかし、グラフィックスAPIで直接レンダリングを行うアプリケーションは、独自のグラフィックスリソースに対して同様の2重または3重のバッファリングを行いたいと思うかもしれません。その場合、インフライトフレームの最大数(resourceLimit() で取得可能)と現在のフレーム(スロット)インデックス(この関数で返される)の値を知っていれば、最も簡単に実現できます。
isRecordingFrame()、beginFrame()、endFrame()も参照 。
QRhiDriverInfo QRhi::driverInfo() const
正常に初期化されたQRhi インスタンスで使用されているグラフィックデバイスのメタデータを返します。
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {})
swapChain の最後のbeginFrame() で開始されたフレームを終了、コミット、提示します。
ダブル(またはトリプル)バッファリングは、QRhiSwapChain とQRhi によって内部的に管理されます。
flags をオプションで使用すると、特定の方法で動作を変更できます。 を渡すと、PresentコマンドのキューイングやswapBuffersの呼び出しが省略される。QRhi::SkipPresent
成功するとQRhi::FrameOpSuccess を返し、失敗するとQRhi::FrameOpResult を返す。これらのエラーのいくつかは、「後で再試行する」タイプのソフトなエラーとして扱われるべきである:QRhi::FrameOpSwapChainOutOfDate が返された場合、スワップチェーンはQRhiSwapChain::createOrResize() を呼び出すことで、サイズ変更または更新される。QRhi::FrameOpDeviceLost はグラフィック・デバイスが失われたことを意味しますが、QRhi 自体を含むすべてのリソースを解放し、すべてのリソースを再作成することで回復できる場合もあります。さらなる議論については、isDeviceLost ()を参照。
beginFrame() およびisDeviceLost()も参照の こと。
QRhi::FrameOpResult QRhi::endOffscreenFrame(QRhi::EndFrameFlags flags = {})
終了、サブミット、オフスクリーンフレームの待機。
flags は現在使用されていません。
beginOffscreenFrame()も参照 。
QRhi::FrameOpResult QRhi::finish()
グラフィックス・キュー(該当する場合)の作業が完了するのを待ち、リードバックの完了やリソースの解放など、すべての遅延操作を実行します。フレームの内側でも外側でも呼び出せますが、パスの内側では呼び出せません。フレーム内では、コマンドバッファ上のすべての作業をサブミットすることを意味します。
注: この関数は避けてください。この関数が必要になるケースとしては、スワップチェインベースのフレームでエンキューされたリードバックの結果が、固定された指定された時点で必要となり、その結果を待ちたい場合があります。
bool QRhi::isClipDepthZeroToOne() const
基礎となるグラフィックス API がクリップ空間で深度範囲 [0, 1] を使用している場合、true
を返します。
OpenGLはポストプロジェクションの深度範囲として[-1, 1]を使用するため、実際にはOpenGLのみfalse
。(glDepthRange()によって制御されるNDCからウィンドウへのマッピングと混同しないように、glDepthRange()は、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 を積極的に使用している場合でもです。
Qt Quick のような、QRhi 上に構築された Qt 独自のフレームワークは、デバイスの損失が発生したときに適切な処理を行い、適切な手段を講じることが期待できます。テクスチャやバッファのようなグラフィックリソースのデータがCPU側でまだ利用可能であれば、その時点でグラフィックリソースをシームレスに再初期化できるため、そのようなイベントはアプリケーションレベルではまったく気にならないかもしれません。しかし、QRhi で直接動作するアプリケーションやライブラリは、デバイスが失われた状況を自ら確認し、処理するように準備することが期待されます。
注意: OpenGLでは、アプリケーションはQOpenGLContext でQSurfaceFormat::ResetNotification を設定することで、コンテキスト・リセット通知にオプトインする必要があるかもしれません。これは通常、QRhiGles2InitParams::format でフラグを有効にすることで行われます。しかし、システムによっては、このフラグが設定されていなくてもコンテキストリセットの状況が生成される場合があることに留意してください。
bool QRhi::isFeatureSupported(QRhi::Feature feature) const
指定されたfeature がサポートされている場合、true
を返す。
bool QRhi::isRecordingFrame() const
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コンテキストをカレントにします。この関数は他のバックエンドには影響しません。
QRhi が OpenGL バックエンドを使用している限り、アプリケーションによって提供される外部の OpenGL コードが、OpenGL を直接使用しても以前と同じように実行できるようにする必要がある場合に、この関数を呼び出すことは、一般的に Qt フレームワークのコードに関係します。
QOpenGLContext::makeCurrent ()と同様に、失敗した場合はfalseを返す。操作に失敗した場合、isDeviceLost() を呼び出して、コンテキストの喪失があったかどうかを判断することができる。このようなチェックは、QOpenGLContext::isValid() によるチェックと同等である。
QOpenGLContext::makeCurrent() およびQOpenGLContext::isValid()も参照 。
[static]
int QRhi::mipLevelsForSize(const QSize &size)
与えられたsize の mip レベル数を返す。
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 は、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 にレンダリングし、非RGBA8QRhiTexture に解決することは、QRhiRenderBuffer をバックアップするストレージが一致する非RGBA8フォーマットを使用することを(いくつかのグラフィックスAPIで)意味します。つまり、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() を呼び出すことで提供されることになります。関連するすべての mip レベルのデータがないテクスチャでサンプラーを使用しようとすると、レンダリングエラーが発生します。
QRhiResource::destroy()も参照してください 。
QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
新しいシェーダーリソースバインディングコレクションリソースを返します。
QRhiResource::destroy() も参照して ください。
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 テクスチャを返します。
1D テクスチャ配列は、flags にQRhiTexture::OneDimensional が設定されている必要があります。pixelSize の高さが 0 の場合、この関数は暗黙的にこのフラグを設定します。
注意: format は要求された内部フォーマットと外部フォーマットを指定します。つまり、テクスチャにアップロードされるデータは互換性のあるフォーマットである必要があり、ネイティブテクスチャは内部でこのフォーマットを使用する可能性があります(ただし、少なくとも OpenGL の場合は保証されません)。
注意: 1Dテクスチャは、実行時にOneDimensionalTextures 機能がサポートされていると報告された場合にのみ機能します。さらに、1Dテクスチャのミップマップは、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 に設定する必要があります。
1D テクスチャは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 を持つ新しい1Dまたは2Dテクスチャ配列を返します。
この関数は暗黙的にflags にQRhiTexture::TextureArray を設定します。
1 次元テクスチャ配列は、flags にQRhiTexture::OneDimensional が設定されている必要があります。pixelSize の高さが 0 の場合、この関数は暗黙的にこのフラグを設定します。
注意: テクスチャ配列とテクスチャの配列を混同しないでください。この関数で作成されたQRhiTexture は、シェーダ内の 1D または 2D 配列サンプラで使用できます。例えば、layout(binding = 1) uniform sampler2DArray texArr;
。テクスチャの配列とは、QRhiShaderResourceBinding::sampledTextures() とカウント > 1 を介してシェーダに公開され、シェーダ内でたとえば次のように宣言されたテクスチャのリストを指します:layout(binding = 1) uniform sampler2D textures[4];
注意: これはTextureArrays 機能が実行時にサポートされていると報告された 場合にのみ機能します。
Note: 1D テクスチャは、OneDimensionalTextures 機能が実行時にサ ポートされていると報告されたときのみ機能します。さらに、1Dテクスチャのミップマップは、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::destroy() を呼び出すことで、バッチは再利用のためにプールに戻されます。
注: 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 から収集されたデータを持つバイナリデータ blob を返す。
キャッシュデータを保存し、同じアプリケーションの後続の実行で再読み込 むことで、パイプラインとシェーダの作成時間を短縮できる可能性があります。キャッシュとその直列化されたバージョンに何が含まれるかは特定されておらず、常に使用されるバックエンドに固有であり、場合によってはグラフィックス API の特定の実装にも依存します。
PipelineCacheDataLoadSave がサポートされていないと報告された場合、返されるQByteArray は空です。
create() の呼び出し時にEnablePipelineCacheDataSave フラグが指定されていない場合、PipelineCacheDataLoadSave 機能がサポートされていても、返されるQByteArray は空になることがある。
返されたデータが空でない場合、それは常に Qt のバージョンとQRhi バックエンドに固有です。さらに、グラフィック・デバイスや使用されているドライバのバージョンに強く依存している場合もあります。QRhi は、データが常に安全にsetPipelineCacheData() に渡されるように、適切なヘッダとセーフガードを追加します。したがって、別のバージョンのドライバで実行されたデータをロードしようとすると、安全かつ優雅に処理されます。
注: releaseCachedResources ()を呼び出すと、バックエンドによっては、収集されたパ イプライン・データがクリアされることがある。その後にこの関数を呼び出すと、データが返されないことがある。
この機能の詳細については、EnablePipelineCacheDataSave を参照。
注: この関数の呼び出し回数は最小限に抑えてください。blobの取得は必ずしも安価な操作ではないため、この関数は低い頻度でのみ呼び出す必要があり、理想的にはアプリケーションを閉じるときなど、1回のみ呼び出す必要があります。
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::runCleanup()
登録されているすべてのクリーンアップ関数を呼び出します。その後、クリーンアップコールバックのリストがクリアされます。通常、QRhi を破棄すると自動的にこの処理が行われますが、キャッシュされた必要でないリソースをすべて解放するためにクリーンアップをトリガーすると便利なことがあります。
addCleanupCallback()も参照 。
void QRhi::setPipelineCacheData(const QByteArray &data)
data をパイプラインキャッシュにロードします。
PipelineCacheDataLoadSave がサポートされていないと報告された場合、この関数を呼び出しても安全であるが、何の効果もない。
pipelineCacheData() によって返される blob は、常に Qt バージョン、QRhi バックエンド、場合によってはグラフィックデバイス、グラフィックドライバの特定のバージョンに固有です。QRhi は、データが常にこの関数に安全に渡されるように、適切なヘッダとセーフガードを追加します。ドライバが新しいバージョンにアップグレードされた場合や、データが異なるQRhi バックエンドから生成された場合など、不一致がある場合は、警告が出力され、data は安全に無視されます。
Vulkanでは、これはVkPipelineCacheに直接マッピングされます。この関数を呼び出すと、新しいVulkanパイプラインキャッシュオブジェクトが作成され、その初期データはdata 。このパイプラインキャッシュオブジェクトは、その後に作成されるすべてのQRhiGraphicsPipeline 、QRhiComputePipeline オブジェクトで使用されるため、パイプラインの作成が高速化される可能性があります。
他の API では、実際のパイプラインキャッシュはありませんが、シェーダーコンパイル(D3D)ま たはプログラムバイナリ(OpenGL)のバイトコードでキャッシュを提供することがあります。実行時にソースから多くのシェーダーコンパイルを行うアプリケーションで は、この関数を使用した以前の実行から「パイプラインキャッシュ」が事前にシードさ れていれば、その後の実行で大幅なブーストを提供できます。
注: QRhi は、data がパイプラインとシェーダ作成のパ フォーマンスに影響を与えることを保証することはできません。Vulkan のような API では、data を何らかの目的で使用するか、無視するかはドライバ次第です。
この機能の詳細についてはEnablePipelineCacheDataSave を参照してください。
注: QRhi によって提供されるこのメカニズムは、ドライバ独自の内部キャッシュメカニズム(もしあれば)とは独立しています。つまり、グラフィックスAPIとその実装によっては、data を取得してから再ロードすることの正確な効果は予測できない。Qt の制御外の他のキャッシュ機構がすでに有効になっている場合、パフォーマンスの向上はまったく見られないかもしれません。
注意: この関数の呼び出し回数は最小限にしてください。blobのロードは常に安価な操作ではないため、この関数は低い頻度でのみ呼び出されるべきで、理想的にはアプリケーションの起動時などに一度だけ呼び出されるべきです。
pipelineCacheData() およびisFeatureSupported()も参照してください 。
[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()も参照のこと 。
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 は、スワップチェーンがターゲットとしているQWindow です。
返された構造体はQRhiSwapChain::setProxyData() に渡すことができる。これは、スレッド化されたレンダリングシステムでは理にかなっています。この静的関数は、すべてのQRhi 操作とは異なり、メイン(gui)スレッドで呼び出され、その後、QRhi とQRhiSwapChain を操作するスレッドに転送され、スワップチェーンに渡されることが期待されます。これにより、例えばNSViewからCAMetalLayerにクエリを実行し、そのデータをレンダリングスレッド上のQRhiSwapChain 。Metalの例では、専用のレンダリングスレッド上でview.layerアクセスを行うと、Xcode Thread Checkerで警告が発生します。データプロキシメカニズムを使用すると、これは回避されます。
スレッドが関与していない場合、QRhiSwapChainProxyData を生成して渡す必要はありません。バックエンドは、必要なものは何でもそれ自身でクエリできることが保証されており、すべてがメイン(gui)スレッドに存在するのであれば、それで十分です。
注: impl は、QRhi が作成されたものと一致しなければならない。例えば、アップル以外のプラットフォームでQRhi::Metal 。
関連する非会員
[alias, since 6.7]
QRhiShaderResourceBindingSet
QRhiShaderResourceBindings のシノニム。
この型定義はQt 6.7で導入された。
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 このドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。