diff options
Diffstat (limited to 'src/gui/rhi/qrhid3d12_p_p.h')
-rw-r--r-- | src/gui/rhi/qrhid3d12_p_p.h | 1194 |
1 files changed, 0 insertions, 1194 deletions
diff --git a/src/gui/rhi/qrhid3d12_p_p.h b/src/gui/rhi/qrhid3d12_p_p.h deleted file mode 100644 index dec217e771..0000000000 --- a/src/gui/rhi/qrhid3d12_p_p.h +++ /dev/null @@ -1,1194 +0,0 @@ -// Copyright (C) 2022 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 QRHID3D12_P_H -#define QRHID3D12_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 "qrhid3d12_p.h" -#include "qrhi_p_p.h" -#include "qshaderdescription_p.h" -#include <QWindow> -#include <QBitArray> - -#include <optional> -#include <array> - -#include <d3d12.h> -#include <d3d12sdklayers.h> -#include <dxgi1_6.h> -#include <dcomp.h> - -#include "D3D12MemAlloc.h" - -QT_BEGIN_NAMESPACE - -static const int QD3D12_FRAMES_IN_FLIGHT = 2; - -class QRhiD3D12; - -struct QD3D12Descriptor -{ - D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = {}; - D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = {}; - - bool isValid() const { return cpuHandle.ptr != 0; } -}; - -struct QD3D12ReleaseQueue; - -struct QD3D12DescriptorHeap -{ - bool isValid() const { return heap && capacity; } - bool create(ID3D12Device *device, - quint32 descriptorCount, - D3D12_DESCRIPTOR_HEAP_TYPE heapType, - D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags); - void createWithExisting(const QD3D12DescriptorHeap &other, - quint32 offsetInDescriptors, - quint32 descriptorCount); - void destroy(); - void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue); - - QD3D12Descriptor get(quint32 count); - QD3D12Descriptor at(quint32 index) const; - quint32 remainingCapacity() const { return capacity - head; } - - QD3D12Descriptor incremented(const QD3D12Descriptor &descriptor, quint32 offsetInDescriptors) const - { - D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = descriptor.cpuHandle; - cpuHandle.ptr += offsetInDescriptors * descriptorByteSize; - D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = descriptor.gpuHandle; - if (gpuHandle.ptr) - gpuHandle.ptr += offsetInDescriptors * descriptorByteSize; - return { cpuHandle, gpuHandle }; - } - - ID3D12DescriptorHeap *heap = nullptr; - quint32 capacity = 0; - QD3D12Descriptor heapStart; - quint32 head = 0; - quint32 descriptorByteSize = 0; - D3D12_DESCRIPTOR_HEAP_TYPE heapType; - D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags; -}; - -struct QD3D12CpuDescriptorPool -{ - bool isValid() const { return !heaps.isEmpty(); } - bool create(ID3D12Device *device, D3D12_DESCRIPTOR_HEAP_TYPE heapType, const char *debugName = ""); - void destroy(); - - QD3D12Descriptor allocate(quint32 count); - void release(const QD3D12Descriptor &descriptor, quint32 count); - - static const int DESCRIPTORS_PER_HEAP = 256; - - struct HeapWithMap { - QD3D12DescriptorHeap heap; - QBitArray map; - static HeapWithMap init(const QD3D12DescriptorHeap &heap, quint32 descriptorCount) { - HeapWithMap result; - result.heap = heap; - result.map.resize(descriptorCount); - return result; - } - }; - - ID3D12Device *device; - quint32 descriptorByteSize; - QVector<HeapWithMap> heaps; - const char *debugName; -}; - -struct QD3D12StagingArea -{ - static const quint32 ALIGNMENT = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT; // 512 so good enough both for cb and texdata - - struct Allocation { - quint8 *p = nullptr; - D3D12_GPU_VIRTUAL_ADDRESS gpuAddr = 0; - ID3D12Resource *buffer = nullptr; - quint32 bufferOffset = 0; - bool isValid() const { return p != nullptr; } - }; - - bool isValid() const { return allocation && mem.isValid(); } - bool create(QRhiD3D12 *rhi, quint32 capacity, D3D12_HEAP_TYPE heapType); - void destroy(); - void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue); - - Allocation get(quint32 byteSize); - - quint32 remainingCapacity() const - { - return capacity - head; - } - - static quint32 allocSizeForArray(quint32 size, int count = 1) - { - return count * ((size + ALIGNMENT - 1) & ~(ALIGNMENT - 1)); - } - - Allocation mem; - ID3D12Resource *resource = nullptr; - D3D12MA::Allocation *allocation = nullptr; - quint32 head; - quint32 capacity; -}; - -struct QD3D12ObjectHandle -{ - quint32 index = 0; - quint32 generation = 0; - - // the default, null handle is guaranteed to give ObjectPool::isValid() == false - bool isNull() const { return index == 0 && generation == 0; } -}; - -inline bool operator==(const QD3D12ObjectHandle &a, const QD3D12ObjectHandle &b) noexcept -{ - return a.index == b.index && a.generation == b.generation; -} - -inline bool operator!=(const QD3D12ObjectHandle &a, const QD3D12ObjectHandle &b) noexcept -{ - return !(a == b); -} - -template<typename T> -struct QD3D12ObjectPool -{ - void create(const char *debugName = "") - { - this->debugName = debugName; - Q_ASSERT(data.isEmpty()); - data.append(Data()); // index 0 is always invalid - } - - void destroy() { - int leakCount = 0; // will nicely destroy everything here, but warn about it if enabled - for (Data &d : data) { - if (d.object.has_value()) { - leakCount += 1; - d.object->releaseResources(); - } - } - data.clear(); -#ifndef QT_NO_DEBUG - // debug builds: just do it always - static bool leakCheck = true; -#else - // release builds: opt-in - static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK"); -#endif - if (leakCheck) { - if (leakCount > 0) { - qWarning("QD3D12ObjectPool::destroy(): Pool %p '%s' had %d unreleased objects", - this, debugName, leakCount); - } - } - } - - bool isValid(const QD3D12ObjectHandle &handle) const - { - return handle.index > 0 - && handle.index < quint32(data.count()) - && handle.generation > 0 - && handle.generation == data[handle.index].generation - && data[handle.index].object.has_value(); - } - - T lookup(const QD3D12ObjectHandle &handle) const - { - return isValid(handle) ? *data[handle.index].object : T(); - } - - const T *lookupRef(const QD3D12ObjectHandle &handle) const - { - return isValid(handle) ? &*data[handle.index].object : nullptr; - } - - T *lookupRef(const QD3D12ObjectHandle &handle) - { - return isValid(handle) ? &*data[handle.index].object : nullptr; - } - - QD3D12ObjectHandle add(const T &object) - { - Q_ASSERT(!data.isEmpty()); - const quint32 count = quint32(data.count()); - quint32 index = 1; // index 0 is always invalid - for (; index < count; ++index) { - if (!data[index].object.has_value()) - break; - } - if (index < count) { - data[index].object = object; - quint32 &generation = data[index].generation; - generation += 1u; - return { index, generation }; - } else { - data.append({ object, 1 }); - return { count, 1 }; - } - } - - void remove(const QD3D12ObjectHandle &handle) - { - if (T *object = lookupRef(handle)) { - object->releaseResources(); - data[handle.index].object.reset(); - } - } - - const char *debugName; - struct Data { - std::optional<T> object; - quint32 generation = 0; - }; - QVector<Data> data; -}; - -struct QD3D12Resource -{ - ID3D12Resource *resource; - D3D12_RESOURCE_STATES state; - D3D12_RESOURCE_DESC desc; - D3D12MA::Allocation *allocation; - void *cpuMapPtr; - enum { UavUsageRead = 0x01, UavUsageWrite = 0x02 }; - int uavUsage; - bool owns; - - // note that this assumes the allocation (if there is one) and the resource - // are separately releaseable, see D3D12MemAlloc docs - static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12Resource> *pool, - ID3D12Resource *resource, - D3D12_RESOURCE_STATES state, - D3D12MA::Allocation *allocation = nullptr, - void *cpuMapPtr = nullptr) - { - Q_ASSERT(resource); - return pool->add({ resource, state, resource->GetDesc(), allocation, cpuMapPtr, 0, true }); - } - - // for QRhiTexture::createFrom() where the ID3D12Resource is not owned by us - static QD3D12ObjectHandle addNonOwningToPool(QD3D12ObjectPool<QD3D12Resource> *pool, - ID3D12Resource *resource, - D3D12_RESOURCE_STATES state) - { - Q_ASSERT(resource); - return pool->add({ resource, state, resource->GetDesc(), nullptr, nullptr, 0, false }); - } - - void releaseResources() - { - if (owns) { - // order matters: resource first, then the allocation - resource->Release(); - if (allocation) - allocation->Release(); - } - } -}; - -struct QD3D12Pipeline -{ - enum Type { - Graphics, - Compute - }; - Type type; - ID3D12PipelineState *pso; - - static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12Pipeline> *pool, - Type type, - ID3D12PipelineState *pso) - { - return pool->add({ type, pso }); - } - - void releaseResources() - { - pso->Release(); - } -}; - -struct QD3D12RootSignature -{ - ID3D12RootSignature *rootSig; - - static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12RootSignature> *pool, - ID3D12RootSignature *rootSig) - { - return pool->add({ rootSig }); - } - - void releaseResources() - { - rootSig->Release(); - } -}; - -struct QD3D12ReleaseQueue -{ - void create(QD3D12ObjectPool<QD3D12Resource> *resourcePool, - QD3D12ObjectPool<QD3D12Pipeline> *pipelinePool, - QD3D12ObjectPool<QD3D12RootSignature> *rootSignaturePool) - { - this->resourcePool = resourcePool; - this->pipelinePool = pipelinePool; - this->rootSignaturePool = rootSignaturePool; - } - - void deferredReleaseResource(const QD3D12ObjectHandle &handle); - void deferredReleaseResourceWithViews(const QD3D12ObjectHandle &handle, - QD3D12CpuDescriptorPool *pool, - const QD3D12Descriptor &viewsStart, - int viewCount); - void deferredReleasePipeline(const QD3D12ObjectHandle &handle); - void deferredReleaseRootSignature(const QD3D12ObjectHandle &handle); - void deferredReleaseCallback(std::function<void(void*)> callback, void *userData); - void deferredReleaseResourceAndAllocation(ID3D12Resource *resource, - D3D12MA::Allocation *allocation); - void deferredReleaseDescriptorHeap(ID3D12DescriptorHeap *heap); - void deferredReleaseViews(QD3D12CpuDescriptorPool *pool, - const QD3D12Descriptor &viewsStart, - int viewCount); - - void activatePendingDeferredReleaseRequests(int frameSlot); - void executeDeferredReleases(int frameSlot, bool forced = false); - void releaseAll(); - - struct DeferredReleaseEntry { - enum Type { - Resource, - Pipeline, - RootSignature, - Callback, - ResourceAndAllocation, - DescriptorHeap, - Views - }; - Type type = Resource; - std::optional<int> frameSlotToBeReleasedIn; - QD3D12ObjectHandle handle; - QD3D12CpuDescriptorPool *poolForViews = nullptr; - QD3D12Descriptor viewsStart; - int viewCount = 0; - std::function<void(void*)> callback = nullptr; - void *callbackUserData = nullptr; - QPair<ID3D12Resource *, D3D12MA::Allocation *> resourceAndAllocation = {}; - ID3D12DescriptorHeap *descriptorHeap = nullptr; - }; - QVector<DeferredReleaseEntry> queue; - QD3D12ObjectPool<QD3D12Resource> *resourcePool = nullptr; - QD3D12ObjectPool<QD3D12Pipeline> *pipelinePool = nullptr; - QD3D12ObjectPool<QD3D12RootSignature> *rootSignaturePool = nullptr; -}; - -struct QD3D12CommandBuffer; - -struct QD3D12ResourceBarrierGenerator -{ - static const int PREALLOC = 16; - - void create(QD3D12ObjectPool<QD3D12Resource> *resourcePool) - { - this->resourcePool = resourcePool; - } - - void addTransitionBarrier(const QD3D12ObjectHandle &resourceHandle, D3D12_RESOURCE_STATES stateAfter); - void enqueueBufferedTransitionBarriers(QD3D12CommandBuffer *cbD); - void enqueueSubresourceTransitionBarrier(QD3D12CommandBuffer *cbD, - const QD3D12ObjectHandle &resourceHandle, - UINT subresource, - D3D12_RESOURCE_STATES stateBefore, - D3D12_RESOURCE_STATES stateAfter); - void enqueueUavBarrier(QD3D12CommandBuffer *cbD, const QD3D12ObjectHandle &resourceHandle); - - struct TransitionResourceBarrier { - QD3D12ObjectHandle resourceHandle; - D3D12_RESOURCE_STATES stateBefore; - D3D12_RESOURCE_STATES stateAfter; - }; - QVarLengthArray<TransitionResourceBarrier, PREALLOC> transitionResourceBarriers; - QD3D12ObjectPool<QD3D12Resource> *resourcePool = nullptr; -}; - -struct QD3D12ShaderBytecodeCache -{ - struct Shader { - Shader() = default; - Shader(const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm) - : bytecode(bytecode), nativeResourceBindingMap(rbm) - { } - QByteArray bytecode; - QShader::NativeResourceBindingMap nativeResourceBindingMap; - }; - - QHash<QRhiShaderStage, Shader> data; - - void insertWithCapacityLimit(const QRhiShaderStage &key, const Shader &s); -}; - -struct QD3D12ShaderVisibleDescriptorHeap -{ - bool create(ID3D12Device *device, D3D12_DESCRIPTOR_HEAP_TYPE type, quint32 perFrameDescriptorCount); - void destroy(); - void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue); - - QD3D12DescriptorHeap heap; - QD3D12DescriptorHeap perFrameHeapSlice[QD3D12_FRAMES_IN_FLIGHT]; -}; - -// wrap foreign struct so we can legally supply equality operators and qHash: -struct Q_D3D12_SAMPLER_DESC -{ - D3D12_SAMPLER_DESC desc; - - friend bool operator==(const Q_D3D12_SAMPLER_DESC &lhs, const Q_D3D12_SAMPLER_DESC &rhs) noexcept - { - return lhs.desc.Filter == rhs.desc.Filter - && lhs.desc.AddressU == rhs.desc.AddressU - && lhs.desc.AddressV == rhs.desc.AddressV - && lhs.desc.AddressW == rhs.desc.AddressW - && lhs.desc.MipLODBias == rhs.desc.MipLODBias - && lhs.desc.MaxAnisotropy == rhs.desc.MaxAnisotropy - && lhs.desc.ComparisonFunc == rhs.desc.ComparisonFunc - // BorderColor is never used, skip it - && lhs.desc.MinLOD == rhs.desc.MinLOD - && lhs.desc.MaxLOD == rhs.desc.MaxLOD; - } - - friend bool operator!=(const Q_D3D12_SAMPLER_DESC &lhs, const Q_D3D12_SAMPLER_DESC &rhs) noexcept - { - return !(lhs == rhs); - } - - friend size_t qHash(const Q_D3D12_SAMPLER_DESC &key, size_t seed = 0) noexcept - { - QtPrivate::QHashCombine hash; - seed = hash(seed, key.desc.Filter); - seed = hash(seed, key.desc.AddressU); - seed = hash(seed, key.desc.AddressV); - seed = hash(seed, key.desc.AddressW); - seed = hash(seed, key.desc.MipLODBias); - seed = hash(seed, key.desc.MaxAnisotropy); - seed = hash(seed, key.desc.ComparisonFunc); - // BorderColor is never used, skip it - seed = hash(seed, key.desc.MinLOD); - seed = hash(seed, key.desc.MaxLOD); - return seed; - } -}; - -struct QD3D12SamplerManager -{ - const quint32 MAX_SAMPLERS = 512; - - bool create(ID3D12Device *device); - void destroy(); - - QD3D12Descriptor getShaderVisibleDescriptor(const D3D12_SAMPLER_DESC &desc); - - ID3D12Device *device = nullptr; - QD3D12ShaderVisibleDescriptorHeap shaderVisibleSamplerHeap; - QHash<Q_D3D12_SAMPLER_DESC, QD3D12Descriptor> gpuMap; -}; - -enum QD3D12Stage { VS = 0, HS, DS, GS, PS, CS }; - -static inline QD3D12Stage qd3d12_stage(QRhiShaderStage::Type type) -{ - switch (type) { - case QRhiShaderStage::Vertex: - return VS; - case QRhiShaderStage::TessellationControl: - return HS; - case QRhiShaderStage::TessellationEvaluation: - return DS; - case QRhiShaderStage::Geometry: - return GS; - case QRhiShaderStage::Fragment: - return PS; - case QRhiShaderStage::Compute: - return CS; - } - Q_UNREACHABLE_RETURN(VS); -} - -static inline D3D12_SHADER_VISIBILITY qd3d12_stageToVisibility(QD3D12Stage s) -{ - switch (s) { - case VS: - return D3D12_SHADER_VISIBILITY_VERTEX; - case HS: - return D3D12_SHADER_VISIBILITY_HULL; - case DS: - return D3D12_SHADER_VISIBILITY_DOMAIN; - case GS: - return D3D12_SHADER_VISIBILITY_GEOMETRY; - case PS: - return D3D12_SHADER_VISIBILITY_PIXEL; - case CS: - return D3D12_SHADER_VISIBILITY_ALL; - } - Q_UNREACHABLE_RETURN(D3D12_SHADER_VISIBILITY_ALL); -} - -static inline QRhiShaderResourceBinding::StageFlag qd3d12_stageToSrb(QD3D12Stage s) -{ - switch (s) { - case VS: - return QRhiShaderResourceBinding::VertexStage; - case HS: - return QRhiShaderResourceBinding::TessellationControlStage; - case DS: - return QRhiShaderResourceBinding::TessellationEvaluationStage; - case GS: - return QRhiShaderResourceBinding::GeometryStage; - case PS: - return QRhiShaderResourceBinding::FragmentStage; - case CS: - return QRhiShaderResourceBinding::ComputeStage; - } - Q_UNREACHABLE_RETURN(QRhiShaderResourceBinding::VertexStage); -} - -struct QD3D12ShaderStageData -{ - bool valid = false; // to allow simple arrays where unused stages are indicated by !valid - QD3D12Stage stage = VS; - QShader::NativeResourceBindingMap nativeResourceBindingMap; -}; - -struct QD3D12ShaderResourceBindings; - -struct QD3D12ShaderResourceVisitor -{ - enum StorageOp { Load = 0, Store, LoadStore }; - - QD3D12ShaderResourceVisitor(const QD3D12ShaderResourceBindings *srb, - const QD3D12ShaderStageData *stageData, - int stageCount) - : srb(srb), - stageData(stageData), - stageCount(stageCount) - { - } - - std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::UniformBufferData &, int, int)> uniformBuffer = nullptr; - std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::TextureAndSampler &, int)> texture = nullptr; - std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::TextureAndSampler &, int)> sampler = nullptr; - std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::StorageImageData &, StorageOp, int)> storageImage = nullptr; - std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::StorageBufferData &, StorageOp, int)> storageBuffer = nullptr; - - void visit(); - - const QD3D12ShaderResourceBindings *srb; - const QD3D12ShaderStageData *stageData; - int stageCount; -}; - -struct QD3D12Readback -{ - // common - int frameSlot = -1; - QRhiReadbackResult *result = nullptr; - QD3D12StagingArea staging; - quint32 byteSize = 0; - // textures - quint32 bytesPerLine = 0; - QSize pixelSize; - QRhiTexture::Format format = QRhiTexture::UnknownFormat; - quint32 stagingRowPitch = 0; -}; - -struct QD3D12MipmapGenerator -{ - bool create(QRhiD3D12 *rhiD); - void destroy(); - void generate(QD3D12CommandBuffer *cbD, const QD3D12ObjectHandle &textureHandle); - - QRhiD3D12 *rhiD; - QD3D12ObjectHandle rootSigHandle; - QD3D12ObjectHandle pipelineHandle; -}; - -struct QD3D12MemoryAllocator -{ - bool create(ID3D12Device *device, IDXGIAdapter1 *adapter); - void destroy(); - - HRESULT createResource(D3D12_HEAP_TYPE heapType, - const D3D12_RESOURCE_DESC *resourceDesc, - D3D12_RESOURCE_STATES initialState, - const D3D12_CLEAR_VALUE *optimizedClearValue, - D3D12MA::Allocation **maybeAllocation, - REFIID riidResource, - void **ppvResource); - - void getBudget(D3D12MA::Budget *localBudget, D3D12MA::Budget *nonLocalBudget); - - bool isUsingD3D12MA() const { return allocator != nullptr; } - - ID3D12Device *device = nullptr; - D3D12MA::Allocator *allocator = nullptr; -}; - -struct QD3D12Buffer : public QRhiBuffer -{ - QD3D12Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size); - ~QD3D12Buffer(); - - void destroy() override; - bool create() override; - QRhiBuffer::NativeBuffer nativeBuffer() override; - char *beginFullDynamicBufferUpdateForCurrentFrame() override; - void endFullDynamicBufferUpdateForCurrentFrame() override; - - void executeHostWritesForFrameSlot(int frameSlot); - - QD3D12ObjectHandle handles[QD3D12_FRAMES_IN_FLIGHT] = {}; - struct HostWrite { - quint32 offset; - QRhiBufferData data; - }; - QVarLengthArray<HostWrite, 16> pendingHostWrites[QD3D12_FRAMES_IN_FLIGHT]; - friend class QRhiD3D12; -}; - -struct QD3D12RenderBuffer : public QRhiRenderBuffer -{ - QD3D12RenderBuffer(QRhiImplementation *rhi, - Type type, - const QSize &pixelSize, - int sampleCount, - Flags flags, - QRhiTexture::Format backingFormatHint); - ~QD3D12RenderBuffer(); - void destroy() override; - bool create() override; - QRhiTexture::Format backingFormat() const override; - - static const DXGI_FORMAT DS_FORMAT = DXGI_FORMAT_D24_UNORM_S8_UINT; - - QD3D12ObjectHandle handle; - QD3D12Descriptor rtv; - QD3D12Descriptor dsv; - DXGI_FORMAT dxgiFormat; - DXGI_SAMPLE_DESC sampleDesc; - uint generation = 0; - friend class QRhiD3D12; -}; - -struct QD3D12Texture : public QRhiTexture -{ - QD3D12Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, - int arraySize, int sampleCount, Flags flags); - ~QD3D12Texture(); - void destroy() override; - bool create() override; - bool createFrom(NativeTexture src) override; - NativeTexture nativeTexture() override; - void setNativeLayout(int layout) override; - - bool prepareCreate(QSize *adjustedSize = nullptr); - bool finishCreate(); - - QD3D12ObjectHandle handle; - QD3D12Descriptor srv; - DXGI_FORMAT dxgiFormat; - uint mipLevelCount; - DXGI_SAMPLE_DESC sampleDesc; - uint generation = 0; - friend class QRhiD3D12; -}; - -struct QD3D12Sampler : public QRhiSampler -{ - QD3D12Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v, AddressMode w); - ~QD3D12Sampler(); - void destroy() override; - bool create() override; - - QD3D12Descriptor lookupOrCreateShaderVisibleDescriptor(); - - D3D12_SAMPLER_DESC desc = {}; - QD3D12Descriptor shaderVisibleDescriptor; -}; - -struct QD3D12RenderPassDescriptor : public QRhiRenderPassDescriptor -{ - QD3D12RenderPassDescriptor(QRhiImplementation *rhi); - ~QD3D12RenderPassDescriptor(); - void destroy() override; - bool isCompatible(const QRhiRenderPassDescriptor *other) const override; - QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; - QVector<quint32> serializedFormat() const override; - - void updateSerializedFormat(); - - static const int MAX_COLOR_ATTACHMENTS = 8; - int colorAttachmentCount = 0; - bool hasDepthStencil = false; - int colorFormat[MAX_COLOR_ATTACHMENTS]; - int dsFormat; - QVector<quint32> serializedFormatData; -}; - -struct QD3D12RenderTargetData -{ - QD3D12RenderTargetData(QRhiImplementation *) { } - - QD3D12RenderPassDescriptor *rp = nullptr; - QSize pixelSize; - float dpr = 1; - int sampleCount = 1; - int colorAttCount = 0; - int dsAttCount = 0; - QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList; - static const int MAX_COLOR_ATTACHMENTS = QD3D12RenderPassDescriptor::MAX_COLOR_ATTACHMENTS; - D3D12_CPU_DESCRIPTOR_HANDLE rtv[MAX_COLOR_ATTACHMENTS]; - D3D12_CPU_DESCRIPTOR_HANDLE dsv; -}; - -struct QD3D12SwapChainRenderTarget : public QRhiSwapChainRenderTarget -{ - QD3D12SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain); - ~QD3D12SwapChainRenderTarget(); - void destroy() override; - - QSize pixelSize() const override; - float devicePixelRatio() const override; - int sampleCount() const override; - - QD3D12RenderTargetData d; -}; - -struct QD3D12TextureRenderTarget : public QRhiTextureRenderTarget -{ - QD3D12TextureRenderTarget(QRhiImplementation *rhi, - const QRhiTextureRenderTargetDescription &desc, - Flags flags); - ~QD3D12TextureRenderTarget(); - void destroy() override; - - QSize pixelSize() const override; - float devicePixelRatio() const override; - int sampleCount() const override; - - QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; - bool create() override; - - QD3D12RenderTargetData d; - bool ownsRtv[QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS]; - QD3D12Descriptor rtv[QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS]; - bool ownsDsv = false; - QD3D12Descriptor dsv; - friend class QRhiD3D12; -}; - -struct QD3D12ShaderResourceBindings : public QRhiShaderResourceBindings -{ - QD3D12ShaderResourceBindings(QRhiImplementation *rhi); - ~QD3D12ShaderResourceBindings(); - void destroy() override; - bool create() override; - void updateResources(UpdateFlags flags) override; - - QD3D12ObjectHandle createRootSignature(const QD3D12ShaderStageData *stageData, int stageCount); - - struct VisitorData { - QVarLengthArray<D3D12_ROOT_PARAMETER1, 2> cbParams[6]; - - D3D12_ROOT_PARAMETER1 srvTables[6] = {}; - QVarLengthArray<D3D12_DESCRIPTOR_RANGE1, 4> srvRanges[6]; - quint32 currentSrvRangeOffset[6] = {}; - - QVarLengthArray<D3D12_ROOT_PARAMETER1, 4> samplerTables[6]; - std::array<D3D12_DESCRIPTOR_RANGE1, 16> samplerRanges[6] = {}; - int samplerRangeHeads[6] = {}; - - D3D12_ROOT_PARAMETER1 uavTables[6] = {}; - QVarLengthArray<D3D12_DESCRIPTOR_RANGE1, 4> uavRanges[6]; - quint32 currentUavRangeOffset[6] = {}; - } visitorData; - - - void visitUniformBuffer(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::UniformBufferData &d, - int shaderRegister, - int binding); - void visitTexture(QD3D12Stage s, - const QRhiShaderResourceBinding::TextureAndSampler &d, - int shaderRegister); - void visitSampler(QD3D12Stage s, - const QRhiShaderResourceBinding::TextureAndSampler &d, - int shaderRegister); - void visitStorageBuffer(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::StorageBufferData &d, - QD3D12ShaderResourceVisitor::StorageOp op, - int shaderRegister); - void visitStorageImage(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::StorageImageData &d, - QD3D12ShaderResourceVisitor::StorageOp op, - int shaderRegister); - - QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings; - bool hasDynamicOffset = false; - uint generation = 0; -}; - -struct QD3D12GraphicsPipeline : public QRhiGraphicsPipeline -{ - QD3D12GraphicsPipeline(QRhiImplementation *rhi); - ~QD3D12GraphicsPipeline(); - void destroy() override; - bool create() override; - - QD3D12ObjectHandle handle; - QD3D12ObjectHandle rootSigHandle; - std::array<QD3D12ShaderStageData, 5> stageData; - D3D12_PRIMITIVE_TOPOLOGY topology; - uint generation = 0; - friend class QRhiD3D12; -}; - -struct QD3D12ComputePipeline : public QRhiComputePipeline -{ - QD3D12ComputePipeline(QRhiImplementation *rhi); - ~QD3D12ComputePipeline(); - void destroy() override; - bool create() override; - - QD3D12ObjectHandle handle; - QD3D12ObjectHandle rootSigHandle; - QD3D12ShaderStageData stageData; - uint generation = 0; - friend class QRhiD3D12; -}; - -struct QD3D12CommandBuffer : public QRhiCommandBuffer -{ - QD3D12CommandBuffer(QRhiImplementation *rhi); - ~QD3D12CommandBuffer(); - void destroy() override; - - const QRhiNativeHandles *nativeHandles(); - - ID3D12GraphicsCommandList *cmdList = nullptr; // not owned - QRhiD3D12CommandBufferNativeHandles nativeHandlesStruct; - - enum PassType { - NoPass, - RenderPass, - ComputePass - }; - - void resetState() - { - recordingPass = NoPass; - currentTarget = nullptr; - - resetPerPassState(); - } - - void resetPerPassState() - { - currentGraphicsPipeline = nullptr; - currentComputePipeline = nullptr; - currentPipelineGeneration = 0; - currentGraphicsSrb = nullptr; - currentComputeSrb = nullptr; - currentSrbGeneration = 0; - currentIndexBuffer = {}; - currentIndexOffset = 0; - currentIndexFormat = DXGI_FORMAT_R16_UINT; - currentVertexBuffers = {}; - currentVertexOffsets = {}; - } - - PassType recordingPass; - QRhiRenderTarget *currentTarget; - - QD3D12GraphicsPipeline *currentGraphicsPipeline; - QD3D12ComputePipeline *currentComputePipeline; - uint currentPipelineGeneration; - QRhiShaderResourceBindings *currentGraphicsSrb; - QRhiShaderResourceBindings *currentComputeSrb; - uint currentSrbGeneration; - QD3D12ObjectHandle currentIndexBuffer; - quint32 currentIndexOffset; - DXGI_FORMAT currentIndexFormat; - std::array<QD3D12ObjectHandle, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> currentVertexBuffers; - std::array<quint32, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> currentVertexOffsets; -}; - -struct QD3D12SwapChain : public QRhiSwapChain -{ - QD3D12SwapChain(QRhiImplementation *rhi); - ~QD3D12SwapChain(); - 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; - - void releaseBuffers(); - void waitCommandCompletionForFrameSlot(int frameSlot); - void addCommandCompletionSignalForCurrentFrameSlot(); - void chooseFormats(); - - QWindow *window = nullptr; - IDXGISwapChain1 *sourceSwapChain1 = nullptr; - IDXGISwapChain3 *swapChain = nullptr; - QSize pixelSize; - UINT swapInterval = 1; - UINT swapChainFlags = 0; - DXGI_FORMAT colorFormat; - DXGI_FORMAT srgbAdjustedColorFormat; - DXGI_COLOR_SPACE_TYPE hdrColorSpace; - IDCompositionTarget *dcompTarget = nullptr; - IDCompositionVisual *dcompVisual = nullptr; - static const UINT BUFFER_COUNT = 3; - QD3D12ObjectHandle colorBuffers[BUFFER_COUNT]; - QD3D12Descriptor rtvs[BUFFER_COUNT]; - DXGI_SAMPLE_DESC sampleDesc; - QD3D12ObjectHandle msaaBuffers[BUFFER_COUNT]; - QD3D12Descriptor msaaRtvs[BUFFER_COUNT]; - QD3D12RenderBuffer *ds = nullptr; - UINT currentBackBufferIndex = 0; - QD3D12SwapChainRenderTarget rtWrapper; - QD3D12CommandBuffer cbWrapper; - - struct FrameResources { - ID3D12Fence *fence = nullptr; - HANDLE fenceEvent = nullptr; - UINT64 fenceCounter = 0; - ID3D12GraphicsCommandList *cmdList = nullptr; - } frameRes[QD3D12_FRAMES_IN_FLIGHT]; - - int currentFrameSlot = 0; // index in frameRes -}; - -class QRhiD3D12 : public QRhiImplementation -{ -public: - // 16MB * QD3D12_FRAMES_IN_FLIGHT; buffer and texture upload staging data that - // gets no space from this will get their own temporary staging areas. - static const quint32 SMALL_STAGING_AREA_BYTES_PER_FRAME = 16 * 1024 * 1024; - - static const quint32 SHADER_VISIBLE_CBV_SRV_UAV_HEAP_PER_FRAME_START_SIZE = 16384; - - QRhiD3D12(QRhiD3D12InitParams *params, QRhiD3D12NativeHandles *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; - - 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 waitGpu(); - DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount, DXGI_FORMAT format) const; - bool ensureDirectCompositionDevice(); - bool startCommandListForCurrentFrameSlot(ID3D12GraphicsCommandList **cmdList); - void enqueueResourceUpdates(QD3D12CommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates); - void finishActiveReadbacks(bool forced = false); - bool ensureShaderVisibleDescriptorHeapCapacity(QD3D12ShaderVisibleDescriptorHeap *h, - D3D12_DESCRIPTOR_HEAP_TYPE type, - int frameSlot, - quint32 neededDescriptorCount, - bool *gotNew); - void bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD); - - bool debugLayer = false; - ID3D12Device *dev = nullptr; - D3D_FEATURE_LEVEL minimumFeatureLevel = D3D_FEATURE_LEVEL(0); - LUID adapterLuid = {}; - bool importedDevice = false; - bool importedCommandQueue = false; - QRhi::Flags rhiFlags; - IDXGIFactory2 *dxgiFactory = nullptr; - bool supportsAllowTearing = false; - IDXGIAdapter1 *activeAdapter = nullptr; - QRhiDriverInfo driverInfoStruct; - QRhiD3D12NativeHandles nativeHandlesStruct; - bool deviceLost = false; - ID3D12CommandQueue *cmdQueue = nullptr; - ID3D12Fence *fullFence = nullptr; - HANDLE fullFenceEvent = nullptr; - UINT64 fullFenceCounter = 0; - ID3D12CommandAllocator *cmdAllocators[QD3D12_FRAMES_IN_FLIGHT] = {}; - QD3D12MemoryAllocator vma; - QD3D12CpuDescriptorPool rtvPool; - QD3D12CpuDescriptorPool dsvPool; - QD3D12CpuDescriptorPool cbvSrvUavPool; - QD3D12ObjectPool<QD3D12Resource> resourcePool; - QD3D12ObjectPool<QD3D12Pipeline> pipelinePool; - QD3D12ObjectPool<QD3D12RootSignature> rootSignaturePool; - QD3D12ReleaseQueue releaseQueue; - QD3D12ResourceBarrierGenerator barrierGen; - QD3D12SamplerManager samplerMgr; - QD3D12MipmapGenerator mipmapGen; - QD3D12StagingArea smallStagingAreas[QD3D12_FRAMES_IN_FLIGHT]; - QD3D12ShaderVisibleDescriptorHeap shaderVisibleCbvSrvUavHeap; - IDCompositionDevice *dcompDevice = nullptr; - QD3D12SwapChain *currentSwapChain = nullptr; - QSet<QD3D12SwapChain *> swapchains; - QD3D12ShaderBytecodeCache shaderBytecodeCache; - QVarLengthArray<QD3D12Readback, 4> activeReadbacks; - bool offscreenActive = false; - QD3D12CommandBuffer *offscreenCb[QD3D12_FRAMES_IN_FLIGHT] = {}; - - struct VisitorData { - QVarLengthArray<QPair<QD3D12ObjectHandle, quint32>, 4> cbufs[6]; - QVarLengthArray<QD3D12Descriptor, 8> srvs[6]; - QVarLengthArray<QD3D12Descriptor, 8> samplers[6]; - QVarLengthArray<QPair<QD3D12ObjectHandle, D3D12_UNORDERED_ACCESS_VIEW_DESC>, 4> uavs[6]; - } visitorData; - - void visitUniformBuffer(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::UniformBufferData &d, - int shaderRegister, - int binding, - int dynamicOffsetCount, - const QRhiCommandBuffer::DynamicOffset *dynamicOffsets); - void visitTexture(QD3D12Stage s, - const QRhiShaderResourceBinding::TextureAndSampler &d, - int shaderRegister); - void visitSampler(QD3D12Stage s, - const QRhiShaderResourceBinding::TextureAndSampler &d, - int shaderRegister); - void visitStorageBuffer(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::StorageBufferData &d, - QD3D12ShaderResourceVisitor::StorageOp op, - int shaderRegister); - void visitStorageImage(QD3D12Stage s, - const QRhiShaderResourceBinding::Data::StorageImageData &d, - QD3D12ShaderResourceVisitor::StorageOp op, - int shaderRegister); -}; - -QT_END_NAMESPACE - -#endif |