From 406fce6f984470c9928378ec675a2d14a771b78d Mon Sep 17 00:00:00 2001 From: Christopher Wallis Date: Fri, 17 Feb 2017 22:49:17 -0800 Subject: [PATCH 1/4] First Iteration of adding D3D12 backend to OpenSubdiv Adds basic d3d12 support for OpenSubdiv. This includes: * D3D12 port of the D3D11 backend osd code * Pooled allocation of command lists and command allocators * Deferred deletion of resources based on fence tracking * Shaders modified to use structured buffers if USE_STRUCTURED_BUFFERS macro is true. This allows the d3d12 implementation to use root views * CMake files modified to grab the Win10 SDK Adding missing FindDX12SDK.cmake Using descriptor tables instead of root views, fixing synchronization bug Adding D3D12VertexBuffer files that were dropped in last commit Removing defaulting of the d3d12/dxgi debug layer and CMake fixes Adding 11on12 to interop with 12 OSD implementation Enabling DXViewer to switch between using DX11 and DX11on12 Additionally fixing DX11 implementation device leaks and removing unnecessary dx12 files Fixing several refcount leaks that were causing issues when transitioning in and out of d3d12 Fixing a missed rebase conflict Cleaning up debug code and other dxviewer cleanup Reverting garbage that came with my last commit First Iteration of adding D3D12 backend to OpenSubdiv Cleaning up hlsl First Iteration of adding D3D12 backend to OpenSubdiv Fixing DXViewer to compile with NODX12 flag First Iteration of adding D3D12 backend to OpenSubdiv --- CMakeLists.txt | 28 +- cmake/FindDX12SDK.cmake | 60 + cmake/FindDXSDK.cmake | 2 +- examples/common/d3d11ControlMeshDisplay.cpp | 4 + examples/common/d3d11Hud.cpp | 45 +- examples/common/d3d11Hud.h | 1 + examples/dxViewer/dxviewer.cpp | 443 +++- opensubdiv/CMakeLists.txt | 7 +- opensubdiv/osd/CMakeLists.txt | 33 +- opensubdiv/osd/cpuD3D11VertexBuffer.cpp | 8 +- opensubdiv/osd/d3d11ComputeEvaluator.cpp | 4 + .../osd/d3d11LegacyGregoryPatchTable.cpp | 3 + opensubdiv/osd/d3d11PatchTable.cpp | 1 + opensubdiv/osd/d3d11VertexBuffer.cpp | 2 + opensubdiv/osd/d3d12CommandQueueContext.cpp | 166 ++ opensubdiv/osd/d3d12CommandQueueContext.h | 134 ++ opensubdiv/osd/d3d12ComputeEvaluator.cpp | 316 +++ opensubdiv/osd/d3d12ComputeEvaluator.h | 268 +++ .../osd/d3d12DeferredDeletionUniquePtr.h | 95 + opensubdiv/osd/d3d12DescriptorHeapManager.cpp | 105 + opensubdiv/osd/d3d12DescriptorHeapManager.h | 77 + opensubdiv/osd/d3d12FenceTrackedObjectQueue.h | 112 + opensubdiv/osd/d3d12PoolAllocator.h | 102 + opensubdiv/osd/d3d12Util.h | 205 ++ opensubdiv/osd/d3d12VertexBuffer.cpp | 156 ++ opensubdiv/osd/d3d12VertexBuffer.h | 106 + opensubdiv/osd/d3dx12.h | 2039 +++++++++++++++++ opensubdiv/osd/hlslComputeKernel.hlsl | 23 +- 28 files changed, 4436 insertions(+), 109 deletions(-) create mode 100644 cmake/FindDX12SDK.cmake create mode 100644 opensubdiv/osd/d3d12CommandQueueContext.cpp create mode 100644 opensubdiv/osd/d3d12CommandQueueContext.h create mode 100644 opensubdiv/osd/d3d12ComputeEvaluator.cpp create mode 100644 opensubdiv/osd/d3d12ComputeEvaluator.h create mode 100644 opensubdiv/osd/d3d12DeferredDeletionUniquePtr.h create mode 100644 opensubdiv/osd/d3d12DescriptorHeapManager.cpp create mode 100644 opensubdiv/osd/d3d12DescriptorHeapManager.h create mode 100644 opensubdiv/osd/d3d12FenceTrackedObjectQueue.h create mode 100644 opensubdiv/osd/d3d12PoolAllocator.h create mode 100644 opensubdiv/osd/d3d12Util.h create mode 100644 opensubdiv/osd/d3d12VertexBuffer.cpp create mode 100644 opensubdiv/osd/d3d12VertexBuffer.h create mode 100644 opensubdiv/osd/d3dx12.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f3cd9d40c..e1375ed75c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,7 +303,8 @@ option(NO_OPENCL "Disable OpenCL backend" OFF) option(NO_CLEW "Disable CLEW wrapper library" OFF) option(NO_OPENGL "Disable OpenGL support") option(NO_METAL "Disable Metal support" OFF) -option(NO_DX "Disable DirectX support") +option(NO_DX11 "Disable DirectX 11 support") +option(NO_DX12 "Disable DirectX 12 support") option(NO_TESTS "Disable all tests") option(NO_GLTESTS "Disable GL tests") @@ -356,7 +357,18 @@ if (OPENGL_FOUND AND NOT IOS) endif() endif() -if (WIN32 AND NOT NO_DX) +if (WIN32 AND NOT NO_DX12) + find_package(DX12SDK) + if(DX12SDK_FOUND) + # The DX12 SDK (Win 10 SDK) is a super-set of the DXSDK + set(DXSDK_FOUND TRUE) + + set(DXSDK_INCLUDE_DIR $(D3D12_INCLUDE_DIRS)) + set(DXSDK_LIBRARIES $(D3D12_LIBRARIES)) + endif() +endif() + +if (WIN32 AND NOT NO_DX11 AND NOT DXSDK_FOUND) find_package(DXSDK) endif() @@ -476,7 +488,7 @@ if(OPENCL_FOUND) endif() endif() - if (DXSDK_FOUND AND NOT NO_DX) + if (DXSDK_FOUND AND NOT NO_DX11) if (OPENCL_CL_D3D11_H_FOUND) set(OPENCL_D3D11_INTEROP_FOUND "YES") add_definitions( @@ -566,13 +578,19 @@ if (WIN32) -DGLEW_STATIC ) endif() + + if(DX12SDK_FOUND AND NOT NO_DX12) + add_definitions( + -DOPENSUBDIV_HAS_DX12 + ) + endif() - if (DXSDK_FOUND AND NOT NO_DX) + if (DXSDK_FOUND AND NOT NO_DX11) add_definitions( -DOPENSUBDIV_HAS_DX11SDK ) set(OSD_GPU TRUE) - elseif(NOT NO_DX) + elseif(NOT NO_DX11) message(WARNING "DirectX11 SDK was not found. " "If you do have DXSDK installed and see this message, " diff --git a/cmake/FindDX12SDK.cmake b/cmake/FindDX12SDK.cmake new file mode 100644 index 0000000000..fbdceed104 --- /dev/null +++ b/cmake/FindDX12SDK.cmake @@ -0,0 +1,60 @@ +# Find the win10 SDK path. +get_filename_component(WIN10_SDK_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;InstallationFolder]" ABSOLUTE CACHE) +get_filename_component(TEMP_WIN10_SDK_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;ProductVersion]" ABSOLUTE CACHE) + +get_filename_component(WIN10_SDK_VERSION ${TEMP_WIN10_SDK_VERSION} NAME) + +# WIN10_SDK_PATH will be something like C:\Program Files (x86)\Windows Kits\10 + +# WIN10_SDK_VERSION will be something like 10.0.14393 or 10.0.14393.0; we need the +# one that matches the directory name. +if (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0") + set(WIN10_SDK_VERSION "${WIN10_SDK_VERSION}.0") +endif (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0") + + +# Find the d3d12 and dxgi include path, it will typically look something like this. +# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\um\d3d12.h +# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\shared\dxgi1_4.h +find_path(D3D12_INCLUDE_DIR # Set variable D3D12_INCLUDE_DIR + d3d12.h # Find a path with d3d12.h + HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/um" + DOC "path to WIN10 SDK header files" + HINTS + ) + +find_path(DXGI_INCLUDE_DIR # Set variable DXGI_INCLUDE_DIR + dxgi1_4.h # Find a path with dxgi1_4.h + HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/shared" + DOC "path to WIN10 SDK header files" + HINTS + ) + +foreach(DX_LIB d3d12 d3d11 d3dcompiler dxgi) + if (CMAKE_GENERATOR MATCHES "Visual Studio.*Win64" ) + find_library(D3D12_${DX_LIB}_LIBRARY NAMES ${DX_LIB}.lib + HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x64 ) + elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM" ) + find_library(D3D12_${DX_LIB}_LIBRARY NAMES ${DX_LIB}.lib + HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm ) + elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM64" ) + find_library(D3D12_${DX_LIB}_LIBRARY NAMES ${DX_LIB}.lib + HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm64 ) + else (CMAKE_GENERATOR MATCHES "Visual Studio.*Win32" ) + find_library(D3D12_${DX_LIB}_LIBRARY NAMES ${DX_LIB}.lib + HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x86 ) + endif (CMAKE_GENERATOR MATCHES "Visual Studio.*Win64" ) + + list(APPEND D3D12_LIBRARIES ${D3D12_${DX_LIB}_LIBRARY}) +endforeach(DX_LIB) + +set(D3D12_INCLUDE_DIRS ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR}) + + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set DX12SDK_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(DX12SDK DEFAULT_MSG + D3D12_INCLUDE_DIRS D3D12_LIBRARIES) + +mark_as_advanced(D3D12_INCLUDE_DIRS D3D12_LIBRARIES) \ No newline at end of file diff --git a/cmake/FindDXSDK.cmake b/cmake/FindDXSDK.cmake index 113ea6d45e..060bfca1a7 100644 --- a/cmake/FindDXSDK.cmake +++ b/cmake/FindDXSDK.cmake @@ -67,7 +67,7 @@ if (WIN32) set(DXSDK_LIBRARY_DIR ${LIBRARY_DIR}) - foreach(DX_LIB d3d11 d3dcompiler) + foreach(DX_LIB d3d11 d3dcompiler dxgi) find_library(DXSDK_${DX_LIB}_LIBRARY NAMES diff --git a/examples/common/d3d11ControlMeshDisplay.cpp b/examples/common/d3d11ControlMeshDisplay.cpp index 1b28ad075b..2fe2481a3c 100644 --- a/examples/common/d3d11ControlMeshDisplay.cpp +++ b/examples/common/d3d11ControlMeshDisplay.cpp @@ -141,6 +141,8 @@ D3D11ControlMeshDisplay::createProgram() { device->CreateBuffer(&cbDesc, NULL, &_constantBuffer); assert(_constantBuffer); + + SAFE_RELEASE(device); return true; } @@ -264,5 +266,7 @@ D3D11ControlMeshDisplay::SetTopology( srvDesc.Buffer.NumElements = _numEdges; hr = device->CreateShaderResourceView(_edgeSharpness, &srvDesc, &_edgeSharpnessSRV); assert(_edgeSharpnessSRV); + + SAFE_RELEASE(device); } diff --git a/examples/common/d3d11Hud.cpp b/examples/common/d3d11Hud.cpp index 64b648e68d..57e8a09c49 100644 --- a/examples/common/d3d11Hud.cpp +++ b/examples/common/d3d11Hud.cpp @@ -68,7 +68,7 @@ D3D11hud::D3D11hud(ID3D11DeviceContext *deviceContext) : _deviceContext(deviceContext), _vbo(0), _staticVbo(0), _fontTexture(0), _inputLayout(0), _shaderResourceView(0), _samplerState(0), _vertexShader(0), - _pixelShader(0), _rasterizerState(0) + _pixelShader(0), _rasterizerState(0), _vboBufferSize(0) { } @@ -83,6 +83,7 @@ D3D11hud::~D3D11hud() SAFE_RELEASE(_vertexShader); SAFE_RELEASE(_pixelShader); SAFE_RELEASE(_rasterizerState); + SAFE_RELEASE(_constantBuffer); } void @@ -187,6 +188,8 @@ D3D11hud::Init(int width, int height, int frameBufferWidth, int frameBufferHeigh device->CreateBuffer(&cbDesc, NULL, &_constantBuffer); assert(_constantBuffer); + + SAFE_RELEASE(device); } void @@ -216,6 +219,8 @@ D3D11hud::Rebuild(int width, int height, int framebufferWidth, int framebufferHe HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_staticVbo); assert(_staticVbo); _staticVboCount = size / 7; + + SAFE_RELEASE(device); } } @@ -226,25 +231,33 @@ D3D11hud::Flush() return false; // update dynamic text - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = (int)getVboSource().size() * sizeof(float); - bufferDesc.Usage = D3D11_USAGE_DEFAULT; - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = 0; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 4*sizeof(float); + static int vboSourceSizeInBytes = (int)(getVboSource().size() * sizeof(float)); + if (_vbo == nullptr || _vboBufferSize < vboSourceSizeInBytes) + { + _vboBufferSize = vboSourceSizeInBytes; - D3D11_SUBRESOURCE_DATA subData; - subData.pSysMem = &getVboSource()[0]; - subData.SysMemPitch = 0; - subData.SysMemSlicePitch = 0; + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = vboSourceSizeInBytes; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 4 * sizeof(float); - SAFE_RELEASE(_vbo); + SAFE_RELEASE(_vbo); - ID3D11Device *device = NULL; - _deviceContext->GetDevice(&device); - HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_vbo); + ID3D11Device *device = NULL; + _deviceContext->GetDevice(&device); + HRESULT hr = device->CreateBuffer(&bufferDesc, nullptr, &_vbo); + + SAFE_RELEASE(device); + } assert(_vbo); + D3D11_MAPPED_SUBRESOURCE MappedVBO; + _deviceContext->Map(_vbo, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedVBO); + memcpy(MappedVBO.pData, &getVboSource()[0], getVboSource().size() * sizeof(float)); + _deviceContext->Unmap(_vbo, 0); + int numVertices = (int)getVboSource().size()/7; /* (x, y, r, g, b, u, v) = 7*/ // reserved space of the vector remains for the next frame. diff --git a/examples/common/d3d11Hud.h b/examples/common/d3d11Hud.h index 694b39e1b4..79c3d05f6d 100644 --- a/examples/common/d3d11Hud.h +++ b/examples/common/d3d11Hud.h @@ -62,6 +62,7 @@ class D3D11hud : public Hud ID3D11RasterizerState *_rasterizerState; ID3D11Buffer* _constantBuffer; int _staticVboCount; + int _vboBufferSize; }; #endif // OPENSUBDIV_EXAMPLES_D3D11_HUD_H diff --git a/examples/dxViewer/dxviewer.cpp b/examples/dxViewer/dxviewer.cpp index 4ba0702043..f2d162e73d 100644 --- a/examples/dxViewer/dxviewer.cpp +++ b/examples/dxViewer/dxviewer.cpp @@ -23,6 +23,11 @@ // #include +#include + +bool g_bUse11on12 = false; +HWND g_hwnd = 0; + #include #include @@ -60,6 +65,35 @@ OpenSubdiv::Osd::D3D11MeshInterface *g_mesh = NULL; OpenSubdiv::Osd::D3D11LegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; +#ifdef OPENSUBDIV_HAS_DX12 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +struct D3D12CommandQueueContextDeleter { + void operator()(OpenSubdiv::Osd::D3D12CommandQueueContext *D3D12CommandQueueContext) { + OpenSubdiv::Osd::FreeD3D12CommandQueueContext(D3D12CommandQueueContext); + } +}; + +typedef std::unique_ptr D3D12CommandQueueContextUniquePtr; +D3D12CommandQueueContextUniquePtr g_D3D12CommandQueueContext; + +OpenSubdiv::Osd::EvaluatorCacheT *g_d3d12ComputeEvaluatorCache; + +ID3D12Device * g_pd3d12Device = NULL; +ID3D12CommandQueue * g_pd3dcommandQueue = NULL; +ID3D11On12Device * g_pd3d11on12Device = NULL; +#endif + #include "../../regression/common/far_utils.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" @@ -89,7 +123,8 @@ enum KernelType { kCPU = 0, kTBB = 2, kCUDA = 3, kCL = 4, - kDirectCompute = 5 }; + kDirectCompute = 5, + kDirect3D12 = 6, }; enum DisplayStyle { kDisplayStyleWire = 0, kDisplayStyleShaded, @@ -148,6 +183,8 @@ float g_rotate[2] = {0, 0}, int g_width = 1024, g_height = 1024; +bool g_isSwapchainInitialized = false; + D3D11hud *g_hud = NULL; D3D11ControlMeshDisplay *g_controlMeshDisplay = NULL; float g_modelViewProjectionMatrix[16]; @@ -171,8 +208,13 @@ float g_moveScale = 0.0f; ID3D11Device * g_pd3dDevice = NULL; ID3D11DeviceContext * g_pd3dDeviceContext = NULL; -IDXGISwapChain * g_pSwapChain = NULL; -ID3D11RenderTargetView * g_pSwapChainRTV = NULL; +IDXGISwapChain1 * g_pSwapChain = NULL; + +UINT g_currentBackBufferIndex = 0; +const UINT g_backBufferCount = 2; +const DXGI_FORMAT g_backBufferFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; +ID3D11RenderTargetView * g_pSwapChainRTVs[g_backBufferCount] = {}; +ID3D11Resource *g_pWrappedBackbufferResources[g_backBufferCount] = {}; ID3D11RasterizerState* g_pRasterizerState = NULL; ID3D11InputLayout* g_pInputLayout = NULL; @@ -193,7 +235,6 @@ bool g_bDone; //------------------------------------------------------------------------------ static void updateGeom() { - int nverts = (int)g_orgPositions.size() / 3; std::vector vertex; @@ -257,13 +298,23 @@ getKernelName(int kernel) { return "OpenCL"; else if (kernel == kDirectCompute) return "DirectCompute"; + else if (kernel == kDirect3D12) + return "Direct3D12"; return "Unknown"; } +static bool needs11on12ForDX11Interop(int kernel) +{ + return kernel == kDirect3D12; +} + +static bool initD3D11(HWND hWnd); +static void initHUD(); +static void deleteAllObjects(); + //------------------------------------------------------------------------------ static void createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=kCatmark) { - using namespace OpenSubdiv; typedef Far::ConstIndexArray IndexArray; @@ -383,6 +434,26 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= level, bits, &d3d11ComputeEvaluatorCache, g_pd3dDeviceContext); +#ifdef OPENSUBDIV_HAS_DX12 + } + else if (g_kernel == kDirect3D12) { + if (!g_d3d12ComputeEvaluatorCache) + { + g_d3d12ComputeEvaluatorCache = new Osd::EvaluatorCacheT; + } + + g_mesh = new Osd::Mesh( + refiner, + numVertexElements, + numVaryingElements, + level, bits, + g_d3d12ComputeEvaluatorCache, + g_D3D12CommandQueueContext.get()); +#endif } else { printf("Unsupported kernel %s\n", getKernelName(kernel)); } @@ -814,7 +885,7 @@ static void display() { float color[4] = {0.006f, 0.006f, 0.006f, 1.0f}; - g_pd3dDeviceContext->ClearRenderTargetView(g_pSwapChainRTV, color); + g_pd3dDeviceContext->ClearRenderTargetView(g_pSwapChainRTVs[g_currentBackBufferIndex], color); // Clear the depth buffer. g_pd3dDeviceContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); @@ -937,7 +1008,17 @@ display() { g_hud->Flush(); } - g_pSwapChain->Present(0, 0); +#ifdef OPENSUBDIV_HAS_DX12 + if (g_bUse11on12) + { + g_pd3d11on12Device->ReleaseWrappedResources(&g_pWrappedBackbufferResources[g_currentBackBufferIndex], 1); + g_pd3dDeviceContext->Flush(); + } +#endif + + static const DXGI_PRESENT_PARAMETERS params = {}; + g_pSwapChain->Present1(0, 0, ¶ms); + g_currentBackBufferIndex = (g_currentBackBufferIndex + 1) % g_backBufferCount; } //------------------------------------------------------------------------------ @@ -976,20 +1057,51 @@ mouse(int button, int state, int x, int y) { } } -//----------------------------------------------------------------------------- -static void -quit() { +static void Syncronize() +{ + g_pd3dDeviceContext->Flush(); + { + IDXGIDevice2 *pDxgiDevice; + g_pd3dDevice->QueryInterface(&pDxgiDevice); - g_bDone = true; + HANDLE Event = CreateEvent(nullptr, FALSE, FALSE, nullptr); + pDxgiDevice->EnqueueSetEvent(Event); + WaitForSingleObject(Event, INFINITE), static_cast(WAIT_OBJECT_0); + CloseHandle(Event); + SAFE_RELEASE(pDxgiDevice); + } +} + +static void deleteAllObjects() +{ if (g_mesh) + { delete g_mesh; + g_mesh = nullptr; + } if (g_hud) + { delete g_hud; + g_hud = nullptr; + } if (g_controlMeshDisplay) + { delete g_controlMeshDisplay; + g_controlMeshDisplay = nullptr; + } + +#ifdef OPENSUBDIV_HAS_DX12 + if (g_d3d12ComputeEvaluatorCache) + { + delete g_d3d12ComputeEvaluatorCache; + g_d3d12ComputeEvaluatorCache = nullptr; + } +#endif + + g_shaderCache.Reset(); SAFE_RELEASE(g_pRasterizerState); SAFE_RELEASE(g_pInputLayout); @@ -999,12 +1111,38 @@ quit() { SAFE_RELEASE(g_pcbLighting); SAFE_RELEASE(g_pcbMaterial); SAFE_RELEASE(g_pDepthStencilView); + SAFE_RELEASE(g_pDepthStencilBuffer); + for (UINT i = 0; i < g_backBufferCount; i++) + { + SAFE_RELEASE(g_pSwapChainRTVs[i]); + SAFE_RELEASE(g_pWrappedBackbufferResources[i]); + } + g_currentBackBufferIndex = 0; + +#ifdef OPENSUBDIV_HAS_DX12 + g_D3D12CommandQueueContext.reset(nullptr); + SAFE_RELEASE(g_pd3d12Device); + SAFE_RELEASE(g_pd3dcommandQueue); + SAFE_RELEASE(g_pd3d11on12Device); +#endif + + Syncronize(); - SAFE_RELEASE(g_pSwapChainRTV); SAFE_RELEASE(g_pSwapChain); SAFE_RELEASE(g_pd3dDeviceContext); SAFE_RELEASE(g_pd3dDevice); + g_isSwapchainInitialized = false; +} + +//----------------------------------------------------------------------------- +static void +quit() { + + g_bDone = true; + + deleteAllObjects(); + PostQuitMessage(0); exit(0); } @@ -1064,6 +1202,16 @@ callbackKernel(int k) { } #endif + if(g_bUse11on12 != needs11on12ForDX11Interop(g_kernel)) + { + g_bUse11on12 = needs11on12ForDX11Interop(g_kernel); + + deleteAllObjects(); + + initD3D11(g_hwnd); + initHUD(); + } + rebuildOsdMesh(); } @@ -1166,22 +1314,26 @@ initHUD() { int compute_pulldown = g_hud->AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'K'); - g_hud->AddPullDownButton(compute_pulldown, "CPU", kCPU); + g_hud->AddPullDownButton(compute_pulldown, "CPU", kCPU, g_kernel == kCPU); #ifdef OPENSUBDIV_HAS_OPENMP - g_hud->AddPullDownButton(compute_pulldown, "OpenMP", kOPENMP); + g_hud->AddPullDownButton(compute_pulldown, "OpenMP", kOPENMP, g_kernel == kOPENMP); #endif #ifdef OPENSUBDIV_HAS_TBB - g_hud->AddPullDownButton(compute_pulldown, "TBB", kTBB); + g_hud->AddPullDownButton(compute_pulldown, "TBB", kTBB, g_kernel == kTBB); #endif #ifdef OPENSUBDIV_HAS_CUDA - g_hud->AddPullDownButton(compute_pulldown, "CUDA", kCUDA); + g_hud->AddPullDownButton(compute_pulldown, "CUDA", kCUDA, g_kernel == kCUDA); #endif #ifdef OPENSUBDIV_HAS_OPENCL_DX_INTEROP if (CLDeviceContext::HAS_CL_VERSION_1_1()) { - g_hud->AddPullDownButton(compute_pulldown, "OpenCL", kCL); + g_hud->AddPullDownButton(compute_pulldown, "OpenCL", kCL, g_kernel == kCL); } #endif - g_hud->AddPullDownButton(compute_pulldown, "HLSL Compute", kDirectCompute); +#ifdef OPENSUBDIV_HAS_DX12 + g_hud->AddPullDownButton(compute_pulldown, "Direct3D12", kDirect3D12, g_kernel == kDirect3D12); +#endif + + g_hud->AddPullDownButton(compute_pulldown, "HLSL Compute", kDirectCompute, g_kernel == kDirectCompute); int displaystyle_pulldown = g_hud->AddPullDown("DisplayStyle (W)", 200, 10, 250, callbackDisplayStyle, 'W'); @@ -1269,6 +1421,20 @@ initHUD() { callbackModel(g_currentShape); } +DXGI_FORMAT ConvertToNonSRGB(DXGI_FORMAT format) { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_UNORM; + default: + return format; + } +} + //------------------------------------------------------------------------------ static bool initD3D11(HWND hWnd) { @@ -1281,22 +1447,18 @@ initD3D11(HWND hWnd) { UINT numDriverTypes = ARRAYSIZE(driverTypes); - DXGI_SWAP_CHAIN_DESC hDXGISwapChainDesc; - hDXGISwapChainDesc.BufferDesc.Width = g_width; - hDXGISwapChainDesc.BufferDesc.Height = g_height; - hDXGISwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - hDXGISwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - hDXGISwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - hDXGISwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - hDXGISwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + DXGI_SWAP_CHAIN_DESC1 hDXGISwapChainDesc = {}; + hDXGISwapChainDesc.Width = g_width; + hDXGISwapChainDesc.Height = g_height; + hDXGISwapChainDesc.Format = ConvertToNonSRGB(g_backBufferFormat); + hDXGISwapChainDesc.Scaling = DXGI_SCALING_NONE; hDXGISwapChainDesc.SampleDesc.Count = 1; hDXGISwapChainDesc.SampleDesc.Quality = 0; hDXGISwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - hDXGISwapChainDesc.BufferCount = 1; - hDXGISwapChainDesc.OutputWindow = hWnd; - hDXGISwapChainDesc.Windowed = TRUE; - hDXGISwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - hDXGISwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + hDXGISwapChainDesc.BufferCount = g_backBufferCount; + hDXGISwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + hDXGISwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + hDXGISwapChainDesc.Flags = 0; // create device and swap chain HRESULT hr; @@ -1304,14 +1466,76 @@ initD3D11(HWND hWnd) { D3D_FEATURE_LEVEL hFeatureLevel = D3D_FEATURE_LEVEL_11_0; for(UINT driverTypeIndex=0; driverTypeIndex < numDriverTypes; driverTypeIndex++){ hDriverType = driverTypes[driverTypeIndex]; - hr = D3D11CreateDeviceAndSwapChain(NULL, - hDriverType, NULL, 0, NULL, 0, - D3D11_SDK_VERSION, &hDXGISwapChainDesc, - &g_pSwapChain, &g_pd3dDevice, - &hFeatureLevel, &g_pd3dDeviceContext); + +#ifdef OPENSUBDIV_HAS_DX12 + if (g_bUse11on12) + { + hr = D3D12CreateDevice(nullptr, hFeatureLevel, IID_PPV_ARGS(&g_pd3d12Device)); + if (FAILED(hr)) goto loopend; + + D3D12_COMMAND_QUEUE_DESC createQueueDesc; + createQueueDesc.NodeMask = 0; + createQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + createQueueDesc.Priority = 0; + createQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + hr = g_pd3d12Device->CreateCommandQueue(&createQueueDesc, IID_PPV_ARGS(&g_pd3dcommandQueue)); + if (FAILED(hr)) goto loopend; + + IUnknown *ppQueues[] = { g_pd3dcommandQueue }; + hr = D3D11On12CreateDevice(g_pd3d12Device, 0, &hFeatureLevel, 1, ppQueues, ARRAYSIZE(ppQueues), 0, &g_pd3dDevice, &g_pd3dDeviceContext, nullptr); + if (FAILED(hr)) goto loopend; + + hr = g_pd3dDevice->QueryInterface(IID_PPV_ARGS(&g_pd3d11on12Device)); + if (FAILED(hr)) goto loopend; + + g_D3D12CommandQueueContext = D3D12CommandQueueContextUniquePtr( + OpenSubdiv::Osd::CreateD3D12CommandQueueContext( + g_pd3dcommandQueue, + 0, + g_pd3dDeviceContext, + g_pd3d11on12Device)); + + } + else +#endif + { + hr = D3D11CreateDevice(nullptr, hDriverType, 0, 0, &hFeatureLevel, 1, D3D11_SDK_VERSION, &g_pd3dDevice, nullptr, &g_pd3dDeviceContext); + } + if (FAILED(hr)) goto loopend; + + + IDXGIFactory2 *pFactory; + hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&pFactory)); + if (FAILED(hr)) goto loopend; + + IUnknown *pDevice = g_pd3dDevice; +#ifdef OPENSUBDIV_HAS_DX12 + if (g_bUse11on12) + { + pDevice = g_pd3dcommandQueue; + } +#endif + + hr = pFactory->CreateSwapChainForHwnd( + pDevice, + hWnd, + &hDXGISwapChainDesc, + nullptr, + nullptr, + &g_pSwapChain); + if(SUCCEEDED(hr)){ + pFactory->Release(); break; } + + loopend: + SAFE_RELEASE(pFactory); +#ifdef OPENSUBDIV_HAS_DX12 + SAFE_RELEASE(g_pd3d12Device); + SAFE_RELEASE(g_pd3dcommandQueue); +#endif } if(FAILED(hr)){ @@ -1394,61 +1618,117 @@ updateRenderTarget(HWND hWnd) { UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; - if (g_pSwapChainRTV && (g_width == width) && (g_height == height)) { - return true; + if (!((g_width == width) && (g_height == height)) || !g_isSwapchainInitialized) { + g_isSwapchainInitialized = true; + g_width = width; + g_height = height; + + g_hud->Rebuild(g_width, g_height); + + Syncronize(); + for (UINT i = 0; i < g_backBufferCount; i++) + { + SAFE_RELEASE(g_pSwapChainRTVs[i]); + SAFE_RELEASE(g_pWrappedBackbufferResources[i]); + } + g_currentBackBufferIndex = 0; + + if (FAILED(g_pSwapChain->ResizeBuffers(0, g_width, g_height, DXGI_FORMAT_UNKNOWN, 0))) + { + MessageBoxW(hWnd, L"ResizeBuffers", L"Err", MB_ICONSTOP); + return false; + } + + // create depth buffer + D3D11_TEXTURE2D_DESC depthBufferDesc; + ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); + depthBufferDesc.Width = g_width; + depthBufferDesc.Height = g_height; + depthBufferDesc.MipLevels = 1; + depthBufferDesc.ArraySize = 1; + depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthBufferDesc.SampleDesc.Count = 1; + depthBufferDesc.SampleDesc.Quality = 0; + depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; + depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthBufferDesc.CPUAccessFlags = 0; + depthBufferDesc.MiscFlags = 0; + + if (FAILED(g_pd3dDevice->CreateTexture2D(&depthBufferDesc, NULL, &g_pDepthStencilBuffer))) + { + MessageBoxW(hWnd, L"CreateTexture2D", L"Err", MB_ICONSTOP); + return false; + } + assert(g_pDepthStencilBuffer); + + + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; + ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); + depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilViewDesc.Texture2D.MipSlice = 0; + + g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &depthStencilViewDesc, &g_pDepthStencilView); + assert(g_pDepthStencilView); } - g_width = width; - g_height = height; - g_hud->Rebuild(g_width, g_height); - SAFE_RELEASE(g_pSwapChainRTV); + if (g_pSwapChainRTVs[g_currentBackBufferIndex] == nullptr) { + ID3D11Resource* hpBackBuffer = NULL; +#ifdef OPENSUBDIV_HAS_DX12 + if (g_bUse11on12) + { + ID3D12Resource* hpBackBuffer12 = NULL; + if (FAILED(g_pSwapChain->GetBuffer(g_currentBackBufferIndex, __uuidof(ID3D12Resource), (void**)&hpBackBuffer12))) { + MessageBoxW(hWnd, L"SwpChain GetBuffer", L"Err", MB_ICONSTOP); + return false; + } - g_pSwapChain->ResizeBuffers(0, g_width, g_height, DXGI_FORMAT_UNKNOWN, 0); + D3D11_RESOURCE_FLAGS d3d11Flags; + d3d11Flags.BindFlags = D3D11_BIND_RENDER_TARGET; + d3d11Flags.CPUAccessFlags = 0; + d3d11Flags.StructureByteStride = 0; + d3d11Flags.MiscFlags = 0; + if (FAILED(g_pd3d11on12Device->CreateWrappedResource(hpBackBuffer12, &d3d11Flags, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&g_pWrappedBackbufferResources[g_currentBackBufferIndex])))) + { + MessageBoxW(hWnd, L"CreateWrappedResource", L"Err", MB_ICONSTOP); + return false; + } + SAFE_RELEASE(hpBackBuffer12); - // get backbuffer of swap chain - ID3D11Texture2D* hpBackBuffer = NULL; - if(FAILED(g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&hpBackBuffer))){ - MessageBoxW(hWnd, L"SwpChain GetBuffer", L"Err", MB_ICONSTOP); - return false; + hpBackBuffer = g_pWrappedBackbufferResources[g_currentBackBufferIndex]; + hpBackBuffer->AddRef(); + } + else +#endif + { + if (FAILED(g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Resource), (void**)&hpBackBuffer))) { + MessageBoxW(hWnd, L"SwpChain GetBuffer", L"Err", MB_ICONSTOP); + return false; + } + } + + // create render target from the back buffer + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Format = g_backBufferFormat; + if (FAILED(g_pd3dDevice->CreateRenderTargetView(hpBackBuffer, &rtvDesc, &g_pSwapChainRTVs[g_currentBackBufferIndex]))) { + MessageBoxW(hWnd, L"CreateRenderTargetView", L"Err", MB_ICONSTOP); + return false; + } + + SAFE_RELEASE(hpBackBuffer); } - // create render target from the back buffer - if(FAILED(g_pd3dDevice->CreateRenderTargetView(hpBackBuffer, NULL, &g_pSwapChainRTV))){ - MessageBoxW(hWnd, L"CreateRenderTargetView", L"Err", MB_ICONSTOP); - return false; +#ifdef OPENSUBDIV_HAS_DX12 + if (g_bUse11on12) + { + g_pd3d11on12Device->AcquireWrappedResources(&g_pWrappedBackbufferResources[g_currentBackBufferIndex], 1); } - SAFE_RELEASE(hpBackBuffer); - - // create depth buffer - D3D11_TEXTURE2D_DESC depthBufferDesc; - ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); - depthBufferDesc.Width = g_width; - depthBufferDesc.Height = g_height; - depthBufferDesc.MipLevels = 1; - depthBufferDesc.ArraySize = 1; - depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - depthBufferDesc.SampleDesc.Count = 1; - depthBufferDesc.SampleDesc.Quality = 0; - depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; - depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - depthBufferDesc.CPUAccessFlags = 0; - depthBufferDesc.MiscFlags = 0; - - g_pd3dDevice->CreateTexture2D(&depthBufferDesc, NULL, &g_pDepthStencilBuffer); - assert(g_pDepthStencilBuffer); - - D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; - ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); - depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - depthStencilViewDesc.Texture2D.MipSlice = 0; - - g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &depthStencilViewDesc, &g_pDepthStencilView); - assert(g_pDepthStencilView); +#endif // set device context to the render target - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_pSwapChainRTV, g_pDepthStencilView); + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_pSwapChainRTVs[g_currentBackBufferIndex], g_pDepthStencilView); // init viewport D3D11_VIEWPORT vp; @@ -1597,6 +1877,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmd OpenSubdiv::Far::SetErrorCallback(callbackError); initD3D11(hWnd); + g_hwnd = hWnd; initHUD(); diff --git a/opensubdiv/CMakeLists.txt b/opensubdiv/CMakeLists.txt index f4dd5b9242..ead45da42b 100644 --- a/opensubdiv/CMakeLists.txt +++ b/opensubdiv/CMakeLists.txt @@ -89,7 +89,12 @@ if (NOT NO_LIB) ) endif() - if( DXSDK_FOUND ) + if ( DX12SDK_FOUND ) + include_directories( "${D3D12_INCLUDE_DIRS}" ) + list(APPEND PLATFORM_GPU_LIBRARIES + ${D3D12_LIBRARIES} + ) + elseif( DXSDK_FOUND ) include_directories( "${DXSDK_INCLUDE_DIR}" ) list(APPEND PLATFORM_GPU_LIBRARIES ${DXSDK_LIBRARIES} diff --git a/opensubdiv/osd/CMakeLists.txt b/opensubdiv/osd/CMakeLists.txt index b849f19712..3fb7de745a 100755 --- a/opensubdiv/osd/CMakeLists.txt +++ b/opensubdiv/osd/CMakeLists.txt @@ -306,6 +306,37 @@ endif() list(APPEND DOXY_HEADER_FILES ${OPENCL_PUBLIC_HEADERS}) +#------------------------------------------------------------------------------- + +# D3D12 code & dependencies +set(D3D12_PUBLIC_HEADERS + d3d12commandqueuecontext.h + d3d12DeferredDeletionUniquePtr.h + d3d12DescriptorHeapManager.h + d3d12FenceTrackedObjectQueue.h + d3d12PoolAllocator.h + d3d12util.h + d3d12computeevaluator.h + d3d12VertexBuffer.h + d3dx12.h +) + +if ( DX12SDK_FOUND ) + list(APPEND GPU_SOURCE_FILES + d3d12commandqueuecontext.cpp + d3d12ComputeEvaluator.cpp + d3d12VertexBuffer.cpp + d3d12DescriptorHeapManager.cpp + ) + list(APPEND PUBLIC_HEADER_FILES ${D3D12_PUBLIC_HEADERS}) + list(APPEND PLATFORM_GPU_LIBRARIES + ${D3D12_LIBRARIES} + ) + include_directories( "${D3D12_INCLUDE_DIRS}" ) +endif() + +list(APPEND DOXY_HEADER_FILES ${D3D12_PUBLIC_HEADERS}) + #------------------------------------------------------------------------------- # CUDA code & dependencies set(CUDA_PUBLIC_HEADERS @@ -408,4 +439,4 @@ if (ANDROID) WORLD_READ ) endif() -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- \ No newline at end of file diff --git a/opensubdiv/osd/cpuD3D11VertexBuffer.cpp b/opensubdiv/osd/cpuD3D11VertexBuffer.cpp index 9fab02b725..27b43065ef 100644 --- a/opensubdiv/osd/cpuD3D11VertexBuffer.cpp +++ b/opensubdiv/osd/cpuD3D11VertexBuffer.cpp @@ -54,8 +54,14 @@ CpuD3D11VertexBuffer::Create(int numElements, int numVertices, new CpuD3D11VertexBuffer(numElements, numVertices); ID3D11Device *device; deviceContext->GetDevice(&device); - if (instance->allocate(device)) return instance; + if (instance->allocate(device)) + { + device->Release(); + return instance; + } delete instance; + + device->Release(); return NULL; } diff --git a/opensubdiv/osd/d3d11ComputeEvaluator.cpp b/opensubdiv/osd/d3d11ComputeEvaluator.cpp index d881ce1dfb..e4644e9780 100644 --- a/opensubdiv/osd/d3d11ComputeEvaluator.cpp +++ b/opensubdiv/osd/d3d11ComputeEvaluator.cpp @@ -140,6 +140,7 @@ D3D11StencilTable::D3D11StencilTable(Far::StencilTable const *stencilTable, _sizes = _offsets = _indices = _weights = NULL; _sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL; } + device->Release(); } D3D11StencilTable::~D3D11StencilTable() { @@ -298,6 +299,7 @@ D3D11ComputeEvaluator::Compile(BufferDescriptor const &srcDesc, cbDesc.ByteWidth = sizeof(KernelUniformArgs); device->CreateBuffer(&cbDesc, NULL, &_uniformArgs); + SAFE_RELEASE(device); return true; } @@ -323,6 +325,8 @@ D3D11ComputeEvaluator::Synchronize(ID3D11DeviceContext *deviceContext) { while (S_OK != deviceContext->GetData(query, NULL, 0, 0)); SAFE_RELEASE(query); + SAFE_RELEASE(device); + } bool diff --git a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp index 4f8a1a7d44..db6696bb4b 100644 --- a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp +++ b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp @@ -135,6 +135,7 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable, } } + pd3d11Device->Release(); return result; } @@ -154,6 +155,8 @@ D3D11LegacyGregoryPatchTable::UpdateVertexBuffer( srvd.Buffer.NumElements = numVertices * numVertexElements; HRESULT hr = pd3d11Device->CreateShaderResourceView(vbo, &srvd, &_vertexSRV); + + pd3d11Device->Release(); if (FAILED(hr)) { return; } diff --git a/opensubdiv/osd/d3d11PatchTable.cpp b/opensubdiv/osd/d3d11PatchTable.cpp index b92236615d..7a40eb86ad 100644 --- a/opensubdiv/osd/d3d11PatchTable.cpp +++ b/opensubdiv/osd/d3d11PatchTable.cpp @@ -133,6 +133,7 @@ D3D11PatchTable::allocate(Far::PatchTable const *farPatchTable, pd3d11DeviceContext->Unmap(_patchParamBuffer, 0); + pd3d11Device->Release(); return true; } diff --git a/opensubdiv/osd/d3d11VertexBuffer.cpp b/opensubdiv/osd/d3d11VertexBuffer.cpp index 8cb2125eba..973f427f83 100644 --- a/opensubdiv/osd/d3d11VertexBuffer.cpp +++ b/opensubdiv/osd/d3d11VertexBuffer.cpp @@ -57,6 +57,8 @@ D3D11VertexBuffer::Create(int numElements, int numVertices, deviceContext->GetDevice(&device); if (instance->allocate(device)) return instance; delete instance; + + device->Release(); return NULL; } diff --git a/opensubdiv/osd/d3d12CommandQueueContext.cpp b/opensubdiv/osd/d3d12CommandQueueContext.cpp new file mode 100644 index 0000000000..12aa2c3777 --- /dev/null +++ b/opensubdiv/osd/d3d12CommandQueueContext.cpp @@ -0,0 +1,166 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../osd/d3d12ComputeEvaluator.h" + +#include +#include +#include + +#include +#include "d3dx12.h" + +#include + + +#include "../far/error.h" +#include "../far/stencilTable.h" + +#include "d3d12util.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + +CommandListAllocatorPairAllocator::CommandListAllocatorPairAllocator(ID3D12Device *device, unsigned int nodeMask) : _device(device), _nodeMask(nodeMask) {} + +CommandListAllocatorPair CommandListAllocatorPairAllocator::Allocate() { + CommandListAllocatorPair pair; + ThrowFailure(_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pair._allocator))); + ThrowFailure(_device->CreateCommandList(_nodeMask, D3D12_COMMAND_LIST_TYPE_DIRECT, pair._allocator, nullptr, IID_PPV_ARGS(&pair._commandList))); + + return pair; +} + +void CommandListAllocatorPairAllocator::Free(CommandListAllocatorPair &allocation) { + allocation._allocator->Release(); + allocation._commandList->Release(); +} + +void CommandListAllocatorPairAllocator::Reset(CommandListAllocatorPair &allocation) { + allocation._allocator->Reset(); + allocation._commandList->Reset(allocation._allocator, nullptr); +} + +void D3D12DeferredDeletionQueue::Push(unsigned long long fenceValue, ID3D12Object *object) +{ + object->AddRef(); + FenceTrackedObjectQueue::Push(fenceValue, object); +} + +void D3D12DeferredDeletionQueue::DeleteObject(ID3D12Object **object) +{ + (*object)->Release(); +} + +D3D12CommandQueueContext::D3D12CommandQueueContext(ID3D12CommandQueue *commandQueue, ID3D12Device *device, unsigned int nodeMask, ID3D11DeviceContext *deviceContext, ID3D11On12Device *D3D11on12Device) : + _queue(commandQueue), + _device(device), + _D3D11Context(deviceContext), + _descriptorHeapManager(device, nodeMask), + _commandListAllocator(CommandListAllocatorPairAllocator(device, nodeMask)), + _D3D11on12Device(D3D11on12Device), + _nodeMask(nodeMask), + _fenceValue(0) +{ + ThrowFailure(_device->CreateFence(_fenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&_fence))); + _fenceValue++; + + _waitEvent = CreateEvent(nullptr, false, false, nullptr); +} + +D3D12CommandQueueContext::~D3D12CommandQueueContext() +{ + Syncronize(); + _commandListAllocator.DeleteUnusedObjects(_fence->GetCompletedValue()); + _deferredDeletionQueue.DeleteUnusedObjects(_fence->GetCompletedValue()); + + CloseHandle(_waitEvent); +} + +CommandListAllocatorPair D3D12CommandQueueContext::GetCommandListAllocatorPair() +{ + return _commandListAllocator.Allocate(_fence->GetCompletedValue()); +} + +void D3D12CommandQueueContext::ExecuteCommandList(ID3D12CommandList *CommandList) +{ + ID3D12CommandList *CommandLists[] = { CommandList }; + _queue->ExecuteCommandLists(ARRAYSIZE(CommandLists), CommandLists); + + SignalAndIncrementFence(); + + NotifyOnCommandListSubmission(); +} + +void D3D12CommandQueueContext::Syncronize() +{ + unsigned long long currentFence = _fenceValue; + SignalAndIncrementFence(); + + ThrowFailure(_fence->SetEventOnCompletion(currentFence, _waitEvent)); + WaitForSingleObject(_waitEvent, INFINITE); +} + +void D3D12CommandQueueContext::SignalAndIncrementFence() +{ + _queue->Signal(_fence, _fenceValue); + _fenceValue++; +} + + +void D3D12CommandQueueContext::ReleaseCommandListAllocatorPair(CommandListAllocatorPair &pair) +{ + _commandListAllocator.Release(_fenceValue, &pair); +} + +void D3D12CommandQueueContext::DeleteD3D12Object(ID3D12Object *Object) +{ + _deferredDeletionQueue.Push(_fenceValue, Object); +} + +void D3D12CommandQueueContext::NotifyOnCommandListSubmission() +{ + // Periodically check on the deletion queue to free up objects + _deferredDeletionQueue.DeleteUnusedObjects(_fence->GetCompletedValue()); +} + + +D3D12CommandQueueContext *CreateD3D12CommandQueueContext(ID3D12CommandQueue *commandQueue, unsigned int nodeMask, ID3D11DeviceContext *deviceContext, ID3D11On12Device *pD3D11on12Device) +{ + CComPtr device; + commandQueue->GetDevice(IID_PPV_ARGS(&device)); + return new D3D12CommandQueueContext(commandQueue, device, nodeMask, deviceContext, pD3D11on12Device); +} + +void FreeD3D12CommandQueueContext(D3D12CommandQueueContext *D3D12CommandQueueContext) +{ + delete D3D12CommandQueueContext; +} + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv diff --git a/opensubdiv/osd/d3d12CommandQueueContext.h b/opensubdiv/osd/d3d12CommandQueueContext.h new file mode 100644 index 0000000000..894a990c3c --- /dev/null +++ b/opensubdiv/osd/d3d12CommandQueueContext.h @@ -0,0 +1,134 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_COMMON_H +#define OPENSUBDIV3_OSD_D3D12_COMMON_H + +#include +#include +#include "d3d12FenceTrackedObjectQueue.h" +#include "d3d12PoolAllocator.h" +#include "d3d12DescriptorHeapManager.h" + +struct ID3D12CommandQueue; +struct ID3D12GraphicsCommandList; +struct ID3D12CommandAllocator; +struct ID3D12Object; +struct ID3D11On12Device; +struct ID3D11DeviceContext; +struct ID3D12Device; +struct ID3D12CommandList; +struct ID3D12Fence; + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + class D3D12DeferredDeletionQueue : public FenceTrackedObjectQueue + { + public: + void Push(unsigned long long fenceValue, ID3D12Object *object); + void DeleteObject(ID3D12Object **object); + }; + + class CommandListAllocatorPair + { + public: + ID3D12GraphicsCommandList *_commandList; + ID3D12CommandAllocator *_allocator; + }; + + class CommandListAllocatorPairAllocator : public IAllocator + { + public: + CommandListAllocatorPairAllocator(ID3D12Device *device, unsigned int nodeMask); + + CommandListAllocatorPair Allocate(); + + void Free(CommandListAllocatorPair &allocation); + void Reset(CommandListAllocatorPair &allocation); + private: + ID3D12Device *_device; + unsigned int _nodeMask; + }; + + class D3D12CommandQueueContext + { + public: + D3D12CommandQueueContext(ID3D12CommandQueue *commandQueue, ID3D12Device *device, unsigned int nodeMask, ID3D11DeviceContext *deviceContext, ID3D11On12Device *D3D11on12Device); + ~D3D12CommandQueueContext(); + + ID3D11On12Device* _D3D11on12Device; + ID3D11DeviceContext* _D3D11Context; + + unsigned int GetNodeMask() { return _nodeMask; } + + ID3D11On12Device *Get11on12Device() { return _D3D11on12Device; } + ID3D11DeviceContext *GetDeviceContext() { return _D3D11Context; } + + CommandListAllocatorPair GetCommandListAllocatorPair(); + + void ExecuteCommandList(ID3D12CommandList *CommandList); + + void Syncronize(); + + void ReleaseCommandListAllocatorPair(CommandListAllocatorPair &pair); + + ID3D12Device *GetDevice() const { + return _device; + } + + ID3D12CommandQueue *GetCommandQueue() const { + return _queue; + } + + D3D12DescriptorHeapManager &GetDescriptorHeapManager() { return _descriptorHeapManager; } + void DeleteD3D12Object(ID3D12Object *Object); + private: + void NotifyOnCommandListSubmission(); + void SignalAndIncrementFence(); + + D3D12DescriptorHeapManager _descriptorHeapManager; + D3D12DeferredDeletionQueue _deferredDeletionQueue; + D3D12PoolAllocator _commandListAllocator; + CComPtr _device; + CComPtr _queue; + CComPtr _fence; + + unsigned long long _fenceValue; + unsigned int _nodeMask; + HANDLE _waitEvent; + }; + + + D3D12CommandQueueContext *CreateD3D12CommandQueueContext(ID3D12CommandQueue *pCommandQueue, unsigned int nodeMask, ID3D11DeviceContext *deviceContext, ID3D11On12Device *d3d11on12Device); + void FreeD3D12CommandQueueContext(D3D12CommandQueueContext *D3D12CommandQueueContext); +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_COMMON_H diff --git a/opensubdiv/osd/d3d12ComputeEvaluator.cpp b/opensubdiv/osd/d3d12ComputeEvaluator.cpp new file mode 100644 index 0000000000..c34b58aa73 --- /dev/null +++ b/opensubdiv/osd/d3d12ComputeEvaluator.cpp @@ -0,0 +1,316 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../osd/d3d12ComputeEvaluator.h" + +#include +#include +#include + +#include +#include "d3dx12.h" + +#include + + +#include "../far/error.h" +#include "../far/stencilTable.h" + +#include "d3d12util.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + +static const char *shaderSource = +#include "../osd/hlslComputeKernel.gen.h" +; + +// ---------------------------------------------------------------------------- + +// must match constant buffer declaration in hlslComputeKernel.hlsl +__declspec(align(16)) + +struct KernelUniformArgs { + + int start; // batch + int end; + + int srcOffset; + int dstOffset; +}; + +D3D12StencilTable::D3D12StencilTable(Far::StencilTable const *stencilTable, + D3D12CommandQueueContext *D3D12CommandQueueContext) + { + ID3D12Device *pDevice = D3D12CommandQueueContext->GetDevice(); + + _numStencils = stencilTable->GetNumStencils(); + if (_numStencils > 0) { + std::vector const &sizes = stencilTable->GetSizes(); + + ScopedCommandListAllocatorPair pair(D3D12CommandQueueContext, D3D12CommandQueueContext->GetCommandListAllocatorPair()); + ID3D12GraphicsCommandList *pCommandList = pair._commandList; + + createBufferWithVectorInitialData(sizes, D3D12CommandQueueContext, pCommandList, _sizesBuffer); + createBufferWithVectorInitialData(stencilTable->GetOffsets(), D3D12CommandQueueContext, pCommandList, _offsetsBuffer); + createBufferWithVectorInitialData(stencilTable->GetControlIndices(), D3D12CommandQueueContext, pCommandList, _indicesBuffer); + createBufferWithVectorInitialData(stencilTable->GetWeights(), D3D12CommandQueueContext, pCommandList, _weightsBuffer); + + _sizes = AllocateSRV(D3D12CommandQueueContext, _sizesBuffer, DXGI_FORMAT_R32_SINT, stencilTable->GetSizes().size()); + _offsets = AllocateSRV(D3D12CommandQueueContext, _offsetsBuffer, DXGI_FORMAT_R32_SINT, stencilTable->GetOffsets().size()); + _indices = AllocateSRV(D3D12CommandQueueContext, _indicesBuffer, DXGI_FORMAT_R32_SINT, stencilTable->GetControlIndices().size()); + _weights = AllocateSRV(D3D12CommandQueueContext, _weightsBuffer, DXGI_FORMAT_R32_FLOAT, stencilTable->GetWeights().size()); + + ThrowFailure(pCommandList->Close()); + D3D12CommandQueueContext->ExecuteCommandList(pCommandList); + } +} + +D3D12StencilTable::~D3D12StencilTable() { +} + +// --------------------------------------------------------------------------- + + +D3D12ComputeEvaluator::D3D12ComputeEvaluator() : + _workGroupSize(64) { + memset(_descriptorTable, 0, sizeof(_descriptorTable)); +} + +D3D12ComputeEvaluator * +D3D12ComputeEvaluator::Create(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + return Create( + srcDesc, + dstDesc, + duDesc, + dvDesc, + BufferDescriptor(), + BufferDescriptor(), + BufferDescriptor(), + D3D12CommandQueueContext); +} + +D3D12ComputeEvaluator * +D3D12ComputeEvaluator::Create(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + + // TODO: implements derivatives + (void)duDesc; + (void)dvDesc; + + D3D12ComputeEvaluator *instance = new D3D12ComputeEvaluator(); + if (instance->Compile(srcDesc, dstDesc, D3D12CommandQueueContext)) return instance; + delete instance; + return NULL; +} + +D3D12ComputeEvaluator::~D3D12ComputeEvaluator() { +} + +bool +D3D12ComputeEvaluator::Compile(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + + if (srcDesc.length > dstDesc.length) { + Far::Error(Far::FAR_RUNTIME_ERROR, + "srcDesc length must be less than or equal to " + "dstDesc length.\n"); + return false; + } + + + ID3D12Device *device = D3D12CommandQueueContext->GetDevice(); + assert(device); + + { + D3D12_DESCRIPTOR_RANGE range[2]; + range[0] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 1); + range[1] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 2, 0); + + UINT parameterIndex = 0; + CD3DX12_ROOT_PARAMETER rootParameters[NumSlots]; + rootParameters[ViewSlot].InitAsDescriptorTable(ARRAYSIZE(range), range); + rootParameters[KernelUniformArgsRootConstantSlot].InitAsConstants(sizeof(KernelUniformArgs) / sizeof(UINT32), 0); + + D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = CD3DX12_ROOT_SIGNATURE_DESC( + ARRAYSIZE(rootParameters), + rootParameters); + + CComPtr rootSignatureBlob, errorBlob; + ThrowFailure(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob)); + + CComPtr rootSignatureComPtr; + ThrowFailure(device->CreateRootSignature(D3D12CommandQueueContext->GetNodeMask(), rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&rootSignatureComPtr))); + _rootSignature.AddRefAndAttach(D3D12CommandQueueContext, rootSignatureComPtr); + } + + DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_ALL_RESOURCES_BOUND | D3DCOMPILE_OPTIMIZATION_LEVEL3; +#if defined(D3D10_SHADER_RESOURCES_MAY_ALIAS) + dwShaderFlags |= D3D10_SHADER_RESOURCES_MAY_ALIAS; +#endif + +#ifdef _DEBUG + dwShaderFlags |= D3DCOMPILE_DEBUG; +#endif + + std::ostringstream ss; + ss << srcDesc.length; std::string lengthValue(ss.str()); ss.str(""); + ss << srcDesc.stride; std::string srcStrideValue(ss.str()); ss.str(""); + ss << dstDesc.stride; std::string dstStrideValue(ss.str()); ss.str(""); + ss << _workGroupSize; std::string workgroupSizeValue(ss.str()); ss.str(""); + + D3D_SHADER_MACRO defines[] = + { "LENGTH", lengthValue.c_str(), + "SRC_STRIDE", srcStrideValue.c_str(), + "DST_STRIDE", dstStrideValue.c_str(), + "WORK_GROUP_SIZE", workgroupSizeValue.c_str(), + 0, 0 }; + + LPCSTR shaderEntrypointName[] = { "cs_singleBuffer", "cs_separateBuffer" }; + for (UINT i = 0; i < NumberOfCSTypes; i++) + { + CComPtr shaderBlob; + CComPtr errorBuffer; + + HRESULT hr = D3DCompile(shaderSource, strlen(shaderSource), + NULL, &defines[0], NULL, + shaderEntrypointName[i], "cs_5_0", + dwShaderFlags, 0, + &shaderBlob, &errorBuffer); + + if (FAILED(hr)) { + if (errorBuffer != NULL) { + Far::Error(Far::FAR_RUNTIME_ERROR, + "Error compiling HLSL shader: %s\n", + (CHAR*)errorBuffer->GetBufferPointer()); + return false; + } + } + + D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {}; + desc.CS = CD3DX12_SHADER_BYTECODE(shaderBlob); + desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + desc.NodeMask = D3D12CommandQueueContext->GetNodeMask(); + desc.pRootSignature = _rootSignature; + + CComPtr computePSOComPtr; + ThrowFailure(device->CreateComputePipelineState(&desc, IID_PPV_ARGS(&computePSOComPtr))); + _computePSOs[i].AddRefAndAttach(D3D12CommandQueueContext, computePSOComPtr); + } + + return true; +} + +/* static */ +void +D3D12ComputeEvaluator::Synchronize(D3D12CommandQueueContext *D3D12CommandQueueContext) { + D3D12CommandQueueContext->Syncronize(); +} + +bool +D3D12ComputeEvaluator::EvalStencils(CPUDescriptorHandle srcUAV, + BufferDescriptor const &srcDesc, + CPUDescriptorHandle dstUAV, + BufferDescriptor const &dstDesc, + CPUDescriptorHandle sizesSRV, + CPUDescriptorHandle offsetsSRV, + CPUDescriptorHandle indicesSRV, + CPUDescriptorHandle weightsSRV, + int start, + int end, + D3D12CommandQueueContext *D3D12CommandQueueContext) const { + assert(D3D12CommandQueueContext); + + int count = end - start; + if (count <= 0) return true; + + KernelUniformArgs args; + args.start = start; + args.end = end; + args.srcOffset = srcDesc.offset; + args.dstOffset = dstDesc.offset; + + ScopedCommandListAllocatorPair pair(D3D12CommandQueueContext, D3D12CommandQueueContext->GetCommandListAllocatorPair()); + ID3D12GraphicsCommandList *pCommandList = pair._commandList; + pCommandList->SetComputeRootSignature(_rootSignature.Get()); + + // Bind constants + pCommandList->SetComputeRoot32BitConstants(KernelUniformArgsRootConstantSlot, sizeof(KernelUniformArgs) / sizeof(UINT32), &args, 0); + + ID3D12DescriptorHeap *descriptorHeaps[] = { D3D12CommandQueueContext->GetDescriptorHeapManager().GetDescriptorHeap() }; + pCommandList->SetDescriptorHeaps(ARRAYSIZE(descriptorHeaps), descriptorHeaps); + + // Bind SRVs + if (_descriptorTable[SizeSRVDescriptorOffset] != sizesSRV || + _descriptorTable[OffsetSRVDescriptorOffset] != offsetsSRV || + _descriptorTable[IndexSRVDescriptorOffset] != indicesSRV || + _descriptorTable[WeightSRVDescriptorOffset] != weightsSRV || + _descriptorTable[SourceUAVDescriptorOffset] != srcUAV || + _descriptorTable[DestinationUAVDescriptorOffset] != dstUAV) + { + _descriptorTable[SizeSRVDescriptorOffset] = sizesSRV; + _descriptorTable[OffsetSRVDescriptorOffset] = offsetsSRV; + _descriptorTable[IndexSRVDescriptorOffset] = indicesSRV; + _descriptorTable[WeightSRVDescriptorOffset] = weightsSRV; + _descriptorTable[SourceUAVDescriptorOffset] = srcUAV; + _descriptorTable[DestinationUAVDescriptorOffset] = dstUAV; + + _lastGpuDescriptorTable = D3D12CommandQueueContext->GetDescriptorHeapManager().UploadDescriptors(NumDescriptors, _descriptorTable); + } + + pCommandList->SetComputeRootDescriptorTable(ViewSlot, D3D12DescriptorHeapManager::ConvertToD3D12GPUHandle(_lastGpuDescriptorTable)); + + // Bind the source UAV + const bool bOnlyUsingSourceUAV = srcUAV == dstUAV; + if (bOnlyUsingSourceUAV) { + pCommandList->SetPipelineState(_computePSOs[SingleBufferCSIndex].Get()); + } else { + pCommandList->SetPipelineState(_computePSOs[SeparateBufferCSIndex].Get()); + } + + pCommandList->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1); + + ThrowFailure(pCommandList->Close()); + D3D12CommandQueueContext->ExecuteCommandList(pCommandList); + + return true; +} + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv diff --git a/opensubdiv/osd/d3d12ComputeEvaluator.h b/opensubdiv/osd/d3d12ComputeEvaluator.h new file mode 100644 index 0000000000..4361ac8185 --- /dev/null +++ b/opensubdiv/osd/d3d12ComputeEvaluator.h @@ -0,0 +1,268 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_COMPUTE_EVALUATOR_H +#define OPENSUBDIV3_OSD_D3D12_COMPUTE_EVALUATOR_H + +#include "../version.h" + +struct ID3D12CommandQueue; +struct ID3D12Resource; +struct ID3D12ComputeShader; +struct ID3D12PipelineState; +struct ID3D12RootSignature; +struct ID3D10Blob; +struct ID3D12CommandAllocator; +struct ID3D12Fence; +struct ID3D12DescriptorHeap; +struct D3D12_CPU_DESCRIPTOR_HANDLE; + +#include "../osd/bufferDescriptor.h" +#include "d3d12commandqueuecontext.h" +#include "d3d12DeferredDeletionUniquePtr.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { + class StencilTable; +} + +namespace Osd { + +/// \brief D3D11 stencil table +/// +/// This class is a D3D11 Shader Resource View representation of +/// Far::StencilTable. +/// +/// D3D12ComputeEvaluator consumes this table to apply stencils +/// +class D3D12StencilTable { +public: + template + static D3D12StencilTable *Create(Far::StencilTable const *stencilTable, + DEVICE_CONTEXT context) { + return new D3D12StencilTable(stencilTable, context->GetDeviceContext()); + } + + static D3D12StencilTable *Create(Far::StencilTable const *stencilTable, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + return new D3D12StencilTable(stencilTable, D3D12CommandQueueContext); + } + + D3D12StencilTable(Far::StencilTable const *stencilTable, + D3D12CommandQueueContext *D3D12CommandQueueContext); + + ~D3D12StencilTable(); + + // interfaces needed for D3D12ComputeEvaluator + CPUDescriptorHandle GetSizesSRV() const { return _sizes; } + CPUDescriptorHandle GetOffsetsSRV() const { return _offsets; } + CPUDescriptorHandle GetIndicesSRV() const { return _indices; } + CPUDescriptorHandle GetWeightsSRV() const { return _weights; } + + + int GetNumStencils() const { return _numStencils; } + +private: + DeferredDeletionUniquePtr _sizesBuffer; + DeferredDeletionUniquePtr _offsetsBuffer; + DeferredDeletionUniquePtr _indicesBuffer; + DeferredDeletionUniquePtr _weightsBuffer; + + CPUDescriptorHandle _sizes; + CPUDescriptorHandle _offsets; + CPUDescriptorHandle _indices; + CPUDescriptorHandle _weights; + + int _numStencils; +}; + +// --------------------------------------------------------------------------- + +class D3D12ComputeEvaluator { +public: + typedef bool Instantiatable; + static D3D12ComputeEvaluator * Create(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext); + + static D3D12ComputeEvaluator * Create(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext); + + /// Constructor. + D3D12ComputeEvaluator(); + + /// Destructor. + ~D3D12ComputeEvaluator(); + + /// \brief Generic static compute function. This function has a same + /// signature as other device kernels have so that it can be called + /// transparently from OsdMesh template interface. + /// + /// @param srcBuffer Input primvar buffer. + /// must have BindVBO() method returning a + /// const float pointer for read + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dstBuffer Output primvar buffer + /// must have BindVBO() method returning a + /// float pointer for write + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param stencilTable stencil table to be applied. The table must have + /// SSBO interfaces. + /// + /// @param instance cached compiled instance. Clients are supposed to + /// pre-compile an instance of this class and provide + /// to this function. If it's null the kernel still + /// compute by instantiating on-demand kernel although + /// it may cause a performance problem. + /// + /// @param deviceContext ID3D11DeviceContext. + /// + template + static bool EvalStencils( + SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc, + DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc, + STENCIL_TABLE const *stencilTable, + D3D12ComputeEvaluator const *instance, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + if (instance) { + return instance->EvalStencils(srcBuffer, srcDesc, + dstBuffer, dstDesc, + stencilTable, + D3D12CommandQueueContext); + } else { + // Create an instace on demand (slow) + instance = Create(srcDesc, dstDesc, + BufferDescriptor(), + BufferDescriptor(), + D3D12CommandQueueContext); + if (instance) { + bool r = instance->EvalStencils(srcBuffer, srcDesc, + dstBuffer, dstDesc, + stencilTable, + D3D12CommandQueueContext); + delete instance; + return r; + } + return false; + } + } + + /// Dispatch the DX compute kernel on GPU asynchronously. + /// returns false if the kernel hasn't been compiled yet. + template + bool EvalStencils( + SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc, + DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc, + STENCIL_TABLE const *stencilTable, + D3D12CommandQueueContext *D3D12CommandQueueContext) const { + return EvalStencils(srcBuffer->BindD3D12UAV(D3D12CommandQueueContext), srcDesc, + dstBuffer->BindD3D12UAV(D3D12CommandQueueContext), dstDesc, + stencilTable->GetSizesSRV(), + stencilTable->GetOffsetsSRV(), + stencilTable->GetIndicesSRV(), + stencilTable->GetWeightsSRV(), + /* start = */ 0, + /* end = */ stencilTable->GetNumStencils(), + D3D12CommandQueueContext); + } + + /// Dispatch the DX compute kernel on GPU asynchronously. + /// returns false if the kernel hasn't been compiled yet. + bool EvalStencils(CPUDescriptorHandle srcSRV, + BufferDescriptor const &srcDesc, + CPUDescriptorHandle dstUAV, + BufferDescriptor const &dstDesc, + CPUDescriptorHandle sizesSRV, + CPUDescriptorHandle offsetsSRV, + CPUDescriptorHandle indicesSRV, + CPUDescriptorHandle weightsSRV, + int start, + int end, + D3D12CommandQueueContext *D3D12CommandQueueContext) const; + + /// Configure DX kernel. Returns false if it fails to compile the kernel. + bool Compile(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + D3D12CommandQueueContext *D3D12CommandQueueContext); + + /// Wait the dispatched kernel finishes. + static void Synchronize(D3D12CommandQueueContext *D3D12CommandQueueContext); + +private: + enum + { + SingleBufferCSIndex = 0, + SeparateBufferCSIndex = 1, + NumberOfCSTypes + }; + + enum + { + ViewSlot = 0, + KernelUniformArgsRootConstantSlot, + NumSlots + }; + + enum + { + SizeSRVDescriptorOffset = 0, + OffsetSRVDescriptorOffset, + IndexSRVDescriptorOffset, + WeightSRVDescriptorOffset, + SourceUAVDescriptorOffset, + DestinationUAVDescriptorOffset, + NumDescriptors, + }; + + DeferredDeletionUniquePtr _rootSignature; + DeferredDeletionUniquePtr _computePSOs[NumberOfCSTypes]; + + mutable CPUDescriptorHandle _descriptorTable[NumDescriptors]; + mutable GPUDescriptorHandle _lastGpuDescriptorTable; + int _workGroupSize; +}; + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + + +#endif // OPENSUBDIV3_OSD_D3D12_COMPUTE_EVALUATOR_H diff --git a/opensubdiv/osd/d3d12DeferredDeletionUniquePtr.h b/opensubdiv/osd/d3d12DeferredDeletionUniquePtr.h new file mode 100644 index 0000000000..fe1f10f6a3 --- /dev/null +++ b/opensubdiv/osd/d3d12DeferredDeletionUniquePtr.h @@ -0,0 +1,95 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_DEFERRED_DELETION_UNIQUE_PTR_H +#define OPENSUBDIV3_OSD_D3D12_DEFERRED_DELETION_UNIQUE_PTR_H + +#include "../version.h" + +#include "../osd/nonCopyable.h" +#include "../osd/d3d12commandqueuecontext.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + + // Unlike D3D11, D3D12 requires applications to explicitly track when the GPU is finished + // with an ID3D12Object before destroying it. DeferredDeletionUniquePtr ensures that when the + // destructor is called, the D3D12Object will be passed along to a Deferred Deletion Queue + // that tracks when the GPU is done with the object + template + class DeferredDeletionUniquePtr : NonCopyable> + { + public: + DeferredDeletionUniquePtr() : + _D3D12CommandQueueContext(nullptr), + _object(nullptr) + {} + + DeferredDeletionUniquePtr(D3D12CommandQueueContext *D3D12CommandQueueContext, Object *object) + { + AddRefAndAttach(D3D12CommandQueueContext, object); + } + + void AddRefAndAttach(D3D12CommandQueueContext *D3D12CommandQueueContext, Object *object) + { + ReleaseObjectToDeletionQueueIfExists(); + + _D3D12CommandQueueContext = D3D12CommandQueueContext; + _object = object; + _object->AddRef(); + } + + ~DeferredDeletionUniquePtr() { + ReleaseObjectToDeletionQueueIfExists(); + } + Object *Get() const { return _object; } + operator Object*() { return _object; } + Object * const *operator&() const { return &_object; } + Object *operator->() { return _object; } + private: + void ReleaseObjectToDeletionQueueIfExists() + { + if (_object) + { + _D3D12CommandQueueContext->DeleteD3D12Object(_object); + + _object->Release(); + _object = nullptr; + } + } + + D3D12CommandQueueContext *_D3D12CommandQueueContext; + Object *_object; + }; + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_DEFERRED_DELETION_UNIQUE_PTR_H diff --git a/opensubdiv/osd/d3d12DescriptorHeapManager.cpp b/opensubdiv/osd/d3d12DescriptorHeapManager.cpp new file mode 100644 index 0000000000..33b51a34e5 --- /dev/null +++ b/opensubdiv/osd/d3d12DescriptorHeapManager.cpp @@ -0,0 +1,105 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "d3d12descriptorHeapManager.h" +#include "d3d12Util.h" +#include +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + D3D12DescriptorHeapManager::D3D12DescriptorHeapManager(ID3D12Device *device, unsigned int nodeMask) : + _device(device), _onlineDescriptorsUsed(0), _descriptorSize(device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)) + { + D3D12_DESCRIPTOR_HEAP_DESC heapDesc; + heapDesc.NodeMask = nodeMask; + heapDesc.NumDescriptors = cMaxSimulataneousDescriptors; + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + ThrowFailure(device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_offlineDescriptorHeap))); + + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + ThrowFailure(device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_onlineDescriptorHeap))); + + for (unsigned int slot = 0; slot < cMaxSimulataneousDescriptors; slot++) + { + _freeSlotsQueue.push(slot); + } + } + + CPUDescriptorHandle D3D12DescriptorHeapManager::AllocateDescriptor() + { + D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(_offlineDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), _freeSlotsQueue.front(), _descriptorSize); + _freeSlotsQueue.pop(); + + return CPUDescriptorHandle.ptr; + } + + void D3D12DescriptorHeapManager::ReleaseDescriptor(CPUDescriptorHandle &handle) + { + D3D12_CPU_DESCRIPTOR_HANDLE base = _offlineDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + _freeSlotsQueue.push((unsigned int)((ConvertToD3D12CPUHandle(handle).ptr - base.ptr) / _descriptorSize)); + } + + GPUDescriptorHandle D3D12DescriptorHeapManager::UploadDescriptors(UINT NumViews, CPUDescriptorHandle *pViews) + { + D3D12_GPU_DESCRIPTOR_HANDLE destGpuHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(_onlineDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), _onlineDescriptorsUsed, _descriptorSize); + + if (_onlineDescriptorsUsed + NumViews > cMaxSimulataneousDescriptors) + { + // Flush here + _onlineDescriptorsUsed = 0; + } + + for (UINT viewIndex = 0; viewIndex < NumViews; viewIndex++) + { + D3D12_CPU_DESCRIPTOR_HANDLE destCpuHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(_onlineDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), _onlineDescriptorsUsed, _descriptorSize); + _device->CopyDescriptorsSimple(1, destCpuHandle, ConvertToD3D12CPUHandle(pViews[viewIndex]), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + _onlineDescriptorsUsed++; + } + + return destGpuHandle.ptr; + } + + D3D12_CPU_DESCRIPTOR_HANDLE D3D12DescriptorHeapManager::ConvertToD3D12CPUHandle(const CPUDescriptorHandle &handle) + { + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle; + cpuHandle.ptr = handle; + return cpuHandle; + } + + D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorHeapManager::ConvertToD3D12GPUHandle(const GPUDescriptorHandle &handle) + { + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; + gpuHandle.ptr = handle; + return gpuHandle; + } +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv diff --git a/opensubdiv/osd/d3d12DescriptorHeapManager.h b/opensubdiv/osd/d3d12DescriptorHeapManager.h new file mode 100644 index 0000000000..e1993338d2 --- /dev/null +++ b/opensubdiv/osd/d3d12DescriptorHeapManager.h @@ -0,0 +1,77 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_DESCRIPTOR_HEAP_MANAGER_H +#define OPENSUBDIV3_OSD_D3D12_DESCRIPTOR_HEAP_MANAGER_H + +#include "../version.h" + +#include +#include + +struct ID3D12Device; +struct D3D12_CPU_DESCRIPTOR_HANDLE; +struct D3D12_GPU_DESCRIPTOR_HANDLE; +struct ID3D12DescriptorHeap; + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + + typedef SIZE_T CPUDescriptorHandle; + typedef unsigned long long GPUDescriptorHandle; + + class D3D12DescriptorHeapManager + { + public: + D3D12DescriptorHeapManager(ID3D12Device *device, unsigned int nodeMask); + + CPUDescriptorHandle AllocateDescriptor(); + void ReleaseDescriptor(CPUDescriptorHandle &handle); + GPUDescriptorHandle UploadDescriptors(unsigned int NumViews, CPUDescriptorHandle *pViews); + ID3D12DescriptorHeap *GetDescriptorHeap() const { return _onlineDescriptorHeap; } + + static D3D12_CPU_DESCRIPTOR_HANDLE ConvertToD3D12CPUHandle(const CPUDescriptorHandle &handle); + static D3D12_GPU_DESCRIPTOR_HANDLE ConvertToD3D12GPUHandle(const GPUDescriptorHandle &handle); + private: + ID3D12Device *_device; + + static const unsigned int cMaxSimulataneousDescriptors = 500; + CComPtr _offlineDescriptorHeap; + std::queue _freeSlotsQueue; + unsigned int _descriptorSize; + + CComPtr _onlineDescriptorHeap; + unsigned int _onlineDescriptorsUsed; + }; + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_DESCRIPTOR_HEAP_MANAGER_H diff --git a/opensubdiv/osd/d3d12FenceTrackedObjectQueue.h b/opensubdiv/osd/d3d12FenceTrackedObjectQueue.h new file mode 100644 index 0000000000..f219ef1ecb --- /dev/null +++ b/opensubdiv/osd/d3d12FenceTrackedObjectQueue.h @@ -0,0 +1,112 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_FENCE_TRACKED_OBJECT_QUEUE_H +#define OPENSUBDIV3_OSD_D3D12_FENCE_TRACKED_OBJECT_QUEUE_H + +#include "../version.h" + +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + + // Keeps a queue of objects that get paired with a fence value + // that mark the last time the GPU referenced that object. + // Several helper functions exist to verify if there are object + // available that are no longer referenced by the GPU + template + class FenceTrackedObjectQueue + { + protected: + virtual void DeleteObject(Object *Object) = 0; + + public: + void Push(unsigned long long fenceValue, Object object) + { + if(!IsEmpty()) assert(GetFrontFenceValue() <= fenceValue); + + _Queue.push(ObjectFencePair(fenceValue, object)); + } + + bool IsEmpty() const + { + return _Queue.empty(); + } + + bool IsObjectAvailable(unsigned long long completedFenceValue) const + { + return !IsEmpty() && completedFenceValue >= _Queue.front()._fenceValue; + } + + Object Pop() + { + assert(!IsEmpty()); + + Object objectToReturn = _Queue.front()._object; + _Queue.pop(); + return objectToReturn; + } + + void DeleteUnusedObjects(unsigned long long completedFenceValue) + { + while (IsObjectAvailable(completedFenceValue)) + { + DeleteObject(&_Queue.front()._object); + _Queue.pop(); + } + } + private: + unsigned long long GetFrontFenceValue() + { + assert(!IsEmpty()); + return _Queue.front()._fenceValue; + } + + template + class ObjectFencePair + { + public: + ObjectFencePair() : _fenceValue(0) {} + + ObjectFencePair(UINT64 fenceValue, typename Object object) : + _fenceValue(fenceValue), _object(object) {} + + UINT64 _fenceValue; + Object _object; + }; + + std::queue> _Queue; + }; + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_FENCE_TRACKED_OBJECT_QUEUE_H diff --git a/opensubdiv/osd/d3d12PoolAllocator.h b/opensubdiv/osd/d3d12PoolAllocator.h new file mode 100644 index 0000000000..1975c92d39 --- /dev/null +++ b/opensubdiv/osd/d3d12PoolAllocator.h @@ -0,0 +1,102 @@ +// +// Copyright 2015 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_POOL_ALLOCATOR_H +#define OPENSUBDIV3_OSD_D3D12_POOL_ALLOCATOR_H + +#include "../version.h" + +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + template + class IAllocator + { + public: + typedef AllocationType Allocation; + AllocationType Allocate() { assert(false); return AllocationType(); }; + void Free(AllocationType &allocation) { assert(false); }; + void Reset(AllocationType &allocation) { assert(false); } + }; + + template + class D3D12PoolAllocator : public FenceTrackedObjectQueue + { + public: + D3D12PoolAllocator(Allocator allocator) : + _allocator(allocator) + { + } + + ~D3D12PoolAllocator() + { + // It's the callers responsibility to make sure all objects + // are trimmed before deleting the allocator + assert(IsEmpty()); + } + + void DeleteObject(AllocationType *allocation) + { + _allocator.Free(*allocation); + } + + AllocationType Allocate(unsigned long long completeFenceValue) + { + if (IsObjectAvailable(completeFenceValue)) + { + AllocationType allocation = Pop(); + + _allocator.Reset(allocation); + return allocation; + } + else + { + return _allocator.Allocate(); + } + } + + void Release(unsigned long long fenceValue, AllocationType *pAllocations, unsigned int numAllocations = 1) + { + assert(numAllocations >= 1); + + for (unsigned int i = 0; i < numAllocations; i++) + { + Push(fenceValue, pAllocations[i]); + } + } + + private: + Allocator _allocator; + }; +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_POOL_ALLOCATOR_H diff --git a/opensubdiv/osd/d3d12Util.h b/opensubdiv/osd/d3d12Util.h new file mode 100644 index 0000000000..1aac42bf29 --- /dev/null +++ b/opensubdiv/osd/d3d12Util.h @@ -0,0 +1,205 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_COMMON_HPP +#define OPENSUBDIV3_OSD_D3D12_COMMON_HPP + +#include +#include +#include "d3dx12.h" +#include +#include + +#include "d3d12DeferredDeletionUniquePtr.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + static void ThrowFailure(HRESULT hr) + { + if (FAILED(hr)) + { + throw hr; + } + } + + class ScopedCommandListAllocatorPair : public CommandListAllocatorPair + { + public: + ScopedCommandListAllocatorPair(D3D12CommandQueueContext *context, CommandListAllocatorPair pair) : + CommandListAllocatorPair(pair), + _D3D12CommandQueueContext(context) + { + } + + ~ScopedCommandListAllocatorPair() + { + _D3D12CommandQueueContext->ReleaseCommandListAllocatorPair(*this); + } + D3D12CommandQueueContext *_D3D12CommandQueueContext; + }; + + typedef DeferredDeletionUniquePtr ResourceDeferredDeletionUniquePtr; + + static D3D12_RESOURCE_STATES GetDefaultResourceStateFromHeapType(D3D12_HEAP_TYPE heapType) + { + switch (heapType) + { + default: + case D3D12_HEAP_TYPE_UPLOAD: + return D3D12_RESOURCE_STATE_GENERIC_READ; + case D3D12_HEAP_TYPE_CUSTOM: + case D3D12_HEAP_TYPE_DEFAULT: + return D3D12_RESOURCE_STATE_COMMON; + case D3D12_HEAP_TYPE_READBACK: + return D3D12_RESOURCE_STATE_COPY_DEST; + } + } + + static void CreateCommittedBuffer( + unsigned int dataSize, + D3D12_HEAP_TYPE heapType, + D3D12_RESOURCE_STATES initialState, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ResourceDeferredDeletionUniquePtr &resource, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE) + { + ID3D12Device *device = D3D12CommandQueueContext->GetDevice(); + CComPtr buffer; + + const D3D12_HEAP_PROPERTIES heapProperties = CD3DX12_HEAP_PROPERTIES(heapType); + const D3D12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize, flags); + + ThrowFailure(device->CreateCommittedResource(&heapProperties, heapFlags, &bufferDesc, initialState, nullptr, IID_PPV_ARGS(&buffer))); + + resource.AddRefAndAttach(D3D12CommandQueueContext, buffer); + } + + static void createBuffer( + unsigned int dataSize, + D3D12_HEAP_TYPE heapType, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ResourceDeferredDeletionUniquePtr &resource) + { + CreateCommittedBuffer(dataSize, heapType, GetDefaultResourceStateFromHeapType(heapType), D3D12CommandQueueContext, resource); + } + + static void createCpuReadableBuffer( + unsigned int dataSize, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ResourceDeferredDeletionUniquePtr &resource) + { + createBuffer(dataSize, D3D12_HEAP_TYPE_READBACK, D3D12CommandQueueContext, resource); + } + + static void createCpuWritableBuffer( + unsigned int dataSize, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ResourceDeferredDeletionUniquePtr &resource) + { + createBuffer(dataSize, D3D12_HEAP_TYPE_UPLOAD, D3D12CommandQueueContext, resource); + } + + static void createDefaultBuffer( + unsigned int dataSize, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ResourceDeferredDeletionUniquePtr &resource) + { + createBuffer(dataSize, D3D12_HEAP_TYPE_DEFAULT, D3D12CommandQueueContext, resource); + } + + static void createBufferWithInitialData(void *pData, + unsigned int dataSize, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ID3D12GraphicsCommandList *pCommandList, + ResourceDeferredDeletionUniquePtr &resource) { + + ID3D12Device *device = D3D12CommandQueueContext->GetDevice(); + createDefaultBuffer(dataSize, D3D12CommandQueueContext, resource); + + ResourceDeferredDeletionUniquePtr uploadHeap; + createCpuWritableBuffer(dataSize, D3D12CommandQueueContext, uploadHeap); + { + void *pMappedData; + uploadHeap.Get()->Map(0, nullptr, &pMappedData); + memcpy(pMappedData, pData, dataSize); + + D3D12_RANGE writtenRange = CD3DX12_RANGE(0, dataSize); + uploadHeap.Get()->Unmap(0, &writtenRange); + } + pCommandList->CopyBufferRegion(resource, 0, uploadHeap.Get(), 0, dataSize); + } + + template + static void createBufferWithVectorInitialData(std::vector const &src, + D3D12CommandQueueContext *D3D12CommandQueueContext, + ID3D12GraphicsCommandList *pCommandList, + ResourceDeferredDeletionUniquePtr &resource) { + return createBufferWithInitialData((void*)&src.at(0), (unsigned int)(src.size() * sizeof(T)), D3D12CommandQueueContext, pCommandList, resource); + } + + static CPUDescriptorHandle AllocateUAV( + D3D12CommandQueueContext *D3D12CommandQueueContext, + ID3D12Resource *resource, + DXGI_FORMAT format, + SIZE_T numElements) + { + CPUDescriptorHandle cpuHandle = D3D12CommandQueueContext->GetDescriptorHeapManager().AllocateDescriptor(); + + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uavDesc.Format = format; + uavDesc.Buffer.NumElements = (unsigned int)numElements; + D3D12CommandQueueContext->GetDevice()->CreateUnorderedAccessView(resource, nullptr, &uavDesc, D3D12DescriptorHeapManager::ConvertToD3D12CPUHandle(cpuHandle)); + + return cpuHandle; + } + + static CPUDescriptorHandle AllocateSRV( + D3D12CommandQueueContext *D3D12CommandQueueContext, + ID3D12Resource *resource, + DXGI_FORMAT format, + SIZE_T numElements) + { + CPUDescriptorHandle cpuHandle = D3D12CommandQueueContext->GetDescriptorHeapManager().AllocateDescriptor(); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + srvDesc.Format = format; + srvDesc.Buffer.NumElements = (unsigned int)numElements; + D3D12CommandQueueContext->GetDevice()->CreateShaderResourceView(resource, &srvDesc, D3D12DescriptorHeapManager::ConvertToD3D12CPUHandle(cpuHandle)); + + return cpuHandle; + } +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_COMMON_HPP diff --git a/opensubdiv/osd/d3d12VertexBuffer.cpp b/opensubdiv/osd/d3d12VertexBuffer.cpp new file mode 100644 index 0000000000..8b18a567da --- /dev/null +++ b/opensubdiv/osd/d3d12VertexBuffer.cpp @@ -0,0 +1,156 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../osd/d3d12VertexBuffer.h" +#include "../far/error.h" + +#include +#include +#include +#include "d3dx12.h" +#include + +#include "d3d12util.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +D3D12VertexBuffer::D3D12VertexBuffer(int numElements, int numVertices) + : _numElements(numElements), _numVertices(numVertices) { +} + +D3D12VertexBuffer::~D3D12VertexBuffer() { +} + +D3D12VertexBuffer* +D3D12VertexBuffer::Create(int numElements, int numVertices, + D3D12CommandQueueContext* D3D12CommandQueueContext) { + D3D12VertexBuffer *instance = + new D3D12VertexBuffer(numElements, numVertices); + + if (instance->allocate(D3D12CommandQueueContext)) return instance; + delete instance; + return NULL; +} + +void +D3D12VertexBuffer::UpdateData(const float *src, int startVertex, int numVertices, + D3D12CommandQueueContext *D3D12CommandQueueContext) { + ID3D12CommandQueue *pCommandQueue = D3D12CommandQueueContext->GetCommandQueue(); + + const unsigned int startOffset = startVertex * numVertices * sizeof(float); + const unsigned int size = GetNumElements() * numVertices * sizeof(float); + void *pData; + ThrowFailure(_uploadBuffer->Map(0, nullptr, &pData)); + + memcpy((BYTE *)pData + startOffset, src, size); + + D3D12_RANGE writtenRange = CD3DX12_RANGE(startOffset, size); + _uploadBuffer->Unmap(0, &writtenRange); + + ScopedCommandListAllocatorPair pair(D3D12CommandQueueContext, D3D12CommandQueueContext->GetCommandListAllocatorPair()); + ID3D12GraphicsCommandList *pCommandList = pair._commandList; + + pCommandList->CopyBufferRegion(_buffer, 0, _uploadBuffer, startOffset, size); + + pCommandList->Close(); + + D3D12CommandQueueContext->ExecuteCommandList(pCommandList); +} + +int +D3D12VertexBuffer::GetNumElements() const { + + return _numElements; +} + +int +D3D12VertexBuffer::GetNumVertices() const { + + return _numVertices; +} + +CPUDescriptorHandle +D3D12VertexBuffer::BindD3D12Buffer(D3D12CommandQueueContext* D3D12CommandQueueContext) { + ID3D11Resource *resourcesToRelease[] = { _d3d11Buffer }; + D3D12CommandQueueContext->Get11on12Device()->ReleaseWrappedResources(resourcesToRelease, ARRAYSIZE(resourcesToRelease)); + + return _uav; +} + +CPUDescriptorHandle +D3D12VertexBuffer::BindD3D12UAV(D3D12CommandQueueContext* D3D12CommandQueueContext) { + + return BindD3D12Buffer(D3D12CommandQueueContext); +} + +ID3D11Buffer *D3D12VertexBuffer::BindVBO(D3D12CommandQueueContext *D3D12CommandQueueContext) +{ + ID3D11Resource *resourcesToAcquire[] = { _d3d11Buffer }; + D3D12CommandQueueContext->Get11on12Device()->AcquireWrappedResources(resourcesToAcquire, ARRAYSIZE(resourcesToAcquire)); + + return _d3d11Buffer; +} + + +bool +D3D12VertexBuffer::allocate(D3D12CommandQueueContext* D3D12CommandQueueContext) { + + ID3D12Device *pDevice = D3D12CommandQueueContext->GetDevice(); + _dataSize = _numElements * _numVertices * sizeof(float); + + CreateCommittedBuffer( + _dataSize, + D3D12_HEAP_TYPE_DEFAULT, + GetDefaultResourceStateFromHeapType(D3D12_HEAP_TYPE_DEFAULT), + D3D12CommandQueueContext, + _buffer, + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + + createCpuWritableBuffer(_dataSize, D3D12CommandQueueContext, _uploadBuffer); + + { + ID3D11On12Device* d3d11on12Device = D3D12CommandQueueContext->Get11on12Device(); + + D3D11_RESOURCE_FLAGS d3d11Flags = {}; + d3d11Flags.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + d3d11Flags.StructureByteStride = sizeof(float); + + d3d11on12Device->CreateWrappedResource(_buffer, &d3d11Flags, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON, IID_PPV_ARGS(&_d3d11Buffer)); + } + + _uav = AllocateUAV(D3D12CommandQueueContext, _buffer, DXGI_FORMAT_R32_FLOAT, _numElements * _numVertices); + + return true; +} + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv + diff --git a/opensubdiv/osd/d3d12VertexBuffer.h b/opensubdiv/osd/d3d12VertexBuffer.h new file mode 100644 index 0000000000..2d36d366a1 --- /dev/null +++ b/opensubdiv/osd/d3d12VertexBuffer.h @@ -0,0 +1,106 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef OPENSUBDIV3_OSD_D3D12_VERTEX_BUFFER_H +#define OPENSUBDIV3_OSD_D3D12_VERTEX_BUFFER_H + +#include "../version.h" +#include "d3d12commandqueuecontext.h" +#include "d3d12deferredDeletionUniquePtr.h" + +struct ID3D11Buffer; +struct ID3D11ImmediateContext; + +struct ID3D12Resource; +struct ID3D12CommandQueue; +struct ID3D12Device; + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Osd { + +/// +/// \brief Concrete vertex buffer class for DirectX subvision and DirectX drawing. +/// +/// D3D12VertexBuffer implements D3D12VertexBufferInterface. An instance +/// of this buffer class can be passed to D3D12ComputeEvaluator. +/// +class D3D12VertexBuffer { +public: + /// Creator. Returns NULL if error. + static D3D12VertexBuffer * Create(int numElements, int numVertices, + D3D12CommandQueueContext* D3D12CommandQueueContext); + + /// Destructor. + virtual ~D3D12VertexBuffer(); + + /// This method is meant to be used in client code in order to provide coarse + /// vertices data to Osd. + void UpdateData(const float *src, int startVertex, int numVertices, + D3D12CommandQueueContext* D3D12CommandQueueContext); + + /// Returns how many elements defined in this vertex buffer. + int GetNumElements() const; + + /// Returns how many vertices allocated in this vertex buffer. + int GetNumVertices() const; + + /// Returns the D3D11 buffer object. + CPUDescriptorHandle BindD3D12Buffer(D3D12CommandQueueContext* D3D12CommandQueueContext); + + + /// Returns the D3D11 buffer object (for Osd::Mesh interface) + ID3D11Buffer *BindVBO(D3D12CommandQueueContext *D3D12CommandQueueContext); + + /// Returns the D3D12 UAV + CPUDescriptorHandle BindD3D12UAV(D3D12CommandQueueContext* D3D12CommandQueueContext); + +protected: + /// Constructor. + D3D12VertexBuffer(int numElements, int numVertices); + + // Allocates D3D11 buffer + bool allocate(D3D12CommandQueueContext* D3D12CommandQueueContext); + +private: + int _numElements; + int _numVertices; + int _dataSize; + DeferredDeletionUniquePtr _buffer; + DeferredDeletionUniquePtr _readbackBuffer; + DeferredDeletionUniquePtr _uploadBuffer; + CComPtr _d3d11Buffer; + + CPUDescriptorHandle _uav; +}; + +} // end namespace Osd + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif // OPENSUBDIV3_OSD_D3D12_VERTEX_BUFFER_H diff --git a/opensubdiv/osd/d3dx12.h b/opensubdiv/osd/d3dx12.h new file mode 100644 index 0000000000..9f7b7449d4 --- /dev/null +++ b/opensubdiv/osd/d3dx12.h @@ -0,0 +1,2039 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#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_VIEWPORT : public D3D12_VIEWPORT +{ + CD3DX12_VIEWPORT() + {} + explicit CD3DX12_VIEWPORT( const D3D12_VIEWPORT& o ) : + D3D12_VIEWPORT( o ) + {} + explicit CD3DX12_VIEWPORT( + FLOAT topLeftX, + FLOAT topLeftY, + FLOAT width, + FLOAT height, + FLOAT minDepth = D3D12_MIN_DEPTH, + FLOAT maxDepth = D3D12_MAX_DEPTH ) + { + TopLeftX = topLeftX; + TopLeftY = topLeftY; + Width = width; + Height = height; + MinDepth = minDepth; + MaxDepth = maxDepth; + } + explicit CD3DX12_VIEWPORT( + _In_ ID3D12Resource* pResource, + UINT mipSlice = 0, + FLOAT topLeftX = 0.0f, + FLOAT topLeftY = 0.0f, + FLOAT minDepth = D3D12_MIN_DEPTH, + FLOAT maxDepth = D3D12_MAX_DEPTH ) + { + D3D12_RESOURCE_DESC Desc = pResource->GetDesc(); + const UINT64 SubresourceWidth = Desc.Width >> mipSlice; + const UINT64 SubresourceHeight = Desc.Height >> mipSlice; + switch (Desc.Dimension) + { + case D3D12_RESOURCE_DIMENSION_BUFFER: + TopLeftX = topLeftX; + TopLeftY = 0.0f; + Width = Desc.Width - topLeftX; + Height = 1.0f; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + TopLeftX = topLeftX; + TopLeftY = 0.0f; + Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX; + Height = 1.0f; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + TopLeftX = topLeftX; + TopLeftY = topLeftY; + Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX; + Height = (SubresourceHeight ? SubresourceHeight: 1.0f) - topLeftY; + break; + default: break; + } + + MinDepth = minDepth; + MaxDepth = maxDepth; + } + ~CD3DX12_VIEWPORT() {} + operator const D3D12_VIEWPORT&() 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_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE +{ + CD3DX12_SHADER_BYTECODE() + {} + explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) : + D3D12_SHADER_BYTECODE(o) + {} + CD3DX12_SHADER_BYTECODE( + _In_ ID3DBlob* pShaderBlob ) + { + pShaderBytecode = pShaderBlob->GetBufferPointer(); + BytecodeLength = pShaderBlob->GetBufferSize(); + } + CD3DX12_SHADER_BYTECODE( + _In_reads_(bytecodeLength) const void* _pShaderBytecode, + SIZE_T bytecodeLength ) + { + pShaderBytecode = _pShaderBytecode; + BytecodeLength = bytecodeLength; + } + operator const D3D12_SHADER_BYTECODE&() 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_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1 +{ + CD3DX12_DESCRIPTOR_RANGE1() { } + explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) : + D3D12_DESCRIPTOR_RANGE1(o) + {} + CD3DX12_DESCRIPTOR_RANGE1( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE1 &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.Flags = flags; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1 +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE1() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) : + D3D12_ROOT_DESCRIPTOR_TABLE1(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE1( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1 +{ + CD3DX12_ROOT_DESCRIPTOR1() {} + explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) : + D3D12_ROOT_DESCRIPTOR1(o) + {} + CD3DX12_ROOT_DESCRIPTOR1( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE) + { + Init(shaderRegister, registerSpace, flags); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE) + { + Init(*this, shaderRegister, registerSpace, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR1 &table, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + table.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1 +{ + CD3DX12_ROOT_PARAMETER1() {} + explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) : + D3D12_ROOT_PARAMETER1(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER1 &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER1 &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_PARAMETER1 &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER1 &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER1 &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* 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_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC +{ + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) : + D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o) + {} + explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) + { + Version = D3D_ROOT_SIGNATURE_VERSION_1_0; + Desc_1_0 = o; + } + explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o) + { + Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + Desc_1_1 = o; + } + CD3DX12_VERSIONED_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_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _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_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init_1_0( + 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_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init_1_0( + _Out_ D3D12_VERSIONED_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.Version = D3D_ROOT_SIGNATURE_VERSION_1_0; + desc.Desc_1_0.NumParameters = numParameters; + desc.Desc_1_0.pParameters = _pParameters; + desc.Desc_1_0.NumStaticSamplers = numStaticSamplers; + desc.Desc_1_0.pStaticSamplers = _pStaticSamplers; + desc.Desc_1_0.Flags = flags; + } + + inline void Init_1_1( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _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_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init_1_1( + _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _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.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + desc.Desc_1_1.NumParameters = numParameters; + desc.Desc_1_1.pParameters = _pParameters; + desc.Desc_1_1.NumStaticSamplers = numStaticSamplers; + desc.Desc_1_1.pStaticSamplers = _pStaticSamplers; + desc.Desc_1_1.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) const + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const + { + 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) const + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + +//------------------------------------------------------------------------------------------------ +// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update. +// To help enable root signature 1.1 features when they are available and not require maintaining +// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when +// 1.1 is not supported. +inline HRESULT D3DX12SerializeVersionedRootSignature( + _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION MaxVersion, + _Outptr_ ID3DBlob** ppBlob, + _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob) +{ + if (ppErrorBlob != NULL) + { + *ppErrorBlob = NULL; + } + + switch (MaxVersion) + { + case D3D_ROOT_SIGNATURE_VERSION_1_0: + switch (pRootSignatureDesc->Version) + { + case D3D_ROOT_SIGNATURE_VERSION_1_0: + return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); + + case D3D_ROOT_SIGNATURE_VERSION_1_1: + { + HRESULT hr = S_OK; + const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1; + + const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters; + void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL; + if (ParametersSize > 0 && pParameters == NULL) + { + hr = E_OUTOFMEMORY; + } + D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast(pParameters); + + if (SUCCEEDED(hr)) + { + for (UINT n = 0; n < desc_1_1.NumParameters; n++) + { + __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters); + pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType; + pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility; + + switch (desc_1_1.pParameters[n].ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues; + pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace; + pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister; + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace; + pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister; + break; + + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable; + + const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges; + void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL; + if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL) + { + hr = E_OUTOFMEMORY; + } + D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast(pDescriptorRanges); + + if (SUCCEEDED(hr)) + { + for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++) + { + __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges); + pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister; + pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors; + pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart; + pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType; + pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace; + } + } + + D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable; + table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges; + table_1_0.pDescriptorRanges = pDescriptorRanges_1_0; + } + } + } + + if (SUCCEEDED(hr)) + { + CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags); + hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); + } + + if (pParameters) + { + for (UINT n = 0; n < desc_1_1.NumParameters; n++) + { + if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + { + HeapFree(GetProcessHeap(), 0, reinterpret_cast(const_cast(pParameters_1_0[n].DescriptorTable.pDescriptorRanges))); + } + } + HeapFree(GetProcessHeap(), 0, pParameters); + } + return hr; + } + } + break; + + case D3D_ROOT_SIGNATURE_VERSION_1_1: + return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob); + } + + return E_INVALIDARG; +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + + diff --git a/opensubdiv/osd/hlslComputeKernel.hlsl b/opensubdiv/osd/hlslComputeKernel.hlsl index 2e02bad03b..7133154f08 100644 --- a/opensubdiv/osd/hlslComputeKernel.hlsl +++ b/opensubdiv/osd/hlslComputeKernel.hlsl @@ -96,14 +96,14 @@ class SingleBufferCompute : IComputeKernel { Vertex dst; clear(dst); - + int offset = offsets[current], size = sizes[current]; - + for (int i=0; i Date: Wed, 28 Jun 2017 21:27:44 -0700 Subject: [PATCH 2/4] Fixing AppVeyor break --- opensubdiv/osd/d3d12DescriptorHeapManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensubdiv/osd/d3d12DescriptorHeapManager.cpp b/opensubdiv/osd/d3d12DescriptorHeapManager.cpp index 33b51a34e5..90b46dd06e 100644 --- a/opensubdiv/osd/d3d12DescriptorHeapManager.cpp +++ b/opensubdiv/osd/d3d12DescriptorHeapManager.cpp @@ -25,7 +25,7 @@ #include "d3d12descriptorHeapManager.h" #include "d3d12Util.h" #include -#include +#include "d3dx12.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { From 049fea3a466c391e46b8419e6a8ce83cf42d3559 Mon Sep 17 00:00:00 2001 From: wallisc Date: Wed, 28 Jun 2017 22:51:40 -0700 Subject: [PATCH 3/4] Fixing d3d12 include formatting for dxviewer --- examples/dxViewer/dxviewer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/dxViewer/dxviewer.cpp b/examples/dxViewer/dxviewer.cpp index f2d162e73d..f1af3c1989 100644 --- a/examples/dxViewer/dxviewer.cpp +++ b/examples/dxViewer/dxviewer.cpp @@ -66,11 +66,10 @@ OpenSubdiv::Osd::D3D11MeshInterface *g_mesh = NULL; OpenSubdiv::Osd::D3D11LegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; #ifdef OPENSUBDIV_HAS_DX12 -#include -#include +#include +#include #include #include -#include #include #include From 7c59a55a8f69e61358fd9f04420304cc16404586 Mon Sep 17 00:00:00 2001 From: wallisc Date: Thu, 29 Jun 2017 21:58:14 -0700 Subject: [PATCH 4/4] Fixing embarrassing Cmake file issues --- CMakeLists.txt | 14 +++++++------- examples/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1375ed75c..2c625d5988 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -362,9 +362,9 @@ if (WIN32 AND NOT NO_DX12) if(DX12SDK_FOUND) # The DX12 SDK (Win 10 SDK) is a super-set of the DXSDK set(DXSDK_FOUND TRUE) - - set(DXSDK_INCLUDE_DIR $(D3D12_INCLUDE_DIRS)) - set(DXSDK_LIBRARIES $(D3D12_LIBRARIES)) + + set(DXSDK_INCLUDE_DIR ${D3D12_INCLUDE_DIRS}) + set(DXSDK_LIBRARIES ${D3D12_LIBRARIES}) endif() endif() @@ -578,12 +578,12 @@ if (WIN32) -DGLEW_STATIC ) endif() - - if(DX12SDK_FOUND AND NOT NO_DX12) - add_definitions( + + if(DX12SDK_FOUND AND NOT NO_DX12) + add_definitions( -DOPENSUBDIV_HAS_DX12 ) - endif() + endif() if (DXSDK_FOUND AND NOT NO_DX11) add_definitions( diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index bd9177a96e..2688551815 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -69,7 +69,7 @@ if (NOT NO_OPENGL) endif() endif() -if (DXSDK_FOUND AND NOT NO_DX) +if (DXSDK_FOUND AND NOT NO_DX11) add_subdirectory(dxViewer)