From e54c8a7c6b1a01eac0310a1a0070221be8fcd1e7 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 1 Nov 2015 19:41:24 -1000 Subject: [PATCH] Initial round of D3D12 implementation --- include/boo/graphicsdev/D3D11.hpp | 35 + include/boo/graphicsdev/D3D12.hpp | 46 + .../boo/graphicsdev/IGraphicsDataFactory.hpp | 19 +- lib/graphicsdev/D3D11.cpp | 0 lib/graphicsdev/D3D12.cpp | 817 +++++++++ lib/graphicsdev/d3dx12.h | 1507 +++++++++++++++++ 6 files changed, 2413 insertions(+), 11 deletions(-) create mode 100644 lib/graphicsdev/D3D11.cpp create mode 100644 lib/graphicsdev/D3D12.cpp create mode 100644 lib/graphicsdev/d3dx12.h diff --git a/include/boo/graphicsdev/D3D11.hpp b/include/boo/graphicsdev/D3D11.hpp index 2b3b8b8..4972d0d 100644 --- a/include/boo/graphicsdev/D3D11.hpp +++ b/include/boo/graphicsdev/D3D11.hpp @@ -8,6 +8,41 @@ namespace boo class D3D11DataFactory : public IGraphicsDataFactory { + IGraphicsContext* m_parent; + IGraphicsData* m_deferredData = nullptr; + std::unordered_set m_committedData; +public: + D3D11DataFactory(IGraphicsContext* parent); + ~D3D11DataFactory() {} + + Platform platform() const {return PlatformD3D11;} + const char* platformName() const {return "Direct 3D 11";} + + const IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t sz); + IGraphicsBufferD* newDynamicBuffer(BufferUse use); + + const ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + const void* data, size_t sz); + ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); + + const IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); + + const IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, + size_t texCount, const char** texNames, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling); + + const IShaderDataBinding* + newShaderDataBinding(const IShaderPipeline* pipeline, + const IVertexFormat* vtxFormat, + const IGraphicsBuffer* vbo, const IGraphicsBuffer* ebo, + size_t ubufCount, const IGraphicsBuffer** ubufs, + size_t texCount, const ITexture** texs); + + void reset(); + IGraphicsData* commit(); + void destroyData(IGraphicsData*); + void destroyAllData(); }; } diff --git a/include/boo/graphicsdev/D3D12.hpp b/include/boo/graphicsdev/D3D12.hpp index 5cd068f..72b9c63 100644 --- a/include/boo/graphicsdev/D3D12.hpp +++ b/include/boo/graphicsdev/D3D12.hpp @@ -2,12 +2,58 @@ #define GDEV_D3D12_HPP #include "IGraphicsDataFactory.hpp" +#include "IGraphicsCommandQueue.hpp" +#include "boo/IGraphicsContext.hpp" +#include +#include +#include + +#include +template +using ComPtr = Microsoft::WRL::ComPtr; namespace boo { class D3D12DataFactory : public IGraphicsDataFactory { + IGraphicsContext* m_parent; + IGraphicsData* m_deferredData = nullptr; + struct D3D12Context* m_ctx; + std::unordered_set m_committedData; +public: + D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx); + ~D3D12DataFactory() {} + + Platform platform() const {return PlatformD3D12;} + const char* platformName() const {return "Direct 3D 12";} + + const IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); + IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count); + + const ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + const void* data, size_t sz); + ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); + + const IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); + + const IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, + ComPtr& vertBlobOut, ComPtr& fragBlobOut, + const IVertexFormat* vtxFmt, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling); + + const IShaderDataBinding* + newShaderDataBinding(IShaderPipeline* pipeline, + IVertexFormat* vtxFormat, + IGraphicsBuffer* vbo, IGraphicsBuffer* ebo, + size_t ubufCount, IGraphicsBuffer** ubufs, + size_t texCount, ITexture** texs); + + void reset(); + IGraphicsData* commit(); + void destroyData(IGraphicsData* data); + void destroyAllData(); }; } diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 52c89fc..dcb9729 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -10,9 +10,6 @@ namespace boo struct IGraphicsBuffer { bool dynamic() const {return m_dynamic;} - virtual void bindVertex() const=0; - virtual void bindIndex() const=0; - virtual void bindUniform(size_t idx) const=0; protected: bool m_dynamic; IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {} @@ -47,7 +44,6 @@ enum BufferUse struct ITexture { bool dynamic() const {return m_dynamic;} - virtual void bind(size_t idx) const=0; protected: bool m_dynamic; ITexture(bool dynamic) : m_dynamic(dynamic) {} @@ -99,6 +95,7 @@ struct VertexElementDescriptor const IGraphicsBuffer* vertBuffer = nullptr; const IGraphicsBuffer* indexBuffer = nullptr; VertexSemantic semantic; + int semanticIdx = 0; }; /** Opaque token for referencing a complete graphics pipeline state necessary @@ -151,9 +148,9 @@ struct IGraphicsDataFactory virtual const char* platformName() const=0; virtual const IGraphicsBufferS* - newStaticBuffer(BufferUse use, const void* data, size_t sz)=0; + newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0; virtual IGraphicsBufferD* - newDynamicBuffer(BufferUse use)=0; + newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0; virtual const ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, @@ -165,11 +162,11 @@ struct IGraphicsDataFactory newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0; virtual const IShaderDataBinding* - newShaderDataBinding(const IShaderPipeline* pipeline, - const IVertexFormat* vtxFormat, - const IGraphicsBuffer* vbo, const IGraphicsBuffer* ebo, - size_t ubufCount, const IGraphicsBuffer** ubufs, - size_t texCount, const ITexture** texs)=0; + newShaderDataBinding(IShaderPipeline* pipeline, + IVertexFormat* vtxFormat, + IGraphicsBuffer* vbo, IGraphicsBuffer* ebo, + size_t ubufCount, IGraphicsBuffer** ubufs, + size_t texCount, ITexture** texs)=0; virtual void reset()=0; virtual IGraphicsData* commit()=0; diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp new file mode 100644 index 0000000..1ea9923 --- /dev/null +++ b/lib/graphicsdev/D3D12.cpp @@ -0,0 +1,817 @@ +#include "boo/graphicsdev/D3D12.hpp" +#include "boo/IGraphicsContext.hpp" +#include +#include +#include +#include + +#include + +#include "d3dx12.h" +#include + +namespace boo +{ +static LogVisor::LogModule Log("boo::GL"); + +static inline void ThrowIfFailed(HRESULT hr) +{ + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + Log.report(LogVisor::FatalError, "General D3D12 err"); + } +} + +static inline UINT64 NextHeapOffset(UINT64 offset, const D3D12_RESOURCE_ALLOCATION_INFO& info) +{ + offset += info.SizeInBytes; + return (offset + info.Alignment - 1) & ~(info.Alignment - 1); +} + +struct D3D12Context +{ + ComPtr m_dev; + ComPtr m_qalloc; + ComPtr m_q; + ComPtr m_loadqalloc; + ComPtr m_loadq; + ComPtr m_frameFence; + ComPtr m_rs; + struct Window + { + ComPtr m_fbs[3]; + }; + std::vector m_windows; +}; + +struct D3D12Data : IGraphicsData +{ + std::vector> m_SPs; + std::vector> m_SBinds; + std::vector> m_SBufs; + std::vector> m_DBufs; + std::vector> m_STexs; + std::vector> m_DTexs; + std::vector> m_VFmts; + ComPtr m_gpuHeap; +}; + +static const D3D12_RESOURCE_STATES USE_TABLE[] = +{ + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, + D3D12_RESOURCE_STATE_INDEX_BUFFER, + D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER +}; + +class D3D12GraphicsBufferS : public IGraphicsBufferS +{ + friend class D3D12DataFactory; + friend struct D3D12CommandQueue; + D3D12_RESOURCE_STATES m_state; + D3D12GraphicsBufferS(BufferUse use, D3D12Context* ctx, const void* data, size_t stride, size_t count) + : m_state(USE_TABLE[use]), m_stride(stride), m_count(count) + { + size_t sz = stride * count; + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sz), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_buf)); + void* m_d3dBuf; + m_buf->Map(0, nullptr, &m_d3dBuf); + memcpy(m_d3dBuf, data, sz); + m_buf->Unmap(0, nullptr); + } +public: + size_t m_stride; + size_t m_count; + ComPtr m_buf; + ComPtr m_gpuBuf; + ~D3D12GraphicsBufferS() = default; + + UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) + { + D3D12_RESOURCE_DESC desc = m_buf->GetDesc(); + ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, m_state, + nullptr, __uuidof(ID3D12Resource), &m_gpuBuf)); + return NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &desc)); + } +}; + +class D3D12GraphicsBufferD : public IGraphicsBufferD +{ + friend class D3D12DataFactory; + friend struct D3D12CommandQueue; + D3D12CommandQueue* m_q; + D3D12_RESOURCE_STATES m_state; + D3D12GraphicsBufferD(D3D12CommandQueue* q, BufferUse use, D3D12Context* ctx, size_t stride, size_t count) + : m_state(USE_TABLE[use]), m_q(q), m_stride(stride), m_count(count) + { + size_t sz = stride * count; + for (int i=0 ; i<3 ; ++i) + { + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sz), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_bufs[i])); + } + } +public: + size_t m_stride; + size_t m_count; + ComPtr m_bufs[3]; + ComPtr m_gpuBufs[3]; + ~D3D12GraphicsBufferD() = default; + + void load(const void* data, size_t sz); + void* map(size_t sz); + void unmap(); + + UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) + { + for (int i=0 ; i<3 ; ++i) + { + D3D12_RESOURCE_DESC desc = m_bufs[i]->GetDesc(); + ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, m_state, + nullptr, __uuidof(ID3D12Resource), &m_gpuBufs[i])); + offset = NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &desc)); + } + return offset; + } +}; + +const IGraphicsBufferS* +D3D12DataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) +{ + D3D12GraphicsBufferS* retval = new D3D12GraphicsBufferS(use, m_ctx, data, stride, count); + static_cast(m_deferredData)->m_SBufs.emplace_back(retval); + return retval; +} + +class D3D12TextureS : public ITextureS +{ + friend class D3D12DataFactory; + D3D12TextureS(D3D12Context* ctx, size_t width, size_t height, size_t mips, + TextureFormat fmt, const void* data, size_t sz) + { + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, mips), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_tex)); + const uint8_t* dataIt = static_cast(data); + if (fmt == TextureFormatRGBA8) + { + for (size_t i=0 ; iMap(i, nullptr, &data); + size_t thisSz = width * height * 4; + memcpy(data, dataIt, thisSz); + m_tex->Unmap(i, nullptr); + dataIt += thisSz; + width /= 2; + height /= 2; + } + } + } +public: + ComPtr m_tex; + ComPtr m_gpuTex; + ~D3D12TextureS() = default; + + UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) + { + D3D12_RESOURCE_DESC desc = m_tex->GetDesc(); + ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + nullptr, __uuidof(ID3D12Resource), &m_gpuTex)); + return NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &desc)); + } +}; + +class D3D12TextureD : public ITextureD +{ + friend class D3D12DataFactory; + friend struct D3D12CommandQueue; + size_t m_width = 0; + size_t m_height = 0; + D3D12CommandQueue* m_q; + D3D12TextureD(D3D12CommandQueue* q, D3D12Context* ctx, size_t width, size_t height, TextureFormat fmt) + : m_q(q) + { + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_texs[0])); + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_texs[1])); + } +public: + ComPtr m_texs[2]; + ComPtr m_gpuTexs[2]; + ~D3D12TextureD() = default; + + void load(const void* data, size_t sz) + { + void* buf; + m_texs[0]->Map(0, nullptr, &buf); + memcpy(buf, data, sz); + m_texs[0]->Unmap(0, nullptr); + } + void* map(size_t sz) + { + void* buf; + m_texs[0]->Map(0, nullptr, &buf); + return buf; + } + void unmap() + { + m_texs[0]->Unmap(0, nullptr); + } + + UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) + { + for (int i=0 ; i<2 ; ++i) + { + D3D12_RESOURCE_DESC desc = m_texs[i]->GetDesc(); + ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + nullptr, __uuidof(ID3D12Resource), &m_gpuTexs[i])); + offset = NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &desc)); + } + return offset; + } +}; + +const ITextureS* +D3D12DataFactory::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + const void* data, size_t sz) +{ + D3D12TextureS* retval = new D3D12TextureS(m_ctx, width, height, mips, fmt, data, sz); + static_cast(m_deferredData)->m_STexs.emplace_back(retval); + return retval; +} + +static const size_t SEMANTIC_SIZE_TABLE[] = +{ + 12, + 12, + 4, + 8, + 16 +}; + +static const char* SEMANTIC_NAME_TABLE[] = +{ + "POSITION", + "NORMAL", + "COLOR", + "UV", + "WEIGHT" +}; + +static const DXGI_FORMAT SEMANTIC_TYPE_TABLE[] = +{ + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT +}; + +struct D3D12VertexFormat : IVertexFormat +{ + size_t m_elementCount; + std::unique_ptr m_elements; + D3D12VertexFormat(size_t elementCount, const VertexElementDescriptor* elements) + : m_elementCount(elementCount), + m_elements(new D3D12_INPUT_ELEMENT_DESC[elementCount]) + { + memset(m_elements.get(), 0, elementCount * sizeof(D3D12_INPUT_ELEMENT_DESC)); + for (size_t i=0 ; isemantic]; + elem.SemanticIndex = elements->semanticIdx; + elem.Format = SEMANTIC_TYPE_TABLE[elements->semantic]; + elem.AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT; + elem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; + } + } +}; + +static const D3D12_BLEND BLEND_FACTOR_TABLE[] = +{ + D3D12_BLEND_ZERO, + D3D12_BLEND_ONE, + D3D12_BLEND_SRC_COLOR, + D3D12_BLEND_INV_SRC_COLOR, + D3D12_BLEND_DEST_COLOR, + D3D12_BLEND_INV_DEST_COLOR, + D3D12_BLEND_SRC_ALPHA, + D3D12_BLEND_INV_SRC_ALPHA, + D3D12_BLEND_DEST_ALPHA, + D3D12_BLEND_INV_DEST_ALPHA +}; + +class D3D12ShaderPipeline : public IShaderPipeline +{ + friend class D3D12DataFactory; + D3D12ShaderPipeline(D3D12Context* ctx, ID3DBlob* vert, ID3DBlob* pixel, + const D3D12VertexFormat* vtxFmt, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling) + { + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; + desc.pRootSignature = ctx->m_rs.Get(); + desc.VS = {vert->GetBufferPointer(), vert->GetBufferSize()}; + desc.PS = {pixel->GetBufferPointer(), pixel->GetBufferSize()}; + desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + if (dstFac != BlendFactorZero) + { + desc.BlendState.RenderTarget[0].BlendEnable = true; + desc.BlendState.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[srcFac]; + desc.BlendState.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[dstFac]; + } + desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + if (!backfaceCulling) + desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + if (!depthTest) + desc.DepthStencilState.DepthEnable = false; + if (!depthWrite) + desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + desc.InputLayout.NumElements = vtxFmt->m_elementCount; + desc.InputLayout.pInputElementDescs = vtxFmt->m_elements.get(); + desc.SampleMask = UINT_MAX; + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + desc.NumRenderTargets = 1; + desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + ThrowIfFailed(ctx->m_dev->CreateGraphicsPipelineState(&desc, __uuidof(ID3D12PipelineState), &m_state)); + } +public: + ComPtr m_state; + ~D3D12ShaderPipeline() = default; + D3D12ShaderPipeline& operator=(const D3D12ShaderPipeline&) = delete; + D3D12ShaderPipeline(const D3D12ShaderPipeline&) = delete; +}; + +const IShaderPipeline* D3D12DataFactory::newShaderPipeline +(const char* vertSource, const char* fragSource, + ComPtr& vertBlobOut, ComPtr& fragBlobOut, + const IVertexFormat* vtxFmt, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling) +{ + ComPtr errBlob; + + if (FAILED(D3DCompile(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main", + "vs_5_0", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &vertBlobOut, &errBlob))) + { + Log.report(LogVisor::FatalError, "error compiling vert shader: %s", errBlob->GetBufferPointer()); + return nullptr; + } + + if (FAILED(D3DCompile(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main", + "ps_5_0", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &fragBlobOut, &errBlob))) + { + Log.report(LogVisor::FatalError, "error compiling pixel shader: %s", errBlob->GetBufferPointer()); + return nullptr; + } + + D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_ctx, vertBlobOut.Get(), fragBlobOut.Get(), + static_cast(vtxFmt), + srcFac, dstFac, depthTest, depthWrite, backfaceCulling); + static_cast(m_deferredData)->m_SPs.emplace_back(retval); + return retval; +} + +static UINT64 PlaceBufferForGPU(IGraphicsBuffer* buf, D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) +{ + if (buf->dynamic()) + return static_cast(buf)->placeForGPU(ctx, gpuHeap, offset); + else + return static_cast(buf)->placeForGPU(ctx, gpuHeap, offset); +} + +static UINT64 PlaceTextureForGPU(ITexture* tex, D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) +{ + if (tex->dynamic()) + return static_cast(tex)->placeForGPU(ctx, gpuHeap, offset); + else + return static_cast(tex)->placeForGPU(ctx, gpuHeap, offset); +} + +static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, + D3D12_SHADER_RESOURCE_VIEW_DESC& descOut) +{ + descOut.Format = DXGI_FORMAT_UNKNOWN; + descOut.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + descOut.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + descOut.Buffer.FirstElement = 0; + descOut.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; + if (buf->dynamic()) + { + const D3D12GraphicsBufferD* cbuf = static_cast(buf); + descOut.Buffer.NumElements = cbuf->m_count; + descOut.Buffer.StructureByteStride = cbuf->m_stride; + return cbuf->m_gpuBufs[idx].Get(); + } + else + { + const D3D12GraphicsBufferS* cbuf = static_cast(buf); + descOut.Buffer.NumElements = cbuf->m_count; + descOut.Buffer.StructureByteStride = cbuf->m_stride; + return cbuf->m_gpuBuf.Get(); + } +} + +static ID3D12Resource* GetTextureGPUResource(const ITexture* tex, int idx) +{ + if (tex->dynamic()) + { + const D3D12TextureD* ctex = static_cast(tex); + return ctex->m_gpuTexs[0].Get(); + } + else + { + const D3D12TextureS* ctex = static_cast(tex); + return ctex->m_gpuTex.Get(); + } +} + +static const struct DefaultTex2DViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC +{ + DefaultTex2DViewDesc() + { + Format = DXGI_FORMAT_R8G8B8A8_UNORM; + ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + Texture2D = {0, -1, 0, 0.0f}; + } +} Tex2DViewDesc; + +struct D3D12ShaderDataBinding : IShaderDataBinding +{ + D3D12ShaderPipeline* m_pipeline; + ComPtr m_gpuHeap; + ComPtr m_descHeap[3]; + IGraphicsBuffer* m_vbuf; + IGraphicsBuffer* m_ibuf; + size_t m_ubufCount; + std::unique_ptr m_ubufs; + size_t m_texCount; + std::unique_ptr m_texs; + D3D12ShaderDataBinding(D3D12Context* ctx, + IShaderPipeline* pipeline, + IGraphicsBuffer* vbuf, IGraphicsBuffer* ibuf, + size_t ubufCount, IGraphicsBuffer** ubufs, + size_t texCount, ITexture** texs) + : m_pipeline(static_cast(pipeline)), + m_vbuf(vbuf), + m_ibuf(ibuf), + m_ubufCount(ubufCount), + m_ubufs(new IGraphicsBuffer*[ubufCount]), + m_texCount(texCount), + m_texs(new ITexture*[texCount]) + { + for (size_t i=0 ; im_dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + for (int b=0 ; b<3 ; ++b) + { + ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&desc, _uuidof(ID3D12DescriptorHeap), &m_descHeap[b])); + CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart()); + D3D12_SHADER_RESOURCE_VIEW_DESC viewDesc; + + ctx->m_dev->CreateShaderResourceView(GetBufferGPUResource(m_vbuf, b, viewDesc), &viewDesc, handle); + handle.Offset(1, incSz); + if (m_ibuf) + ctx->m_dev->CreateShaderResourceView(GetBufferGPUResource(m_ibuf, b, viewDesc), &viewDesc, handle); + handle.Offset(1, incSz); + for (size_t i=0 ; im_dev->CreateShaderResourceView(GetBufferGPUResource(m_ubufs[i], b, viewDesc), &viewDesc, handle); + handle.Offset(1, incSz); + } + for (size_t i=0 ; im_dev->CreateShaderResourceView(GetTextureGPUResource(m_texs[i], b), &Tex2DViewDesc, handle); + handle.Offset(1, incSz); + } + } + } +}; + +const IShaderDataBinding* +D3D12DataFactory::newShaderDataBinding(IShaderPipeline* pipeline, + IVertexFormat* vtxFormat, + IGraphicsBuffer* vbuf, IGraphicsBuffer* ibuf, + size_t ubufCount, IGraphicsBuffer** ubufs, + size_t texCount, ITexture** texs) +{ + D3D12ShaderDataBinding* retval = + new D3D12ShaderDataBinding(m_ctx, pipeline, vbuf, ibuf, ubufCount, ubufs, texCount, texs); + static_cast(m_deferredData)->m_SBinds.emplace_back(retval); + return retval; +} + +D3D12DataFactory::D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx) +: m_parent(parent), m_deferredData(new struct D3D12Data()), m_ctx(ctx) +{ + CD3DX12_DESCRIPTOR_RANGE cbvRange(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 0); + CD3DX12_DESCRIPTOR_RANGE srvRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 8, 0); + CD3DX12_ROOT_PARAMETER rootParms[2]; + rootParms[0].InitAsDescriptorTable(1, &cbvRange, D3D12_SHADER_VISIBILITY_VERTEX); + rootParms[1].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); + + ComPtr rsOutBlob; + ComPtr rsErrorBlob; + ThrowIfFailed(D3D12SerializeRootSignature( + &CD3DX12_ROOT_SIGNATURE_DESC(2, rootParms, 1, &CD3DX12_STATIC_SAMPLER_DESC(0)), + D3D_ROOT_SIGNATURE_VERSION_1, &rsOutBlob, &rsErrorBlob)); + + ThrowIfFailed(ctx->m_dev->CreateRootSignature(0, rsOutBlob->GetBufferPointer(), + rsOutBlob->GetBufferSize(), __uuidof(ID3D12RootSignature), &ctx->m_rs)); +} + +void D3D12DataFactory::reset() +{ + delete static_cast(m_deferredData); + m_deferredData = new struct D3D12Data(); +} + +IGraphicsData* D3D12DataFactory::commit() +{ + D3D12Data* retval = static_cast(m_deferredData); + + /* Gather resource descriptions */ + std::vector descs; + descs.reserve(retval->m_SBufs.size() + retval->m_DBufs.size() * 3 + + retval->m_STexs.size() + retval->m_DTexs.size() * 2); + + for (std::unique_ptr& buf : retval->m_SBufs) + descs.push_back(buf->m_buf->GetDesc()); + + for (std::unique_ptr& buf : retval->m_DBufs) + { + descs.push_back(buf->m_bufs[0]->GetDesc()); + descs.push_back(buf->m_bufs[1]->GetDesc()); + descs.push_back(buf->m_bufs[2]->GetDesc()); + } + + for (std::unique_ptr& tex : retval->m_STexs) + descs.push_back(tex->m_tex->GetDesc()); + + for (std::unique_ptr& tex : retval->m_DTexs) + { + descs.push_back(tex->m_texs[0]->GetDesc()); + descs.push_back(tex->m_texs[1]->GetDesc()); + descs.push_back(tex->m_texs[2]->GetDesc()); + } + + /* Calculate resources allocation */ + D3D12_RESOURCE_ALLOCATION_INFO allocInfo = + m_ctx->m_dev->GetResourceAllocationInfo(0, descs.size(), descs.data()); + + /* Create heap */ + ThrowIfFailed(m_ctx->m_dev->CreateHeap(&CD3DX12_HEAP_DESC(allocInfo, + D3D12_HEAP_TYPE_DEFAULT), __uuidof(ID3D12Heap), &retval->m_gpuHeap)); + ID3D12Heap* gpuHeap = retval->m_gpuHeap.Get(); + + /* Place resources */ + UINT64 offset = 0; + for (std::unique_ptr& buf : retval->m_SBufs) + offset = PlaceBufferForGPU(buf.get(), m_ctx, gpuHeap, offset); + + for (std::unique_ptr& buf : retval->m_DBufs) + offset = PlaceBufferForGPU(buf.get(), m_ctx, gpuHeap, offset); + + for (std::unique_ptr& tex : retval->m_STexs) + offset = PlaceTextureForGPU(tex.get(), m_ctx, gpuHeap, offset); + + for (std::unique_ptr& tex : retval->m_DTexs) + offset = PlaceTextureForGPU(tex.get(), m_ctx, gpuHeap, offset); + + /* Commit data bindings (create descriptor heaps) */ + for (std::unique_ptr& bind : retval->m_SBinds) + bind->commit(m_ctx); + + /* All set! */ + m_deferredData = new struct D3D12Data(); + m_committedData.insert(retval); + return retval; +} + +void D3D12DataFactory::destroyData(IGraphicsData* d) +{ + D3D12Data* data = static_cast(d); + m_committedData.erase(data); + delete data; +} + +void D3D12DataFactory::destroyAllData() +{ + for (IGraphicsData* data : m_committedData) + delete static_cast(data); + m_committedData.clear(); +} + +struct D3D12CommandQueue : IGraphicsCommandQueue +{ + Platform platform() const {return IGraphicsDataFactory::PlatformD3D12;} + const char* platformName() const {return "Direct 3D 12";} + D3D12Context* m_ctx; + IGraphicsContext* m_parent; + ComPtr m_cmdList; + + size_t m_fillBuf = 0; + size_t m_completeBuf = 0; + size_t m_drawBuf = 0; + + D3D12CommandQueue(D3D12Context* ctx, IGraphicsContext* parent) + : m_ctx(ctx), m_parent(parent) + { + ThrowIfFailed(ctx->m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), + &ctx->m_qalloc)); + D3D12_COMMAND_QUEUE_DESC desc = + { + D3D12_COMMAND_LIST_TYPE_DIRECT, + D3D12_COMMAND_QUEUE_PRIORITY_HIGH, + D3D12_COMMAND_QUEUE_FLAG_NONE + }; + ThrowIfFailed(ctx->m_dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), &ctx->m_q)); + ThrowIfFailed(ctx->m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, + __uuidof(ID3D12Fence), &ctx->m_frameFence)); + ThrowIfFailed(ctx->m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, ctx->m_qalloc.Get(), + nullptr, __uuidof(ID3D12GraphicsCommandList), &m_cmdList)); + m_cmdList->SetGraphicsRootSignature(m_ctx->m_rs.Get()); + } + + void setShaderDataBinding(const IShaderDataBinding* binding) + { + const D3D12ShaderDataBinding* cbind = static_cast(binding); + ID3D12DescriptorHeap* descHeap = cbind->m_descHeap[m_fillBuf].Get(); + m_cmdList->SetDescriptorHeaps(1, &descHeap); + m_cmdList->SetPipelineState(cbind->m_pipeline->m_state.Get()); + } + void setRenderTarget(const ITextureD* target) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpSetRenderTarget); + cmds.back().target = target; + } + + void setClearColor(const float rgba[4]) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpSetClearColor); + cmds.back().rgba[0] = rgba[0]; + cmds.back().rgba[1] = rgba[1]; + cmds.back().rgba[2] = rgba[2]; + cmds.back().rgba[3] = rgba[3]; + } + void clearTarget(bool render=true, bool depth=true) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpClearTarget); + cmds.back().flags = 0; + if (render) + cmds.back().flags |= GL_COLOR_BUFFER_BIT; + if (depth) + cmds.back().flags |= GL_DEPTH_BUFFER_BIT; + } + + void setDrawPrimitive(Primitive prim) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpSetDrawPrimitive); + if (prim == PrimitiveTriangles) + cmds.back().prim = GL_TRIANGLES; + else if (prim == PrimitiveTriStrips) + cmds.back().prim = GL_TRIANGLE_STRIP; + } + void draw(size_t start, size_t count) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpDraw); + cmds.back().start = start; + cmds.back().count = count; + } + void drawIndexed(size_t start, size_t count) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpDrawIndexed); + cmds.back().start = start; + cmds.back().count = count; + } + void drawInstances(size_t start, size_t count, size_t instCount) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpDrawInstances); + cmds.back().start = start; + cmds.back().count = count; + cmds.back().instCount = instCount; + } + void drawInstancesIndexed(size_t start, size_t count, size_t instCount) + { + std::vector& cmds = m_cmdBufs[m_fillBuf]; + cmds.emplace_back(Command::OpDrawInstancesIndexed); + cmds.back().start = start; + cmds.back().count = count; + cmds.back().instCount = instCount; + } + + void present() + { + m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); + } + + void execute() + { + std::unique_lock lk(m_mt); + m_completeBuf = m_fillBuf; + for (size_t i=0 ; i<3 ; ++i) + { + if (i == m_completeBuf || i == m_drawBuf) + continue; + m_fillBuf = i; + break; + } + lk.unlock(); + m_cv.notify_one(); + m_cmdBufs[m_fillBuf].clear(); + } +}; + +void D3D12GraphicsBufferD::load(const void* data, size_t sz) +{ + glBindBuffer(m_target, m_bufs[m_q->m_fillBuf]); + glBufferData(m_target, sz, data, GL_DYNAMIC_DRAW); +} +void* D3D12GraphicsBufferD::map(size_t sz) +{ + if (m_mappedBuf) + free(m_mappedBuf); + m_mappedBuf = malloc(sz); + m_mappedSize = sz; + return m_mappedBuf; +} +void D3D12GraphicsBufferD::unmap() +{ + glBindBuffer(m_target, m_bufs[m_q->m_fillBuf]); + glBufferData(m_target, m_mappedSize, m_mappedBuf, GL_DYNAMIC_DRAW); + free(m_mappedBuf); + m_mappedBuf = nullptr; +} + +IGraphicsBufferD* +D3D12DataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) +{ + D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(use, stride, count); + static_cast(m_deferredData)->m_DBufs.emplace_back(retval); + return retval; +} + +ITextureD* +D3D12DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) +{ + D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); + D3D12TextureD* retval = new D3D12TextureD(q, width, height, fmt); + static_cast(m_deferredData)->m_DTexs.emplace_back(retval); + return retval; +} + +const IVertexFormat* D3D12DataFactory::newVertexFormat +(size_t elementCount, const VertexElementDescriptor* elements) +{ + D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); + D3D12VertexFormat* retval = new struct D3D12VertexFormat(q, elementCount, elements); + static_cast(m_deferredData)->m_VFmts.emplace_back(retval); + return retval; +} + +IGraphicsCommandQueue* _NewD3D12CommandQueue(IGraphicsContext* parent) +{ + return new struct D3D12CommandQueue(parent); +} + +} diff --git a/lib/graphicsdev/d3dx12.h b/lib/graphicsdev/d3dx12.h new file mode 100644 index 0000000..de0fbdf --- /dev/null +++ b/lib/graphicsdev/d3dx12.h @@ -0,0 +1,1507 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx12.h +// Content: D3DX12 utility library +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3DX12_H__ +#define __D3DX12_H__ + +#include "d3d12.h" + +#if defined( __cplusplus ) + +struct CD3DX12_DEFAULT {}; +extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT; + +//------------------------------------------------------------------------------------------------ +inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ + return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width && + l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth; +} + +//------------------------------------------------------------------------------------------------ +inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RECT : public D3D12_RECT +{ + CD3DX12_RECT() + {} + explicit CD3DX12_RECT( const D3D12_RECT& o ) : + D3D12_RECT( o ) + {} + explicit CD3DX12_RECT( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + right = Right; + bottom = Bottom; + } + ~CD3DX12_RECT() {} + operator const D3D12_RECT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BOX : public D3D12_BOX +{ + CD3DX12_BOX() + {} + explicit CD3DX12_BOX( const D3D12_BOX& o ) : + D3D12_BOX( o ) + {} + explicit CD3DX12_BOX( + LONG Left, + LONG Right ) + { + left = Left; + top = 0; + front = 0; + right = Right; + bottom = 1; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + front = 0; + right = Right; + bottom = Bottom; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Front, + LONG Right, + LONG Bottom, + LONG Back ) + { + left = Left; + top = Top; + front = Front; + right = Right; + bottom = Bottom; + back = Back; + } + ~CD3DX12_BOX() {} + operator const D3D12_BOX&() const { return *this; } +}; +inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r ) +{ + return l.left == r.left && l.top == r.top && l.front == r.front && + l.right == r.right && l.bottom == r.bottom && l.back == r.back; +} +inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC +{ + CD3DX12_DEPTH_STENCIL_DESC() + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) : + D3D12_DEPTH_STENCIL_DESC( o ) + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) + { + DepthEnable = TRUE; + DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + DepthFunc = D3D12_COMPARISON_FUNC_LESS; + StencilEnable = FALSE; + StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = + { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS }; + FrontFace = defaultStencilOp; + BackFace = defaultStencilOp; + } + explicit CD3DX12_DEPTH_STENCIL_DESC( + BOOL depthEnable, + D3D12_DEPTH_WRITE_MASK depthWriteMask, + D3D12_COMPARISON_FUNC depthFunc, + BOOL stencilEnable, + UINT8 stencilReadMask, + UINT8 stencilWriteMask, + D3D12_STENCIL_OP frontStencilFailOp, + D3D12_STENCIL_OP frontStencilDepthFailOp, + D3D12_STENCIL_OP frontStencilPassOp, + D3D12_COMPARISON_FUNC frontStencilFunc, + D3D12_STENCIL_OP backStencilFailOp, + D3D12_STENCIL_OP backStencilDepthFailOp, + D3D12_STENCIL_OP backStencilPassOp, + D3D12_COMPARISON_FUNC backStencilFunc ) + { + DepthEnable = depthEnable; + DepthWriteMask = depthWriteMask; + DepthFunc = depthFunc; + StencilEnable = stencilEnable; + StencilReadMask = stencilReadMask; + StencilWriteMask = stencilWriteMask; + FrontFace.StencilFailOp = frontStencilFailOp; + FrontFace.StencilDepthFailOp = frontStencilDepthFailOp; + FrontFace.StencilPassOp = frontStencilPassOp; + FrontFace.StencilFunc = frontStencilFunc; + BackFace.StencilFailOp = backStencilFailOp; + BackFace.StencilDepthFailOp = backStencilDepthFailOp; + BackFace.StencilPassOp = backStencilPassOp; + BackFace.StencilFunc = backStencilFunc; + } + ~CD3DX12_DEPTH_STENCIL_DESC() {} + operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC +{ + CD3DX12_BLEND_DESC() + {} + explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) : + D3D12_BLEND_DESC( o ) + {} + explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) + { + AlphaToCoverageEnable = FALSE; + IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + RenderTarget[ i ] = defaultRenderTargetBlendDesc; + } + ~CD3DX12_BLEND_DESC() {} + operator const D3D12_BLEND_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC +{ + CD3DX12_RASTERIZER_DESC() + {} + explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) : + D3D12_RASTERIZER_DESC( o ) + {} + explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + MultisampleEnable = FALSE; + AntialiasedLineEnable = FALSE; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + INT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + BOOL multisampleEnable, + BOOL antialiasedLineEnable, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + MultisampleEnable = multisampleEnable; + AntialiasedLineEnable = antialiasedLineEnable; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + ~CD3DX12_RASTERIZER_DESC() {} + operator const D3D12_RASTERIZER_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO +{ + CD3DX12_RESOURCE_ALLOCATION_INFO() + {} + explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) : + D3D12_RESOURCE_ALLOCATION_INFO( o ) + {} + CD3DX12_RESOURCE_ALLOCATION_INFO( + UINT64 size, + UINT64 alignment ) + { + SizeInBytes = size; + Alignment = alignment; + } + operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES +{ + CD3DX12_HEAP_PROPERTIES() + {} + explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) : + D3D12_HEAP_PROPERTIES(o) + {} + CD3DX12_HEAP_PROPERTIES( + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = D3D12_HEAP_TYPE_CUSTOM; + CPUPageProperty = cpuPageProperty; + MemoryPoolPreference = memoryPoolPreference; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + explicit CD3DX12_HEAP_PROPERTIES( + D3D12_HEAP_TYPE type, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = type; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + operator const D3D12_HEAP_PROPERTIES&() const { return *this; } + bool IsCPUAccessible() const + { + return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM && + (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); + } +}; +inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ + return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && + l.MemoryPoolPreference == r.MemoryPoolPreference && + l.CreationNodeMask == r.CreationNodeMask && + l.VisibleNodeMask == r.VisibleNodeMask; +} +inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC +{ + CD3DX12_HEAP_DESC() + {} + explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) : + D3D12_HEAP_DESC(o) + {} + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_PROPERTIES properties, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = properties; + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_TYPE type, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_PROPERTIES properties, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = properties; + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_TYPE type, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + operator const D3D12_HEAP_DESC&() const { return *this; } + bool IsCPUAccessible() const + { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); } +}; +inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ + return l.SizeInBytes == r.SizeInBytes && + l.Properties == r.Properties && + l.Alignment == r.Alignment && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE +{ + CD3DX12_CLEAR_VALUE() + {} + explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) : + D3D12_CLEAR_VALUE(o) + {} + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + const FLOAT color[4] ) + { + Format = format; + memcpy( Color, color, sizeof( Color ) ); + } + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + FLOAT depth, + UINT8 stencil ) + { + Format = format; + /* Use memcpy to preserve NAN values */ + memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) ); + DepthStencil.Stencil = stencil; + } + operator const D3D12_CLEAR_VALUE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RANGE : public D3D12_RANGE +{ + CD3DX12_RANGE() + {} + explicit CD3DX12_RANGE(const D3D12_RANGE &o) : + D3D12_RANGE(o) + {} + CD3DX12_RANGE( + SIZE_T begin, + SIZE_T end ) + { + Begin = begin; + End = end; + } + operator const D3D12_RANGE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE +{ + CD3DX12_TILED_RESOURCE_COORDINATE() + {} + explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) : + D3D12_TILED_RESOURCE_COORDINATE(o) + {} + CD3DX12_TILED_RESOURCE_COORDINATE( + UINT x, + UINT y, + UINT z, + UINT subresource ) + { + X = x; + Y = y; + Z = z; + Subresource = subresource; + } + operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE +{ + CD3DX12_TILE_REGION_SIZE() + {} + explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) : + D3D12_TILE_REGION_SIZE(o) + {} + CD3DX12_TILE_REGION_SIZE( + UINT numTiles, + BOOL useBox, + UINT width, + UINT16 height, + UINT16 depth ) + { + NumTiles = numTiles; + UseBox = useBox; + Width = width; + Height = height; + Depth = depth; + } + operator const D3D12_TILE_REGION_SIZE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING +{ + CD3DX12_SUBRESOURCE_TILING() + {} + explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) : + D3D12_SUBRESOURCE_TILING(o) + {} + CD3DX12_SUBRESOURCE_TILING( + UINT widthInTiles, + UINT16 heightInTiles, + UINT16 depthInTiles, + UINT startTileIndexInOverallResource ) + { + WidthInTiles = widthInTiles; + HeightInTiles = heightInTiles; + DepthInTiles = depthInTiles; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_SUBRESOURCE_TILING&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE +{ + CD3DX12_TILE_SHAPE() + {} + explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) : + D3D12_TILE_SHAPE(o) + {} + CD3DX12_TILE_SHAPE( + UINT widthInTexels, + UINT heightInTexels, + UINT depthInTexels ) + { + WidthInTexels = widthInTexels; + HeightInTexels = heightInTexels; + DepthInTexels = depthInTexels; + } + operator const D3D12_TILE_SHAPE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER +{ + CD3DX12_RESOURCE_BARRIER() + {} + explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) : + D3D12_RESOURCE_BARRIER(o) + {} + static inline CD3DX12_RESOURCE_BARRIER Transition( + _In_ ID3D12Resource* pResource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + result.Flags = flags; + barrier.Transition.pResource = pResource; + barrier.Transition.StateBefore = stateBefore; + barrier.Transition.StateAfter = stateAfter; + barrier.Transition.Subresource = subresource; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER Aliasing( + _In_ ID3D12Resource* pResourceBefore, + _In_ ID3D12Resource* pResourceAfter) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = pResourceBefore; + barrier.Aliasing.pResourceAfter = pResourceAfter; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER UAV( + _In_ ID3D12Resource* pResource) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = pResource; + return result; + } + operator const D3D12_RESOURCE_BARRIER&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO +{ + CD3DX12_PACKED_MIP_INFO() + {} + explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) : + D3D12_PACKED_MIP_INFO(o) + {} + CD3DX12_PACKED_MIP_INFO( + UINT8 numStandardMips, + UINT8 numPackedMips, + UINT numTilesForPackedMips, + UINT startTileIndexInOverallResource ) + { + NumStandardMips = numStandardMips; + NumPackedMips = numPackedMips; + NumTilesForPackedMips = numTilesForPackedMips; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_PACKED_MIP_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT +{ + CD3DX12_SUBRESOURCE_FOOTPRINT() + {} + explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) : + D3D12_SUBRESOURCE_FOOTPRINT(o) + {} + CD3DX12_SUBRESOURCE_FOOTPRINT( + DXGI_FORMAT format, + UINT width, + UINT height, + UINT depth, + UINT rowPitch ) + { + Format = format; + Width = width; + Height = height; + Depth = depth; + RowPitch = rowPitch; + } + explicit CD3DX12_SUBRESOURCE_FOOTPRINT( + const D3D12_RESOURCE_DESC& resDesc, + UINT rowPitch ) + { + Format = resDesc.Format; + Width = UINT( resDesc.Width ); + Height = resDesc.Height; + Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1); + RowPitch = rowPitch; + } + operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION +{ + CD3DX12_TEXTURE_COPY_LOCATION() + {} + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + SubresourceIndex = Sub; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE +{ + CD3DX12_DESCRIPTOR_RANGE() { } + explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) : + D3D12_DESCRIPTOR_RANGE(o) + {} + CD3DX12_DESCRIPTOR_RANGE( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) : + D3D12_ROOT_DESCRIPTOR_TABLE(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS +{ + CD3DX12_ROOT_CONSTANTS() {} + explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) : + D3D12_ROOT_CONSTANTS(o) + {} + CD3DX12_ROOT_CONSTANTS( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(num32BitValues, shaderRegister, registerSpace); + } + + inline void Init( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, num32BitValues, shaderRegister, registerSpace); + } + + static inline void Init( + _Out_ D3D12_ROOT_CONSTANTS &rootConstants, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + rootConstants.Num32BitValues = num32BitValues; + rootConstants.ShaderRegister = shaderRegister; + rootConstants.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR +{ + CD3DX12_ROOT_DESCRIPTOR() {} + explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) : + D3D12_ROOT_DESCRIPTOR(o) + {} + CD3DX12_ROOT_DESCRIPTOR( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(shaderRegister, registerSpace); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, shaderRegister, registerSpace); + } + + static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER +{ + CD3DX12_ROOT_PARAMETER() {} + explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) : + D3D12_ROOT_PARAMETER(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace); + } + + static inline void InitAsConstantBufferView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility); + } + + inline void InitAsConstants( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility); + } + + inline void InitAsConstantBufferView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC +{ + CD3DX12_STATIC_SAMPLER_DESC() {} + explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) : + D3D12_STATIC_SAMPLER_DESC(o) + {} + CD3DX12_STATIC_SAMPLER_DESC( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC +{ + CD3DX12_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) : + D3D12_ROOT_SIGNATURE_DESC(o) + {} + CD3DX12_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + desc.NumParameters = numParameters; + desc.pParameters = _pParameters; + desc.NumStaticSamplers = numStaticSamplers; + desc.pStaticSamplers = _pStaticSamplers; + desc.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) : + D3D12_CPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE +{ + CD3DX12_GPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) : + D3D12_GPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + +