qt6windows7/qtbase/src/gui/rhi/qrhid3d11_p.h

855 lines
30 KiB
C++

// 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
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qrhi_p.h"
#include <rhi/qshaderdescription.h>
#include <QWindow>
#include <d3d11_1.h>
#include <dxgi1_6.h>
#include <dcomp.h>
QT_BEGIN_NAMESPACE
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 {
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 {
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));
}
};
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
struct QD3D11Timestamps
{
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
bool active[MAX_TIMESTAMP_PAIRS] = {};
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
int pairCount = 0;
bool prepare(int pairCount, QRhiD3D11 *rhiD);
void destroy();
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
};
struct QD3D11SwapChain : public QRhiSwapChain
{
QD3D11SwapChain(QRhiImplementation *rhi);
~QD3D11SwapChain();
void destroy() override;
QRhiCommandBuffer *currentFrameCommandBuffer() override;
QRhiRenderTarget *currentFrameRenderTarget() override;
QSize surfacePixelSize() override;
bool isFormatSupported(Format f) override;
QRhiSwapChainHdrInfo hdrInfo() override;
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
bool createOrResize() override;
bool createOrResizeWin7();
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;
QD3D11CommandBuffer cb;
DXGI_FORMAT colorFormat;
DXGI_FORMAT srgbAdjustedColorFormat;
IDXGISwapChain *swapChain = nullptr;
UINT swapChainFlags = 0;
ID3D11Texture2D *backBufferTex;
ID3D11RenderTargetView *backBufferRtv;
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
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;
QD3D11Timestamps timestamps;
};
class QRhiD3D11 : public QRhiImplementation
{
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, QD3D11SwapChain *timestampSwapChain = nullptr);
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;
QD3D11Timestamps timestamps;
int timestampIdx = 0;
} 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