QRhiSwapChain Class

スワップチェーンリソース。詳細...

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
Inherits: QRhiResource

パブリック・タイプ

enum Flag { SurfaceHasPreMulAlpha, SurfaceHasNonPreMulAlpha, sRGB, UsedAsTransferSource, NoVSync, MinimalBufferCount }
flags Flags
enum Format { SDR, HDRExtendedSrgbLinear, HDR10, HDRExtendedDisplayP3Linear }
enum StereoTargetBuffer { LeftBuffer, RightBuffer }

パブリック関数

virtual bool createOrResize() = 0
virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0
virtual QRhiRenderTarget *currentFrameRenderTarget() = 0
virtual QRhiRenderTarget *currentFrameRenderTarget(QRhiSwapChain::StereoTargetBuffer targetBuffer)
QSize currentPixelSize() const
QRhiRenderBuffer *depthStencil() const
QRhiSwapChain::Flags flags() const
QRhiSwapChain::Format format() const
virtual QRhiSwapChainHdrInfo hdrInfo()
virtual bool isFormatSupported(QRhiSwapChain::Format f) = 0
virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0
QRhiSwapChainProxyData proxyData() const
QRhiRenderPassDescriptor *renderPassDescriptor() const
int sampleCount() const
void setDepthStencil(QRhiRenderBuffer *ds)
void setFlags(QRhiSwapChain::Flags f)
void setFormat(QRhiSwapChain::Format f)
void setProxyData(const QRhiSwapChainProxyData &d)
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
void setSampleCount(int samples)
void setWindow(QWindow *window)
virtual QSize surfacePixelSize() = 0
QWindow *window() const

再実装されたパブリック関数

virtual QRhiResource::Type resourceType() const override

詳細説明

スワップチェーンは、サーフェスへのレンダリング結果の提示を可能にする。スワップチェーンは通常、カラーバッファのセットによって支えられている。これらのうち、一度に表示されるのは1つである。

以下は、QWindow にレンダリングするためにスワップチェーンと関連リソースを作成・管理するための典型的なパターンである:

void init()
{
    sc = rhi->newSwapChain();
    ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
                              QSize(), // no need to set the size here due to UsedWithSwapChainOnly
                              1,
                              QRhiRenderBuffer::UsedWithSwapChainOnly);
    sc->setWindow(window);
    sc->setDepthStencil(ds);
    rp = sc->newCompatibleRenderPassDescriptor();
    sc->setRenderPassDescriptor(rp);
    resizeSwapChain();
}

void resizeSwapChain()
{
    hasSwapChain = sc->createOrResize();
}

void render()
{
    if (!hasSwapChain || notExposed)
        return;

    if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
        resizeSwapChain();
        if (!hasSwapChain)
            return;
        newlyExposed = false;
    }

    rhi->beginFrame(sc);
    // ...
    rhi->endFrame(sc);
}

スワップチェーンのサイズを変更するために、QWindow のリサイズ・イベントに依存することは避けてください。特に、サーフェスのサイズがQWindow で報告された寸法と完全に一致するとは限りません。安全でクロスプラットフォームなアプローチは、新しいフレームを開始するたびにsurfacePixelSize() を介してチェックを行うことです。

スワップチェーンの解放は、QWindow 、基盤となるネイティブ・ウィンドウが完全に立ち上がり、実行されている間に行わなければなりません。先ほどの例を基に説明します:

void releaseSwapChain()
{
    if (hasSwapChain) {
        sc->destroy();
        hasSwapChain = false;
    }
}

// assuming Window is our QWindow subclass
bool Window::event(QEvent *e)
{
    switch (e->type()) {
    case QEvent::UpdateRequest: // for QWindow::requestUpdate()
        render();
        break;
    case QEvent::PlatformSurface:
        if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
            releaseSwapChain();
        break;
    default:
        break;
    }
    return QWindow::event(e);
}

スワップチェーンの初期化と最初のフレームのレンダリング開始は、いつでも開始できるわけではありません。安全でクロスプラットフォームなアプローチは、exposeイベントに依存することです。QExposeEvent は緩く指定されたイベントで、プラットフォームによって異なりますが、ウィンドウがマップされたり、見えなくなったり、サイズが変更されたりするたびに送信されます。

void Window::exposeEvent(QExposeEvent *)
{
    // initialize and start rendering when the window becomes usable for graphics purposes
    if (isExposed() && !running) {
        running = true;
        init();
    }

    // stop pushing frames when not exposed or size becomes 0
    if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
        notExposed = true;

    // continue when exposed again and the surface has a valid size
    if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
        notExposed = false;
        newlyExposed = true;
    }

    if (isExposed() && !sc->surfacePixelSize().isEmpty())
        render();
}

レンダリングが開始されると、新しいフレームを要求する簡単な方法はQWindow::requestUpdate() です。プラットフォームによっては、これは単なる小さなタイマーですが、特定の実装を持つものもあります。たとえば、macOSやiOSでは、CVDisplayLinkによってバックアップされている場合があります。例えば、macOSやiOSではCVDisplayLinkによってバッ クアップされる。上記の例では、QEvent::UpdateRequest を処理することで、すでに更新要求の準備をしている。

QRhiRenderTarget 、QRhiSwapChainはQRhiCommandBuffer も管理する。QRhi::endFrame ()を呼び出すと、記録されたコマンドが送信され、present リクエストもエンキューされる。デフォルトの動作は、ディスプレイの垂直リフレッシュへの同期が有効であることを意味する、スワップ間隔1でこれを行うことです。したがって、beginFrame()とendFrame()を呼び出すレンダリングスレッドは、vsyncにスロットルされます。バックエンドによっては、flags ()でQRhiSwapChain:NoVSync

マルチサンプリング(MSAA)は、setSampleCount ()を介して要求された場合、アプリケーションに対して透過的に処理されます。該当する場合、QRhiSwapChainは追加のカラーバッファを作成し、フレーム終了時にmultisample resolveコマンドを発行します。OpenGLの場合は、QRhi を初期化する前にQSurfaceFormat::setDefaultFormat() を呼び出して、QSurfaceFormat を介して適切なサンプル数を要求する必要があります。

注: これは互換性保証に制限のあるRHI APIです。詳細はQRhi を参照してください。

メンバー型ドキュメント

enum QRhiSwapChain::Flag
flags QRhiSwapChain::Flags

スワップチェーンのプロパティを表すフラグ値

定数説明
QRhiSwapChain::SurfaceHasPreMulAlpha1 << 0ターゲットのサーフェスがアルファを事前に乗算した透明度を持つことを示します。例えば、これは Qt Quick が、ターゲットQWindow でアルファチャンネルが有効になっているときに使用するものです。これは、scenegraph rendrerer が、常に赤、緑、青の値にアルファを乗算したフラグメントを出力するためです。プラットフォーム間で同一の動作を保証するために、スワップチェーン上でこのフラグが設定されるときは常に、ターゲットQWindow 上でQSurfaceFormat::alphaBufferSize() をゼロ以外の値に設定してください。
QRhiSwapChain::SurfaceHasNonPreMulAlpha1 << 1ターゲットのサーフェスがアルファを乗算しない透明度を持つことを示す。システム・コンポジターが常に事前乗算されたアルファを持つコンテンツを期待している場合、これはシステムによってはサポートされないことに注意してください。その場合、このフラグを設定した場合の動作はSurfaceHasPreMulAlphaと同等になることが期待されます。
QRhiSwapChain::sRGB1 << 2スワップチェーンのカラーバッファおよび/またはレンダーターゲットビューにsRGBフォーマットを選択する要求。これは、このスワップチェーンをターゲットとするすべてのコンテンツでsRGBフレームバッファの更新とブレンドが有効になることを意味し、オプトアウトは不可能であることに注意してください。OpenGLの場合は、さらにQWindowQSurfaceFormatsRGBColorSpace を設定する。スワップチェーン形式がQRhiSwapChain::SDR に設定されている場合にのみ適用される。
QRhiSwapChain::UsedAsTransferSource1 << 3QRhiResourceUpdateBatch::readBackTexture() のリードバックのソースとしてスワップチェーンが使用されることを示す。
QRhiSwapChain::NoVSync1 << 4垂直同期待ちを無効にすることを要求し、レンダリングスレッドのスロットルも回避します。この動作はバックエンドに依存し、制御可能な場合にのみ適用されます。リクエストを完全に無視するものもあります。OpenGLの場合、代わりにQSurfaceFormat::setSwapInterval()を介してQWindow でスワップ間隔を0に設定してみてください。
QRhiSwapChain::MinimalBufferCount1 << 5バッファの最小数でスワップチェーンを作成することを要求します。これは、グラフィックスの実装がそれよりも高い最小数を持たない限り、実際には2です。このような制御がグラフィックスAPIを介して利用可能なバックエンドでのみ適用可能です。デフォルトでは、要求するバッファ数を決めるのはバックエンド次第であり(実際にはほとんど常に2か3です)、アプリケーションには関係ありません。しかし、例えばVulkanの場合、モバイルデバイス上のVulkan実装で奇妙なパフォーマンスの問題を避けるため、バックエンドはおそらく高い数(3)を好むでしょう。いくつかのプラットフォームでは、低いバッファ数(2)を強制することが有益であることが証明される可能性があります。スワップチェーンの画像バッファ数がN よりも大きい場合でも、CPU(QRhi )は GPU よりも最大N - 1 フレーム先にフレームを準備します(N =QRhi::FramesInFlight 、通常は 2 )。

Flags 型はQFlags<Flag> の typedef です。Flag値のORの組み合わせを格納する。

enum QRhiSwapChain::Format

スワップチェーン・フォーマットを記述する。デフォルトのフォーマットはSDRである。

この列挙型は、isFormatSupported() と共に使用され、指定されたフォーマットでスワップチェーンを作成することがプラットフォームとウィンドウの関連スクリーンでサポートされているかどうかを事前にチェックします。また、setFormat() と共に使用され、createOrResize() を初めて呼び出す前に、要求されたフォーマットをスワップチェーンに設定します。

定数説明
QRhiSwapChain::SDR0バックエンドとプラットフォームに応じて、8ビットRGBAまたはBGRA。特にOpenGL ESでは、プラットフォームが8ビット未満を提供することが起こり得ます(例えば、EGLとQSurfaceFormat が565または444フォーマットを選択するため - これはQRhi の制御外です)。標準ダイナミックレンジ。QRhiSwapChain::sRGB フラグの設定と組み合わせてもよい。
QRhiSwapChain::HDRExtendedSrgbLinear116ビットフロートRGBA、ハイダイナミックレンジ、拡張リニアsRGB(scRGB)色空間。これはRec.709プライマリ(SDR/sRGBと同じ)とリニアカラーを含む。ディスプレイのネイティブ色空間(HDR10など)への変換は、ウィンドウシステムによって実行されます。Windowsでは、これはシステムコンポジターの標準色空間であり、デスクトッププラットフォームでは一般的にHDRスワップチェーンの推奨フォーマットです。
QRhiSwapChain::HDR10210ビット符号なしint RGBまたはBGR、2ビットアルファ付き、ハイダイナミックレンジ、HDR10(Rec.2020)色空間、ST2084 PQ伝達関数付き。
QRhiSwapChain::HDRExtendedDisplayP3Linear316ビットfloat RGBA、ハイダイナミックレンジ、拡張リニアディスプレイP3色空間。iOSやVisionOSなどのプラットフォームにおけるHDRの主要な選択肢。

enum QRhiSwapChain::StereoTargetBuffer

ステレオスコピック・スワップチェーンで使用するバックバッファを選択します。

定数
QRhiSwapChain::LeftBuffer0
QRhiSwapChain::RightBuffer1

メンバー関数 ドキュメント

[pure virtual] bool QRhiSwapChain::createOrResize()

まだスワップチェインが作成されていない場合はスワップチェインを作成し、スワップチェインバッファのサイズをターゲットサーフェスの現在のサイズに合わせて変更します。ターゲットサーフェスのサイズが以前と異なるときはいつでもこれを呼び出す。

注意: destroy() を呼び出すのは、スワップチェーンを完全に解放する必要があるときだけで、通常はQPlatformSurfaceEvent::SurfaceAboutToBeDestroyed のときである。サイズ変更を行うには、createOrResize()を呼び出すだけでよい。

成功した場合はtrue を返し、グラフィックス操作に失敗した場合はfalse を返す。戻り値に関係なく、destroy ()を呼び出すことは常に安全である。

[pure virtual] QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer()

このスワップチェーンで beginFrame() が呼び出されたと仮定して、beginFrame -endFrame ブロック内でレンダリングコマンドとリソースの更新を記録できるコマンドバッファを返します。

注: 返されたオブジェクトは、endFrame() の後、次の beginFrame() まで有効ですが、返されたコマンドバッファは、そのときにコマンドを記録するために使用すべきではありません。むしろ、lastCompletedGpuTime ()を呼び出すなどして、フレーム(または前のフレーム)中に収集されたデータを照会するために使用することができます。

注: この値は、フレーム間でキャッシュして再利用してはならない。呼び出し元は、beginFrame ()が再度呼び出されると、返されたオブジェクトを保持すべきではありません。代わりに、この関数を呼び出してコマンドバッファオブジェクトを再度照会する必要があります。

[pure virtual] QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()

swapchain の現在のバックバッファをレンダリングするために beginPass() で使用できるレンダーターゲットを返します。このスワップチェーンで beginFrame() が呼び出されたQRhi::beginFrame() -QRhi::endFrame() ブロック内でのみ有効です。

注意: この値をキャッシュしたり、フレーム間で再利用したりしてはいけません。

[virtual] QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(QRhiSwapChain::StereoTargetBuffer targetBuffer)

swapchain の左または右のバックバッファにレンダリングするために beginPass() で使用できるレンダーターゲットを返します。このオーバーロードは、ステレオスコピックレンダリング、つまり、関連するQWindow が、1 つだけでなく、それぞれの目に対して 1 つずつ、2 つのカラーバッファによってバックアップされている場合にのみ使用する必要があります。

立体視レンダリングがサポートされていない場合、戻り値はデフォルトのターゲットになります。これは、実行時にグラフィックスおよびディスプレイドライバスタックでサポートされていることを前提に、QSurfaceFormat::StereoBuffers と組み合わせて、Metal を除くすべてのハードウェアバックエンドでサポートされています。MetalとNullのバックエンドは、このオーバーロードからデフォルトのレンダーターゲットを返します。

注意: 値はキャッシュされ、フレーム間で再利用されてはいけません。

QSize QRhiSwapChain::currentPixelSize() const

スワップチェーンが最後に正常に構築されたサイズを返します。createOrResize currentPixelSize() != surfacePixelSize() の場合、スワップチェーンのサイズを変更する必要があります。

注意: 典型的なレンダリングロジックでは、新しいフレームの準備を開始するときにこの関数を呼び出して出力サイズを取得し、この関数から返されたサイズを基に依存する計算(ビューポートなど)を行います。

多くの場合、この値はQWindow::size() * QWindow::devicePixelRatio() と同じですが、QWindow で報告されるサイズに依存することは、すべてのプラットフォームやグラフィックス API の実装で正しいことを保証するものではありません。したがって、出力レイヤーやサーフェスの寸法をピクセル単位で特定する必要がある場合は、この関数を使用することを強く推奨します。

また、QRhi をレンダリング専用スレッドで使用する場合、QWindow 関数を呼び出す必要があり、メインスレッドで更新されたデータにアクセスする可能性があるため、データ競合の可能性を回避できるという利点もあります。

surfacePixelSize()も参照

QRhiRenderBuffer *QRhiSwapChain::depthStencil() const

depth-stencil に現在関連付けられているレンダーバッファを返します。

setDepthStencil()も参照

QRhiSwapChain::Flags QRhiSwapChain::flags() const

現在設定されているフラグを返します。

setFlags()も参照

QRhiSwapChain::Format QRhiSwapChain::format() const

現在設定されているフォーマットを返します。

setFormat() も参照して ください。

[virtual] QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()

関連するディスプレイのHDR情報を返す。

これは安価な操作であると思わないでください。プラットフォームによっては、この関数は様々なプラットフォームクエリーを行い、パフォーマンスに影響を与える可能性があります。

注: ウィンドウがset である限り、createOrResize() の前に呼び出すことができる。

注意 : swapchainが初期化されたウィンドウをディスプレイ間で移動する場合(HDRから特性の異なるHDR、HDRからSDRなど)に何が起こるかは、現在のところよく定義されておらず、ウィンドウシステムとコンポジターに大きく依存し、プラットフォームによって動作が異なる可能性があります。現在のところ、QRhi は、hdrInfo() が、createOrResize() の時点でスワップチェーンの関連ウィンドウが属していたディスプレイに対して、有効なデータがあればそれを返すことだけを保証している。

QRhiSwapChainHdrInfoも参照のこと

[pure virtual] bool QRhiSwapChain::isFormatSupported(QRhiSwapChain::Format f)

指定されたスワップチェーン・フォーマットf がサポートされている場合、true を返す。SDRは常にサポートされている。

注意: createOrResize() とは無関係に呼び出すことができるが、window() がすでに設定されている必要がある。ウィンドウが設定されていない状態で呼び出すと、バックエンドやプラットフォームによっては予期しない結果になる可能性があります (どの HDR フォーマットでも false になる可能性が高いです)。なぜなら、HDR フォーマットのサポートは、通常、スワップチェーンの関連ウィンドウが属する出力 (スクリーン) に紐づいているからです。結果がHDRフォーマットに対してtrueの場合、ウィンドウがその間に別のスクリーンに移動されない限り、そのフォーマットでスワップチェーンを作成することは成功すると予想される。

この関数の主な用途は、ウィンドウがすでに設定された後の最初のcreateOrResize ()の前に呼び出すことである。これにより、QRhi バックエンドは、プラットフォームまたはウィンドウシステム固有のクエリを実行し、ウィンドウ(およびそれがあるスクリーン)が指定されたフォーマットで真のHDR出力が可能かどうかを判断することができます。

フォーマットがサポートされていると報告されたら、setFormat()をコールして要求されたフォーマットを設定し、createOrResize()をコールする。HDRフォーマットのリクエストに成功すると、異なる色空間への対応、HDR非対応コンテンツのホワイトレベル補正、トーンマッピング方法の調整、オフスクリーンレンダリングターゲット設定の調整などが必要になります。

setFormat()も参照

[pure virtual] QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor()

この swapchain と互換性のある新しいQRhiRenderPassDescriptor を返します。

返された値は、setRenderPassDescriptor() とQRhiGraphicsPipeline::setRenderPassDescriptor() に渡すことができる。レンダーパス記述子は、flags() によって影響を受けることができるアタッチメント(色、深度/ステンシル)とロード/ストアの動作を記述する。QRhiGraphicsPipeline は、compatible QRhiRenderPassDescriptor が設定されたスワップチェーンと組み合わせてのみ使用できる。

createOrResize()も参照

QRhiSwapChainProxyData QRhiSwapChain::proxyData() const

現在設定されているプロキシ・データを返す。

setProxyData()も参照

QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const

現在関連付けられているQRhiRenderPassDescriptor オブジェクトを返します。

setRenderPassDescriptor()も参照

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

再インプリメント:QRhiResource::resourceType() const.

リソースタイプを返します。

int QRhiSwapChain::sampleCount() const

現在設定されているサンプル数を返します。1 は、マルチサンプルアンチエイリアスを行わないことを意味します。

setSampleCount()も参照してください

void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)

深度ステンシルバッファとして使用するためにレンダーバッファds を設定します。

depthStencil()も参照

void QRhiSwapChain::setFlags(QRhiSwapChain::Flags f)

フラグf を設定します。

flags()も参照

void QRhiSwapChain::setFormat(QRhiSwapChain::Format f)

フォーマットf を設定します。

isFormatSupported() からサポートされていないと報告されたフォーマットの設定は避けてください。指定した書式がサポートされているかどうかは、スワップチェーンの関連ウィンドウが開いている画面によって異なることに注意。WindowsやmacOSなど一部のプラットフォームでは、HDR出力が機能するためには、ディスプレイ設定でHDR出力を有効にしておく必要があります。

ハイダイナミックレンジ出力の詳細については、isFormatSupported(),QRhiSwapChainHdrInfo,Format を参照。

format()も参照

void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)

プロキシデータを設定するd

proxyData() およびQRhi::updateSwapChainProxyData() も参照

void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)

QRhiRenderPassDescriptor desc に関連付けます。

renderPassDescriptor()も参照

void QRhiSwapChain::setSampleCount(int samples)

サンプル数を設定します。samples の一般的な値は、1 (MSAA なし)、4 (4x MSAA)、または 8 (8x MSAA) です。

sampleCount() およびQRhi::supportedSampleCounts()も参照

void QRhiSwapChain::setWindow(QWindow *window)

window を設定する。

window() も参照して ください。

[pure virtual] QSize QRhiSwapChain::surfacePixelSize()

戻り値 ウィンドウに関連付けられたサーフェスまたはレイヤーのサイズ。

警告: これはQWindow::size() * QWindow::devicePixelRatio() と同じだと思わないでください。いくつかのグラフィックスAPIとウィンドウシステムインタフェース(例えば、Vulkan)では、サーフェスが関連するウィンドウと異なるサイズを仮定する理論的な可能性があります。このようなケースをサポートするために、レンダリングロジックは常に、QRhiSwapChain から報告されたサイズに基づいてサイズ由来の計算(ビューポートなど)を行う必要があり、QWindow からクエリされたサイズに基づいてはなりません

注意: 少なくともwindow() がすでに設定されていれば、createOrResize() の前に呼び出すこともできる。currentPixelSize() と組み合わせて使用することで、スワップチェーンのサイズ変更が必要なタイミングを検出できる。ただし、基礎となるネイティブオブジェクト(サーフェス、レイヤーなど)のサイズは「ライブ」であるため、この関数が呼び出されるたびに、基礎となる実装によって報告された最新の値が返され、アトミック性は保証されません。したがって、フレーム内で使用されるグラフィックリソースのピクセルサイズを決定するためにこの関数を使用することは強く推奨されません。代わりにcurrentPixelSize() を使用してください。この関数はアトミックであり、createOrResize() を呼び出しても変更されないサイズを返します。

注意: スワップチェーンのカラーバッファと組み合わせて使用される深度ステンシルバッファについては、QRhiRenderBuffer:UsedWithSwapChainOnly フラグによって提供される自動サイズ調整と再構築の動作に依存することを強く推奨します。QRhiRenderBuffer::setPixelSize() に渡せるサイズを取得するためだけに、この関数でサーフェスサイズを問い合わせることは避けてください。

currentPixelSize()も参照

QWindow *QRhiSwapChain::window() const

現在設定されているウィンドウを返します。

setWindow() も参照して ください。

本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。