diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f3cd9d40c..2c625d5988 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/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) 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..f1af3c1989 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,34 @@ OpenSubdiv::Osd::D3D11MeshInterface *g_mesh = NULL; OpenSubdiv::Osd::D3D11LegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; +#ifdef OPENSUBDIV_HAS_DX12 +#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 +122,8 @@ enum KernelType { kCPU = 0, kTBB = 2, kCUDA = 3, kCL = 4, - kDirectCompute = 5 }; + kDirectCompute = 5, + kDirect3D12 = 6, }; enum DisplayStyle { kDisplayStyleWire = 0, kDisplayStyleShaded, @@ -148,6 +182,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 +207,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 +234,6 @@ bool g_bDone; //------------------------------------------------------------------------------ static void updateGeom() { - int nverts = (int)g_orgPositions.size() / 3; std::vector vertex; @@ -257,13 +297,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 +433,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 +884,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 +1007,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 +1056,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 +1110,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 +1201,16 @@ callbackKernel(int k) { } #endif + if(g_bUse11on12 != needs11on12ForDX11Interop(g_kernel)) + { + g_bUse11on12 = needs11on12ForDX11Interop(g_kernel); + + deleteAllObjects(); + + initD3D11(g_hwnd); + initHUD(); + } + rebuildOsdMesh(); } @@ -1166,22 +1313,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 +1420,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 +1446,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 +1465,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 +1617,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 +1876,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..90b46dd06e --- /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 "d3dx12.h" + +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