diff options
Diffstat (limited to 'src/gui/rhi/qrhid3d11_p.h')
-rw-r--r-- | src/gui/rhi/qrhid3d11_p.h | 895 |
1 files changed, 840 insertions, 55 deletions
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h index ed26e9af16..7644748407 100644 --- a/src/gui/rhi/qrhid3d11_p.h +++ b/src/gui/rhi/qrhid3d11_p.h @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Gui module -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QRHID3D11_H -#define QRHID3D11_H +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QRHID3D11_P_H +#define QRHID3D11_P_H // // W A R N I N G @@ -51,31 +15,852 @@ // We mean it. // -#include <private/qrhi_p.h> +#include "qrhi_p.h" +#include <rhi/qshaderdescription.h> +#include <QWindow> -// no d3d includes here, to prevent precompiled header mess due to COM +#include <d3d11_1.h> +#include <dxgi1_6.h> +#include <dcomp.h> QT_BEGIN_NAMESPACE -struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams +class QRhiD3D11; + +struct QD3D11Buffer : public QRhiBuffer +{ + QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size); + ~QD3D11Buffer(); + void destroy() override; + bool create() override; + QRhiBuffer::NativeBuffer nativeBuffer() override; + char *beginFullDynamicBufferUpdateForCurrentFrame() override; + void endFullDynamicBufferUpdateForCurrentFrame() override; + + ID3D11UnorderedAccessView *unorderedAccessView(quint32 offset); + + ID3D11Buffer *buffer = nullptr; + char *dynBuf = nullptr; + bool hasPendingDynamicUpdates = false; + QHash<quint32, ID3D11UnorderedAccessView *> uavs; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11RenderBuffer : public QRhiRenderBuffer +{ + QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, + int sampleCount, QRhiRenderBuffer::Flags flags, + QRhiTexture::Format backingFormatHint); + ~QD3D11RenderBuffer(); + void destroy() override; + bool create() override; + QRhiTexture::Format backingFormat() const override; + + ID3D11Texture2D *tex = nullptr; + ID3D11DepthStencilView *dsv = nullptr; + ID3D11RenderTargetView *rtv = nullptr; + DXGI_FORMAT dxgiFormat; + DXGI_SAMPLE_DESC sampleDesc; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11Texture : public QRhiTexture +{ + QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, + int arraySize, int sampleCount, Flags flags); + ~QD3D11Texture(); + void destroy() override; + bool create() override; + bool createFrom(NativeTexture src) override; + NativeTexture nativeTexture() override; + + bool prepareCreate(QSize *adjustedSize = nullptr); + bool finishCreate(); + ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level); + ID3D11Resource *textureResource() const + { + if (tex) + return tex; + else if (tex1D) + return tex1D; + return tex3D; + } + + ID3D11Texture2D *tex = nullptr; + ID3D11Texture3D *tex3D = nullptr; + ID3D11Texture1D *tex1D = nullptr; + bool owns = true; + ID3D11ShaderResourceView *srv = nullptr; + DXGI_FORMAT dxgiFormat; + uint mipLevelCount = 0; + DXGI_SAMPLE_DESC sampleDesc; + ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS]; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11Sampler : public QRhiSampler +{ + QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, + AddressMode u, AddressMode v, AddressMode w); + ~QD3D11Sampler(); + void destroy() override; + bool create() override; + + ID3D11SamplerState *samplerState = nullptr; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor +{ + QD3D11RenderPassDescriptor(QRhiImplementation *rhi); + ~QD3D11RenderPassDescriptor(); + void destroy() override; + bool isCompatible(const QRhiRenderPassDescriptor *other) const override; + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; + QVector<quint32> serializedFormat() const override; +}; + +struct QD3D11RenderTargetData +{ + QD3D11RenderTargetData(QRhiImplementation *) + { + for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i) + rtv[i] = nullptr; + } + + QD3D11RenderPassDescriptor *rp = nullptr; + QSize pixelSize; + float dpr = 1; + int sampleCount = 1; + int colorAttCount = 0; + int dsAttCount = 0; + + static const int MAX_COLOR_ATTACHMENTS = 8; + ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS]; + ID3D11DepthStencilView *dsv = nullptr; + + QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList; +}; + +struct QD3D11SwapChainRenderTarget : public QRhiSwapChainRenderTarget +{ + QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain); + ~QD3D11SwapChainRenderTarget(); + void destroy() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; + + QD3D11RenderTargetData d; +}; + +struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget +{ + QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); + ~QD3D11TextureRenderTarget(); + void destroy() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool create() override; + + QD3D11RenderTargetData d; + bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]; + ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]; + bool ownsDsv = false; + ID3D11DepthStencilView *dsv = nullptr; + friend class QRhiD3D11; +}; + +struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings +{ + QD3D11ShaderResourceBindings(QRhiImplementation *rhi); + ~QD3D11ShaderResourceBindings(); + void destroy() override; + bool create() override; + void updateResources(UpdateFlags flags) override; + + bool hasDynamicOffset = false; + QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings; + uint generation = 0; + + // Keep track of the generation number of each referenced QRhi* to be able + // to detect that the batched bindings are out of date. + struct BoundUniformBufferData { + quint64 id; + uint generation; + }; + struct BoundSampledTextureData { + int count; + struct { + quint64 texId; + uint texGeneration; + quint64 samplerId; + uint samplerGeneration; + } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE]; + }; + struct BoundStorageImageData { + quint64 id; + uint generation; + }; + struct BoundStorageBufferData { + quint64 id; + uint generation; + }; + struct BoundResourceData { + union { + BoundUniformBufferData ubuf; + BoundSampledTextureData stex; + BoundStorageImageData simage; + BoundStorageBufferData sbuf; + }; + }; + QVarLengthArray<BoundResourceData, 8> boundResourceData; + + struct StageUniformBufferBatches { + bool present = false; + QRhiBatchedBindings<ID3D11Buffer *> ubufs; + QRhiBatchedBindings<UINT> ubuforigbindings; + QRhiBatchedBindings<UINT> ubufoffsets; + QRhiBatchedBindings<UINT> ubufsizes; + void finish() { + present = ubufs.finish(); + ubuforigbindings.finish(); + ubufoffsets.finish(); + ubufsizes.finish(); + } + void clear() { + ubufs.clear(); + ubuforigbindings.clear(); + ubufoffsets.clear(); + ubufsizes.clear(); + } + }; + + struct StageSamplerBatches { + bool present = false; + QRhiBatchedBindings<ID3D11SamplerState *> samplers; + QRhiBatchedBindings<ID3D11ShaderResourceView *> shaderresources; + void finish() { + present = samplers.finish(); + shaderresources.finish(); + } + void clear() { + samplers.clear(); + shaderresources.clear(); + } + }; + + struct StageUavBatches { + bool present = false; + QRhiBatchedBindings<ID3D11UnorderedAccessView *> uavs; + void finish() { + present = uavs.finish(); + } + void clear() { + uavs.clear(); + } + }; + + StageUniformBufferBatches vsUniformBufferBatches; + StageUniformBufferBatches hsUniformBufferBatches; + StageUniformBufferBatches dsUniformBufferBatches; + StageUniformBufferBatches gsUniformBufferBatches; + StageUniformBufferBatches fsUniformBufferBatches; + StageUniformBufferBatches csUniformBufferBatches; + + StageSamplerBatches vsSamplerBatches; + StageSamplerBatches hsSamplerBatches; + StageSamplerBatches dsSamplerBatches; + StageSamplerBatches gsSamplerBatches; + StageSamplerBatches fsSamplerBatches; + StageSamplerBatches csSamplerBatches; + + StageUavBatches csUavBatches; + + friend class QRhiD3D11; +}; + +Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE); + +struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline +{ + QD3D11GraphicsPipeline(QRhiImplementation *rhi); + ~QD3D11GraphicsPipeline(); + void destroy() override; + bool create() override; + + ID3D11DepthStencilState *dsState = nullptr; + ID3D11BlendState *blendState = nullptr; + struct { + ID3D11VertexShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } vs; + struct { + ID3D11HullShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } hs; + struct { + ID3D11DomainShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } ds; + struct { + ID3D11GeometryShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } gs; + struct { + ID3D11PixelShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } fs; + ID3D11InputLayout *inputLayout = nullptr; + D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + ID3D11RasterizerState *rastState = nullptr; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11ComputePipeline : public QRhiComputePipeline +{ + QD3D11ComputePipeline(QRhiImplementation *rhi); + ~QD3D11ComputePipeline(); + void destroy() override; + bool create() override; + + struct { + ID3D11ComputeShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } cs; + uint generation = 0; + friend class QRhiD3D11; +}; + +struct QD3D11SwapChain; + +struct QD3D11CommandBuffer : public QRhiCommandBuffer +{ + QD3D11CommandBuffer(QRhiImplementation *rhi); + ~QD3D11CommandBuffer(); + void destroy() override; + + // these must be kept at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; + static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8; + + struct Command { + enum Cmd { + BeginFrame, + EndFrame, + ResetShaderResources, + SetRenderTarget, + Clear, + Viewport, + Scissor, + BindVertexBuffers, + BindIndexBuffer, + BindGraphicsPipeline, + BindShaderResources, + StencilRef, + BlendConstants, + Draw, + DrawIndexed, + UpdateSubRes, + CopySubRes, + ResolveSubRes, + GenMip, + DebugMarkBegin, + DebugMarkEnd, + DebugMarkMsg, + BindComputePipeline, + Dispatch + }; + enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 }; + Cmd cmd; + + // QRhi*/QD3D11* references should be kept at minimum (so no + // QRhiTexture/Buffer/etc. pointers). + union Args { + struct { + ID3D11Query *tsQuery; + ID3D11Query *tsDisjointQuery; + QD3D11RenderTargetData *swapchainData; + } beginFrame; + struct { + ID3D11Query *tsQuery; + ID3D11Query *tsDisjointQuery; + } endFrame; + struct { + QRhiRenderTarget *rt; + } setRenderTarget; + struct { + QRhiRenderTarget *rt; + int mask; + float c[4]; + float d; + quint32 s; + } clear; + struct { + float x, y, w, h; + float d0, d1; + } viewport; + struct { + int x, y, w, h; + } scissor; + struct { + int startSlot; + int slotCount; + ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT]; + UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT]; + UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT]; + } bindVertexBuffers; + struct { + ID3D11Buffer *buffer; + quint32 offset; + DXGI_FORMAT format; + } bindIndexBuffer; + struct { + QD3D11GraphicsPipeline *ps; + } bindGraphicsPipeline; + struct { + QD3D11ShaderResourceBindings *srb; + bool offsetOnlyChange; + int dynamicOffsetCount; + uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants + } bindShaderResources; + struct { + QD3D11GraphicsPipeline *ps; + quint32 ref; + } stencilRef; + struct { + QD3D11GraphicsPipeline *ps; + float c[4]; + } blendConstants; + struct { + QD3D11GraphicsPipeline *ps; + quint32 vertexCount; + quint32 instanceCount; + quint32 firstVertex; + quint32 firstInstance; + } draw; + struct { + QD3D11GraphicsPipeline *ps; + quint32 indexCount; + quint32 instanceCount; + quint32 firstIndex; + qint32 vertexOffset; + quint32 firstInstance; + } drawIndexed; + struct { + ID3D11Resource *dst; + UINT dstSubRes; + bool hasDstBox; + D3D11_BOX dstBox; + const void *src; // must come from retain*() + UINT srcRowPitch; + } updateSubRes; + struct { + ID3D11Resource *dst; + UINT dstSubRes; + UINT dstX; + UINT dstY; + UINT dstZ; + ID3D11Resource *src; + UINT srcSubRes; + bool hasSrcBox; + D3D11_BOX srcBox; + } copySubRes; + struct { + ID3D11Resource *dst; + UINT dstSubRes; + ID3D11Resource *src; + UINT srcSubRes; + DXGI_FORMAT format; + } resolveSubRes; + struct { + ID3D11ShaderResourceView *srv; + } genMip; + struct { + char s[64]; + } debugMark; + struct { + QD3D11ComputePipeline *ps; + } bindComputePipeline; + struct { + UINT x; + UINT y; + UINT z; + } dispatch; + } args; + }; + + enum PassType { + NoPass, + RenderPass, + ComputePass + }; + + QRhiBackendCommandList<Command> commands; + PassType recordingPass; + double lastGpuTime = 0; + QRhiRenderTarget *currentTarget; + QRhiGraphicsPipeline *currentGraphicsPipeline; + QRhiComputePipeline *currentComputePipeline; + uint currentPipelineGeneration; + QRhiShaderResourceBindings *currentGraphicsSrb; + QRhiShaderResourceBindings *currentComputeSrb; + uint currentSrbGeneration; + ID3D11Buffer *currentIndexBuffer; + quint32 currentIndexOffset; + DXGI_FORMAT currentIndexFormat; + ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + + QVarLengthArray<QByteArray, 4> dataRetainPool; + QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool; + QVarLengthArray<QImage, 4> imageRetainPool; + + // relies heavily on implicit sharing (no copies of the actual data will be made) + const uchar *retainData(const QByteArray &data) { + dataRetainPool.append(data); + return reinterpret_cast<const uchar *>(dataRetainPool.last().constData()); + } + const uchar *retainBufferData(const QRhiBufferData &data) { + bufferDataRetainPool.append(data); + return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData()); + } + const uchar *retainImage(const QImage &image) { + imageRetainPool.append(image); + return imageRetainPool.last().constBits(); + } + void resetCommands() { + commands.reset(); + dataRetainPool.clear(); + bufferDataRetainPool.clear(); + imageRetainPool.clear(); + } + void resetState() { + recordingPass = NoPass; + // do not zero lastGpuTime + currentTarget = nullptr; + resetCommands(); + resetCachedState(); + } + void resetCachedState() { + currentGraphicsPipeline = nullptr; + currentComputePipeline = nullptr; + currentPipelineGeneration = 0; + currentGraphicsSrb = nullptr; + currentComputeSrb = nullptr; + currentSrbGeneration = 0; + currentIndexBuffer = nullptr; + currentIndexOffset = 0; + currentIndexFormat = DXGI_FORMAT_R16_UINT; + memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers)); + memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets)); + } +}; + +struct QD3D11SwapChainTimestamps +{ + static const int TIMESTAMP_PAIRS = 2; + + bool active[TIMESTAMP_PAIRS] = {}; + ID3D11Query *disjointQuery[TIMESTAMP_PAIRS] = {}; + ID3D11Query *query[TIMESTAMP_PAIRS * 2] = {}; + + bool prepare(QRhiD3D11 *rhiD); + void destroy(); + bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec); +}; + +struct QD3D11SwapChain : public QRhiSwapChain { - bool enableDebugLayer = false; + QD3D11SwapChain(QRhiImplementation *rhi); + ~QD3D11SwapChain(); + void destroy() override; - int framesUntilKillingDeviceViaTdr = -1; - bool repeatDeviceKill = false; + QRhiCommandBuffer *currentFrameCommandBuffer() override; + QRhiRenderTarget *currentFrameRenderTarget() override; + QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override; + + QSize surfacePixelSize() override; + bool isFormatSupported(Format f) override; + QRhiSwapChainHdrInfo hdrInfo() override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool createOrResize() override; + + void releaseBuffers(); + bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, + ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const; + + QWindow *window = nullptr; + QSize pixelSize; + QD3D11SwapChainRenderTarget rt; + QD3D11SwapChainRenderTarget rtRight; + QD3D11CommandBuffer cb; + DXGI_FORMAT colorFormat; + DXGI_FORMAT srgbAdjustedColorFormat; + IDXGISwapChain *swapChain = nullptr; + UINT swapChainFlags = 0; + ID3D11Texture2D *backBufferTex; + ID3D11RenderTargetView *backBufferRtv; + ID3D11RenderTargetView *backBufferRtvRight = nullptr; + static const int BUFFER_COUNT = 2; + ID3D11Texture2D *msaaTex[BUFFER_COUNT]; + ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT]; + DXGI_SAMPLE_DESC sampleDesc; + int currentFrameSlot = 0; + int frameCount = 0; + QD3D11RenderBuffer *ds = nullptr; + UINT swapInterval = 1; + IDCompositionTarget *dcompTarget = nullptr; + IDCompositionVisual *dcompVisual = nullptr; + QD3D11SwapChainTimestamps timestamps; + int currentTimestampPairIndex = 0; }; -struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles +class QRhiD3D11 : public QRhiImplementation { - // to import a device and a context - void *dev = nullptr; - void *context = nullptr; - // alternatively, to specify the device feature level and/or the adapter to use - int featureLevel = 0; - quint32 adapterLuidLow = 0; - qint32 adapterLuidHigh = 0; +public: + QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr); + + bool create(QRhi::Flags flags) override; + void destroy() override; + + QRhiGraphicsPipeline *createGraphicsPipeline() override; + QRhiComputePipeline *createComputePipeline() override; + QRhiShaderResourceBindings *createShaderResourceBindings() override; + QRhiBuffer *createBuffer(QRhiBuffer::Type type, + QRhiBuffer::UsageFlags usage, + quint32 size) override; + QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type, + const QSize &pixelSize, + int sampleCount, + QRhiRenderBuffer::Flags flags, + QRhiTexture::Format backingFormatHint) override; + QRhiTexture *createTexture(QRhiTexture::Format format, + const QSize &pixelSize, + int depth, + int arraySize, + int sampleCount, + QRhiTexture::Flags flags) override; + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, + QRhiSampler::Filter mipmapMode, + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; + + QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, + QRhiTextureRenderTarget::Flags flags) override; + + QRhiSwapChain *createSwapChain() override; + QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; + QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; + QRhi::FrameOpResult finish() override; + + void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void beginPass(QRhiCommandBuffer *cb, + QRhiRenderTarget *rt, + const QColor &colorClearValue, + const QRhiDepthStencilClearValue &depthStencilClearValue, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; + void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void setGraphicsPipeline(QRhiCommandBuffer *cb, + QRhiGraphicsPipeline *ps) override; + + void setShaderResources(QRhiCommandBuffer *cb, + QRhiShaderResourceBindings *srb, + int dynamicOffsetCount, + const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; + + void setVertexInput(QRhiCommandBuffer *cb, + int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, + QRhiBuffer *indexBuf, quint32 indexOffset, + QRhiCommandBuffer::IndexFormat indexFormat) override; + + void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; + void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; + void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override; + void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override; + + void draw(QRhiCommandBuffer *cb, quint32 vertexCount, + quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override; + + void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, + quint32 instanceCount, quint32 firstIndex, + qint32 vertexOffset, quint32 firstInstance) override; + + void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; + void debugMarkEnd(QRhiCommandBuffer *cb) override; + void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; + + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; + void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; + void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; + + const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; + void beginExternal(QRhiCommandBuffer *cb) override; + void endExternal(QRhiCommandBuffer *cb) override; + double lastCompletedGpuTime(QRhiCommandBuffer *cb) override; + + QList<int> supportedSampleCounts() const override; + int ubufAlignment() const override; + bool isYUpInFramebuffer() const override; + bool isYUpInNDC() const override; + bool isClipDepthZeroToOne() const override; + QMatrix4x4 clipSpaceCorrMatrix() const override; + bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; + bool isFeatureSupported(QRhi::Feature feature) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; + const QRhiNativeHandles *nativeHandles() override; + QRhiDriverInfo driverInfo() const override; + QRhiStats statistics() override; + bool makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; + bool isDeviceLost() const override; + + QByteArray pipelineCacheData() override; + void setPipelineCacheData(const QByteArray &data) override; + + void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, + int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); + void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); + void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, + const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]); + void executeBufferHostWrites(QD3D11Buffer *bufD); + void bindShaderResources(QD3D11ShaderResourceBindings *srbD, + const uint *dynOfsPairs, int dynOfsPairCount, + bool offsetOnlyChange); + void resetShaderResources(); + void executeCommandBuffer(QD3D11CommandBuffer *cbD); + DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const; + void finishActiveReadbacks(); + void reportLiveObjects(ID3D11Device *device); + void clearShaderCache(); + QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags, + QString *error, QShaderKey *usedShaderKey); + bool ensureDirectCompositionDevice(); + + QRhi::Flags rhiFlags; + bool debugLayer = false; + bool importedDeviceAndContext = false; + ID3D11Device *dev = nullptr; + ID3D11DeviceContext1 *context = nullptr; + D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL(0); + LUID adapterLuid = {}; + ID3DUserDefinedAnnotation *annotations = nullptr; + IDXGIAdapter1 *activeAdapter = nullptr; + IDXGIFactory1 *dxgiFactory = nullptr; + IDCompositionDevice *dcompDevice = nullptr; + bool supportsAllowTearing = false; + bool useLegacySwapchainModel = false; + bool deviceLost = false; + QRhiD3D11NativeHandles nativeHandlesStruct; + QRhiDriverInfo driverInfoStruct; + + struct { + int vsHighestActiveVertexBufferBinding = -1; + bool vsHasIndexBufferBound = false; + int vsHighestActiveSrvBinding = -1; + int hsHighestActiveSrvBinding = -1; + int dsHighestActiveSrvBinding = -1; + int gsHighestActiveSrvBinding = -1; + int fsHighestActiveSrvBinding = -1; + int csHighestActiveSrvBinding = -1; + int csHighestActiveUavBinding = -1; + QD3D11SwapChain *currentSwapChain = nullptr; + } contextState; + + struct OffscreenFrame { + OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } + bool active = false; + QD3D11CommandBuffer cbWrapper; + ID3D11Query *tsQueries[2] = {}; + ID3D11Query *tsDisjointQuery = nullptr; + } ofr; + + struct TextureReadback { + QRhiReadbackDescription desc; + QRhiReadbackResult *result; + ID3D11Texture2D *stagingTex; + quint32 byteSize; + quint32 bpl; + QSize pixelSize; + QRhiTexture::Format format; + }; + QVarLengthArray<TextureReadback, 2> activeTextureReadbacks; + struct BufferReadback { + QRhiReadbackResult *result; + quint32 byteSize; + ID3D11Buffer *stagingBuf; + }; + QVarLengthArray<BufferReadback, 2> activeBufferReadbacks; + + struct Shader { + Shader() = default; + Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm) + : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { } + IUnknown *s; + QByteArray bytecode; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + }; + QHash<QRhiShaderStage, Shader> m_shaderCache; + + // This is what gets exposed as the "pipeline cache", not that that concept + // applies anyway. Here we are just storing the DX bytecode for a shader so + // we can skip the HLSL->DXBC compilation when the QShader has HLSL source + // code and the same shader source has already been compiled before. + // m_shaderCache seemingly does the same, but this here does not care about + // the ID3D11*Shader, this is just about the bytecode and about allowing + // the data to be serialized to persistent storage and then reloaded in + // future runs of the app, or when creating another QRhi, etc. + struct BytecodeCacheKey { + QByteArray sourceHash; + QByteArray target; + QByteArray entryPoint; + uint compileFlags; + }; + QHash<BytecodeCacheKey, QByteArray> m_bytecodeCache; }; +Q_DECLARE_TYPEINFO(QRhiD3D11::TextureReadback, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(QRhiD3D11::BufferReadback, Q_RELOCATABLE_TYPE); + +inline bool operator==(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept +{ + return a.sourceHash == b.sourceHash + && a.target == b.target + && a.entryPoint == b.entryPoint + && a.compileFlags == b.compileFlags; +} + +inline bool operator!=(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept +{ + return !(a == b); +} + +inline size_t qHash(const QRhiD3D11::BytecodeCacheKey &k, size_t seed = 0) noexcept +{ + return qHash(k.sourceHash, seed) ^ qHash(k.target) ^ qHash(k.entryPoint) ^ k.compileFlags; +} + QT_END_NAMESPACE #endif |