aboutsummaryrefslogtreecommitdiff
path: root/samples/D3D12/src
diff options
context:
space:
mode:
authorlbavoil <[email protected]>2016-03-25 13:01:54 +0100
committerlbavoil <[email protected]>2016-03-25 13:01:54 +0100
commit99174e4e5fb4b7079da80b35a6dfd68f3fd56a1c (patch)
treefbcd4260d6c953d569a887505336a1c3f202e10f /samples/D3D12/src
downloadhbaoplus-99174e4e5fb4b7079da80b35a6dfd68f3fd56a1c.tar.xz
hbaoplus-99174e4e5fb4b7079da80b35a6dfd68f3fd56a1c.zip
GFSDK_HBAO+_distro_r3.0_cl20573789
Diffstat (limited to 'samples/D3D12/src')
-rw-r--r--samples/D3D12/src/BinMeshReader.h60
-rw-r--r--samples/D3D12/src/SSAO12_2015.sln28
-rw-r--r--samples/D3D12/src/SibenikIndices.binbin0 -> 939564 bytes
-rw-r--r--samples/D3D12/src/SibenikVertices.binbin0 -> 1189884 bytes
-rw-r--r--samples/D3D12/src/Viewer.cpp1216
-rw-r--r--samples/D3D12/src/Viewer.hlsl40
-rw-r--r--samples/D3D12/src/Viewer.vcxproj229
-rw-r--r--samples/D3D12/src/Viewer.vcxproj.filters57
-rw-r--r--samples/D3D12/src/WaveFrontReader.h541
-rw-r--r--samples/D3D12/src/d3dx12.h1508
-rw-r--r--samples/D3D12/src/d3dx12p.h1590
11 files changed, 5269 insertions, 0 deletions
diff --git a/samples/D3D12/src/BinMeshReader.h b/samples/D3D12/src/BinMeshReader.h
new file mode 100644
index 0000000..2b1679b
--- /dev/null
+++ b/samples/D3D12/src/BinMeshReader.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2008-2016, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#pragma once
+
+bool LoadVertices(const WCHAR* FileName, std::vector<Vertex>& OutVertices)
+{
+ FILE* fp = _wfopen(FileName, L"rb");
+ if (!fp) return false;
+
+ fseek(fp, 0L, SEEK_END);
+ UINT FileSize = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ UINT NumVertices = FileSize / sizeof(Vertex::position);
+
+ for (UINT Idx = 0; Idx < NumVertices; ++Idx)
+ {
+ Vertex vertex;
+ fread(&vertex.position, sizeof(XMFLOAT3), 1, fp);
+ vertex.normal.x = vertex.normal.y = 0;
+ vertex.normal.z = 1.0;
+ vertex.textureCoordinate.x = vertex.textureCoordinate.y = 0;
+ OutVertices.push_back(vertex);
+ }
+
+ fclose(fp);
+ return true;
+}
+
+bool LoadIndices(const WCHAR* FileName, std::vector<uint32_t>& OutIndices)
+{
+ FILE* fp = _wfopen(FileName, L"rb");
+ if (!fp) return false;
+
+ fseek(fp, 0L, SEEK_END);
+ UINT FileSize = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ UINT NumIndices = FileSize / sizeof(uint32_t);
+
+ for (UINT Idx = 0; Idx < NumIndices; ++Idx)
+ {
+ uint32_t index;
+ fread(&index, sizeof(index), 1, fp);
+ OutIndices.push_back(index);
+ }
+
+ fclose(fp);
+ return true;
+}
+
+
diff --git a/samples/D3D12/src/SSAO12_2015.sln b/samples/D3D12/src/SSAO12_2015.sln
new file mode 100644
index 0000000..d0f2f76
--- /dev/null
+++ b/samples/D3D12/src/SSAO12_2015.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Viewer", "Viewer.vcxproj", "{CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Debug|x64.ActiveCfg = Debug|x64
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Debug|x64.Build.0 = Debug|x64
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Debug|x86.ActiveCfg = Debug|Win32
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Debug|x86.Build.0 = Debug|Win32
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Release|x64.ActiveCfg = Release|x64
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Release|x64.Build.0 = Release|x64
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Release|x86.ActiveCfg = Release|Win32
+ {CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/D3D12/src/SibenikIndices.bin b/samples/D3D12/src/SibenikIndices.bin
new file mode 100644
index 0000000..8775c0c
--- /dev/null
+++ b/samples/D3D12/src/SibenikIndices.bin
Binary files differ
diff --git a/samples/D3D12/src/SibenikVertices.bin b/samples/D3D12/src/SibenikVertices.bin
new file mode 100644
index 0000000..561d39e
--- /dev/null
+++ b/samples/D3D12/src/SibenikVertices.bin
Binary files differ
diff --git a/samples/D3D12/src/Viewer.cpp b/samples/D3D12/src/Viewer.cpp
new file mode 100644
index 0000000..e445ffd
--- /dev/null
+++ b/samples/D3D12/src/Viewer.cpp
@@ -0,0 +1,1216 @@
+/*
+* Copyright (c) 2008-2016, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include <Windows.h>
+#include <tchar.h>
+#include <wrl/client.h>
+#include <stdexcept>
+#include <dxgi1_4.h>
+#include <d3d12.h>
+#include <d3dcompiler.h>
+#include <d3dx12.h>
+#include <d3dx12p.h>
+
+#include <DirectXMath.h>
+
+// For UI rendering
+#include <imgui.h>
+#include "imgui_impl_dx12.h"
+
+#include <string>
+#include <vector>
+
+// Header for HBAO+
+#include "GFSDK_SSAO.h"
+
+// Library link for HBAO+
+#ifdef _WIN64
+#pragma comment(lib, "GFSDK_SSAO_D3D12.win64.lib")
+#else
+#pragma comment(lib, "GFSDK_SSAO_D3D12.win32.lib")
+#endif
+
+// Use binary mesh reader or obj reader
+#define USE_BIN_MESH_READER 1
+
+// MSAA sample count for Viewer application
+#define MSAA_SAMPLE_COUNT 1
+
+#define SRC_PATH L"..\\src\\"
+#define HLSL_FILE_PATH SRC_PATH L"Viewer.hlsl"
+#define VERTEX_BIN_FILE_PATH SRC_PATH L"SibenikVertices.bin"
+#define INDEX_BIN_FILE_PATH SRC_PATH L"SibenikIndices.bin"
+
+using namespace std;
+using namespace DirectX;
+using Microsoft::WRL::ComPtr;
+
+struct Vertex
+{
+ DirectX::XMFLOAT3 position;
+ DirectX::XMFLOAT3 normal;
+ DirectX::XMFLOAT2 textureCoordinate;
+};
+
+struct Mesh
+{
+ std::vector<Vertex> vertices;
+ std::vector<uint32_t> indices;
+};
+
+// For mesh loading
+#if USE_BIN_MESH_READER
+#include "BinMeshReader.h"
+#else
+#include "WaveFrontReader.h"
+#endif
+
+#pragma comment(lib, "dxgi.lib")
+#pragma comment(lib, "d3d12.lib")
+#pragma comment(lib, "d3dcompiler.lib")
+
+namespace
+{
+ int gWindowWidth = 1280;
+ int gWindowHeight = 720;
+ bool gIsWindowed = true;
+ int gAdapterIndex = -1;
+ HWND gMainWindowHandle = 0;
+ float gCameraDistance = 1.0f;
+ float gModelRotation = 90.0f;
+ bool gUseSSAO = true;
+ bool gDrawUI = true;
+ std::string gSelectedGraphicsAdapter;
+ DXGI_FORMAT gColorTextureFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ DXGI_FORMAT gNormalTextureFormat = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ DXGI_FORMAT gDepthTextureFormat = DXGI_FORMAT_D32_FLOAT;
+};
+
+void CHK(HRESULT hr)
+{
+ if (FAILED(hr))
+ throw runtime_error("HRESULT is failed value.");
+}
+
+class D3D
+{
+public:
+ // Number of swap chains
+ static const UINT FrameCount = 4;
+
+ ComPtr<IDXGIFactory4> mDxgiFactory;
+ ComPtr<IDXGISwapChain3> mSwapChain;
+
+ int mBufferWidth, mBufferHeight;
+ UINT mFrameIndex = 0;
+
+ ID3D12Device* mDev;
+ ComPtr<ID3D12CommandAllocator> mCmdAllocs[FrameCount];
+ ComPtr<ID3D12CommandQueue> mCmdQueue;
+
+ ComPtr<ID3D12GraphicsCommandList> mCmdList;
+
+ ComPtr<ID3D12Fence> mFence;
+ UINT64 mFenceValues[FrameCount];
+ HANDLE mFenceEvent = 0;
+
+ ComPtr<ID3D12DescriptorHeap> mDescHeapRtv;
+ ComPtr<ID3D12DescriptorHeap> mDescHeapDsv;
+ ComPtr<ID3D12DescriptorHeap> mDescHeapCbvSrvUav;
+ ComPtr<ID3D12DescriptorHeap> mDescHeapSampler;
+ ComPtr<ID3D12DescriptorHeap> mSsaoDescHeapCbvSrvUav;
+
+ ComPtr<ID3D12RootSignature> mRootSignature;
+ ComPtr<ID3D12PipelineState> mPso;
+
+ ComPtr<ID3D12Resource> mVB;
+ D3D12_VERTEX_BUFFER_VIEW mVBView = {};
+ D3D12_INDEX_BUFFER_VIEW mIBView = {};
+ UINT mIndexCount = 0;
+ UINT mVBIndexOffset = 0;
+
+ ComPtr<ID3D12Resource> mDepthBuffer;
+ ComPtr<ID3D12Resource> mConstantBuffer;
+ void* mCBUploadPtr = nullptr;
+
+ // Normal buffer and render target
+ ComPtr<ID3D12Resource> mNormalBuffer[FrameCount];
+ GFSDK_SSAO_RenderTargetView_D3D12 mNormalRTV[FrameCount];
+ GFSDK_SSAO_ShaderResourceView_D3D12 mNormalSRV[FrameCount];
+
+ // Color buffer and render target
+ ComPtr<ID3D12Resource> mColorBuffer[FrameCount];
+ GFSDK_SSAO_RenderTargetView_D3D12 mColorRTV[FrameCount];
+
+ // HBAO+ context and parameter
+ GFSDK_SSAO_Context_D3D12* mSSAO;
+ GFSDK_SSAO_Parameters mAOParams;
+
+public:
+ //--------------------------------------------------------------------------------
+ D3D(int Width, int Height, HWND hWnd, BOOL IsWindowed, INT AdapterIndex)
+ : mBufferWidth(Width), mBufferHeight(Height), mDev(nullptr), mFrameIndex(0), mSSAO(nullptr)
+ {
+ CHK(CreateDXGIFactory1(IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf())));
+
+#if _DEBUG
+ ID3D12Debug* debug = nullptr;
+ D3D12GetDebugInterface(IID_PPV_ARGS(&debug));
+ if (debug)
+ {
+ debug->EnableDebugLayer();
+ debug->Release();
+ debug = nullptr;
+ }
+#endif /* _DEBUG */
+
+ ZeroMemory(mFenceValues, sizeof(mFenceValues));
+
+ ID3D12Device* dev = nullptr;
+ bool UseWarpDevice = false;
+
+ if (UseWarpDevice)
+ {
+ ComPtr<IDXGIAdapter> warpAdapter;
+ CHK(mDxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
+
+ CHK(D3D12CreateDevice(
+ warpAdapter.Get(),
+ D3D_FEATURE_LEVEL_11_0,
+ IID_PPV_ARGS(&dev)
+ ));
+ }
+ else
+ {
+ ComPtr<IDXGIAdapter> Adapter;
+ UINT NumAdapters = 0;
+ std::vector< ComPtr<IDXGIAdapter> > Adapters;
+ for (UINT idx = 0; mDxgiFactory->EnumAdapters(idx, Adapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++idx)
+ {
+ DXGI_ADAPTER_DESC AdapterDesc;
+ Adapter->GetDesc(&AdapterDesc);
+ // GPU name : adapter_desc.Description
+ wchar_t buff[1024];
+ swprintf(buff, L"Graphics Adapter(%d) : %s\n", idx, &AdapterDesc.Description);
+ OutputDebugStringW(buff);
+ Adapters.push_back(Adapter);
+ NumAdapters++;
+ }
+
+ if ((AdapterIndex >= 0) && (AdapterIndex < (INT)NumAdapters))
+ {
+ Adapter = Adapters[AdapterIndex];
+ }
+ else
+ {
+ Adapter = Adapters[0];
+ }
+
+ DXGI_ADAPTER_DESC AdapterDesc;
+ Adapter->GetDesc(&AdapterDesc);
+ std::wstring DescW = AdapterDesc.Description;
+ std::string DescA = std::string(DescW.begin(), DescW.end());
+ gSelectedGraphicsAdapter = DescA;
+ Adapters.push_back(Adapter);
+
+ CHK(D3D12CreateDevice(Adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev)));
+ }
+
+ mDev = dev;
+
+ const UINT NodeMask = 1;
+
+ for (UINT n = 0; n < FrameCount; n++)
+ {
+ CHK(mDev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCmdAllocs[n])));
+ }
+
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ queueDesc.NodeMask = NodeMask;
+ CHK(mDev->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(mCmdQueue.ReleaseAndGetAddressOf())));
+
+ CHK(mDev->CreateCommandList(NodeMask, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAllocs[mFrameIndex].Get(), nullptr, IID_PPV_ARGS(&mCmdList)));
+
+#define SSAO_NUM_DEPTH_SRV 1
+#define SSAO_NUM_NORMAL_SRV FrameCount
+#define SSAO_NUM_SRV (SSAO_NUM_DEPTH_SRV + SSAO_NUM_NORMAL_SRV + GFSDK_SSAO_NUM_DESCRIPTORS_CBV_SRV_UAV_HEAP_D3D12)
+
+#define IMGUI_NUM_CBV 1
+#define IMGUI_NUM_SRV 1
+
+#define VIEWER_NUM_CBV 1
+#define VIEWER_NUM_COLOR_RTV FrameCount
+#define VIEWER_NUM_NORMAL_RTV FrameCount
+
+#define VIEWER_NUM_RTV (VIEWER_NUM_COLOR_RTV + VIEWER_NUM_NORMAL_RTV)
+#define VIEWER_NUM_DSV 1
+#define VIEWER_NUM_SAMPLER 0
+
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC desc = {};
+
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+ desc.NumDescriptors = VIEWER_NUM_RTV + GFSDK_SSAO_NUM_DESCRIPTORS_RTV_HEAP_D3D12;
+ desc.NodeMask = NodeMask;
+ CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapRtv.ReleaseAndGetAddressOf())));
+ mDescHeapRtv->SetName(L"ViewerDescHeapRtv");
+
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
+ desc.NumDescriptors = VIEWER_NUM_DSV;
+ desc.NodeMask = NodeMask;
+ CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapDsv.ReleaseAndGetAddressOf())));
+ mDescHeapDsv->SetName(L"ViewerDescHeapDsv");
+
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ desc.NumDescriptors = VIEWER_NUM_CBV + IMGUI_NUM_CBV + IMGUI_NUM_SRV;
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ desc.NodeMask = NodeMask;
+ CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapCbvSrvUav.ReleaseAndGetAddressOf())));
+ mDescHeapCbvSrvUav->SetName(L"ViewerDescHeapCbvSrvUav");
+
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
+ desc.NumDescriptors = VIEWER_NUM_SAMPLER;
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ desc.NodeMask = NodeMask;
+ if (desc.NumDescriptors > 0)
+ {
+ CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapSampler.ReleaseAndGetAddressOf())));
+ mDescHeapSampler->SetName(L"ViewerDescHeapSampler");
+ }
+ }
+
+ // Create a desc heap for SSAO
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC desc = {};
+
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ desc.NumDescriptors = SSAO_NUM_SRV;
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ desc.NodeMask = NodeMask;
+ CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mSsaoDescHeapCbvSrvUav.ReleaseAndGetAddressOf())));
+ mSsaoDescHeapCbvSrvUav->SetName(L"ViewerSsaoDescHeapCbvSrvUav");
+ }
+
+ CHK(mDev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.ReleaseAndGetAddressOf())));
+ mFence->SetName(L"ViewerFence");
+
+ mFenceValues[mFrameIndex]++;
+
+ mFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
+
+ ResizeD3D(hWnd, Width, Height, IsWindowed);
+
+ {
+ CD3DX12_DESCRIPTOR_RANGE descRange1[1];
+ descRange1[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
+
+ CD3DX12_ROOT_PARAMETER rootParam[1];
+ rootParam[0].InitAsDescriptorTable(ARRAYSIZE(descRange1), descRange1);
+
+ ID3D10Blob *sig, *info;
+ auto rootSigDesc = D3D12_ROOT_SIGNATURE_DESC();
+ rootSigDesc.NumParameters = 1;
+ rootSigDesc.NumStaticSamplers = 0;
+ rootSigDesc.pParameters = rootParam;
+ rootSigDesc.pStaticSamplers = nullptr;
+ rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+ CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &sig, &info));
+ mDev->CreateRootSignature(
+ 0,
+ sig->GetBufferPointer(),
+ sig->GetBufferSize(),
+ IID_PPV_ARGS(mRootSignature.ReleaseAndGetAddressOf()));
+ mRootSignature->SetName(L"ViewerRS");
+ sig->Release();
+ }
+
+ ID3D10Blob *vs, *ps;
+ {
+ ID3D10Blob *info;
+ UINT flag = 0;
+#if _DEBUG
+ flag |= D3DCOMPILE_DEBUG;
+#endif /* _DEBUG */
+ CHK(D3DCompileFromFile(HLSL_FILE_PATH, nullptr, nullptr, "VSMain", "vs_5_0", flag, 0, &vs, &info));
+ CHK(D3DCompileFromFile(HLSL_FILE_PATH, nullptr, nullptr, "PSMain", "ps_5_0", flag, 0, &ps, &info));
+ }
+ D3D12_INPUT_ELEMENT_DESC inputLayout[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ };
+
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ psoDesc.InputLayout.NumElements = 3;
+ psoDesc.InputLayout.pInputElementDescs = inputLayout;
+ psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
+ psoDesc.pRootSignature = mRootSignature.Get();
+ psoDesc.VS.pShaderBytecode = vs->GetBufferPointer();
+ psoDesc.VS.BytecodeLength = vs->GetBufferSize();
+ psoDesc.PS.pShaderBytecode = ps->GetBufferPointer();
+ psoDesc.PS.BytecodeLength = ps->GetBufferSize();
+ psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
+ psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
+ psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
+ psoDesc.DepthStencilState.DepthEnable = true;
+ psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
+ psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ psoDesc.DepthStencilState.StencilEnable = false;
+ psoDesc.SampleMask = UINT_MAX;
+ psoDesc.NumRenderTargets = 1;
+ psoDesc.RTVFormats[0] = gNormalTextureFormat;
+ psoDesc.DSVFormat = gDepthTextureFormat;
+ psoDesc.SampleDesc.Count = MSAA_SAMPLE_COUNT;
+ CHK(mDev->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(mPso.ReleaseAndGetAddressOf())));
+ mPso->SetName(L"ViewerPSO");
+ vs->Release();
+ ps->Release();
+
+#if (USE_BIN_MESH_READER)
+ Mesh mesh;
+ LoadVertices(VERTEX_BIN_FILE_PATH, mesh.vertices);
+ LoadIndices(INDEX_BIN_FILE_PATH, mesh.indices);
+#else
+ WaveFrontReader<uint32_t> mesh;
+ CHK(mesh.Load(L"sibenik.obj"));
+#endif
+
+ mIndexCount = static_cast<UINT>(mesh.indices.size());
+ mVBIndexOffset = static_cast<UINT>(sizeof(mesh.vertices[0]) * mesh.vertices.size());
+ UINT IBSize = static_cast<UINT>(sizeof(mesh.indices[0]) * mIndexCount);
+
+ void* vbData = mesh.vertices.data();
+ void* ibData = mesh.indices.data();
+ CHK(mDev->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(mVBIndexOffset + IBSize),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(mVB.ReleaseAndGetAddressOf())));
+ mVB->SetName(L"VertexBuffer");
+
+ char* vbUploadPtr = nullptr;
+ CHK(mVB->Map(0, nullptr, reinterpret_cast<void**>(&vbUploadPtr)));
+ memcpy_s(vbUploadPtr, mVBIndexOffset, vbData, mVBIndexOffset);
+ memcpy_s(vbUploadPtr + mVBIndexOffset, IBSize, ibData, IBSize);
+ mVB->Unmap(0, nullptr);
+
+ mVBView.BufferLocation = mVB->GetGPUVirtualAddress();
+ mVBView.StrideInBytes = sizeof(mesh.vertices[0]);
+ mVBView.SizeInBytes = mVBIndexOffset;
+ mIBView.BufferLocation = mVB->GetGPUVirtualAddress() + mVBIndexOffset;
+ mIBView.Format = (sizeof(mesh.indices[0]) == 2) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
+ mIBView.SizeInBytes = IBSize;
+
+ // Constant buffer
+ CHK(mDev->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(mConstantBuffer.ReleaseAndGetAddressOf())));
+ mConstantBuffer->SetName(L"ViewerConstantBuffer");
+
+ D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
+ cbvDesc.BufferLocation = mConstantBuffer->GetGPUVirtualAddress();
+ cbvDesc.SizeInBytes = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; // must be a multiple of 256
+ mDev->CreateConstantBufferView(&cbvDesc, mDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart());
+ CHK(mConstantBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mCBUploadPtr)));
+
+ InitSSAO();
+
+ mAOParams = {};
+ mAOParams.Radius = 2.f;
+ mAOParams.Bias = 0.2f;
+ mAOParams.PowerExponent = 2.f;
+ mAOParams.Blur.Enable = true;
+ mAOParams.Blur.Sharpness = 32.f;
+ mAOParams.Blur.Radius = GFSDK_SSAO_BLUR_RADIUS_4;
+
+ ImGui_ImplDX12_Init(hWnd, dev, mCmdQueue.Get(), mCmdList.Get(), mDescHeapCbvSrvUav.Get(), VIEWER_NUM_CBV);
+ }
+
+ //--------------------------------------------------------------------------------
+ void Release()
+ {
+ ReleaseSSAO();
+ ImGui_ImplDX12_Shutdown();
+
+ mConstantBuffer->Unmap(0, nullptr);
+ CloseHandle(mFenceEvent);
+ for (UINT Idx = 0; Idx < FrameCount; ++Idx)
+ {
+ mCmdAllocs[Idx].Reset();
+ mColorBuffer[Idx].Reset();
+ mNormalBuffer[Idx].Reset();
+ }
+ mCmdList.Reset();
+ mFence.Reset();
+ mCmdQueue.Reset();
+ mSsaoDescHeapCbvSrvUav.Reset();
+ mDescHeapCbvSrvUav.Reset();
+ mDescHeapDsv.Reset();
+ mDescHeapRtv.Reset();
+ mDescHeapSampler.Reset();
+ if (mSwapChain)
+ {
+ mSwapChain->SetFullscreenState(FALSE, NULL);
+ mSwapChain.Reset();
+ }
+ mConstantBuffer.Reset();
+ mDepthBuffer.Reset();
+ mDxgiFactory.Reset();
+ mPso.Reset();
+ mRootSignature.Reset();
+ mVB.Reset();
+ }
+
+ //--------------------------------------------------------------------------------
+ ~D3D()
+ {
+ Release();
+ }
+
+ //--------------------------------------------------------------------------------
+ void ResizeD3D(HWND hWnd, int Width, int Height, BOOL IsWindowed)
+ {
+ if (!mDev)
+ {
+ return;
+ }
+
+ DXGI_SWAP_CHAIN_DESC scDesc = {};
+ scDesc.BufferCount = FrameCount;
+ scDesc.BufferDesc.Width = Width;
+ scDesc.BufferDesc.Height = Height;
+ scDesc.BufferDesc.Format = gColorTextureFormat;
+ scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ //scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; // For better framerate in windowed mode, but it won't allow fullscreen switching
+ scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ scDesc.OutputWindow = hWnd;
+ scDesc.SampleDesc.Count = 1;
+ scDesc.SampleDesc.Quality = 0;
+ scDesc.Windowed = IsWindowed;
+
+ WaitForGpuIdle();
+
+ // Release color/normal render targets before calling ResizeBuffers().
+ // Also reset the frame fence values.
+ for (UINT Idx = 0; Idx < FrameCount; ++Idx)
+ {
+ mColorBuffer[Idx].Reset();
+ mNormalBuffer[Idx].Reset();
+ mFenceValues[Idx] = mFenceValues[mFrameIndex];
+ }
+
+ ComPtr<IDXGISwapChain> swapChain;
+ if (!mSwapChain)
+ {
+ CHK(mDxgiFactory->CreateSwapChain(mCmdQueue.Get(), &scDesc, &swapChain));
+ swapChain.As(&mSwapChain);
+ }
+
+ DXGI_SWAP_CHAIN_DESC desc = {};
+ mSwapChain->GetDesc(&desc);
+ CHK(mSwapChain->ResizeBuffers(FrameCount, Width, Height, gColorTextureFormat, desc.Flags));
+
+ mBufferWidth = Width;
+ mBufferHeight = Height;
+
+ mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
+
+ for (UINT i = 0; i < FrameCount; i++)
+ {
+ CHK(mSwapChain->GetBuffer(i, IID_PPV_ARGS(mColorBuffer[i].ReleaseAndGetAddressOf())));
+ mColorBuffer[i]->SetName(L"SwapChain_Buffer");
+ }
+
+ for (UINT FrameIndex = 0; FrameIndex < FrameCount; ++FrameIndex)
+ {
+ // Create color buffer RTV
+ {
+ D3D12_RENDER_TARGET_VIEW_DESC colorRTVDesc = {};
+ colorRTVDesc.Format = gColorTextureFormat;
+ colorRTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE ColorRTV(
+ mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(),
+ FrameIndex * mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV));
+ mDev->CreateRenderTargetView(mColorBuffer[FrameIndex].Get(), &colorRTVDesc, ColorRTV);
+
+ mColorRTV[FrameIndex] = {};
+ mColorRTV[FrameIndex].CpuHandle = ColorRTV.ptr;
+ mColorRTV[FrameIndex].pResource = mColorBuffer[FrameIndex].Get();
+ }
+ }
+
+ // Create depth buffer and SRV
+ {
+ // Create depth resource
+ {
+ D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(
+ DXGI_FORMAT_R32_TYPELESS, mBufferWidth, mBufferHeight, 1, 1, MSAA_SAMPLE_COUNT, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL,
+ D3D12_TEXTURE_LAYOUT_UNKNOWN, 0);
+
+ D3D12_CLEAR_VALUE dsvClearValue;
+ dsvClearValue.Format = gDepthTextureFormat;
+ dsvClearValue.DepthStencil.Depth = 1.0f;
+ dsvClearValue.DepthStencil.Stencil = 0;
+
+ CHK(mDev->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), // No need to read/write by CPU
+ D3D12_HEAP_FLAG_NONE,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_COMMON,
+ &dsvClearValue,
+ IID_PPV_ARGS(mDepthBuffer.ReleaseAndGetAddressOf())));
+ mDepthBuffer->SetName(L"DepthTexture");
+ }
+
+ // Depth DSV
+ {
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+#if MSAA_SAMPLE_COUNT > 1
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;
+#else
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
+#endif
+ dsvDesc.Format = gDepthTextureFormat;
+ dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE DepthDSV(mDescHeapDsv->GetCPUDescriptorHandleForHeapStart());
+ mDev->CreateDepthStencilView(mDepthBuffer.Get(), &dsvDesc, DepthDSV);
+ }
+
+ // Depth SRV
+ {
+ D3D12_SHADER_RESOURCE_VIEW_DESC depthSRVDesc = {};
+
+ depthSRVDesc.Format = DXGI_FORMAT_R32_FLOAT;
+ depthSRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+#if MSAA_SAMPLE_COUNT > 1
+ depthSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
+#else
+ depthSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ depthSRVDesc.Texture2D.MipLevels = 1;
+ depthSRVDesc.Texture2D.MostDetailedMip = 0; // No MIP
+ depthSRVDesc.Texture2D.PlaneSlice = 0;
+ depthSRVDesc.Texture2D.ResourceMinLODClamp = 0.0f;
+#endif
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE DepthSRV(
+ mSsaoDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart());
+ mDev->CreateShaderResourceView(mDepthBuffer.Get(), &depthSRVDesc, DepthSRV);
+ }
+ }
+
+ // Normal render targets
+ for (UINT FrameIndex = 0; FrameIndex < FrameCount; ++FrameIndex)
+ {
+ D3D12_RESOURCE_DESC NormalRTVDesc = CD3DX12_RESOURCE_DESC::Tex2D(
+ gNormalTextureFormat, mBufferWidth, mBufferHeight, 1, 1, MSAA_SAMPLE_COUNT, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
+ D3D12_TEXTURE_LAYOUT_UNKNOWN, 0);
+
+ FLOAT ClearColor[] = { 0, 0, 0, 1.0f };
+ CD3DX12_CLEAR_VALUE NormalClearValue(NormalRTVDesc.Format, ClearColor);
+ mDev->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,
+ &NormalRTVDesc, D3D12_RESOURCE_STATE_COMMON, &NormalClearValue, IID_PPV_ARGS(mNormalBuffer[FrameIndex].ReleaseAndGetAddressOf()));
+ mNormalBuffer[FrameIndex]->SetName(L"NormalBuffer");
+
+ // SRV
+ D3D12_SHADER_RESOURCE_VIEW_DESC NormalSRVDesc = {};
+ NormalSRVDesc.Format = NormalRTVDesc.Format;
+ NormalSRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+#if MSAA_SAMPLE_COUNT > 1
+ NormalSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
+#else
+ NormalSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ NormalSRVDesc.Texture2D.MipLevels = 1;
+ NormalSRVDesc.Texture2D.MostDetailedMip = 0; // No MIP
+ NormalSRVDesc.Texture2D.PlaneSlice = 0;
+ NormalSRVDesc.Texture2D.ResourceMinLODClamp = 0.0f;
+#endif
+
+ mNormalSRV[FrameIndex] = {};
+ mNormalSRV[FrameIndex].pResource = mNormalBuffer[FrameIndex].Get();
+ CD3DX12_CPU_DESCRIPTOR_HANDLE NormalSRVHandle(
+ mSsaoDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart(),
+ SSAO_NUM_DEPTH_SRV + FrameIndex,
+ mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
+ mDev->CreateShaderResourceView(mNormalBuffer[FrameIndex].Get(), &NormalSRVDesc, NormalSRVHandle);
+
+ // RTV
+ D3D12_RENDER_TARGET_VIEW_DESC normalRTVDesc = {};
+ normalRTVDesc.Format = NormalRTVDesc.Format;
+#if MSAA_SAMPLE_COUNT > 1
+ normalRTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
+#else
+ normalRTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+ normalRTVDesc.Texture2D.MipSlice = 0;
+#endif
+ mNormalRTV[FrameIndex] = {};
+ mNormalRTV[FrameIndex].pResource = mNormalBuffer[FrameIndex].Get();
+ mNormalRTV[FrameIndex].CpuHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(
+ mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(),
+ VIEWER_NUM_COLOR_RTV + FrameIndex,
+ mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV)).ptr;
+ mDev->CreateRenderTargetView(mNormalBuffer[FrameIndex].Get(), &normalRTVDesc, { mNormalRTV[FrameIndex].CpuHandle });
+ }
+ }
+
+ void InitSSAO()
+ {
+ const UINT NodeMask = 1;
+
+ GFSDK_SSAO_CustomHeap CustomHeap;
+ CustomHeap.new_ = ::operator new;
+ CustomHeap.delete_ = ::operator delete;
+
+ GFSDK_SSAO_DescriptorHeaps_D3D12 DescriptorHeaps;
+
+ DescriptorHeaps.CBV_SRV_UAV.pDescHeap = mSsaoDescHeapCbvSrvUav.Get();
+ DescriptorHeaps.CBV_SRV_UAV.BaseIndex = SSAO_NUM_DEPTH_SRV + SSAO_NUM_NORMAL_SRV;
+ DescriptorHeaps.CBV_SRV_UAV.NumDescriptors = GFSDK_SSAO_NUM_DESCRIPTORS_CBV_SRV_UAV_HEAP_D3D12;
+
+ DescriptorHeaps.RTV.pDescHeap = mDescHeapRtv.Get();
+ DescriptorHeaps.RTV.BaseIndex = VIEWER_NUM_RTV;
+ DescriptorHeaps.RTV.NumDescriptors = GFSDK_SSAO_NUM_DESCRIPTORS_RTV_HEAP_D3D12;
+
+ GFSDK_SSAO_Status status = GFSDK_SSAO_CreateContext_D3D12(mDev, NodeMask, DescriptorHeaps, &mSSAO, &CustomHeap);
+ assert(status == GFSDK_SSAO_OK);
+ }
+
+ void ReleaseSSAO()
+ {
+ if (mSSAO)
+ {
+ mSSAO->Release();
+ mSSAO = nullptr;
+ }
+ }
+
+ //--------------------------------------------------------------------------------
+ ID3D12Device* GetDevice() const
+ {
+ return mDev;
+ }
+
+ void WaitForGpuIdle()
+ {
+ // Schedule a Signal command in the queue.
+ const UINT64 currentFenceValue = mFenceValues[mFrameIndex];
+ CHK(mCmdQueue->Signal(mFence.Get(), currentFenceValue));
+
+ CHK(mFence->SetEventOnCompletion(mFenceValues[mFrameIndex], mFenceEvent));
+ WaitForSingleObjectEx(mFenceEvent, INFINITE, FALSE);
+ }
+
+ //--------------------------------------------------------------------------------
+ void Draw()
+ {
+ // Upload constant buffer
+ XMMATRIX ViewMat, ProjMat, WorldMat, ViewProjMat;
+ {
+#if USE_BIN_MESH_READER
+ ViewMat = XMMatrixIdentity();
+ WorldMat = XMMatrixIdentity();
+#else
+ WorldMat = XMMatrixRotationY(XMConvertToRadians(gModelRotation));
+ ViewMat = XMMatrixLookAtLH({ 0, 1, gCameraDistance }, { 0, 0, 0 }, { 0, 1, 0 });
+#endif
+
+ float nearPlane = .01f;
+ float farPlane = 500.0f;
+ ProjMat = XMMatrixPerspectiveFovLH(40 * 3.141592f / 180.f, (float)mBufferWidth / mBufferHeight, nearPlane, farPlane);
+ XMMATRIX MVPTransMat = XMMatrixTranspose(WorldMat * ViewMat * ProjMat);
+ XMMATRIX WorldTransMat = XMMatrixTranspose(WorldMat);
+
+ ViewProjMat = XMMatrixMultiply(ViewMat, ProjMat);
+
+ // mCBUploadPtr is Write-Combine memory
+ memcpy_s(mCBUploadPtr, 64, &MVPTransMat, 64);
+ memcpy_s(reinterpret_cast<char*>(mCBUploadPtr) + 64, 64, &WorldTransMat, 64);
+ }
+
+ // Get current RTV descriptor
+ CD3DX12_CPU_DESCRIPTOR_HANDLE descHandleRtv(
+ mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(),
+ mFrameIndex,
+ mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV));
+
+ // Get current swap chain
+ ID3D12Resource* ColorBuffer = mColorBuffer[mFrameIndex].Get();
+ ID3D12Resource* DepthBuffer = mDepthBuffer.Get();
+
+ // Get DSV
+ CD3DX12_CPU_DESCRIPTOR_HANDLE DepthDSV(mDescHeapDsv->GetCPUDescriptorHandleForHeapStart());
+
+ SetResourceBarrier(mCmdList.Get(), ColorBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ SetResourceBarrier(mCmdList.Get(), DepthBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+
+ // Viewport & Scissor
+ D3D12_VIEWPORT viewport = {};
+ viewport.Width = (float)mBufferWidth;
+ viewport.Height = (float)mBufferHeight;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ mCmdList->RSSetViewports(1, &viewport);
+ D3D12_RECT scissor = {};
+ scissor.right = (LONG)mBufferWidth;
+ scissor.bottom = (LONG)mBufferHeight;
+ mCmdList->RSSetScissorRects(1, &scissor);
+
+ // Clear DepthTexturesh
+ mCmdList->ClearDepthStencilView(DepthDSV, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
+
+ // Draw the geometry
+ D3D12_CPU_DESCRIPTOR_HANDLE RTVs[] = { { mNormalRTV[mFrameIndex].CpuHandle } };
+ mCmdList->OMSetRenderTargets(ARRAYSIZE(RTVs), RTVs, false, &DepthDSV);
+
+ mCmdList->SetGraphicsRootSignature(mRootSignature.Get());
+ ID3D12DescriptorHeap* descHeaps[] = { mDescHeapCbvSrvUav.Get() };
+ mCmdList->SetDescriptorHeaps(ARRAYSIZE(descHeaps), descHeaps);
+
+ mCmdList->SetGraphicsRootDescriptorTable(0, mDescHeapCbvSrvUav->GetGPUDescriptorHandleForHeapStart());
+ mCmdList->SetPipelineState(mPso.Get());
+ mCmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ mCmdList->IASetVertexBuffers(0, 1, &mVBView);
+ mCmdList->IASetIndexBuffer(&mIBView);
+ mCmdList->DrawIndexedInstanced(mIndexCount, 1, 0, 0, 0);
+
+ SetResourceBarrier(mCmdList.Get(), DepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
+
+ if (gUseSSAO)
+ {
+ // Set input data
+ GFSDK_SSAO_InputData_D3D12 InputData = {};
+ InputData.DepthData.DepthTextureType = GFSDK_SSAO_HARDWARE_DEPTHS;
+
+ // FullResDepthTextureSRV
+ {
+ CD3DX12_GPU_DESCRIPTOR_HANDLE DepthSrvGpuHandle(
+ mSsaoDescHeapCbvSrvUav->GetGPUDescriptorHandleForHeapStart());
+ InputData.DepthData.FullResDepthTextureSRV.pResource = DepthBuffer;
+ InputData.DepthData.FullResDepthTextureSRV.GpuHandle = DepthSrvGpuHandle.ptr;
+ }
+
+ // DepthData
+ InputData.DepthData.ProjectionMatrix.Data = GFSDK_SSAO_Float4x4((const GFSDK_SSAO_FLOAT*)&ProjMat);
+ InputData.DepthData.ProjectionMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER;
+
+#if USE_BIN_MESH_READER
+ InputData.DepthData.MetersToViewSpaceUnits = 0.005f;
+#else
+ InputData.DepthData.MetersToViewSpaceUnits = 1.f;
+#endif
+
+ // NormalData
+ {
+ CD3DX12_GPU_DESCRIPTOR_HANDLE NormalSrvGpuHandle(
+ mSsaoDescHeapCbvSrvUav->GetGPUDescriptorHandleForHeapStart(),
+ SSAO_NUM_DEPTH_SRV + mFrameIndex,
+ mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
+
+ mNormalSRV[mFrameIndex].GpuHandle = NormalSrvGpuHandle.ptr;
+
+#if USE_BIN_MESH_READER
+ InputData.NormalData.Enable = false;
+#else
+ InputData.NormalData.Enable = true;
+#endif
+
+ if (InputData.NormalData.Enable)
+ {
+ InputData.NormalData.WorldToViewMatrix.Data = GFSDK_SSAO_Float4x4((const GFSDK_SSAO_FLOAT*)&ViewMat);
+ InputData.NormalData.WorldToViewMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER;
+ InputData.NormalData.FullResNormalTextureSRV = mNormalSRV[mFrameIndex];
+ }
+ }
+
+ //GFSDK_SSAO_RenderMask RenderMask = GFSDK_SSAO_RENDER_DEBUG_NORMAL;
+ GFSDK_SSAO_RenderMask RenderMask = GFSDK_SSAO_RENDER_AO;
+
+ // Set SSAO descriptor heap
+ {
+ ID3D12DescriptorHeap* descHeaps[] = { mSsaoDescHeapCbvSrvUav.Get() };
+ mCmdList->SetDescriptorHeaps(ARRAYSIZE(descHeaps), descHeaps);
+ }
+
+ GFSDK_SSAO_Output_D3D12 Output;
+ Output.pRenderTargetView = &mColorRTV[mFrameIndex];
+
+ GFSDK_SSAO_Status status = mSSAO->RenderAO(mCmdQueue.Get(), mCmdList.Get(), InputData, mAOParams, Output, RenderMask);
+ assert(status == GFSDK_SSAO_OK);
+
+ // Revert to the original descriptor heap
+ {
+ ID3D12DescriptorHeap* descHeaps[] = { mDescHeapCbvSrvUav.Get() };
+ mCmdList->SetDescriptorHeaps(ARRAYSIZE(descHeaps), descHeaps);
+ }
+ }
+
+ if (gDrawUI)
+ {
+ D3D12_CPU_DESCRIPTOR_HANDLE RTVs[] = { mColorRTV[mFrameIndex].CpuHandle };
+
+ mCmdList->OMSetRenderTargets(ARRAYSIZE(RTVs), RTVs, false, nullptr);
+ DrawUI();
+ }
+
+ // Barrier RenderTarget -> Present
+ SetResourceBarrier(mCmdList.Get(), ColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
+
+ // Exec
+ CHK(mCmdList->Close());
+ ID3D12CommandList* const cmdList = mCmdList.Get();
+ mCmdQueue->ExecuteCommandLists(1, &cmdList);
+
+ // Present
+ CHK(mSwapChain->Present(0, 0));
+
+ // Move to next frame
+ {
+ // Schedule a Signal command in the queue.
+ const UINT64 currentFenceValue = mFenceValues[mFrameIndex];
+ CHK(mCmdQueue->Signal(mFence.Get(), currentFenceValue));
+
+ // Update the frame index.
+ mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
+
+ // If the next frame is not ready to be rendered yet, wait until it is ready.
+ UINT64 CompletedValue = mFence->GetCompletedValue();
+ if (CompletedValue < mFenceValues[mFrameIndex])
+ {
+ CHK(mFence->SetEventOnCompletion(mFenceValues[mFrameIndex], mFenceEvent));
+ WaitForSingleObjectEx(mFenceEvent, INFINITE, FALSE);
+ }
+
+ // Set the fence value for the next frame.
+ mFenceValues[mFrameIndex] = currentFenceValue + 1;
+ }
+
+ // Command list allocators can only be reset when the associated
+ // command lists have finished execution on the GPU; apps should use
+ // fences to determine GPU execution progress.
+ CHK(mCmdAllocs[mFrameIndex]->Reset());
+
+ // However, when ExecuteCommandList() is called on a particular command
+ // list, that command list can then be reset at any time and must be before
+ // re-recording.
+ CHK(mCmdList->Reset(mCmdAllocs[mFrameIndex].Get(), nullptr));
+ }
+
+ //--------------------------------------------------------------------------------
+ void DrawUI()
+ {
+ // Draw UI
+ ImGui_ImplDX12_NewFrame();
+
+ bool show_ssao_window = true;
+ bool show_test_window = false;
+
+ // Show SSAO property window
+ if (show_ssao_window)
+ {
+ ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiSetCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiSetCond_FirstUseEver);
+ ImGui::Begin("HBAO+", &show_ssao_window);
+
+ GFSDK_SSAO_Version Version;
+ GFSDK_SSAO_Status Status;
+ Status = GFSDK_SSAO_GetVersion(&Version);
+ assert(Status == GFSDK_SSAO_OK);
+
+ ImGui::Text("D3D12 HBAO+ %d.%d.%d.%d", Version.Major, Version.Minor, Version.Branch, Version.Revision);
+
+ ImGui::Text("%s", gSelectedGraphicsAdapter.c_str());
+#if MSAA_SAMPLE_COUNT > 1
+ ImGui::Text("%dx MSAA", MSAA_SAMPLE_COUNT);
+#endif
+ ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+
+ float radius = mAOParams.Radius;
+ ImGui::DragFloat("Radius", &radius, 0.05f, 0.0f, 100.0f);
+ if (radius != mAOParams.Radius)
+ {
+ mAOParams.Radius = radius;
+ int stop = 0;
+ stop = stop;
+ }
+ ImGui::DragFloat("PowerExponent", &mAOParams.PowerExponent, 0.05f, 1.f, 8.f);
+ ImGui::DragFloat("Bias", &mAOParams.Bias, 0.001f, 0, 0.5f);
+
+ ImGui::DragFloat("NearAO", &mAOParams.NearAO, 0.01f, 1.f, 2.f);
+ ImGui::DragFloat("FarAO", &mAOParams.FarAO, 0.01f, 1.f, 2.f);
+
+ bool BlurEnabled = mAOParams.Blur.Enable ? true : false;
+ ImGui::Checkbox("Blur.Enable", &BlurEnabled);
+ mAOParams.Blur.Enable = BlurEnabled;
+
+ const char* listbox_items[] = { "GFSDK_SSAO_BLUR_RADIUS_2", "GFSDK_SSAO_BLUR_RADIUS_4" };
+ int listbox_item_current = (int)mAOParams.Blur.Radius;
+ ImGui::ListBox("Blur.Radius", &listbox_item_current, listbox_items, ARRAYSIZE(listbox_items), 2);
+ mAOParams.Blur.Radius = (GFSDK_SSAO_BlurRadius)(listbox_item_current);
+
+ ImGui::DragFloat("Blur.Sharpness", &mAOParams.Blur.Sharpness, 0.f, 0.f, 32.0f);
+
+ ImGui::End();
+ }
+
+ // Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
+ if (show_test_window)
+ {
+ ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
+ ImGui::ShowTestWindow(&show_test_window);
+ }
+
+ ImGui::Render();
+ }
+
+private:
+ void SetResourceBarrier(ID3D12GraphicsCommandList* commandList,
+ ID3D12Resource* res,
+ D3D12_RESOURCE_STATES before,
+ D3D12_RESOURCE_STATES after)
+ {
+ D3D12_RESOURCE_BARRIER desc = {};
+ desc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ desc.Transition.pResource = res;
+ desc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ desc.Transition.StateBefore = before;
+ desc.Transition.StateAfter = after;
+ desc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ commandList->ResourceBarrier(1, &desc);
+ }
+};
+
+D3D* gD3D = nullptr;
+
+extern LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//--------------------------------------------------------------------------------
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static WORD sLastX = 0, sLastY = 0;
+
+ ImGui_ImplDX12_WndProcHandler(hWnd, message, wParam, lParam);
+
+ switch (message)
+ {
+ case WM_SIZE:
+ {
+ if (gD3D)
+ {
+ BOOL IsFullScreen = FALSE;
+ if (gD3D->mSwapChain) {
+ gD3D->mSwapChain->GetFullscreenState(&IsFullScreen, NULL);
+ }
+ gD3D->ResizeD3D(hWnd, LOWORD(lParam), HIWORD(lParam), !IsFullScreen);
+ }
+ }
+ break;
+ case WM_KEYDOWN:
+ if (wParam == VK_ESCAPE)
+ {
+ gDrawUI = !gDrawUI;
+ //PostMessage(hWnd, WM_DESTROY, 0, 0);
+ //return 0;
+ }
+ if (wParam == VK_F5)
+ {
+ gD3D->ReleaseSSAO();
+ gD3D->InitSSAO();
+ OutputDebugStringA("SSAO Reloaded\n");
+ }
+ if (wParam == 'W')
+ {
+ gCameraDistance -= 0.1f;
+ }
+ else if (wParam == 'S')
+ {
+ gCameraDistance += 0.1f;
+ }
+
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ WORD x = LOWORD(lParam);
+ WORD y = HIWORD(lParam);
+
+ if (wParam & MK_RBUTTON)
+ {
+ gModelRotation -= float(x - sLastX);
+ }
+ sLastX = x;
+ sLastY = y;
+ }
+ break;
+ case WM_PAINT:
+ if (gD3D) gD3D->Draw();
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------------------
+void FitToDesiredClientSize(HWND hwnd, int Width, int Height, DWORD window_style, bool has_menu)
+{
+ RECT current_win_rect;
+ ::GetWindowRect(hwnd, &current_win_rect);
+ RECT desired_rect = current_win_rect;
+ desired_rect.right = current_win_rect.left + Width;
+ desired_rect.bottom = current_win_rect.top + Height;
+ ::AdjustWindowRect(&desired_rect, window_style, (has_menu) ? TRUE : FALSE);
+ Width = desired_rect.right - desired_rect.left;
+ Height = desired_rect.bottom - desired_rect.top;
+ ::SetWindowLongPtr(hwnd, GWL_STYLE, window_style);
+ ::SetWindowPos(hwnd, HWND_TOP, 0, 0, Width, Height, SWP_SHOWWINDOW);
+}
+
+//--------------------------------------------------------------------------------
+static HWND SetupWindow(int Width, int Height, bool IsWindowed)
+{
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = (HMODULE)GetModuleHandle(0);
+ wcex.hIcon = nullptr;
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wcex.lpszMenuName = nullptr;
+ wcex.lpszClassName = _T("WindowClass");
+ wcex.hIconSm = nullptr;
+ if (!RegisterClassEx(&wcex))
+ {
+ throw runtime_error("RegisterClassEx()");
+ }
+
+ DWORD windowStyle = WS_OVERLAPPEDWINDOW;
+ HWND hWnd = CreateWindowEx(
+ 0, // WS_EX_TOPMOST,
+ _T("WindowClass"), _T("HBAO+ DX12"),
+ windowStyle,
+ 0, 0, Width, Height,
+ nullptr, nullptr, nullptr, nullptr);
+ if (!hWnd)
+ {
+ throw runtime_error("CreateWindow()");
+ }
+
+ if (IsWindowed)
+ {
+ FitToDesiredClientSize(hWnd, Width, Height, windowStyle, false);
+ }
+
+ return hWnd;
+}
+
+//--------------------------------------------------------------------------------
+int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR CmdLine, int)
+{
+ MSG msg;
+ ZeroMemory(&msg, sizeof msg);
+
+ ID3D12Device* dev = nullptr;
+
+ std::vector<std::string> arguments;
+ if (CmdLine)
+ {
+ char buff[1024];
+ strcpy(buff, CmdLine);
+ char * pch = strtok(buff, " ");
+ while (pch != NULL)
+ {
+ arguments.push_back(pch);
+ pch = strtok(NULL, " ");
+ }
+ }
+
+ for (size_t idx = 0; idx < arguments.size(); ++idx)
+ {
+ std::string arg = arguments[idx];
+ if (_stricmp(arg.c_str(), "-width") == 0)
+ {
+ gWindowWidth = atoi(arguments[idx + 1].c_str());
+ idx++;
+ }
+ else if (_stricmp(arg.c_str(), "-height") == 0)
+ {
+ gWindowHeight = atoi(arguments[idx + 1].c_str());
+ idx++;
+ }
+ else if (_stricmp(arg.c_str(), "-window") == 0)
+ {
+ gIsWindowed = (atoi(arguments[idx + 1].c_str()) == 1) ? true : false;
+ idx++;
+ }
+ else if (_stricmp(arg.c_str(), "-ui") == 0)
+ {
+ gDrawUI = (atoi(arguments[idx + 1].c_str()) == 1) ? true : false;
+ idx++;
+ }
+ else if (_stricmp(arg.c_str(), "-adapter") == 0)
+ {
+ gAdapterIndex = (atoi(arguments[idx + 1].c_str()) == 1) ? true : false;
+ idx++;
+ }
+ }
+
+#ifdef NDEBUG
+ try
+#endif
+ {
+ gMainWindowHandle = SetupWindow(gWindowWidth, gWindowHeight, gIsWindowed);
+ ShowWindow(gMainWindowHandle, SW_SHOW);
+ UpdateWindow(gMainWindowHandle);
+
+ gD3D = new D3D(gWindowWidth, gWindowHeight, gMainWindowHandle, gIsWindowed, gAdapterIndex);
+ dev = gD3D->GetDevice();
+
+ while (msg.message != WM_QUIT)
+ {
+ if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+#ifdef NDEBUG
+ catch (std::exception &e)
+ {
+ MessageBoxA(gMainWindowHandle, e.what(), "Exception occured.", MB_ICONSTOP);
+ }
+#endif
+
+ if (gD3D)
+ delete gD3D;
+
+ if (dev)
+ dev->Release();
+
+ return static_cast<int>(msg.wParam);
+}
diff --git a/samples/D3D12/src/Viewer.hlsl b/samples/D3D12/src/Viewer.hlsl
new file mode 100644
index 0000000..b3b418c
--- /dev/null
+++ b/samples/D3D12/src/Viewer.hlsl
@@ -0,0 +1,40 @@
+struct VSIn
+{
+ float3 pos : POSITION;
+ float3 normal : NORMAL;
+};
+
+struct VSOut
+{
+ float4 pos : SV_POSITION;
+ float3 normal : TEXCOORD;
+};
+
+cbuffer Scene
+{
+ float4x4 worldViewProjMatrix;
+ float4x4 worldMatrix;
+};
+
+VSOut VSMain(VSIn vsIn)
+{
+ VSOut output;
+ output.pos = mul(float4(vsIn.pos.xyz, 1), worldViewProjMatrix);
+ output.normal = mul(vsIn.normal.xyz, (float3x3)(worldMatrix));
+ return output;
+}
+
+struct PSOutputDepthTextures
+{
+ float4 WorldNormal : SV_Target0;
+};
+
+PSOutputDepthTextures PSMain(VSOut vsOut)
+{
+ PSOutputDepthTextures OUT;
+
+ float3 worldNormal = normalize(vsOut.normal);
+ OUT.WorldNormal = float4(worldNormal.xyz, 1.f);
+
+ return OUT;
+} \ No newline at end of file
diff --git a/samples/D3D12/src/Viewer.vcxproj b/samples/D3D12/src/Viewer.vcxproj
new file mode 100644
index 0000000..afd9721
--- /dev/null
+++ b/samples/D3D12/src/Viewer.vcxproj
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CFEEDBA7-74CF-4AF1-9A14-0E890CE94DF8}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>hbaop_dx12</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
+ <ProjectName>SampleApp_D3D12</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_IncludePath);$(ProjectDir)..\..\..\include;$(ProjectDir);$(VC_IncludePath);$(ProjectDir)..\external\imgui\examples\directx12_example;$(ProjectDir)..\external\imgui\</IncludePath>
+ <LibraryPath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86)</LibraryPath>
+ <OutDir>..\Bin\</OutDir>
+ <IntDir>..\Temp\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ <TargetName>$(ProjectName).debug.win32</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_IncludePath);$(ProjectDir)..\..\..\include;$(ProjectDir);$(VC_IncludePath);$(ProjectDir)..\external\imgui\examples\directx12_example;$(ProjectDir)..\external\imgui\</IncludePath>
+ <LibraryPath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_LibraryPath_x64);$(VC_LibraryPath_x64)</LibraryPath>
+ <OutDir>..\Bin\</OutDir>
+ <IntDir>..\Temp\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ <TargetName>$(ProjectName).debug.win64</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IncludePath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_IncludePath);$(ProjectDir)..\..\..\include;$(ProjectDir);$(VC_IncludePath);$(ProjectDir)..\external\imgui\examples\directx12_example;$(ProjectDir)..\external\imgui\</IncludePath>
+ <LibraryPath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86)</LibraryPath>
+ <OutDir>..\Bin\</OutDir>
+ <IntDir>..\Temp\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ <TargetName>$(ProjectName).win32</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IncludePath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_IncludePath);$(ProjectDir)..\..\..\include;$(ProjectDir);$(VC_IncludePath);$(ProjectDir)..\external\imgui\examples\directx12_example;$(ProjectDir)..\external\imgui\</IncludePath>
+ <LibraryPath>$(ProjectDir)..\..\..\lib;$(WindowsSDK_LibraryPath_x64);$(VC_LibraryPath_x64)</LibraryPath>
+ <OutDir>..\Bin\</OutDir>
+ <IntDir>..\Temp\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ <TargetName>$(ProjectName).win64</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <DisableSpecificWarnings>4312</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>
+ </AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>copy /Y ..\..\..\lib\GFSDK_SSAO_D3D12.win32.dll ..\Bin</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <DisableSpecificWarnings>4312</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>
+ </AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>copy /Y ..\..\..\lib\GFSDK_SSAO_D3D12.win64.dll ..\Bin</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <DisableSpecificWarnings>4312</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>
+ </AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>copy /Y ..\..\..\lib\GFSDK_SSAO_D3D12.win32.dll ..\Bin</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <DisableSpecificWarnings>4312</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>
+ </AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>copy /Y ..\..\..\lib\GFSDK_SSAO_D3D12.win64.dll ..\Bin</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\external\imgui\examples\directx12_example\imgui_impl_dx12.cpp" />
+ <ClCompile Include="..\external\imgui\imgui.cpp" />
+ <ClCompile Include="..\external\imgui\imgui_demo.cpp" />
+ <ClCompile Include="..\external\imgui\imgui_draw.cpp" />
+ <ClCompile Include="Viewer.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <FxCompile Include="..\bin\Viewer.hlsl">
+ <EntryPointName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">PSMain</EntryPointName>
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
+ <EntryPointName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">PSMain</EntryPointName>
+ <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel>
+ <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </FxCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\external\imgui\examples\directx12_example\imgui_impl_dx12.h" />
+ <ClInclude Include="..\external\imgui\imconfig.h" />
+ <ClInclude Include="..\external\imgui\imgui.h" />
+ <ClInclude Include="..\external\imgui\stb_rect_pack.h" />
+ <ClInclude Include="..\external\imgui\stb_textedit.h" />
+ <ClInclude Include="..\external\imgui\stb_truetype.h" />
+ <ClInclude Include="BinMeshReader.h" />
+ <ClInclude Include="WaveFrontReader.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/samples/D3D12/src/Viewer.vcxproj.filters b/samples/D3D12/src/Viewer.vcxproj.filters
new file mode 100644
index 0000000..bd01d4e
--- /dev/null
+++ b/samples/D3D12/src/Viewer.vcxproj.filters
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="shaders">
+ <UniqueIdentifier>{0e1a96a7-3888-4f55-b5b2-5aa8917b7309}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{837694ff-54c1-41d9-a277-db25d377c998}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\external\imgui\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\external\imgui\examples\directx12_example\imgui_impl_dx12.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\external\imgui\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\external\imgui\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="Viewer.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="WaveFrontReader.h" />
+ <ClInclude Include="..\external\imgui\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\external\imgui\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\external\imgui\stb_rect_pack.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\external\imgui\stb_textedit.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\external\imgui\stb_truetype.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\external\imgui\examples\directx12_example\imgui_impl_dx12.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="BinMeshReader.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <FxCompile Include="..\bin\Viewer.hlsl">
+ <Filter>shaders</Filter>
+ </FxCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/samples/D3D12/src/WaveFrontReader.h b/samples/D3D12/src/WaveFrontReader.h
new file mode 100644
index 0000000..f68f2bf
--- /dev/null
+++ b/samples/D3D12/src/WaveFrontReader.h
@@ -0,0 +1,541 @@
+//--------------------------------------------------------------------------------------
+// File: WaveFrontReader.h
+//
+// Code for loading basic mesh data from a WaveFront OBJ file
+//
+// http://en.wikipedia.org/wiki/Wavefront_.obj_file
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkID=324981
+//--------------------------------------------------------------------------------------
+
+#include <windows.h>
+
+#include <algorithm>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <stdint.h>
+#pragma warning(pop)
+
+#include <directxmath.h>
+#include <directxcollision.h>
+
+template<class index_t>
+class WaveFrontReader
+{
+public:
+ typedef index_t index_t;
+
+ struct Vertex
+ {
+ DirectX::XMFLOAT3 position;
+ DirectX::XMFLOAT3 normal;
+ DirectX::XMFLOAT2 textureCoordinate;
+ };
+
+ WaveFrontReader() : hasNormals(false), hasTexcoords(false) {}
+
+ HRESULT Load( _In_z_ const wchar_t* szFileName, bool ccw = true )
+ {
+ Clear();
+
+ static const size_t MAX_POLY = 64;
+
+ using namespace DirectX;
+
+ std::wifstream InFile( szFileName );
+ if( !InFile )
+ return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
+
+ WCHAR fname[_MAX_FNAME];
+ _wsplitpath_s( szFileName, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, nullptr, 0 );
+
+ name = fname;
+
+ std::vector<XMFLOAT3> positions;
+ std::vector<XMFLOAT3> normals;
+ std::vector<XMFLOAT2> texCoords;
+
+ VertexCache vertexCache;
+
+ Material defmat;
+
+ wcscpy_s( defmat.strName, L"default" );
+ materials.push_back( defmat );
+
+ uint32_t curSubset = 0;
+
+ WCHAR strCommand[256] = {0};
+ WCHAR strMaterialFilename[MAX_PATH] = {0};
+ for( ;; )
+ {
+ InFile >> strCommand;
+ if( !InFile )
+ break;
+
+ if( 0 == wcscmp( strCommand, L"#" ) )
+ {
+ // Comment
+ }
+ else if( 0 == wcscmp( strCommand, L"v" ) )
+ {
+ // Vertex Position
+ float x, y, z;
+ InFile >> x >> y >> z;
+ positions.push_back( XMFLOAT3( x, y, z ) );
+ }
+ else if( 0 == wcscmp( strCommand, L"vt" ) )
+ {
+ // Vertex TexCoord
+ float u, v;
+ InFile >> u >> v;
+ texCoords.push_back( XMFLOAT2( u, v ) );
+
+ hasTexcoords = true;
+ }
+ else if( 0 == wcscmp( strCommand, L"vn" ) )
+ {
+ // Vertex Normal
+ float x, y, z;
+ InFile >> x >> y >> z;
+ normals.push_back( XMFLOAT3( x, y, z ) );
+
+ hasNormals = true;
+ }
+ else if( 0 == wcscmp( strCommand, L"f" ) )
+ {
+ // Face
+ UINT iPosition, iTexCoord, iNormal;
+ Vertex vertex;
+
+ DWORD faceIndex[ MAX_POLY ];
+ size_t iFace = 0;
+ for(;;)
+ {
+ if ( iFace >= MAX_POLY )
+ {
+ // Too many polygon verts for the reader
+ return E_FAIL;
+ }
+
+ memset( &vertex, 0, sizeof( vertex ) );
+
+ // OBJ format uses 1-based arrays
+ InFile >> iPosition;
+ if ( iPosition > positions.size() )
+ return E_FAIL;
+
+ vertex.position = positions[ iPosition - 1 ];
+
+ if( '/' == InFile.peek() )
+ {
+ InFile.ignore();
+
+ if( '/' != InFile.peek() )
+ {
+ // Optional texture coordinate
+ InFile >> iTexCoord;
+ if ( iTexCoord > texCoords.size() )
+ return E_FAIL;
+
+ vertex.textureCoordinate = texCoords[ iTexCoord - 1 ];
+ }
+
+ if( '/' == InFile.peek() )
+ {
+ InFile.ignore();
+
+ // Optional vertex normal
+ InFile >> iNormal;
+ if ( iNormal > normals.size() )
+ return E_FAIL;
+
+ vertex.normal = normals[ iNormal - 1 ];
+ }
+ }
+
+ // If a duplicate vertex doesn't exist, add this vertex to the Vertices
+ // list. Store the index in the Indices array. The Vertices and Indices
+ // lists will eventually become the Vertex Buffer and Index Buffer for
+ // the mesh.
+ DWORD index = AddVertex( iPosition, &vertex, vertexCache );
+ if ( index == (DWORD)-1 )
+ return E_OUTOFMEMORY;
+
+#pragma warning( suppress : 4127 )
+ if ( sizeof(index_t) == 2 && ( index >= 0xFFFF ) )
+ {
+ // Too many indices for 16-bit IB!
+ return E_FAIL;
+ }
+ else if ( sizeof(index_t) == 4 && ( index >= 0xFFFFFFFF ) )
+ {
+ // Too many indices for 32-bit IB!
+ return E_FAIL;
+ }
+
+ faceIndex[ iFace ] = index;
+ ++iFace;
+
+ // Check for more face data or end of the face statement
+ bool faceEnd = false;
+ for(;;)
+ {
+ wchar_t p = InFile.peek();
+
+ if ( '\n' == p || !InFile )
+ {
+ faceEnd = true;
+ break;
+ }
+ else if ( isdigit( p ) )
+ break;
+
+ InFile.ignore();
+ }
+
+ if ( faceEnd )
+ break;
+ }
+
+ if ( iFace < 3 )
+ {
+ // Need at least 3 points to form a triangle
+ return E_FAIL;
+ }
+
+ // Convert polygons to triangles
+ DWORD i0 = faceIndex[0];
+ DWORD i1 = faceIndex[1];
+
+ for( size_t j = 2; j < iFace; ++ j )
+ {
+ DWORD index = faceIndex[ j ];
+ indices.push_back( static_cast<index_t>( i0 ) );
+ if ( ccw )
+ {
+ indices.push_back( static_cast<index_t>( i1 ) );
+ indices.push_back( static_cast<index_t>( index ) );
+ }
+ else
+ {
+ indices.push_back( static_cast<index_t>( index ) );
+ indices.push_back( static_cast<index_t>( i1 ) );
+ }
+
+ attributes.push_back( curSubset );
+
+ i1 = index;
+ }
+
+ assert( attributes.size()*3 == indices.size() );
+ }
+ else if( 0 == wcscmp( strCommand, L"mtllib" ) )
+ {
+ // Material library
+ InFile >> strMaterialFilename;
+ }
+ else if( 0 == wcscmp( strCommand, L"usemtl" ) )
+ {
+ // Material
+ WCHAR strName[MAX_PATH] = {0};
+ InFile >> strName;
+
+ bool bFound = false;
+ uint32_t count = 0;
+ for( auto it = materials.cbegin(); it != materials.cend(); ++it, ++count )
+ {
+ if( 0 == wcscmp( it->strName, strName ) )
+ {
+ bFound = true;
+ curSubset = count;
+ break;
+ }
+ }
+
+ if( !bFound )
+ {
+ Material mat;
+ curSubset = static_cast<uint32_t>( materials.size() );
+ wcscpy_s( mat.strName, MAX_PATH - 1, strName );
+ materials.push_back( mat );
+ }
+ }
+ else
+ {
+ // Unimplemented or unrecognized command
+ //OutputDebugStringW( strCommand );
+ }
+
+ InFile.ignore( 1000, '\n' );
+ }
+
+ // Cleanup
+ InFile.close();
+
+ BoundingBox::CreateFromPoints( bounds, positions.size(), &positions.front(), sizeof(XMFLOAT3) );
+
+ // If an associated material file was found, read that in as well.
+ if (0) //@jihoc if( *strMaterialFilename )
+ {
+ WCHAR ext[_MAX_EXT];
+ _wsplitpath_s( strMaterialFilename, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT );
+
+ WCHAR drive[_MAX_DRIVE];
+ WCHAR dir[_MAX_DIR];
+ _wsplitpath_s( szFileName, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0 );
+
+ WCHAR szPath[ MAX_PATH ];
+ _wmakepath_s( szPath, MAX_PATH, drive, dir, fname, ext );
+
+ HRESULT hr = LoadMTL( szPath );
+ if ( FAILED(hr) )
+ return hr;
+ }
+
+ return S_OK;
+ }
+
+ HRESULT LoadMTL( _In_z_ const wchar_t* szFileName )
+ {
+ // Assumes MTL is in CWD along with OBJ
+ std::wifstream InFile( szFileName );
+ if( !InFile )
+ return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
+
+ auto curMaterial = materials.end();
+
+ WCHAR strCommand[256] = {0};
+ for( ;; )
+ {
+ InFile >> strCommand;
+ if( !InFile )
+ break;
+
+ if( 0 == wcscmp( strCommand, L"newmtl" ) )
+ {
+ // Switching active materials
+ WCHAR strName[MAX_PATH] = {0};
+ InFile >> strName;
+
+ curMaterial = materials.end();
+ for( auto it = materials.begin(); it != materials.end(); ++it )
+ {
+ if( 0 == wcscmp( it->strName, strName ) )
+ {
+ curMaterial = it;
+ break;
+ }
+ }
+ }
+
+ // The rest of the commands rely on an active material
+ if( curMaterial == materials.end() )
+ continue;
+
+ if( 0 == wcscmp( strCommand, L"#" ) )
+ {
+ // Comment
+ }
+ else if( 0 == wcscmp( strCommand, L"Ka" ) )
+ {
+ // Ambient color
+ float r, g, b;
+ InFile >> r >> g >> b;
+ curMaterial->vAmbient = XMFLOAT3( r, g, b );
+ }
+ else if( 0 == wcscmp( strCommand, L"Kd" ) )
+ {
+ // Diffuse color
+ float r, g, b;
+ InFile >> r >> g >> b;
+ curMaterial->vDiffuse = XMFLOAT3( r, g, b );
+ }
+ else if( 0 == wcscmp( strCommand, L"Ks" ) )
+ {
+ // Specular color
+ float r, g, b;
+ InFile >> r >> g >> b;
+ curMaterial->vSpecular = XMFLOAT3( r, g, b );
+ }
+ else if( 0 == wcscmp( strCommand, L"d" ) ||
+ 0 == wcscmp( strCommand, L"Tr" ) )
+ {
+ // Alpha
+ InFile >> curMaterial->fAlpha;
+ }
+ else if( 0 == wcscmp( strCommand, L"Ns" ) )
+ {
+ // Shininess
+ int nShininess;
+ InFile >> nShininess;
+ curMaterial->nShininess = nShininess;
+ }
+ else if( 0 == wcscmp( strCommand, L"illum" ) )
+ {
+ // Specular on/off
+ int illumination;
+ InFile >> illumination;
+ curMaterial->bSpecular = ( illumination == 2 );
+ }
+ else if( 0 == wcscmp( strCommand, L"map_Kd" ) )
+ {
+ // Texture
+ InFile >> curMaterial->strTexture;
+ }
+ else
+ {
+ // Unimplemented or unrecognized command
+ }
+
+ InFile.ignore( 1000, L'\n' );
+ }
+
+ InFile.close();
+
+ return S_OK;
+ }
+
+ void Clear()
+ {
+ vertices.clear();
+ indices.clear();
+ attributes.clear();
+ materials.clear();
+ name.clear();
+ hasNormals = false;
+ hasTexcoords = false;
+
+ bounds.Center.x = bounds.Center.y = bounds.Center.z = 0.f;
+ bounds.Extents.x = bounds.Extents.y = bounds.Extents.z = 0.f;
+ }
+
+ HRESULT LoadVBO( _In_z_ const wchar_t* szFileName )
+ {
+ Clear();
+
+ WCHAR fname[_MAX_FNAME];
+ _wsplitpath_s( szFileName, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, nullptr, 0 );
+
+ name = fname;
+
+ Material defmat;
+ wcscpy_s( defmat.strName, L"default" );
+ materials.push_back( defmat );
+
+ std::ifstream vboFile(szFileName, std::ifstream::in | std::ifstream::binary);
+ if ( !vboFile.is_open() )
+ return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
+
+ hasNormals = hasTexcoords = true;
+
+ uint32_t numVertices = 0;
+ uint32_t numIndices = 0;
+
+ vboFile.read( reinterpret_cast<char*>( &numVertices ), sizeof(uint32_t ) );
+ if ( !numVertices )
+ return E_FAIL;
+
+ vboFile.read( reinterpret_cast<char*>( &numIndices ), sizeof(uint32_t ) );
+ if ( !numIndices )
+ return E_FAIL;
+
+ vertices.resize( numVertices );
+ vboFile.read( reinterpret_cast<char*>( &vertices.front() ), sizeof(Vertex) * numVertices );
+
+#pragma warning( suppress : 4127 )
+ if ( sizeof( index_t ) == 2 )
+ {
+ indices.resize( numIndices );
+ vboFile.read( reinterpret_cast<char*>( &indices.front() ), sizeof(uint16_t) * numIndices );
+ }
+ else
+ {
+ std::vector<uint16_t> tmp;
+ tmp.resize( numIndices );
+ vboFile.read( reinterpret_cast<char*>( &tmp.front() ), sizeof(uint16_t) * numIndices );
+
+ indices.reserve( numIndices );
+ for( auto it = tmp.cbegin(); it != tmp.cend(); ++it )
+ {
+ indices.push_back( *it );
+ }
+ }
+
+ BoundingBox::CreateFromPoints( bounds, vertices.size(), reinterpret_cast<const XMFLOAT3*>( &vertices.front() ), sizeof(Vertex) );
+
+ vboFile.close();
+
+ return S_OK;
+ }
+
+ struct Material
+ {
+ DirectX::XMFLOAT3 vAmbient;
+ DirectX::XMFLOAT3 vDiffuse;
+ DirectX::XMFLOAT3 vSpecular;
+ uint32_t nShininess;
+ float fAlpha;
+
+ bool bSpecular;
+
+ WCHAR strName[MAX_PATH];
+ WCHAR strTexture[MAX_PATH];
+
+ Material() :
+ vAmbient( 0.2f, 0.2f, 0.2f ),
+ vDiffuse( 0.8f, 0.8f, 0.8f ),
+ vSpecular( 1.0f, 1.0f, 1.0f ),
+ nShininess( 0 ),
+ fAlpha( 1.f ),
+ bSpecular( false )
+ { memset(strName, 0, MAX_PATH); memset(strTexture, 0, MAX_PATH); }
+ };
+
+ std::vector<Vertex> vertices;
+ std::vector<index_t> indices;
+ std::vector<uint32_t> attributes;
+ std::vector<Material> materials;
+
+ std::wstring name;
+ bool hasNormals;
+ bool hasTexcoords;
+
+ DirectX::BoundingBox bounds;
+
+private:
+ typedef std::unordered_multimap<UINT, UINT> VertexCache;
+
+ DWORD AddVertex( UINT hash, Vertex* pVertex, VertexCache& cache )
+ {
+ auto f = cache.equal_range( hash );
+
+ for( auto it = f.first; it != f.second; ++it )
+ {
+ auto& tv = vertices[ it->second ];
+
+ if ( 0 == memcmp( pVertex, &tv, sizeof(Vertex) ) )
+ {
+ return it->second;
+ }
+ }
+
+ DWORD index = static_cast<UINT>( vertices.size() );
+ vertices.push_back( *pVertex );
+
+ VertexCache::value_type entry( hash, index );
+ cache.insert( entry );
+ return index;
+ }
+};
diff --git a/samples/D3D12/src/d3dx12.h b/samples/D3D12/src/d3dx12.h
new file mode 100644
index 0000000..ba59dfc
--- /dev/null
+++ b/samples/D3D12/src/d3dx12.h
@@ -0,0 +1,1508 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// 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 <typename T, typename U, typename V>
+inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )
+{
+ MipSlice = static_cast<T>(Subresource % MipLevels);
+ ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);
+ PlaneSlice = static_cast<V>(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<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
+ const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(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<void**>(&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<void**>(&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<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
+ if (MemToAlloc > SIZE_MAX)
+ {
+ return 0;
+ }
+ void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
+ if (pMem == NULL)
+ {
+ return 0;
+ }
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
+ UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
+ UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
+
+ D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
+ ID3D12Device* pDevice;
+ pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&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 <UINT MaxSubresources>
+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<void**>(&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<ID3D12CommandList * const *>(pp);
+}
+
+
+#endif // defined( __cplusplus )
+
+#endif //__D3DX12_H__
+
+
+
diff --git a/samples/D3D12/src/d3dx12p.h b/samples/D3D12/src/d3dx12p.h
new file mode 100644
index 0000000..40535a8
--- /dev/null
+++ b/samples/D3D12/src/d3dx12p.h
@@ -0,0 +1,1590 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+// File: d3dx12.h
+// Content: D3DX12 utility library
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef __D3DX12_H__
+#define __D3DX12_H__
+
+#include "d3d12p.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 <typename T, typename U, typename V>
+inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )
+{
+ MipSlice = static_cast<T>(Subresource % MipLevels);
+ ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);
+ PlaneSlice = static_cast<V>(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<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
+ const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(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<void**>(&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<void**>(&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<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
+ if (MemToAlloc > SIZE_MAX)
+ {
+ return 0;
+ }
+ void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
+ if (pMem == NULL)
+ {
+ return 0;
+ }
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
+ UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
+ UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
+
+ D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
+ ID3D12Device* pDevice;
+ pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&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 <UINT MaxSubresources>
+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<void**>(&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<ID3D12CommandList * const *>(pp);
+}
+
+//
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_RESOURCE_DIMENSION& val )
+{
+ switch( val )
+ {
+ case D3D12_RESOURCE_DIMENSION_UNKNOWN: return "D3D12_RESOURCE_DIMENSION_UNKNOWN";
+ case D3D12_RESOURCE_DIMENSION_BUFFER: return "D3D12_RESOURCE_DIMENSION_BUFFER";
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D: return "D3D12_RESOURCE_DIMENSION_TEXTURE1D";
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D: return "D3D12_RESOURCE_DIMENSION_TEXTURE2D";
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D: return "D3D12_RESOURCE_DIMENSION_TEXTURE3D";
+ case D3D12_RESOURCE_DIMENSION_MAX_VALID: return "D3D12_RESOURCE_DIMENSION_MAX_VALID";
+ default: return "Unrecognized";
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_TEXTURE_LAYOUT& val )
+{
+ switch( val )
+ {
+ case D3D12_TEXTURE_LAYOUT_UNKNOWN: return "D3D12_TEXTURE_LAYOUT_UNKNOWN";
+ case D3D12_TEXTURE_LAYOUT_ROW_MAJOR: return "D3D12_TEXTURE_LAYOUT_ROW_MAJOR";
+ case D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE: return "D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE";
+ case D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE: return "D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE";
+ default: return "Unrecognized";
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_RESOURCE_HEAP_TIER& val )
+{
+ switch( val )
+ {
+ case D3D12_RESOURCE_HEAP_TIER_1: return "D3D12_RESOURCE_HEAP_TIER_1";
+ case D3D12_RESOURCE_HEAP_TIER_2: return "D3D12_RESOURCE_HEAP_TIER_2";
+ default: return "Unrecognized";
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_HEAP_TYPE& val )
+{
+ switch( val )
+ {
+ case D3D12_HEAP_TYPE_UNKNOWN: return "D3D12_HEAP_TYPE_UNKNOWN";
+ case D3D12_HEAP_TYPE_DEFAULT: return "D3D12_HEAP_TYPE_DEFAULT";
+ case D3D12_HEAP_TYPE_UPLOAD: return "D3D12_HEAP_TYPE_UPLOAD";
+ case D3D12_HEAP_TYPE_READBACK: return "D3D12_HEAP_TYPE_READBACK";
+ case D3D12_HEAP_TYPE_CUSTOM: return "D3D12_HEAP_TYPE_CUSTOM";
+ case D3D12_HEAP_TYPE_MAX_VALID: return "D3D12_HEAP_TYPE_MAX_VALID";
+ default: return "Unrecognized";
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_CPU_PAGE_PROPERTY& val )
+{
+ switch( val )
+ {
+ case D3D12_CPU_PAGE_PROPERTY_UNKNOWN: return "D3D12_CPU_PAGE_PROPERTY_UNKNOWN";
+ case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE: return "D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE";
+ case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE: return "D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE";
+ case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK: return "D3D12_CPU_PAGE_PROPERTY_WRITE_BACK";
+ case D3D12_CPU_PAGE_PROPERTY_MAX_VALID: return "D3D12_CPU_PAGE_PROPERTY_MAX_VALID";
+ default: return "Unrecognized";
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+inline const char* D3D12ToStr( const D3D12_MEMORY_POOL& val )
+{
+ switch( val )
+ {
+ case D3D12_MEMORY_POOL_UNKNOWN: return "D3D12_MEMORY_POOL_UNKNOWN";
+ case D3D12_MEMORY_POOL_L0: return "D3D12_MEMORY_POOL_L0";
+ case D3D12_MEMORY_POOL_L1: return "D3D12_MEMORY_POOL_L1";
+ case D3D12_MEMORY_POOL_MAX_VALID: return "D3D12_MEMORY_POOL_MAX_VALID";
+ default: return "Unrecognized";
+ }
+}
+//
+
+#endif // defined( __cplusplus )
+
+#endif //__D3DX12_H__
+
+
+