summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2016-08-20 06:35:47 +0000
committerEgor Yusov <egor.yusov@gmail.com>2016-08-20 06:35:47 +0000
commit2b64f003622ee7871fd7aec041622427dd2fc88f (patch)
tree893dab48c6d0e7121e047d8d3bb6d5bf172ce2d5 /Graphics/GraphicsEngineD3D12
parentRelease v1.0.0 (diff)
downloadDiligentCore-2b64f003622ee7871fd7aec041622427dd2fc88f.tar.gz
DiligentCore-2b64f003622ee7871fd7aec041622427dd2fc88f.zip
Updated to Diligent Engine 2.0
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj200
-rw-r--r--Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj.filters2
-rw-r--r--Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj286
-rw-r--r--Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj.filters9
-rw-r--r--Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems159
-rw-r--r--Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems.filters244
-rw-r--r--Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.props24
-rw-r--r--Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h114
-rw-r--r--Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h59
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandContext.h615
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h61
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandListManager.h73
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h53
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.h56
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12TypeDefinitions.h187
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12Utils.h31
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h362
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h142
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DynamicUploadHeap.h134
-rw-r--r--Graphics/GraphicsEngineD3D12/include/GenerateMips.h64
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h93
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h133
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RootSignature.h312
-rw-r--r--Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h57
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h79
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h81
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h304
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h396
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h94
-rw-r--r--Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h69
-rw-r--r--Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h97
-rw-r--r--Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h65
-rw-r--r--Graphics/GraphicsEngineD3D12/include/d3dx12_win.h1508
-rw-r--r--Graphics/GraphicsEngineD3D12/include/pch.h47
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h56
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/BufferViewD3D12.h47
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h57
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h49
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h104
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/SamplerD3D12.h50
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/ShaderD3D12.h50
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/ShaderResourceBindingD3D12.h45
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/SwapChainD3D12.h50
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/TextureD3D12.h50
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/TextureViewD3D12.h47
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli206
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaCS.hlsl15
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddCS.hlsl16
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddXCS.hlsl16
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddYCS.hlsl16
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearCS.hlsl14
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddCS.hlsl15
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddXCS.hlsl15
-rw-r--r--Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddYCS.hlsl15
-rw-r--r--Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp373
-rw-r--r--Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp43
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandContext.cpp449
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp106
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12ResourceBase.cpp30
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp295
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp45
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DLLMain.cpp49
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp342
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp724
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DynamicUploadHeap.cpp152
-rw-r--r--Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp185
-rw-r--r--Graphics/GraphicsEngineD3D12/src/GraphicsEngineD3D12.def3
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp335
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp509
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp334
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp959
-rw-r--r--Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp62
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp81
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp139
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp84
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp1038
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp93
-rw-r--r--Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp262
-rw-r--r--Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp511
-rw-r--r--Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp61
-rw-r--r--Graphics/GraphicsEngineD3D12/src/pch.cpp24
81 files changed, 14431 insertions, 0 deletions
diff --git a/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj b/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj
new file mode 100644
index 00000000..ca0468a5
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1a5a1c1d-c717-4680-a929-40e6324fe048}</ProjectGuid>
+ <Keyword>StaticLibrary</Keyword>
+ <RootNamespace>GraphicsEngineD3D12</RootNamespace>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+ <AppContainerApplication>true</AppContainerApplication>
+ <ApplicationType>Windows Store</ApplicationType>
+ <WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>
+ <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.Shared.vcxitems" Label="Shared" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_Win32Dbg.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_Win32Rel.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_ArmDbg.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_ArmRel.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_X64Dbg.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\UWP\UWP_X64Rel.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <GenerateManifest>false</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <CompileAsWinRT>false</CompileAsWinRT>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj.filters b/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj.filters
new file mode 100644
index 00000000..c31757ec
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/UWP/GraphicsEngineD3D12.vcxproj.filters
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" /> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj b/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj
new file mode 100644
index 00000000..b930c993
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="DbgDLL|Win32">
+ <Configuration>DbgDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DbgDLL|x64">
+ <Configuration>DbgDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelDLL|Win32">
+ <Configuration>RelDLL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelDLL|x64">
+ <Configuration>RelDLL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FFF8071A-DB82-485B-ADC3-F0B675296869}</ProjectGuid>
+ <RootNamespace>GraphicsEngineD3D12</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.Shared.vcxitems" Label="Shared" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32d.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32d.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32r.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win32r.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64d.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64d.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64r.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\Shared\build\Windows\Win64r.props" />
+ <Import Project="..\Windows.Shared\GraphicsEngineD3D12.props" />
+ <Import Project="..\..\..\Shared\build\Windows\DLLCommon.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineD3D12.def</ModuleDefinitionFile>
+ <AdditionalDependencies>dxgi.lib;d3d12.lib;d3dcompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DbgDLL|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineD3D12.def</ModuleDefinitionFile>
+ <AdditionalDependencies>dxgi.lib;d3d12.lib;d3dcompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <DisableSpecificWarnings>4100;4505;4189</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <DisableSpecificWarnings>4100;4505;4189</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineD3D12.def</ModuleDefinitionFile>
+ <AdditionalDependencies>dxgi.lib;d3d12.lib;d3dcompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <DisableSpecificWarnings>4100;4505;4189</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelDLL|x64'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <DisableSpecificWarnings>4100;4505;4189</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <ModuleDefinitionFile>..\..\src\GraphicsEngineD3D12.def</ModuleDefinitionFile>
+ <AdditionalDependencies>dxgi.lib;d3d12.lib;d3dcompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\Common\build\Win32\Common.vcxproj">
+ <Project>{7380f7e6-315f-4b4e-92eb-e6aeee865298}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\Platforms\Basic\build\Win32\BasicPlatform.vcxproj">
+ <Project>{8ada5f93-7a38-4ad8-b8f5-1ffd4d4f630c}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\Platforms\Win32\build\Win32\WindowsPlatform.vcxproj">
+ <Project>{58f32677-436b-412a-bbf8-2b1310d82cd8}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\GraphicsEngineD3DBase\build\Win32\GraphicsEngineD3DBase.vcxproj">
+ <Project>{40fd58ed-aabc-4cbd-bee4-33116995a626}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\GraphicsEngine\build\Win32\GraphicsEngine.vcxproj">
+ <Project>{052dd700-477c-4512-a7f4-b05ebef5c80e}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\GraphicsTools\build\Win32\GraphicsTools.vcxproj">
+ <Project>{c6014499-0cf2-43ec-a773-a4e354fb2d74}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\src\GraphicsEngineD3D12.def" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\DLLMain.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj.filters b/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj.filters
new file mode 100644
index 00000000..789137b8
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/Win32/GraphicsEngineD3D12.vcxproj.filters
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <None Include="..\..\src\GraphicsEngineD3D12.def" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\DLLMain.cpp" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems
new file mode 100644
index 00000000..c67117a6
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Globals">
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+ <HasSharedItems>true</HasSharedItems>
+ <ItemsProjectGuid>{628cb771-ed9d-4874-a69e-3484343a4890}</ItemsProjectGuid>
+ <ItemsRootNamespace>ElevationDataSource</ItemsRootNamespace>
+ <ItemsProjectName>GraphicsEngineD3D12.Shared</ItemsProjectName>
+ <CodeSharingProject>248F659F-DAC5-46E8-AC09-60EC9FC95053</CodeSharingProject>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectCapability Include="SourceItemsFromImports" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\BufferD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\BufferViewD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandContext.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandListD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandListManager.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12ResourceBase.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12TypeConversions.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12TypeDefinitions.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12Utils.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\d3dx12_win.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DescriptorHeap.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DeviceContextD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DynamicUploadHeap.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\GenerateMips.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\pch.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\PipelineStateD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\RenderDeviceD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\RootSignature.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\SamplerD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceBindingD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceCacheD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceLayoutD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourcesD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\SwapChainD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureViewD3D12Impl.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\BufferD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\BufferViewD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\PipelineStateD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\RenderDeviceD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\RenderDeviceFactoryD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\SamplerD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\ShaderD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\ShaderResourceBindingD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\SwapChainD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\TextureD3D12.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\TextureViewD3D12.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddXCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddYCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddXCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddYCS.hlsl">
+ <ShaderType>Compute</ShaderType>
+ <ShaderModel>5.0</ShaderModel>
+ <HeaderFileOutput>$(IntDir)CompiledShaders\GenerateMips\%(Filename).h</HeaderFileOutput>
+ <ObjectFileOutput>
+ </ObjectFileOutput>
+ <VariableName>g_p%(Filename)</VariableName>
+ </FxCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsCS.hlsli">
+ <FileType>Document</FileType>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\BufferD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\BufferViewD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\CommandContext.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\CommandListManager.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12ResourceBase.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12TypeConversions.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12Utils.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DescriptorHeap.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DeviceContextD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DynamicUploadHeap.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\GenerateMips.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\pch.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\PipelineStateD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RenderDeviceD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RenderDeviceFactoryD3D12.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RootSignature.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\SamplerD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceBindingD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceCacheD3D12.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceLayoutD3D12.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourcesD3D12.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\SwapChainD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureD3D12Impl.cpp" />
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureViewD3D12Impl.cpp" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems.filters b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems.filters
new file mode 100644
index 00000000..30e44dcd
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.Shared.vcxitems.filters
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="include">
+ <UniqueIdentifier>{cb8a7049-3fb3-490e-a55b-75c8422dbeb5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="interface">
+ <UniqueIdentifier>{8852250e-f6e5-48a5-94db-cb8334f9079c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Shaders">
+ <UniqueIdentifier>{65c29537-6d5a-41e1-9454-2a96e01ebad1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Shaders\GenerateMips">
+ <UniqueIdentifier>{b3e2774b-fc99-4266-b197-bc1f10110a39}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src">
+ <UniqueIdentifier>{3be622ce-7600-4bd7-9dfe-36521ba36715}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\BufferD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\BufferViewD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandContext.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandListD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\CommandListManager.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12ResourceBase.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12TypeConversions.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12TypeDefinitions.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\D3D12Utils.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\d3dx12_win.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DescriptorHeap.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DeviceContextD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DynamicUploadHeap.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\GenerateMips.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\pch.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\PipelineStateD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\RenderDeviceD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\RootSignature.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\SamplerD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceBindingD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceCacheD3D12.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourceLayoutD3D12.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ShaderResourcesD3D12.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\SwapChainD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\TextureViewD3D12Impl.h">
+ <Filter>include</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\BufferD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\BufferViewD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\PipelineStateD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\RenderDeviceD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\RenderDeviceFactoryD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\SamplerD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\ShaderD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\ShaderResourceBindingD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\SwapChainD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\TextureD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ <ClInclude Include="$(MSBuildThisFileDirectory)..\..\interface\TextureViewD3D12.h">
+ <Filter>interface</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddXCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsGammaOddYCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddXCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ <FxCompile Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsLinearOddYCS.hlsl">
+ <Filter>Shaders\GenerateMips</Filter>
+ </FxCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="$(MSBuildThisFileDirectory)..\..\shaders\GenerateMips\GenerateMipsCS.hlsli">
+ <Filter>Shaders\GenerateMips</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\BufferD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\BufferViewD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\CommandContext.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\CommandListManager.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12ResourceBase.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12TypeConversions.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\D3D12Utils.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DescriptorHeap.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DeviceContextD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DynamicUploadHeap.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\GenerateMips.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\pch.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\PipelineStateD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RenderDeviceD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RenderDeviceFactoryD3D12.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\RootSignature.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\SamplerD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceBindingD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceCacheD3D12.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourceLayoutD3D12.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\ShaderResourcesD3D12.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\SwapChainD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\TextureViewD3D12Impl.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.props b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.props
new file mode 100644
index 00000000..adf13e2d
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/build/Windows.Shared/GraphicsEngineD3D12.props
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets" />
+ <PropertyGroup Label="UserMacros">
+ <EngineRoot>..\..\..\..</EngineRoot>
+ <GraphicsRoot>..\..\..</GraphicsRoot>
+ <ProjectRoot>..\..</ProjectRoot>
+ </PropertyGroup>
+ <PropertyGroup>
+ <IncludePath>$(GraphicsRoot)\GraphicsEngineD3D12\include;$(GraphicsRoot)\GraphicsEngineD3D12\interface;$(GraphicsRoot)\GraphicsEngine\include;$(GraphicsRoot)\GraphicsEngine\interface;$(GraphicsRoot)\GraphicsEngineD3DBase\include;$(GraphicsRoot)\GraphicsTools\include;$(EngineRoot)\Common\include;$(EngineRoot)\Common\interface;$(EngineRoot)\Platforms\interface;$(IntDir)CompiledShaders;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup />
+ <ItemGroup>
+ <BuildMacro Include="EngineRoot">
+ <Value>$(EngineRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GraphicsRoot">
+ <Value>$(GraphicsRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="ProjectRoot">
+ <Value>$(ProjectRoot)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h
new file mode 100644
index 00000000..9ee4e25d
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h
@@ -0,0 +1,114 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::BufferD3D12Impl class
+
+#include "BufferD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "BufferBase.h"
+#include "BufferViewD3D12Impl.h"
+#include "D3D12ResourceBase.h"
+#include "DynamicUploadHeap.h"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+
+/// Implementation of the Diligent::IBufferD3D12 interface
+class BufferD3D12Impl : public BufferBase<IBufferD3D12, BufferViewD3D12Impl, FixedBlockMemoryAllocator, FixedBlockMemoryAllocator>, public D3D12ResourceBase
+{
+public:
+ typedef BufferBase<IBufferD3D12, BufferViewD3D12Impl, FixedBlockMemoryAllocator, FixedBlockMemoryAllocator> TBufferBase;
+ BufferD3D12Impl(FixedBlockMemoryAllocator &BufferObjMemAllocator,
+ FixedBlockMemoryAllocator &BuffViewObjMemAllocator,
+ class RenderDeviceD3D12Impl *pDeviceD3D12,
+ const BufferDesc& BuffDesc,
+ const BufferData &BuffData = BufferData());
+ ~BufferD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 Offset, Uint32 Size, const PVoid pData )override;
+ virtual void CopyData( IDeviceContext *pContext, IBuffer *pSrcBuffer, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size )override;
+ virtual void Map( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData )override;
+ virtual void Unmap( IDeviceContext *pContext, MAP_TYPE MapType )override;
+
+#ifdef _DEBUG
+ void DbgVerifyDynamicAllocation(Uint32 ContextId);
+#endif
+
+ virtual ID3D12Resource *GetD3D12Buffer(size_t &DataStartByteOffset, Uint32 ContextId)override final
+ {
+ if(m_Desc.Usage == USAGE_DYNAMIC)
+ {
+#ifdef _DEBUG
+ DbgVerifyDynamicAllocation(ContextId);
+#endif
+ DataStartByteOffset = m_DynamicData[ContextId].Offset;
+ return m_DynamicData[ContextId].pBuffer;
+ }
+ else
+ {
+ DataStartByteOffset = 0;
+ return GetD3D12Resource();
+ }
+ }
+
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint32 ContextId)
+ {
+ if(m_Desc.Usage == USAGE_DYNAMIC)
+ {
+#ifdef _DEBUG
+ DbgVerifyDynamicAllocation(ContextId);
+#endif
+ return m_DynamicData[ContextId].GPUAddress;
+ }
+ else
+ {
+ return GetD3D12Resource()->GetGPUVirtualAddress();
+ }
+ }
+
+ D3D12_CPU_DESCRIPTOR_HANDLE GetCBVHandle(){return m_CBVDescriptorAllocation.GetCpuHandle();}
+
+private:
+ virtual void CreateViewInternal( const struct BufferViewDesc &ViewDesc, IBufferView **ppView, bool bIsDefaultView )override;
+
+ void CreateUAV( struct BufferViewDesc &UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVDescriptor );
+ void CreateSRV( struct BufferViewDesc &SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVDescriptor );
+ void CreateCBV( D3D12_CPU_DESCRIPTOR_HANDLE CBVDescriptor );
+ DescriptorHeapAllocation m_CBVDescriptorAllocation;
+
+#ifdef _DEBUG
+ std::vector<MAP_TYPE, STDAllocatorRawMem<MAP_TYPE> > m_DbgMapType;
+#endif
+
+ friend class DeviceContextD3D12Impl;
+ std::vector<DynamicAllocation, STDAllocatorRawMem<DynamicAllocation> > m_DynamicData;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h
new file mode 100644
index 00000000..f5aff0ab
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h
@@ -0,0 +1,59 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::BufferViewD3D12Impl class
+
+#include "BufferViewD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "BufferViewBase.h"
+#include "DescriptorHeap.h"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+/// Implementation of the Diligent::IBufferViewD3D12 interface
+class BufferViewD3D12Impl : public BufferViewBase<IBufferViewD3D12, FixedBlockMemoryAllocator>
+{
+public:
+ typedef BufferViewBase<IBufferViewD3D12, FixedBlockMemoryAllocator> TBufferViewBase;
+
+ BufferViewD3D12Impl( FixedBlockMemoryAllocator &BuffViewAllocator,
+ IRenderDevice *pDevice,
+ const BufferViewDesc& ViewDesc,
+ class IBuffer *pBuffer,
+ DescriptorHeapAllocation &&HandleAlloc,
+ bool bIsDefaultView);
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle()override{return m_DescriptorHandle.GetCpuHandle();}
+
+protected:
+ DescriptorHeapAllocation m_DescriptorHandle;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.h b/Graphics/GraphicsEngineD3D12/include/CommandContext.h
new file mode 100644
index 00000000..71482511
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.h
@@ -0,0 +1,615 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+// Adapted to Diligent Engine: Egor Yusov
+//
+
+#pragma once
+
+#include "pch.h"
+#include <vector>
+
+#include "D3D12ResourceBase.h"
+#include "TextureViewD3D12.h"
+#include "TextureD3D12.h"
+#include "BufferD3D12.h"
+#include "DescriptorHeap.h"
+
+namespace Diligent
+{
+
+
+struct DWParam
+{
+ DWParam( FLOAT f ) : Float(f) {}
+ DWParam( UINT u ) : Uint(u) {}
+ DWParam( INT i ) : Int(i) {}
+
+ void operator= ( FLOAT f ) { Float = f; }
+ void operator= ( UINT u ) { Uint = u; }
+ void operator= ( INT i ) { Int = i; }
+
+ union
+ {
+ FLOAT Float;
+ UINT Uint;
+ INT Int;
+ };
+};
+
+
+class CommandContext
+{
+public:
+
+ CommandContext( IMemoryAllocator &MemAllocator,
+ class CommandListManager& CmdListManager,
+ GPUDescriptorHeap GPUDescriptorHeaps[],
+ Uint32 DynamicDescriptorAllocationChunkSize[]);
+
+ ~CommandContext(void);
+
+ // Submit the command buffer and reset it. This is encouraged to keep the GPU busy and reduce latency.
+ // Taking too long to build command lists and submit them can idle the GPU.
+ // Returns a fence value to verify completion. (Use it with the CommandListManager.)
+
+ ID3D12GraphicsCommandList* Close(ID3D12CommandAllocator **ppAllocator);
+ void Reset( CommandListManager& CmdListManager );
+
+ class GraphicsContext& AsGraphicsContext();
+ class ComputeContext& AsComputeContext();
+
+ void ClearUAVFloat( ITextureViewD3D12 *pTexView, const float* Color );
+ void ClearUAVUint( ITextureViewD3D12 *pTexView, const UINT *Color );
+
+ void CopyResource(ID3D12Resource *pDstRes, ID3D12Resource *pSrcRes)
+ {
+ m_pCommandList->CopyResource(pDstRes, pSrcRes);
+ }
+
+ //void CopyBuffer( GpuResource& Dest, GpuResource& Src );
+ //void CopyBufferRegion( GpuResource& Dest, size_t DestOffset, GpuResource& Src, size_t SrcOffset, size_t NumBytes );
+ //void CopySubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex);
+ //void CopyCounter(GpuResource& Dest, size_t DestOffset, StructuredBuffer& Src);
+ //void ResetCounter(StructuredBuffer& Buf, uint32_t Value = 0);
+
+ //static void InitializeTextureArraySlice(GpuResource& Dest, UINT SliceIndex, GpuResource& Src);
+
+ void TransitionResource(ITextureD3D12 *pTexture, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
+ void TransitionResource(IBufferD3D12 *pBuffer, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
+ //void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
+ void FlushResourceBarriers();
+
+ //void InsertTimeStamp( ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx );
+ //void ResolveTimeStamps( ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries );
+ //void PIXBeginEvent(const wchar_t* label);
+ //void PIXEndEvent(void);
+ //void PIXSetMarker(const wchar_t* label);
+
+ struct ShaderDescriptorHeaps
+ {
+ ID3D12DescriptorHeap* pSrvCbvUavHeap;
+ ID3D12DescriptorHeap* pSamplerHeap;
+ ShaderDescriptorHeaps(ID3D12DescriptorHeap* _pSrvCbvUavHeap = nullptr, ID3D12DescriptorHeap* _pSamplerHeap = nullptr) :
+ pSrvCbvUavHeap(_pSrvCbvUavHeap),
+ pSamplerHeap(_pSamplerHeap)
+ {}
+ bool operator == (const ShaderDescriptorHeaps& rhs)const
+ {
+ return pSrvCbvUavHeap == rhs.pSrvCbvUavHeap && pSamplerHeap == rhs.pSamplerHeap;
+ }
+ operator bool()const
+ {
+ return pSrvCbvUavHeap != nullptr || pSamplerHeap != nullptr;
+ }
+ };
+ void SetDescriptorHeaps( ShaderDescriptorHeaps& Heaps );
+
+ void ExecuteIndirect(ID3D12CommandSignature *pCmdSignature, ID3D12Resource *pBuff, Uint64 ArgsOffset)
+ {
+ FlushResourceBarriers();
+ m_pCommandList->ExecuteIndirect(pCmdSignature, 1, pBuff, ArgsOffset, nullptr, 0);
+ }
+
+ void SetID(const Char* ID) { m_ID = ID; }
+ ID3D12GraphicsCommandList *GetCommandList(){return m_pCommandList;}
+
+ void DiscardUsedDescriptorHeaps(Uint64 FrameNumber);
+ DescriptorHeapAllocation AllocateDynamicGPUVisibleDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
+
+ void InsertUAVBarrier(D3D12ResourceBase& Resource, IDeviceObject &Object, bool FlushImmediate = false);
+
+protected:
+ void TransitionResource(D3D12ResourceBase& Resource, IDeviceObject &Object, D3D12_RESOURCE_STATES NewState, bool FlushImmediate);
+ void InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, IDeviceObject &BeforeObj, IDeviceObject &AfterObj, bool FlushImmediate = false);
+
+ //void FinishTimeStampQueryBatch();
+ //void BindDescriptorHeaps( void );
+
+ CComPtr<ID3D12GraphicsCommandList> m_pCommandList;
+ CComPtr<ID3D12CommandAllocator> m_pCurrentAllocator;
+
+ ID3D12RootSignature* m_pCurGraphicsRootSignature;
+ ID3D12PipelineState* m_pCurGraphicsPipelineState;
+ ID3D12RootSignature* m_pCurComputeRootSignature;
+ ID3D12PipelineState* m_pCurComputePipelineState;
+
+ static const int MaxPendingBarriers = 16;
+ std::vector<D3D12_RESOURCE_BARRIER, STDAllocatorRawMem<D3D12_RESOURCE_BARRIER> > m_PendingResourceBarriers;
+ // We must make sure that all referenced objects are alive until barriers are executed
+ // Keeping reference to ID3D12Resource is not sufficient!
+ // TextureD3D12Impl::~TextureD3D12Impl() and BufferD3D12Impl::~BufferD3D12Impl()
+ // are responsible for putting the D3D12 resource in the release queue
+ std::vector< RefCntAutoPtr<IDeviceObject>, STDAllocatorRawMem<RefCntAutoPtr<IDeviceObject>> > m_PendingBarrierObjects;
+
+ ShaderDescriptorHeaps m_BoundDescriptorHeaps;
+
+ // Every context must use its own allocator that maintains individual list of retired descriptor heaps to
+ // avoid interference with other command contexts
+ // The heaps can only be discarded after the command list is submitted for execution
+ DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2];
+
+ String m_ID;
+
+ D3D12_PRIMITIVE_TOPOLOGY m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+};
+
+
+class GraphicsContext : public CommandContext
+{
+public:
+ void ClearRenderTarget( ITextureViewD3D12 *pRTV, const float *Color );
+ void ClearDepthStencil( ITextureViewD3D12 *pDSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil );
+
+ void SetRootSignature( ID3D12RootSignature *pRootSig )
+ {
+ if (pRootSig != m_pCurGraphicsRootSignature)
+ {
+ m_pCommandList->SetGraphicsRootSignature(m_pCurGraphicsRootSignature = pRootSig);
+ }
+ }
+
+ void SetRenderTargets( UINT NumRTVs, ITextureViewD3D12** ppRTVs, ITextureViewD3D12* pDSV );
+
+ void SetViewports( UINT NumVPs, const D3D12_VIEWPORT* pVPs )
+ {
+ m_pCommandList->RSSetViewports(NumVPs, pVPs);
+ }
+
+ void SetScissorRects( UINT NumRects, const D3D12_RECT* pRects )
+ {
+ m_pCommandList->RSSetScissorRects(NumRects, pRects);
+ }
+
+ void SetStencilRef( UINT StencilRef )
+ {
+ m_pCommandList->OMSetStencilRef( StencilRef );
+ }
+
+ void SetBlendFactor( const float* BlendFactor )
+ {
+ m_pCommandList->OMSetBlendFactor( BlendFactor );
+ }
+
+ void SetPrimitiveTopology( D3D12_PRIMITIVE_TOPOLOGY Topology )
+ {
+ if(m_PrimitiveTopology != Topology)
+ {
+ m_PrimitiveTopology = Topology;
+ m_pCommandList->IASetPrimitiveTopology(Topology);
+ }
+ }
+
+ void SetPipelineState( ID3D12PipelineState* pPSO )
+ {
+ if (pPSO != m_pCurGraphicsPipelineState)
+ {
+ m_pCommandList->SetPipelineState(m_pCurGraphicsPipelineState = pPSO);
+ }
+ }
+
+ void SetConstants( UINT RootIndex, UINT NumConstants, const void* pConstants )
+ {
+ m_pCommandList->SetGraphicsRoot32BitConstants( RootIndex, NumConstants, pConstants, 0 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X )
+ {
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y )
+ {
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z )
+ {
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W )
+ {
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );
+ m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, W.Uint, 3 );
+ }
+
+ void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )
+ {
+ m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV);
+ }
+
+ //void SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData );
+ //void SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV );
+ //void SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV );
+ void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )
+ {
+ m_pCommandList->SetGraphicsRootDescriptorTable( RootIndex, FirstHandle );
+ }
+
+
+ //void SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );
+ //void SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );
+
+ void SetIndexBuffer( const D3D12_INDEX_BUFFER_VIEW& IBView )
+ {
+ m_pCommandList->IASetIndexBuffer(&IBView);
+ }
+
+ void SetVertexBuffers( UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[] )
+ {
+ m_pCommandList->IASetVertexBuffers(StartSlot, Count, VBViews);
+ }
+
+ //void SetDynamicVB( UINT Slot, size_t NumVertices, size_t VertexStride, const void* VBData );
+ //void SetDynamicIB( size_t IndexCount, const uint16_t* IBData );
+ //void SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData);
+
+ void Draw(UINT VertexCountPerInstance, UINT InstanceCount,
+ UINT StartVertexLocation, UINT StartInstanceLocation)
+ {
+ FlushResourceBarriers();
+ m_pCommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);
+ }
+
+ void DrawIndexed(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation,
+ INT BaseVertexLocation, UINT StartInstanceLocation)
+ {
+ FlushResourceBarriers();
+ m_pCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);
+ }
+};
+
+class ComputeContext : public CommandContext
+{
+public:
+
+ void SetRootSignature( ID3D12RootSignature *pRootSig )
+ {
+ if (pRootSig != m_pCurComputeRootSignature)
+ {
+ m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig);
+ }
+ }
+
+
+ void SetPipelineState( ID3D12PipelineState* pPSO )
+ {
+ if (pPSO != m_pCurComputePipelineState)
+ {
+ m_pCommandList->SetPipelineState(m_pCurComputePipelineState = pPSO);
+ }
+ }
+
+ void SetConstants( UINT RootIndex, UINT NumConstants, const void* pConstants )
+ {
+ m_pCommandList->SetComputeRoot32BitConstants( RootIndex, NumConstants, pConstants, 0 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X )
+ {
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y )
+ {
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z )
+ {
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Z.Uint, 2 );
+ }
+
+ void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W )
+ {
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Z.Uint, 2 );
+ m_pCommandList->SetComputeRoot32BitConstant( RootIndex, W.Uint, 3 );
+ }
+
+
+ void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )
+ {
+ m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV);
+ }
+
+ //void SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData );
+ //void SetDynamicSRV( UINT RootIndex, size_t BufferSize, const void* BufferData );
+ //void SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV );
+ //void SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV );
+ void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )
+ {
+ m_pCommandList->SetComputeRootDescriptorTable( RootIndex, FirstHandle );
+ }
+
+
+ //void SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );
+ //void SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );
+
+ void Dispatch( size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1 )
+ {
+ FlushResourceBarriers();
+ m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ);
+ }
+};
+
+inline GraphicsContext& CommandContext::AsGraphicsContext()
+{
+ return static_cast<GraphicsContext&>(*this);
+}
+
+inline ComputeContext& CommandContext::AsComputeContext()
+{
+ return static_cast<ComputeContext&>(*this);
+}
+
+#if 0
+
+inline void GraphicsContext::SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData )
+{
+ ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));
+ DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);
+ //SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);
+ memcpy(cb.DataPtr, BufferData, BufferSize);
+ m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, cb.GpuAddress);
+}
+
+inline void ComputeContext::SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData )
+{
+ ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));
+ DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);
+ //SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);
+ memcpy(cb.DataPtr, BufferData, BufferSize);
+ m_pCommandList->SetComputeRootConstantBufferView(RootIndex, cb.GpuAddress);
+}
+
+inline void GraphicsContext::SetDynamicVB( UINT Slot, size_t NumVertices, size_t VertexStride, const void* VertexData )
+{
+ ASSERT(VertexData != nullptr && Math::IsAligned(VertexData, 16));
+
+ size_t BufferSize = Math::AlignUp(NumVertices * VertexStride, 16);
+ DynAlloc vb = m_CpuLinearAllocator.Allocate(BufferSize);
+
+ SIMDMemCopy(vb.DataPtr, VertexData, BufferSize >> 4);
+
+ D3D12_VERTEX_BUFFER_VIEW VBView;
+ VBView.BufferLocation = vb.GpuAddress;
+ VBView.SizeInBytes = (UINT)BufferSize;
+ VBView.StrideInBytes = (UINT)VertexStride;
+
+ m_pCommandList->IASetVertexBuffers(Slot, 1, &VBView);
+}
+
+inline void GraphicsContext::SetDynamicIB( size_t IndexCount, const uint16_t* IndexData )
+{
+ ASSERT(IndexData != nullptr && Math::IsAligned(IndexData, 16));
+
+ size_t BufferSize = Math::AlignUp(IndexCount * sizeof(uint16_t), 16);
+ DynAlloc ib = m_CpuLinearAllocator.Allocate(BufferSize);
+
+ SIMDMemCopy(ib.DataPtr, IndexData, BufferSize >> 4);
+
+ D3D12_INDEX_BUFFER_VIEW IBView;
+ IBView.BufferLocation = ib.GpuAddress;
+ IBView.SizeInBytes = (UINT)(IndexCount * sizeof(uint16_t));
+ IBView.Format = DXGI_FORMAT_R16_UINT;
+
+ m_pCommandList->IASetIndexBuffer(&IBView);
+}
+
+inline void GraphicsContext::SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData)
+{
+ ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));
+ DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);
+ SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);
+ m_pCommandList->SetGraphicsRootShaderResourceView(RootIndex, cb.GpuAddress);
+}
+
+inline void ComputeContext::SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData)
+{
+ ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));
+ DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);
+ SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);
+ m_pCommandList->SetComputeRootShaderResourceView(RootIndex, cb.GpuAddress);
+}
+
+inline void GraphicsContext::SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV )
+{
+ ASSERT((SRV.m_UsageState & (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)) != 0);
+ m_pCommandList->SetGraphicsRootShaderResourceView(RootIndex, SRV.GetGpuVirtualAddress());
+}
+
+inline void ComputeContext::SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV )
+{
+ ASSERT((SRV.m_UsageState & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) != 0);
+ m_pCommandList->SetComputeRootShaderResourceView(RootIndex, SRV.GetGpuVirtualAddress());
+}
+
+inline void GraphicsContext::SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV )
+{
+ ASSERT((UAV.m_UsageState & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != 0);
+ m_pCommandList->SetGraphicsRootUnorderedAccessView(RootIndex, UAV.GetGpuVirtualAddress());
+}
+
+inline void ComputeContext::SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV )
+{
+ ASSERT((UAV.m_UsageState & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != 0);
+ m_pCommandList->SetComputeRootUnorderedAccessView(RootIndex, UAV.GetGpuVirtualAddress());
+}
+
+
+
+inline void CommandContext::SetDescriptorHeap( D3D12_DESCRIPTOR_HEAP_TYPE Type, ID3D12DescriptorHeap* HeapPtr )
+{
+ if (m_CurrentDescriptorHeaps[Type] != HeapPtr)
+ {
+ m_CurrentDescriptorHeaps[Type] = HeapPtr;
+ BindDescriptorHeaps();
+ }
+}
+#endif
+
+inline void CommandContext::SetDescriptorHeaps( ShaderDescriptorHeaps& Heaps )
+{
+#ifdef _DEBUG
+ VERIFY(Heaps.pSrvCbvUavHeap != nullptr || Heaps.pSamplerHeap != nullptr, "At least one heap is expected to be set");
+ VERIFY(Heaps.pSrvCbvUavHeap == nullptr || Heaps.pSrvCbvUavHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, "Invalid heap type provided in pSrvCbvUavHeap");
+ VERIFY(Heaps.pSamplerHeap == nullptr || Heaps.pSamplerHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type provided in pSamplerHeap");
+#endif
+
+ if (!(Heaps == m_BoundDescriptorHeaps))
+ {
+ m_BoundDescriptorHeaps = Heaps;
+
+ ID3D12DescriptorHeap **ppHeaps = reinterpret_cast<ID3D12DescriptorHeap**>(&Heaps);
+ UINT NumHeaps = (ppHeaps[0] != nullptr ? 1 : 0) + (ppHeaps[1] != nullptr ? 1 : 0);
+ if(ppHeaps[0] == nullptr)
+ ++ppHeaps;
+
+ m_pCommandList->SetDescriptorHeaps(NumHeaps, ppHeaps);
+ }
+}
+
+#if 0
+inline void GraphicsContext::SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )
+{
+ SetDynamicDescriptors(RootIndex, Offset, 1, &Handle);
+}
+
+inline void ComputeContext::SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )
+{
+ SetDynamicDescriptors(RootIndex, Offset, 1, &Handle);
+}
+
+inline void GraphicsContext::SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )
+{
+ m_DynamicDescriptorHeap.SetGraphicsDescriptorHandles(RootIndex, Offset, Count, Handles);
+}
+
+inline void ComputeContext::SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )
+{
+ m_DynamicDescriptorHeap.SetComputeDescriptorHandles(RootIndex, Offset, Count, Handles);
+}
+
+
+inline void CommandContext::CopyBuffer( GpuResource& Dest, GpuResource& Src )
+{
+ TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);
+ TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ FlushResourceBarriers();
+ m_pCommandList->CopyResource(Dest.GetResource(), Src.GetResource());
+}
+
+
+inline void CommandContext::CopyCounter(GpuResource& Dest, size_t DestOffset, StructuredBuffer& Src)
+{
+ TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);
+ TransitionResource(Src.GetCounterBuffer(), D3D12_RESOURCE_STATE_COPY_SOURCE);
+ FlushResourceBarriers();
+ m_pCommandList->CopyBufferRegion(Dest.GetResource(), DestOffset, Src.GetCounterBuffer().GetResource(), 0, 4);
+}
+
+inline void CommandContext::ResetCounter(StructuredBuffer& Buf, uint32_t Value )
+{
+ FillBuffer(Buf.GetCounterBuffer(), 0, Value, sizeof(uint32_t));
+ TransitionResource(Buf.GetCounterBuffer(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+}
+
+inline void CommandContext::InsertTimeStamp(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx)
+{
+ m_pCommandList->EndQuery(pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, QueryIdx);
+}
+
+inline void CommandContext::ResolveTimeStamps(ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries)
+{
+ m_pCommandList->ResolveQueryData(pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, NumQueries, pReadbackHeap, 0);
+}
+
+inline void CommandContext::PIXBeginEvent(const wchar_t* label)
+{
+#if defined(RELEASE) || _MSC_VER < 1800
+ (label);
+#else
+ ::PIXBeginEvent(m_pCommandList, 0, label);
+#endif
+}
+
+inline void CommandContext::PIXEndEvent(void)
+{
+#if !defined(RELEASE) && _MSC_VER >= 1800
+ ::PIXEndEvent(m_pCommandList);
+#endif
+}
+
+inline void CommandContext::PIXSetMarker(const wchar_t* label)
+{
+#if defined(RELEASE) || _MSC_VER < 1800
+ (label);
+#else
+ ::PIXSetMarker(m_pCommandList, 0, label);
+#endif
+}
+#endif
+} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h
new file mode 100644
index 00000000..00e5fcaa
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h
@@ -0,0 +1,61 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::CommandListD3D12Impl class
+
+#include "CommandListBase.h"
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::ICommandList interface
+class CommandListD3D12Impl : public CommandListBase<ICommandList, FixedBlockMemoryAllocator>
+{
+public:
+ typedef CommandListBase<ICommandList, FixedBlockMemoryAllocator> TCommandListBase;
+ CommandListD3D12Impl(FixedBlockMemoryAllocator &Allocator, IRenderDevice *pDevice, class CommandContext* pCmdContext) :
+ TCommandListBase(Allocator, pDevice),
+ m_pCmdContext(pCmdContext)
+ {
+ }
+
+ ~CommandListD3D12Impl()
+ {
+ VERIFY(m_pCmdContext == nullptr, "Destroying command list that was never executed");
+ }
+
+ CommandContext* Close()
+ {
+ CommandContext* pCmdContext = m_pCmdContext;
+ m_pCmdContext = nullptr;
+ return pCmdContext;
+ }
+
+private:
+ CommandContext* m_pCmdContext = nullptr;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListManager.h b/Graphics/GraphicsEngineD3D12/include/CommandListManager.h
new file mode 100644
index 00000000..a9b79650
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/CommandListManager.h
@@ -0,0 +1,73 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+// Adapted to Diligent Engine: Egor Yusov
+
+#pragma once
+
+#include <vector>
+#include <deque>
+#include <mutex>
+#include <stdint.h>
+
+namespace Diligent
+{
+
+class CommandListManager
+{
+public:
+ CommandListManager(class RenderDeviceD3D12Impl *pDeviceD3D12);
+ ~CommandListManager();
+
+ CommandListManager(const CommandListManager&) = delete;
+ CommandListManager(CommandListManager&&) = delete;
+ CommandListManager& operator = (const CommandListManager&) = delete;
+ CommandListManager& operator = (CommandListManager&&) = delete;
+
+ void CreateNewCommandList( ID3D12GraphicsCommandList** ppList, ID3D12CommandAllocator** ppAllocator );
+ void DiscardAllocator( Uint64 FenceValueForReset, ID3D12CommandAllocator* pAllocator );
+ void RequestAllocator(ID3D12CommandAllocator** ppAllocator);
+
+private:
+ // Since there is only a "main pool" so far, everything below corresponds to that pool. It should be renamed and/or
+ // restructured if we add other pools.
+ typedef std::pair<Uint64, CComPtr<ID3D12CommandAllocator> > DiscardedAllocatorQueueElemType;
+ std::deque< DiscardedAllocatorQueueElemType, STDAllocatorRawMem<DiscardedAllocatorQueueElemType> > m_DiscardedAllocators;
+
+ std::mutex m_AllocatorMutex;
+ RenderDeviceD3D12Impl *m_pDeviceD3D12;
+};
+
+} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h
new file mode 100644
index 00000000..e8faa4a3
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h
@@ -0,0 +1,53 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Implementation of the Diligent::D3D12ResourceBase class
+
+namespace Diligent
+{
+
+/// Base implementation of a D3D12 resource
+class D3D12ResourceBase
+{
+public:
+ D3D12ResourceBase() :
+ m_UsageState(D3D12_RESOURCE_STATE_COMMON)/*,
+ m_TransitioningState((D3D12_RESOURCE_STATES)-1)*/
+ {}
+
+ D3D12_RESOURCE_STATES GetState()const{return m_UsageState;}
+ void SetState(D3D12_RESOURCE_STATES UsageState){m_UsageState = UsageState;}
+ bool CheckAllStates(D3D12_RESOURCE_STATES States)const{return (m_UsageState & States) == States;}
+ bool CheckAnyState(D3D12_RESOURCE_STATES States)const{return (m_UsageState & States) != 0;}
+ ID3D12Resource *GetD3D12Resource(){ return m_pd3d12Resource; }
+
+protected:
+ D3D12_RESOURCE_STATES m_UsageState;
+ //D3D12_RESOURCE_STATES m_TransitioningState;
+ CComPtr<ID3D12Resource> m_pd3d12Resource; ///< D3D12 buffer object
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.h b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.h
new file mode 100644
index 00000000..d909bd42
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.h
@@ -0,0 +1,56 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Type conversion routines
+
+#include "GraphicsTypes.h"
+
+namespace Diligent
+{
+
+D3D12_COMPARISON_FUNC ComparisonFuncToD3D12ComparisonFunc(COMPARISON_FUNCTION Func);
+D3D12_FILTER FilterTypeToD3D12Filter(FILTER_TYPE MinFilter, FILTER_TYPE MagFilter, FILTER_TYPE MipFilter);
+D3D12_TEXTURE_ADDRESS_MODE TexAddressModeToD3D12AddressMode(TEXTURE_ADDRESS_MODE Mode);
+D3D12_PRIMITIVE_TOPOLOGY TopologyToD3D12Topology(PRIMITIVE_TOPOLOGY Topology);
+
+void DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(const DepthStencilStateDesc &DepthStencilDesc, D3D12_DEPTH_STENCIL_DESC &d3d12DSSDesc);
+void RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(const RasterizerStateDesc &RasterizerDesc, D3D12_RASTERIZER_DESC &d3d11RSDesc);
+void BlendStateDesc_To_D3D12_BLEND_DESC(const BlendStateDesc &BSDesc, D3D12_BLEND_DESC &d3d12BlendDesc);
+
+void LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(const std::vector<LayoutElement, STDAllocatorRawMem<LayoutElement>> &LayoutElements,
+ std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC> > &d3d12InputElements);
+
+void TextureViewDesc_to_D3D12_SRV_DESC(const TextureViewDesc& SRVDesc, D3D12_SHADER_RESOURCE_VIEW_DESC &D3D12SRVDesc, Uint32 SampleCount);
+void TextureViewDesc_to_D3D12_RTV_DESC(const TextureViewDesc& RTVDesc, D3D12_RENDER_TARGET_VIEW_DESC &D3D12RTVDesc, Uint32 SampleCount);
+void TextureViewDesc_to_D3D12_DSV_DESC(const TextureViewDesc& DSVDesc, D3D12_DEPTH_STENCIL_VIEW_DESC &D3D12DSVDesc, Uint32 SampleCount);
+void TextureViewDesc_to_D3D12_UAV_DESC(const TextureViewDesc& UAVDesc, D3D12_UNORDERED_ACCESS_VIEW_DESC &D3D12UAVDesc);
+
+void BufferViewDesc_to_D3D12_SRV_DESC(const BufferDesc &BuffDesc, const BufferViewDesc& SRVDesc, D3D12_SHADER_RESOURCE_VIEW_DESC &D3D12SRVDesc);
+void BufferViewDesc_to_D3D12_UAV_DESC(const BufferDesc &BuffDesc, const BufferViewDesc& UAVDesc, D3D12_UNORDERED_ACCESS_VIEW_DESC &D3D12UAVDesc);
+
+D3D12_STATIC_BORDER_COLOR BorderColorToD3D12StaticBorderColor(const Float32 BorderColor[]);
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12TypeDefinitions.h b/Graphics/GraphicsEngineD3D12/include/D3D12TypeDefinitions.h
new file mode 100644
index 00000000..892de4aa
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12TypeDefinitions.h
@@ -0,0 +1,187 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definitions of D3D12 types
+
+// Filters
+#define D3D_FILTER_MIN_MAG_MIP_POINT D3D12_FILTER_MIN_MAG_MIP_POINT
+#define D3D_FILTER_MIN_MAG_POINT_MIP_LINEAR D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MIN_POINT_MAG_MIP_LINEAR D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR
+#define D3D_FILTER_MIN_LINEAR_MAG_MIP_POINT D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT
+#define D3D_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MIN_MAG_LINEAR_MIP_POINT D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MIN_MAG_MIP_LINEAR D3D12_FILTER_MIN_MAG_MIP_LINEAR
+#define D3D_FILTER_ANISOTROPIC D3D12_FILTER_ANISOTROPIC
+
+#define D3D_FILTER_COMPARISON_MIN_MAG_MIP_POINT D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT
+#define D3D_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR
+#define D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT
+#define D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR
+#define D3D_FILTER_COMPARISON_ANISOTROPIC D3D12_FILTER_COMPARISON_ANISOTROPIC
+
+#define D3D_FILTER_MINIMUM_MIN_MAG_MIP_POINT D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT
+#define D3D_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR D3D12_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT D3D12_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR D3D12_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR
+#define D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT
+#define D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT D3D12_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR D3D12_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR
+#define D3D_FILTER_MINIMUM_ANISOTROPIC D3D12_FILTER_MINIMUM_ANISOTROPIC
+
+#define D3D_FILTER_MAXIMUM_MIN_MAG_MIP_POINT D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT
+#define D3D_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR D3D12_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR
+#define D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT
+#define D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR
+#define D3D_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT D3D12_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT
+#define D3D_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR
+#define D3D_FILTER_MAXIMUM_ANISOTROPIC D3D12_FILTER_MAXIMUM_ANISOTROPIC
+
+// Comparison functions
+#define D3D_COMPARISON_FUNC_NEVER D3D12_COMPARISON_FUNC_NEVER
+#define D3D_COMPARISON_FUNC_LESS D3D12_COMPARISON_FUNC_LESS
+#define D3D_COMPARISON_FUNC_EQUAL D3D12_COMPARISON_FUNC_EQUAL
+#define D3D_COMPARISON_FUNC_LESS_EQUAL D3D12_COMPARISON_FUNC_LESS_EQUAL
+#define D3D_COMPARISON_FUNC_GREATER D3D12_COMPARISON_FUNC_GREATER
+#define D3D_COMPARISON_FUNC_NOT_EQUAL D3D12_COMPARISON_FUNC_NOT_EQUAL
+#define D3D_COMPARISON_FUNC_GREATER_EQUAL D3D12_COMPARISON_FUNC_GREATER_EQUAL
+#define D3D_COMPARISON_FUNC_ALWAYS D3D12_COMPARISON_FUNC_ALWAYS
+
+// Stencil operations
+#define D3D_STENCIL_OP_KEEP D3D12_STENCIL_OP_KEEP
+#define D3D_STENCIL_OP_ZERO D3D12_STENCIL_OP_ZERO
+#define D3D_STENCIL_OP_REPLACE D3D12_STENCIL_OP_REPLACE
+#define D3D_STENCIL_OP_INCR_SAT D3D12_STENCIL_OP_INCR_SAT
+#define D3D_STENCIL_OP_DECR_SAT D3D12_STENCIL_OP_DECR_SAT
+#define D3D_STENCIL_OP_INVERT D3D12_STENCIL_OP_INVERT
+#define D3D_STENCIL_OP_INCR D3D12_STENCIL_OP_INCR
+#define D3D_STENCIL_OP_DECR D3D12_STENCIL_OP_DECR
+
+// Depth write masks
+#define D3D_DEPTH_WRITE_MASK_ALL D3D12_DEPTH_WRITE_MASK_ALL
+#define D3D_DEPTH_WRITE_MASK_ZERO D3D12_DEPTH_WRITE_MASK_ZERO
+
+// Cull modes
+#define D3D_CULL_MODE_NONE D3D12_CULL_MODE_NONE
+#define D3D_CULL_MODE_FRONT D3D12_CULL_MODE_FRONT
+#define D3D_CULL_MODE_BACK D3D12_CULL_MODE_BACK
+
+// Fill modes
+#define D3D_FILL_MODE_WIREFRAME D3D12_FILL_MODE_WIREFRAME
+#define D3D_FILL_MODE_SOLID D3D12_FILL_MODE_SOLID
+
+// Blend sources
+#define D3D_BLEND_ZERO D3D12_BLEND_ZERO
+#define D3D_BLEND_ONE D3D12_BLEND_ONE
+#define D3D_BLEND_SRC_COLOR D3D12_BLEND_SRC_COLOR
+#define D3D_BLEND_INV_SRC_COLOR D3D12_BLEND_INV_SRC_COLOR
+#define D3D_BLEND_SRC_ALPHA D3D12_BLEND_SRC_ALPHA
+#define D3D_BLEND_INV_SRC_ALPHA D3D12_BLEND_INV_SRC_ALPHA
+#define D3D_BLEND_DEST_ALPHA D3D12_BLEND_DEST_ALPHA
+#define D3D_BLEND_INV_DEST_ALPHA D3D12_BLEND_INV_DEST_ALPHA
+#define D3D_BLEND_DEST_COLOR D3D12_BLEND_DEST_COLOR
+#define D3D_BLEND_INV_DEST_COLOR D3D12_BLEND_INV_DEST_COLOR
+#define D3D_BLEND_SRC_ALPHA_SAT D3D12_BLEND_SRC_ALPHA_SAT
+#define D3D_BLEND_BLEND_FACTOR D3D12_BLEND_BLEND_FACTOR
+#define D3D_BLEND_INV_BLEND_FACTOR D3D12_BLEND_INV_BLEND_FACTOR
+#define D3D_BLEND_SRC1_COLOR D3D12_BLEND_SRC1_COLOR
+#define D3D_BLEND_INV_SRC1_COLOR D3D12_BLEND_INV_SRC1_COLOR
+#define D3D_BLEND_SRC1_ALPHA D3D12_BLEND_SRC1_ALPHA
+#define D3D_BLEND_INV_SRC1_ALPHA D3D12_BLEND_INV_SRC1_ALPHA
+
+// Blend operations
+#define D3D_BLEND_OP_ADD D3D12_BLEND_OP_ADD
+#define D3D_BLEND_OP_SUBTRACT D3D12_BLEND_OP_SUBTRACT
+#define D3D_BLEND_OP_REV_SUBTRACT D3D12_BLEND_OP_REV_SUBTRACT
+#define D3D_BLEND_OP_MIN D3D12_BLEND_OP_MIN
+#define D3D_BLEND_OP_MAX D3D12_BLEND_OP_MAX
+
+// Color masks
+#define D3D_COLOR_WRITE_ENABLE_RED D3D12_COLOR_WRITE_ENABLE_RED
+#define D3D_COLOR_WRITE_ENABLE_GREEN D3D12_COLOR_WRITE_ENABLE_GREEN
+#define D3D_COLOR_WRITE_ENABLE_BLUE D3D12_COLOR_WRITE_ENABLE_BLUE
+#define D3D_COLOR_WRITE_ENABLE_ALPHA D3D12_COLOR_WRITE_ENABLE_ALPHA
+
+// Input classification
+#define D3D_INPUT_CLASSIFICATION_PER_VERTEX_DATA D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA
+#define D3D_INPUT_CLASSIFICATION_PER_INSTANCE_DATA D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA
+
+// Texture address modes
+#define D3D_TEXTURE_ADDRESS_WRAP D3D12_TEXTURE_ADDRESS_MODE_WRAP
+#define D3D_TEXTURE_ADDRESS_MIRROR D3D12_TEXTURE_ADDRESS_MODE_MIRROR
+#define D3D_TEXTURE_ADDRESS_CLAMP D3D12_TEXTURE_ADDRESS_MODE_CLAMP
+#define D3D_TEXTURE_ADDRESS_BORDER D3D12_TEXTURE_ADDRESS_MODE_BORDER
+#define D3D_TEXTURE_ADDRESS_MIRROR_ONCE D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE
+
+// SRV Dimensions
+#define D3D_SRV_DIMENSION_UNKNOWN D3D12_SRV_DIMENSION_UNKNOWN
+#define D3D_SRV_DIMENSION_BUFFER D3D12_SRV_DIMENSION_BUFFER
+#define D3D_SRV_DIMENSION_TEXTURE1D D3D12_SRV_DIMENSION_TEXTURE1D
+#define D3D_SRV_DIMENSION_TEXTURE1DARRAY D3D12_SRV_DIMENSION_TEXTURE1DARRAY
+#define D3D_SRV_DIMENSION_TEXTURE2D D3D12_SRV_DIMENSION_TEXTURE2D
+#define D3D_SRV_DIMENSION_TEXTURE2DARRAY D3D12_SRV_DIMENSION_TEXTURE2DARRAY
+#define D3D_SRV_DIMENSION_TEXTURE2DMS D3D12_SRV_DIMENSION_TEXTURE2DMS
+#define D3D_SRV_DIMENSION_TEXTURE2DMSARRAY D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY
+#define D3D_SRV_DIMENSION_TEXTURE3D D3D12_SRV_DIMENSION_TEXTURE3D
+#define D3D_SRV_DIMENSION_TEXTURECUBE D3D12_SRV_DIMENSION_TEXTURECUBE
+#define D3D_SRV_DIMENSION_TEXTURECUBEARRAY D3D12_SRV_DIMENSION_TEXTURECUBEARRAY
+
+// RTV Dimensions
+#define D3D_RTV_DIMENSION_UNKNOWN D3D12_RTV_DIMENSION_UNKNOWN
+#define D3D_RTV_DIMENSION_BUFFER D3D12_RTV_DIMENSION_BUFFER
+#define D3D_RTV_DIMENSION_TEXTURE1D D3D12_RTV_DIMENSION_TEXTURE1D
+#define D3D_RTV_DIMENSION_TEXTURE1DARRAY D3D12_RTV_DIMENSION_TEXTURE1DARRAY
+#define D3D_RTV_DIMENSION_TEXTURE2D D3D12_RTV_DIMENSION_TEXTURE2D
+#define D3D_RTV_DIMENSION_TEXTURE2DARRAY D3D12_RTV_DIMENSION_TEXTURE2DARRAY
+#define D3D_RTV_DIMENSION_TEXTURE2DMS D3D12_RTV_DIMENSION_TEXTURE2DMS
+#define D3D_RTV_DIMENSION_TEXTURE2DMSARRAY D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY
+#define D3D_RTV_DIMENSION_TEXTURE3D D3D12_RTV_DIMENSION_TEXTURE3D
+
+
+// DSV Dimensions
+#define D3D_DSV_DIMENSION_UNKNOWN D3D12_DSV_DIMENSION_UNKNOWN
+#define D3D_DSV_DIMENSION_TEXTURE1D D3D12_DSV_DIMENSION_TEXTURE1D
+#define D3D_DSV_DIMENSION_TEXTURE1DARRAY D3D12_DSV_DIMENSION_TEXTURE1DARRAY
+#define D3D_DSV_DIMENSION_TEXTURE2D D3D12_DSV_DIMENSION_TEXTURE2D
+#define D3D_DSV_DIMENSION_TEXTURE2DARRAY D3D12_DSV_DIMENSION_TEXTURE2DARRAY
+#define D3D_DSV_DIMENSION_TEXTURE2DMS D3D12_DSV_DIMENSION_TEXTURE2DMS
+#define D3D_DSV_DIMENSION_TEXTURE2DMSARRAY D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY
+
+// UAV Dimensions
+#define D3D_UAV_DIMENSION_UNKNOWN D3D12_UAV_DIMENSION_UNKNOWN
+#define D3D_UAV_DIMENSION_BUFFER D3D12_UAV_DIMENSION_BUFFER
+#define D3D_UAV_DIMENSION_TEXTURE1D D3D12_UAV_DIMENSION_TEXTURE1D
+#define D3D_UAV_DIMENSION_TEXTURE1DARRAY D3D12_UAV_DIMENSION_TEXTURE1DARRAY
+#define D3D_UAV_DIMENSION_TEXTURE2D D3D12_UAV_DIMENSION_TEXTURE2D
+#define D3D_UAV_DIMENSION_TEXTURE2DARRAY D3D12_UAV_DIMENSION_TEXTURE2DARRAY
+#define D3D_UAV_DIMENSION_TEXTURE3D D3D12_UAV_DIMENSION_TEXTURE3D \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h b/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h
new file mode 100644
index 00000000..64ee7c40
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h
@@ -0,0 +1,31 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "BasicTypes.h"
+namespace Diligent
+{
+ const Char* GetD3D12DescriptorHeapTypeLiteralName(D3D12_DESCRIPTOR_HEAP_TYPE Type);
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
new file mode 100644
index 00000000..b96977e6
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
@@ -0,0 +1,362 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+#include <queue>
+#include <string>
+#include <set>
+#include "ObjectBase.h"
+#include "FreeBlockListManagerGPU.h"
+
+namespace Diligent
+{
+
+class DescriptorHeapAllocation;
+class DescriptorHeapAllocationManager;
+class RenderDeviceD3D12Impl;
+
+class IDescriptorAllocator
+{
+public:
+ virtual DescriptorHeapAllocation Allocate( uint32_t Count ) = 0;
+ virtual void Free(DescriptorHeapAllocation&& Allocation) = 0;
+ virtual Uint32 GetDescriptorSize()const = 0;
+};
+
+class DescriptorHeapAllocation
+{
+public:
+ DescriptorHeapAllocation() :
+ m_NumHandles(1), // One null descriptor handle
+ m_pDescriptorHeap(nullptr),
+ m_DescriptorSize(0)
+ {
+ m_FirstCpuHandle.ptr = 0;
+ m_FirstGpuHandle.ptr = 0;
+ }
+
+ DescriptorHeapAllocation( IDescriptorAllocator *pAllocator, ID3D12DescriptorHeap *pHeap, D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, Uint32 NHandles ) :
+ m_FirstCpuHandle(CpuHandle),
+ m_pAllocator(pAllocator),
+ m_pDescriptorHeap(pHeap),
+ m_NumHandles(NHandles)
+ {
+ m_FirstGpuHandle.ptr = 0;
+ VERIFY_EXPR(m_pAllocator != nullptr && m_pDescriptorHeap != nullptr);
+ auto DescriptorSize = m_pAllocator->GetDescriptorSize();
+ VERIFY(DescriptorSize < std::numeric_limits<Uint16>::max(), "DescriptorSize exceeds allowed limit")
+ m_DescriptorSize = static_cast<Uint16>( DescriptorSize );
+ }
+
+ DescriptorHeapAllocation( IDescriptorAllocator *pAllocator, ID3D12DescriptorHeap *pHeap, D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, Uint32 NHandles, Uint16 AllocationManagerId = static_cast<Uint16>(-1) ) :
+ m_FirstCpuHandle(CpuHandle),
+ m_FirstGpuHandle(GpuHandle),
+ m_pAllocator(pAllocator),
+ m_NumHandles(NHandles),
+ m_pDescriptorHeap(pHeap),
+ m_AllocationManagerId(AllocationManagerId)
+ {
+ VERIFY_EXPR(m_pAllocator != nullptr && m_pDescriptorHeap != nullptr);
+ auto DescriptorSize = m_pAllocator->GetDescriptorSize();
+ VERIFY(DescriptorSize < std::numeric_limits<Uint16>::max(), "DescriptorSize exceeds allowed limit")
+ m_DescriptorSize = static_cast<Uint16>( DescriptorSize );
+ }
+
+ DescriptorHeapAllocation(DescriptorHeapAllocation &&Allocation) :
+ m_FirstCpuHandle(Allocation.m_FirstCpuHandle),
+ m_FirstGpuHandle(Allocation.m_FirstGpuHandle),
+ m_NumHandles(Allocation.m_NumHandles),
+ m_pAllocator(std::move(Allocation.m_pAllocator)),
+ m_AllocationManagerId(std::move(Allocation.m_AllocationManagerId)),
+ m_pDescriptorHeap(std::move(Allocation.m_pDescriptorHeap) ),
+ m_DescriptorSize(std::move(Allocation.m_DescriptorSize) )
+ {
+ Allocation.m_pAllocator = nullptr;
+ Allocation.m_FirstCpuHandle.ptr = 0;
+ Allocation.m_FirstGpuHandle.ptr = 0;
+ Allocation.m_NumHandles = 0;
+ Allocation.m_pDescriptorHeap = nullptr;
+ Allocation.m_DescriptorSize = 0;
+ Allocation.m_AllocationManagerId = static_cast<Uint16>(-1);
+ }
+
+ DescriptorHeapAllocation& operator = (DescriptorHeapAllocation &&Allocation)
+ {
+ m_FirstCpuHandle = Allocation.m_FirstCpuHandle;
+ m_FirstGpuHandle = Allocation.m_FirstGpuHandle;
+ m_NumHandles = Allocation.m_NumHandles;
+ m_pAllocator = std::move(Allocation.m_pAllocator);
+ m_AllocationManagerId = std::move(Allocation.m_AllocationManagerId);
+ m_pDescriptorHeap = std::move(Allocation.m_pDescriptorHeap);
+ m_DescriptorSize = std::move(Allocation.m_DescriptorSize);
+
+ Allocation.m_FirstCpuHandle.ptr = 0;
+ Allocation.m_FirstGpuHandle.ptr = 0;
+ Allocation.m_NumHandles = 0;
+ Allocation.m_pAllocator = nullptr;
+ Allocation.m_pDescriptorHeap = nullptr;
+ Allocation.m_DescriptorSize = 0;
+ Allocation.m_AllocationManagerId = static_cast<Uint16>(-1);
+
+ return *this;
+ }
+
+ ~DescriptorHeapAllocation()
+ {
+ if(!IsNull() && m_pAllocator)
+ m_pAllocator->Free(std::move(*this));
+ }
+
+ D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Uint32 Offset = 0) const
+ {
+ VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles);
+
+ D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle = m_FirstCpuHandle;
+ if (Offset != 0)
+ {
+ CPUHandle.ptr += m_DescriptorSize * Offset;
+ }
+ return CPUHandle;
+ }
+
+ D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Uint32 Offset = 0) const
+ {
+ VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles);
+ D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle = m_FirstGpuHandle;
+ if (Offset != 0)
+ {
+ GPUHandle.ptr += m_DescriptorSize * Offset;
+ }
+ return GPUHandle;
+ }
+
+ ID3D12DescriptorHeap *GetDescriptorHeap(){return m_pDescriptorHeap;}
+
+ size_t GetNumHandles(){return m_NumHandles;}
+
+ bool IsNull() const { return m_FirstCpuHandle.ptr == 0; }
+ bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; }
+ size_t GetAllocationManagerId(){return m_AllocationManagerId;}
+ UINT GetDescriptorSize()const{return m_DescriptorSize;}
+
+private:
+ DescriptorHeapAllocation(const DescriptorHeapAllocation&) = delete;
+ DescriptorHeapAllocation& operator= (const DescriptorHeapAllocation&) = delete;
+
+ D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCpuHandle = {0};
+ D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGpuHandle = {0};
+ // Keep strong reference to the parent heap to make sure it is alive while allocation is alive
+ //RefCntAutoPtr<IDescriptorAllocator> m_pAllocator;
+ IDescriptorAllocator* m_pAllocator = nullptr;
+ ID3D12DescriptorHeap* m_pDescriptorHeap = nullptr;
+ Uint32 m_NumHandles = 0;
+ Uint16 m_AllocationManagerId = static_cast<Uint16>(-1);
+ Uint16 m_DescriptorSize = 0;
+};
+
+
+class DescriptorHeapAllocationManager
+{
+public:
+ DescriptorHeapAllocationManager(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12Impl,
+ IDescriptorAllocator *pParentAllocator,
+ size_t ThisManagerId,
+ const D3D12_DESCRIPTOR_HEAP_DESC &HeapDesc);
+ DescriptorHeapAllocationManager(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12Impl,
+ IDescriptorAllocator *pParentAllocator,
+ size_t ThisManagerId,
+ ID3D12DescriptorHeap *pd3d12DescriptorHeap,
+ Uint32 FirstDescriptor,
+ Uint32 NumDescriptors);
+
+
+ // = default causes compiler error when instantiating std::vector::emplace_back() in Visual Studio 2015 (Version 14.0.23107.0 D14REL)
+ DescriptorHeapAllocationManager(DescriptorHeapAllocationManager&& rhs) :
+ m_FreeBlockManager(std::move(rhs.m_FreeBlockManager)),
+ m_HeapDesc(rhs.m_HeapDesc),
+ m_pd3d12DescriptorHeap(std::move(rhs.m_pd3d12DescriptorHeap)),
+ m_FirstCPUHandle(rhs.m_FirstCPUHandle),
+ m_FirstGPUHandle(rhs.m_FirstGPUHandle),
+ m_DescriptorSize(rhs.m_DescriptorSize),
+ m_NumDescriptorsInAllocation(rhs.m_NumDescriptorsInAllocation),
+ // Mutex is not movable
+ //m_AllocationMutex(std::move(rhs.m_AllocationMutex))
+ m_pDeviceD3D12Impl(rhs.m_pDeviceD3D12Impl),
+ m_pParentAllocator(rhs.m_pParentAllocator),
+ m_ThisManagerId(rhs.m_ThisManagerId)
+ {
+ rhs.m_FirstCPUHandle.ptr = 0;
+ rhs.m_FirstGPUHandle.ptr = 0;
+ rhs.m_DescriptorSize = 0;
+ rhs.m_NumDescriptorsInAllocation = 0;
+ rhs.m_HeapDesc.NumDescriptors = 0;
+ rhs.m_pDeviceD3D12Impl = nullptr;
+ rhs.m_pParentAllocator = nullptr;
+ rhs.m_ThisManagerId = static_cast<size_t>(-1);
+ }
+
+ DescriptorHeapAllocationManager& operator = (DescriptorHeapAllocationManager&& rhs) = delete;
+ DescriptorHeapAllocationManager(const DescriptorHeapAllocationManager&) = delete;
+ DescriptorHeapAllocationManager& operator = (const DescriptorHeapAllocationManager&) = delete;
+
+ ~DescriptorHeapAllocationManager();
+
+ DescriptorHeapAllocation Allocate( uint32_t Count );
+ void Free(DescriptorHeapAllocation&& Allocation);
+ void ReleaseStaleAllocations(Uint64 NumCompletedFrames);
+ size_t GetNumAvailableDescriptors()const{return m_FreeBlockManager.GetFreeSize();}
+
+private:
+ FreeBlockListManagerGPU m_FreeBlockManager;
+ D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+ CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
+ D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCPUHandle = {0};
+ D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGPUHandle = {0};
+ UINT m_DescriptorSize = 0;
+ Uint32 m_NumDescriptorsInAllocation = 0;
+ std::mutex m_AllocationMutex;
+ RenderDeviceD3D12Impl *m_pDeviceD3D12Impl = nullptr;
+ IDescriptorAllocator *m_pParentAllocator = nullptr;
+ size_t m_ThisManagerId = static_cast<size_t>(-1);
+};
+
+// This is an unbounded resource descriptor heap. It is intended to provide space for CPU-visible resource descriptors
+// as resources are created as well as for static and mutable shader descriptor tables.
+class CPUDescriptorHeap : public IDescriptorAllocator
+{
+public:
+ CPUDescriptorHeap(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12Impl,
+ Uint32 NumDescriptorsInHeap,
+ D3D12_DESCRIPTOR_HEAP_TYPE Type,
+ D3D12_DESCRIPTOR_HEAP_FLAGS Flags);
+
+ CPUDescriptorHeap(const CPUDescriptorHeap&) = delete;
+ CPUDescriptorHeap(CPUDescriptorHeap&&) = delete;
+ CPUDescriptorHeap& operator = (const CPUDescriptorHeap&) = delete;
+ CPUDescriptorHeap& operator = (CPUDescriptorHeap&&) = delete;
+
+ ~CPUDescriptorHeap();
+
+ virtual DescriptorHeapAllocation Allocate( uint32_t Count )override;
+ virtual void Free(DescriptorHeapAllocation&& Allocation)override;
+ virtual Uint32 GetDescriptorSize()const override{return m_DescriptorSize;}
+
+ void ReleaseStaleAllocations(Uint64 NumCompletedFrames);
+
+protected:
+
+ std::vector<DescriptorHeapAllocationManager, STDAllocatorRawMem<DescriptorHeapAllocationManager> > m_HeapPool;
+ std::set<size_t, std::less<size_t>, STDAllocatorRawMem<size_t> > m_AvailableHeaps;
+ IMemoryAllocator &m_MemAllocator;
+
+ std::mutex m_AllocationMutex;
+
+ D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+ UINT m_DescriptorSize;
+ RenderDeviceD3D12Impl *m_pDeviceD3D12Impl;
+ Uint32 m_MaxHeapSize = 0;
+ Uint32 m_CurrentSize = 0; // This size does not count stale allocation
+};
+
+
+class GPUDescriptorHeap : public IDescriptorAllocator
+{
+public:
+ GPUDescriptorHeap(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDevice,
+ Uint32 NumDescriptorsInHeap,
+ Uint32 NumDynamicDescriptors,
+ D3D12_DESCRIPTOR_HEAP_TYPE Type,
+ D3D12_DESCRIPTOR_HEAP_FLAGS Flags);
+
+ GPUDescriptorHeap(const GPUDescriptorHeap&) = delete;
+ GPUDescriptorHeap(GPUDescriptorHeap&&) = delete;
+ GPUDescriptorHeap& operator = (const GPUDescriptorHeap&) = delete;
+ GPUDescriptorHeap& operator = (GPUDescriptorHeap&&) = delete;
+
+ ~GPUDescriptorHeap();
+
+ virtual DescriptorHeapAllocation Allocate( uint32_t Count )override;
+ virtual void Free(DescriptorHeapAllocation&& Allocation)override;
+ virtual Uint32 GetDescriptorSize()const override{return m_DescriptorSize;}
+
+ DescriptorHeapAllocation AllocateDynamic( uint32_t Count );
+
+ void ReleaseStaleAllocations(Uint64 NumCompletedFrames);
+
+ D3D12_DESCRIPTOR_HEAP_DESC &GetHeapDesc(){return m_HeapDesc;}
+
+protected:
+
+ D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+ CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
+
+
+ UINT m_DescriptorSize = 0;
+
+ std::mutex m_Mutex;
+ DescriptorHeapAllocationManager m_HeapAllocationManager;
+ DescriptorHeapAllocationManager m_DynamicAllocationsManager;
+
+ RenderDeviceD3D12Impl *m_pDeviceD3D12;
+ Uint32 m_CurrentSize = 0;
+ Uint32 m_MaxHeapSize = 0;
+ Uint32 m_CurrentDynamicSize = 0;
+ Uint32 m_MaxDynamicSize = 0;
+};
+
+
+
+class DynamicSuballocationsManager : public IDescriptorAllocator
+{
+public:
+ DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize);
+
+ DynamicSuballocationsManager(const DynamicSuballocationsManager&) = delete;
+ DynamicSuballocationsManager(DynamicSuballocationsManager&&) = delete;
+ DynamicSuballocationsManager& operator = (const DynamicSuballocationsManager&) = delete;
+ DynamicSuballocationsManager& operator = (DynamicSuballocationsManager&&) = delete;
+
+ void DiscardAllocations(Uint64 FrameNumber);
+
+ virtual DescriptorHeapAllocation Allocate( Uint32 Count )override;
+ virtual void Free(DescriptorHeapAllocation&& Allocation)override;
+
+ virtual Uint32 GetDescriptorSize()const override{return m_ParentGPUHeap.GetDescriptorSize();}
+
+private:
+ std::vector<DescriptorHeapAllocation, STDAllocatorRawMem<DescriptorHeapAllocation> > m_Suballocations;
+
+ Uint32 m_CurrentSuballocationOffset = 0;
+ Uint32 m_DynamicChunkSize = 0;
+
+ GPUDescriptorHeap &m_ParentGPUHeap;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
new file mode 100644
index 00000000..ffe8598a
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
@@ -0,0 +1,142 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::DeviceContextD3D12Impl class
+
+#include "DeviceContext.h"
+#include "DeviceContextBase.h"
+#include "GenerateMips.h"
+
+#ifdef _DEBUG
+# define VERIFY_CONTEXT_BINDINGS
+#endif
+
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IDeviceContext interface
+class DeviceContextD3D12Impl : public DeviceContextBase<IDeviceContext>
+{
+public:
+ typedef DeviceContextBase<IDeviceContext> TDeviceContextBase;
+
+ DeviceContextD3D12Impl(IMemoryAllocator &RawMemAllocator, class RenderDeviceD3D12Impl *pDevice, bool bIsDeferred, const EngineD3D12Attribs &Attribs, Uint32 ContextId);
+ ~DeviceContextD3D12Impl();
+ //virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override final;
+
+ virtual void SetPipelineState(IPipelineState *pPipelineState)override final;
+
+ virtual void TransitionShaderResources(IPipelineState *pPipelineState, IShaderResourceBinding *pShaderResourceBinding)override final;
+
+ virtual void CommitShaderResources(IShaderResourceBinding *pShaderResourceBinding, Uint32 Flags)override final;
+
+ virtual void SetStencilRef(Uint32 StencilRef)override final;
+
+ virtual void SetBlendFactors(const float* pBlendFactors = nullptr)override final;
+
+ virtual void SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer **ppBuffers, Uint32 *pStrides, Uint32 *pOffsets, Uint32 Flags )override final;
+ virtual void ClearState()override final;
+
+ virtual void SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset )override final;
+
+ virtual void SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )override final;
+
+ virtual void SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )override final;
+
+ virtual void SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil )override final;
+
+ virtual void Draw( DrawAttribs &DrawAttribs )override final;
+
+ virtual void DispatchCompute( const DispatchComputeAttribs &DispatchAttrs )override final;
+
+ virtual void ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil)override final;
+
+ virtual void ClearRenderTarget( ITextureView *pView, const float *RGBA )override final;
+
+ virtual void Flush()override final;
+
+ virtual void FinishCommandList(class ICommandList **ppCommandList)override final;
+
+ virtual void ExecuteCommandList(class ICommandList *pCommandList)override final;
+
+ ///// Clears the state caches. This function is called once per frame
+ ///// (before present) to release all outstanding objects
+ ///// that are only kept alive by references in the cache
+ //void ClearShaderStateCache();
+
+ ///// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute)
+ //static const int NumShaderTypes = 6;
+
+ void UpdateBufferRegion(class BufferD3D12Impl *pBuffD3D12, const void *pData, Uint64 DstOffset, Uint64 NumBytes);
+ void CopyBufferRegion(class BufferD3D12Impl *pSrcBuffD3D12, class BufferD3D12Impl *pDstBuffD3D12, Uint64 SrcOffset, Uint64 DstOffset, Uint64 NumBytes);
+ void CopyTextureRegion(class TextureD3D12Impl *pSrcTexture, Uint32 SrcSubResIndex, const D3D12_BOX *pD3D12SrcBox,
+ class TextureD3D12Impl *pDstTexture, Uint32 DstSubResIndex, Uint32 DstX, Uint32 DstY, Uint32 DstZ);
+
+ void GenerateMips(class TextureViewD3D12Impl *pTexView);
+
+ struct DynamicAllocation AllocateDynamicSpace(size_t NumBytes);
+
+ Uint32 GetContextId()const{return m_ContextId;}
+
+private:
+ void CommitD3D12IndexBuffer(VALUE_TYPE IndexType);
+ void CommitD3D12VertexBuffers(class GraphicsContext &GraphCtx);
+ void TransitionD3D12VertexBuffers(class GraphicsContext &GraphCtx);
+ void RebindRenderTargets();
+ void CommitViewports();
+ void CommitScissorRects();
+ void Flush(bool RequestNewCmdCtx);
+
+ friend class SwapChainD3D12Impl;
+ inline class CommandContext* RequestCmdContext(){return m_pCurrCmdCtx;}
+ size_t m_NumCommandsInCurCtx = 0;
+ const Uint32 m_NumCommandsToFlush = 192;
+ CommandContext* m_pCurrCmdCtx = nullptr;
+
+ CComPtr<ID3D12Resource> m_CommittedD3D12IndexBuffer;
+ VALUE_TYPE m_CommittedIBFormat = VT_UNDEFINED;
+ Uint32 m_CommittedD3D12IndexDataStartOffset = 0;
+
+ CComPtr<ID3D12CommandSignature> m_pDrawIndirectSignature;
+ CComPtr<ID3D12CommandSignature> m_pDrawIndexedIndirectSignature;
+ CComPtr<ID3D12CommandSignature> m_pDispatchIndirectSignature;
+
+ GenerateMipsHelper m_MipsGenerator;
+ class DynamicUploadHeap* m_pUploadHeap = nullptr;
+
+ /// Flag indicating if currently committed D3D12 vertex buffers are up to date
+ bool m_bCommittedD3D12VBsUpToDate = false;
+
+ /// Flag indicating if currently committed D3D11 index buffer is up to date
+ bool m_bCommittedD3D12IBUpToDate = false;
+
+ class ShaderResourceCacheD3D12 *m_pCommittedResourceCache = nullptr;
+
+ FixedBlockMemoryAllocator m_CmdListAllocator;
+ const Uint32 m_ContextId;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/DynamicUploadHeap.h b/Graphics/GraphicsEngineD3D12/include/DynamicUploadHeap.h
new file mode 100644
index 00000000..a4799ded
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/DynamicUploadHeap.h
@@ -0,0 +1,134 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "RingBuffer.h"
+
+namespace Diligent
+{
+
+// Constant blocks must be multiples of 16 constants @ 16 bytes each
+#define DEFAULT_ALIGN 256
+
+struct DynamicAllocation
+{
+ DynamicAllocation(ID3D12Resource *pBuff = nullptr, size_t ThisOffset = 0, size_t ThisSize = 0)
+ : pBuffer(pBuff), Offset(ThisOffset), Size(ThisSize) {}
+
+ //CComPtr<ID3D12Resource> pBuffer; // The D3D buffer associated with this memory.
+ ID3D12Resource *pBuffer = nullptr; // The D3D buffer associated with this memory.
+ size_t Offset = 0; // Offset from start of buffer resource
+ size_t Size = 0; // Reserved size of this allocation
+ void* CPUAddress = 0; // The CPU-writeable address
+ D3D12_GPU_VIRTUAL_ADDRESS GPUAddress = 0; // The GPU-visible address
+#ifdef _DEBUG
+ Uint64 FrameNum = static_cast<Uint64>(-1);
+#endif
+};
+
+class GPURingBuffer : public RingBuffer
+{
+public:
+ GPURingBuffer(size_t MaxSize, IMemoryAllocator &Allocator, ID3D12Device *pd3d12Device, bool AllowCPUAccess);
+
+ GPURingBuffer(GPURingBuffer&& rhs) :
+ RingBuffer(std::move(rhs)),
+ m_CpuVirtualAddress(rhs.m_CpuVirtualAddress),
+ m_GpuVirtualAddress(rhs.m_GpuVirtualAddress),
+ m_pBuffer(std::move(rhs.m_pBuffer))
+ {
+ rhs.m_CpuVirtualAddress = nullptr;
+ rhs.m_GpuVirtualAddress = 0;
+ rhs.m_pBuffer.Release();
+ }
+
+ GPURingBuffer& operator =(GPURingBuffer&& rhs)
+ {
+ Destroy();
+
+ static_cast<RingBuffer&>(*this) = std::move(rhs);
+ m_CpuVirtualAddress = rhs.m_CpuVirtualAddress;
+ m_GpuVirtualAddress = rhs.m_GpuVirtualAddress;
+ m_pBuffer = std::move(rhs.m_pBuffer);
+ rhs.m_CpuVirtualAddress = 0;
+ rhs.m_GpuVirtualAddress = 0;
+
+ return *this;
+ }
+
+ ~GPURingBuffer();
+
+ DynamicAllocation Allocate(size_t SizeInBytes)
+ {
+ auto Offset = RingBuffer::Allocate(SizeInBytes);
+ if (Offset != RingBuffer::InvalidOffset)
+ {
+ DynamicAllocation DynAlloc(m_pBuffer, Offset, SizeInBytes);
+ DynAlloc.GPUAddress = m_GpuVirtualAddress + Offset;
+ DynAlloc.CPUAddress = m_CpuVirtualAddress;
+ if(DynAlloc.CPUAddress)
+ DynAlloc.CPUAddress = reinterpret_cast<char*>(DynAlloc.CPUAddress) + Offset;
+ return DynAlloc;
+ }
+ else
+ {
+ return DynamicAllocation(nullptr, 0, 0);
+ }
+ }
+
+ GPURingBuffer(const GPURingBuffer&) = delete;
+ GPURingBuffer& operator =(GPURingBuffer&) = delete;
+
+private:
+ void Destroy();
+
+ void* m_CpuVirtualAddress;
+ D3D12_GPU_VIRTUAL_ADDRESS m_GpuVirtualAddress;
+ CComPtr<ID3D12Resource> m_pBuffer;
+};
+
+class DynamicUploadHeap
+{
+public:
+
+ DynamicUploadHeap(IMemoryAllocator &Allocator, bool bIsCPUAccessible, class RenderDeviceD3D12Impl* pDevice, size_t InitialSize);
+
+ DynamicUploadHeap(const DynamicUploadHeap&)=delete;
+ DynamicUploadHeap(DynamicUploadHeap&&)=delete;
+ DynamicUploadHeap& operator=(const DynamicUploadHeap&)=delete;
+ DynamicUploadHeap& operator=(DynamicUploadHeap&&)=delete;
+
+ DynamicAllocation Allocate( size_t SizeInBytes, size_t Alignment = DEFAULT_ALIGN );
+
+ void FinishFrame(Uint64 FrameNum, Uint64 NumCompletedFrames);
+
+private:
+ const bool m_bIsCPUAccessible;
+ std::vector<GPURingBuffer, STDAllocatorRawMem<GPURingBuffer> > m_RingBuffers;
+ IMemoryAllocator &m_Allocator;
+ RenderDeviceD3D12Impl* m_pDeviceD3D12 = nullptr;
+ //std::mutex m_Mutex;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/GenerateMips.h b/Graphics/GraphicsEngineD3D12/include/GenerateMips.h
new file mode 100644
index 00000000..22e81589
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/GenerateMips.h
@@ -0,0 +1,64 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+
+// The source code in this file is derived from ColorBuffer.h and GraphicsCore.h developed by Minigraph
+// Original source files header:
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+
+#pragma once
+
+/// \file
+/// Implementation of mipmap generation routines
+
+
+namespace Diligent
+{
+ class GenerateMipsHelper
+ {
+ public:
+ GenerateMipsHelper(ID3D12Device *pd3d12Device);
+
+ void GenerateMips(class RenderDeviceD3D12Impl *pRenderDeviceD3D12, class TextureViewD3D12Impl *pTexView, class CommandContext &Ctx);
+
+ private:
+ CComPtr<ID3D12RootSignature> m_pGenerateMipsRS;
+ CComPtr<ID3D12PipelineState> m_pGenerateMipsLinearPSO[4];
+ CComPtr<ID3D12PipelineState> m_pGenerateMipsGammaPSO[4];
+ };
+
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h
new file mode 100644
index 00000000..1ac6564f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h
@@ -0,0 +1,93 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::PipelineStateD3D12Impl class
+
+#include "RenderDeviceD3D12.h"
+#include "PipelineStateD3D12.h"
+#include "PipelineStateBase.h"
+#include "RootSignature.h"
+#include "ShaderResourceLayoutD3D12.h"
+#include "AdaptiveFixedBlockAllocator.h"
+
+/// Namespace for the Direct3D11 implementation of the graphics engine
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+/// Implementation of the Diligent::IRenderDeviceD3D12 interface
+class PipelineStateD3D12Impl : public PipelineStateBase<IPipelineStateD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator>
+{
+public:
+ typedef PipelineStateBase<IPipelineStateD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator> TPipelineStateBase;
+
+ PipelineStateD3D12Impl( FixedBlockMemoryAllocator &PSOAllocator, class RenderDeviceD3D12Impl *pDeviceD3D12, const PipelineStateDesc &PipelineDesc );
+ ~PipelineStateD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ virtual ID3D12PipelineState *GetD3D12PipelineState()const override final{return m_pd3d12PSO;}
+
+ virtual void BindShaderResources( IResourceMapping *pResourceMapping, Uint32 Flags )override;
+
+ virtual void CreateShaderResourceBinding( IShaderResourceBinding **ppShaderResourceBinding )override;
+
+ virtual ID3D12RootSignature *GetD3D12RootSignature()const override final{return m_RootSig.GetD3D12RootSignature(); }
+
+ ShaderResourceCacheD3D12* CommitAndTransitionShaderResources(IShaderResourceBinding *pShaderResourceBinding,
+ class CommandContext &Ctx,
+ bool CommitResources,
+ bool TransitionResources)const;
+
+ const RootSignature& GetRootSignature()const{return m_RootSig;}
+
+ const ShaderResourceLayoutD3D12& GetShaderResLayout(SHADER_TYPE ShaderType)const;
+
+ bool dbgContainsShaderResources()const;
+
+ IMemoryAllocator &GetResourceCacheDataAllocator(){return m_ResourceCacheDataAllocator;}
+ IMemoryAllocator &GetShaderResourceLayoutDataAllocator(Uint32 ShaderInd){return m_ShaderResLayoutDataAllocators[ShaderInd];}
+
+ IShaderVariable *GetDummyShaderVar(){return &m_DummyVar;}
+
+private:
+
+ void ParseShaderResourceLayout(IShader *pShader);
+
+ /// D3D12 device
+ CComPtr<ID3D12PipelineState> m_pd3d12PSO;
+ RootSignature m_RootSig;
+ DummyShaderVariable m_DummyVar;
+
+ AdaptiveFixedBlockAllocator m_ShaderResLayoutDataAllocators[6];
+ ShaderResourceLayoutD3D12* m_pShaderResourceLayouts[6] = {};
+ AdaptiveFixedBlockAllocator m_ResourceCacheDataAllocator; // Use separate allocator for every shader stage
+
+ // Do not use strong reference to avoid cyclic references
+ std::unique_ptr<class ShaderResourceBindingD3D12Impl, STDDeleter<ShaderResourceBindingD3D12Impl, FixedBlockMemoryAllocator> > m_pDefaultShaderResBinding;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
new file mode 100644
index 00000000..0294a8b8
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
@@ -0,0 +1,133 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::RenderDeviceD3D12Impl class
+
+#include "RenderDeviceD3D12.h"
+#include "RenderDeviceD3DBase.h"
+#include "DescriptorHeap.h"
+#include "CommandListManager.h"
+#include "CommandContext.h"
+#include "DynamicUploadHeap.h"
+
+/// Namespace for the Direct3D11 implementation of the graphics engine
+namespace Diligent
+{
+
+/// Implementation of the Diligent::IRenderDeviceD3D12 interface
+class RenderDeviceD3D12Impl : public RenderDeviceD3DBase<IRenderDeviceD3D12>
+{
+public:
+ typedef RenderDeviceD3DBase<IRenderDeviceD3D12> TRenderDeviceBase;
+
+ RenderDeviceD3D12Impl( IMemoryAllocator &RawMemAllocator, const EngineD3D12Attribs &CreationAttribs, ID3D12Device *pD3D12Device, ID3D12CommandQueue *pd3d12CmdQueue, Uint32 NumDeferredContexts );
+ ~RenderDeviceD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void CreatePipelineState( const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState )override;
+
+ virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBuffer);
+
+ virtual void CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader);
+
+ virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture);
+
+ void CreateTexture(TextureDesc& TexDesc, ID3D12Resource *pd3d12Texture, class TextureD3D12Impl **ppTexture);
+
+ virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler);
+
+ virtual ID3D12Device* GetD3D12Device()override{return m_pd3d12Device;}
+
+ DescriptorHeapAllocation AllocateDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
+ DescriptorHeapAllocation AllocateGPUDescriptors( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
+
+ bool IsFenceComplete(Uint64 FenceValue);
+ bool IsFrameComplete(Uint64 Frame);
+
+ ID3D12CommandQueue *GetCmdQueue(){return m_pd3d12CmdQueue;}
+
+ Uint64 IncrementFence();
+ void WaitForFence(Uint64 FenceValue);
+ void IdleGPU(bool ReleasePendingObjects = false);
+ CommandContext* AllocateCommandContext(const Char *ID = "");
+ Uint64 CloseAndExecuteCommandContext(CommandContext *pCtx);
+ void DisposeCommandContext(CommandContext*);
+
+ void SafeReleaseD3D12Object(ID3D12Object* pObj);
+ Uint64 FinishFrame();
+
+ DynamicUploadHeap* RequestUploadHeap();
+ void ReleaseUploadHeap(DynamicUploadHeap* pUploadHeap);
+ Uint64 GetCurrentFrame()const {return m_CurrentFrame;}
+
+private:
+ virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat );
+ void ProcessReleaseQueue(bool ForceRelease = false);
+
+ /// D3D12 device
+ CComPtr<ID3D12Device> m_pd3d12Device;
+ CComPtr<ID3D12CommandQueue> m_pd3d12CmdQueue;
+
+ EngineD3D12Attribs m_EngineAttribs;
+
+ CPUDescriptorHeap m_CPUDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
+ GPUDescriptorHeap m_GPUDescriptorHeaps[2]; // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == 0
+ // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER == 1
+
+ std::mutex m_FenceMutex;
+ std::mutex m_EventMutex;
+
+ CComPtr<ID3D12Fence> m_pFence;
+ Uint64 m_NextFenceValue;
+ Uint64 m_LastCompletedFenceValue;
+ HANDLE m_FenceEventHandle;
+
+ CComPtr<ID3D12Fence> m_pNumCompletedFramesFence;
+ Uint64 m_CurrentFrame = 0;
+ Uint64 m_NumCompletedFrames = 0;
+
+
+ CommandListManager m_CmdListManager;
+
+ typedef std::unique_ptr<CommandContext, STDDeleterRawMem<CommandContext> > ContextPoolElemType;
+ std::vector< ContextPoolElemType, STDAllocatorRawMem<ContextPoolElemType> > m_ContextPool;
+
+ std::deque<CommandContext*, STDAllocatorRawMem<CommandContext*> > m_AvailableContexts;
+ std::mutex m_ContextAllocationMutex;
+
+ // Object that must be kept alive
+ std::mutex m_ReleasedObjectsMutex;
+ // Release queue
+ typedef std::pair<Uint64, CComPtr<ID3D12Object> > ReleaseQueueElemType;
+ std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_D3D12ObjReleaseQueue;
+
+ std::mutex m_UploadHeapMutex;
+ typedef std::unique_ptr<DynamicUploadHeap, STDDeleterRawMem<DynamicUploadHeap> > UploadHeapPoolElemType;
+ std::vector< UploadHeapPoolElemType, STDAllocatorRawMem<UploadHeapPoolElemType> > m_UploadHeaps;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.h b/Graphics/GraphicsEngineD3D12/include/RootSignature.h
new file mode 100644
index 00000000..750b2b9d
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.h
@@ -0,0 +1,312 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::RootSignature class
+#include "ShaderD3DBase.h"
+#include "ShaderResourceLayoutD3D12.h"
+
+namespace Diligent
+{
+
+SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility);
+D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType);
+D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE RangeType);
+
+class RootParameter
+{
+public:
+
+ RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, Uint32 RootIndex, UINT Register, UINT RegisterSpace, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType) :
+ m_RootIndex(RootIndex),
+ m_ShaderVarType(VarType)
+ {
+ VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list");
+ m_RootParam.ParameterType = ParameterType;
+ m_RootParam.ShaderVisibility = Visibility;
+ m_RootParam.Descriptor.ShaderRegister = Register;
+ m_RootParam.Descriptor.RegisterSpace = RegisterSpace;
+ }
+
+ RootParameter( D3D12_ROOT_PARAMETER_TYPE ParameterType, Uint32 RootIndex, UINT Register, UINT RegisterSpace, UINT NumDwords, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType) :
+ m_RootIndex(RootIndex),
+ m_ShaderVarType(VarType)
+ {
+ VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list");
+ m_RootParam.ParameterType = ParameterType;
+ m_RootParam.ShaderVisibility = Visibility;
+ m_RootParam.Constants.Num32BitValues = NumDwords;
+ m_RootParam.Constants.ShaderRegister = Register;
+ m_RootParam.Constants.RegisterSpace = RegisterSpace;
+ }
+
+ RootParameter( D3D12_ROOT_PARAMETER_TYPE ParameterType, Uint32 RootIndex, UINT NumRanges, D3D12_DESCRIPTOR_RANGE *pRanges, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType) :
+ m_RootIndex(RootIndex),
+ m_ShaderVarType(VarType)
+ {
+ VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list");
+ VERIFY_EXPR(pRanges != nullptr);
+ m_RootParam.ParameterType = ParameterType;
+ m_RootParam.ShaderVisibility = Visibility;
+ m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges;
+ m_RootParam.DescriptorTable.pDescriptorRanges = pRanges;
+#ifdef _DEBUG
+ for(Uint32 r=0; r < NumRanges; ++r)
+ pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
+#endif
+ }
+
+ RootParameter(const RootParameter &RP):
+ m_RootParam( RP.m_RootParam),
+ m_DescriptorTableSize(RP.m_DescriptorTableSize),
+ m_ShaderVarType(RP.m_ShaderVarType),
+ m_RootIndex(RP.m_RootIndex)
+ {
+ VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table")
+ }
+
+ RootParameter(const RootParameter &RP, UINT NumRanges, D3D12_DESCRIPTOR_RANGE *pRanges):
+ m_RootParam( RP.m_RootParam),
+ m_DescriptorTableSize(RP.m_DescriptorTableSize),
+ m_ShaderVarType(RP.m_ShaderVarType),
+ m_RootIndex(RP.m_RootIndex)
+ {
+ VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table")
+ VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one")
+ auto &DstTbl = m_RootParam.DescriptorTable;
+ DstTbl.NumDescriptorRanges = NumRanges;
+ DstTbl.pDescriptorRanges = pRanges;
+ const auto &SrcTbl = RP.m_RootParam.DescriptorTable;
+ memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE));
+#ifdef _DEBUG
+ {
+ Uint32 dbgTableSize = 0;
+ for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r)
+ {
+ const auto &Range = SrcTbl.pDescriptorRanges[r];
+ dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors);
+ }
+ VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size");
+
+ for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r)
+ pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
+ }
+#endif
+ }
+
+ RootParameter& operator = (const RootParameter &RP) = delete;
+ RootParameter& operator = (RootParameter &&RP) = delete;
+
+ void SetDescriptorRange( UINT RangeIndex, D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, UINT Space = 0, UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
+ auto &Tbl = m_RootParam.DescriptorTable;
+ VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index");
+ D3D12_DESCRIPTOR_RANGE &range = const_cast<D3D12_DESCRIPTOR_RANGE &>(Tbl.pDescriptorRanges[RangeIndex]);
+ VERIFY(range.RangeType == static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly");
+ range.RangeType = Type;
+ range.NumDescriptors = Count;
+ range.BaseShaderRegister = Register;
+ range.RegisterSpace = Space;
+ range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart;
+ m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count);
+ }
+
+ SHADER_VARIABLE_TYPE GetShaderVariableType()const{ return m_ShaderVarType; }
+ Uint32 GetDescriptorTableSize()const
+ {
+ VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
+ return m_DescriptorTableSize;
+ }
+ D3D12_SHADER_VISIBILITY GetShaderVisibility()const{return m_RootParam.ShaderVisibility;}
+ D3D12_ROOT_PARAMETER_TYPE GetParameterType()const{return m_RootParam.ParameterType;}
+
+ Uint32 GetRootIndex()const{return m_RootIndex;}
+
+ operator const D3D12_ROOT_PARAMETER&()const{return m_RootParam;}
+
+private:
+
+ SHADER_VARIABLE_TYPE m_ShaderVarType = static_cast<SHADER_VARIABLE_TYPE>(-1);
+ D3D12_ROOT_PARAMETER m_RootParam = {};
+ Uint32 m_DescriptorTableSize = 0;
+ Uint32 m_RootIndex = static_cast<Uint32>(-1);
+};
+
+
+
+/// Implementation of the Diligent::RootSignature class
+class RootSignature
+{
+public:
+ RootSignature();
+
+ void AllocateStaticSamplers(IShader* const *ppShaders, Uint32 NumShaders);
+
+ void Finalize(ID3D12Device *pd3d12Device);
+
+ ID3D12RootSignature* GetD3D12RootSignature()const{return m_pd3d12RootSignature;}
+ void InitResourceCache(class RenderDeviceD3D12Impl *pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator &CacheMemAllocator)const;
+
+ void InitStaticSampler(SHADER_TYPE ShaderType, const String &TextureName, const D3DShaderResourceAttribs &ShaderResAttribs);
+
+ void AllocateResourceSlot(SHADER_TYPE ShaderType, const D3DShaderResourceAttribs &ShaderResAttribs, D3D12_DESCRIPTOR_RANGE_TYPE RangeType, Uint32 &RootIndex, Uint32 &OffsetFromTableStart);
+
+ // This method should be thread-safe as it does not modify any object state
+ void (RootSignature::*CommitDescriptorHandles)(class RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx,
+ bool IsCompute)const = nullptr;
+
+ void (RootSignature::*TransitionAndCommitDescriptorHandles)(class RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx,
+ bool IsCompute)const = nullptr;
+
+ void TransitionResources(ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx)const;
+
+ void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx,
+ bool IsCompute,
+ Uint32 ContextId)const;
+
+ Uint32 GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE VarType)const
+ {
+ VERIFY_EXPR(VarType >= 0 && VarType < SHADER_VARIABLE_TYPE_NUM_TYPES);
+ return m_TotalSrvCbvUavSlots[VarType];
+ }
+ Uint32 GetTotalSamplerSlots(SHADER_VARIABLE_TYPE VarType)const
+ {
+ VERIFY_EXPR(VarType >= 0 && VarType < SHADER_VARIABLE_TYPE_NUM_TYPES);
+ return m_TotalSamplerSlots[VarType];
+ }
+
+private:
+#ifdef _DEBUG
+ void dbgVerifyRootParameters()const;
+#endif
+
+ Uint32 m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_NUM_TYPES];
+ Uint32 m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_NUM_TYPES];
+
+ CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
+
+ class RootParamsManager
+ {
+ public:
+ RootParamsManager(IMemoryAllocator &MemAllocator);
+
+ RootParamsManager(const RootParamsManager&) = delete;
+ RootParamsManager& operator= (const RootParamsManager&) = delete;
+ RootParamsManager(RootParamsManager&&) = delete;
+ RootParamsManager& operator= (RootParamsManager&&) = delete;
+
+ Uint32 GetNumRootTables()const{return m_NumRootTables;}
+ Uint32 GetNumRootViews()const{return m_NumRootViews;}
+
+ const RootParameter& GetRootTable(Uint32 TableInd)const
+ {
+ VERIFY_EXPR(TableInd < m_NumRootTables);
+ return m_pRootTables[TableInd];
+ }
+
+ RootParameter& GetRootTable(Uint32 TableInd)
+ {
+ VERIFY_EXPR(TableInd < m_NumRootTables);
+ return m_pRootTables[TableInd];
+ }
+
+ const RootParameter& GetRootView(Uint32 ViewInd)const
+ {
+ VERIFY_EXPR(ViewInd < m_NumRootViews);
+ return m_pRootViews[ViewInd];
+ }
+
+ RootParameter& GetRootView(Uint32 ViewInd)
+ {
+ VERIFY_EXPR(ViewInd < m_NumRootViews);
+ return m_pRootViews[ViewInd];
+ }
+
+ void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, Uint32 RootIndex, UINT Register, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType);
+ void AddRootTable(Uint32 RootIndex, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType, Uint32 NumRangesInNewTable = 1);
+ void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1);
+
+ template<class TOperation>
+ void ProcessRootTables(TOperation)const;
+
+ private:
+ size_t GetRequiredMemorySize(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges)const;
+ D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges, Uint32 RootTableToAddRanges = static_cast<Uint32>(-1));
+
+ IMemoryAllocator &m_MemAllocator;
+ std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
+ Uint32 m_NumRootTables = 0;
+ Uint32 m_NumRootViews = 0;
+ Uint32 m_TotalDescriptorRanges = 0;
+ RootParameter *m_pRootTables = nullptr;
+ RootParameter *m_pRootViews = nullptr;
+ };
+
+ static const Uint8 InvalidRootTableIndex = static_cast<Uint8>(-1);
+ Uint8 m_SrvCbvUavRootTablesMap[SHADER_VARIABLE_TYPE_NUM_TYPES * 6];
+ Uint8 m_SamplerRootTablesMap[SHADER_VARIABLE_TYPE_NUM_TYPES * 6];
+ RootParamsManager m_RootParams;
+
+ struct StaticSamplerAttribs
+ {
+ StaticSamplerDesc SamplerDesc;
+ UINT ShaderRegister = static_cast<UINT>(-1);
+ UINT ArraySize = 0;
+ UINT RegisterSpace = 0;
+ D3D12_SHADER_VISIBILITY ShaderVisibility = static_cast<D3D12_SHADER_VISIBILITY>(-1);
+
+ StaticSamplerAttribs(){}
+ StaticSamplerAttribs(const StaticSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) :
+ SamplerDesc(SamDesc),
+ ShaderVisibility(Visibility)
+ {}
+ };
+ // Note: sizeof(m_StaticSamplers) == 56 (MS compiler, release x64)
+ std::vector<StaticSamplerAttribs, STDAllocatorRawMem<StaticSamplerAttribs> > m_StaticSamplers;
+
+ IMemoryAllocator &m_MemAllocator;
+
+ // Commits descriptor handles for static and mutable variables
+ template<bool PerformResourceTransitions>
+ void CommitDescriptorHandlesInternal_SM(class RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx,
+ bool IsCompute)const;
+ template<bool PerformResourceTransitions>
+ // Commits descriptor handles for static, mutable, and dynamic variables
+ void CommitDescriptorHandlesInternal_SMD(class RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx,
+ bool IsCompute)const;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h
new file mode 100644
index 00000000..11226b64
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h
@@ -0,0 +1,57 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::SamplerD3D12Impl class
+
+#include "SamplerD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "SamplerBase.h"
+#include "DescriptorHeap.h"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+/// Implementation of the Diligent::ISamplerD3D12 interface
+class SamplerD3D12Impl : public SamplerBase<ISamplerD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator>
+{
+public:
+ typedef SamplerBase<ISamplerD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator> TSamplerBase;
+
+ SamplerD3D12Impl(FixedBlockMemoryAllocator &SamplerObjAllocator, class RenderDeviceD3D12Impl *pRenderDeviceD3D12, const SamplerDesc& SamplerDesc);
+ ~SamplerD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle()override{ return m_Descriptor.GetCpuHandle(); }
+
+private:
+ friend class ShaderD3D12Impl;
+ /// D3D12 sampler
+ DescriptorHeapAllocation m_Descriptor;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h
new file mode 100644
index 00000000..b39c70d6
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h
@@ -0,0 +1,79 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderD3D12Impl class
+
+#include "RenderDeviceD3D12.h"
+#include "ShaderD3D12.h"
+#include "ShaderBase.h"
+#include "ShaderD3DBase.h"
+#include "ShaderResourceLayoutD3D12.h"
+
+#ifdef _DEBUG
+# define VERIFY_SHADER_BINDINGS
+#endif
+
+namespace Diligent
+{
+
+class ResourceMapping;
+class FixedBlockMemoryAllocator;
+
+/// Implementation of the Diligent::IShaderD3D12 interface
+class ShaderD3D12Impl : public ShaderBase<IShaderD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator>, public ShaderD3DBase
+{
+public:
+ typedef ShaderBase<IShaderD3D12, IRenderDeviceD3D12, FixedBlockMemoryAllocator> TShaderBase;
+
+ ShaderD3D12Impl(FixedBlockMemoryAllocator& ShaderObjAllocator, class RenderDeviceD3D12Impl *pRenderDeviceD3D12, const ShaderCreationAttribs &ShaderCreationAttribs);
+ ~ShaderD3D12Impl();
+
+ //virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override;
+
+ virtual IShaderVariable* GetShaderVariable(const Char* Name)override;
+
+ ID3DBlob* GetShaderByteCode(){return m_pShaderByteCode;}
+ const std::shared_ptr<const ShaderResourcesD3D12>& GetShaderResources()const{return m_pShaderResources;}
+ const ShaderResourceLayoutD3D12& GetConstResLayout()const{return m_StaticResLayout;}
+
+#ifdef VERIFY_SHADER_BINDINGS
+ void DbgVerifyStaticResourceBindings();
+#endif
+
+private:
+
+ DummyShaderVariable m_DummyShaderVar; ///< Dummy shader variable
+
+ // ShaderResources class instance must be referenced through the shared pointer, because
+ // it is referenced by ShaderResourceLayoutD3D12 class instances
+ std::shared_ptr<const ShaderResourcesD3D12> m_pShaderResources;
+ ShaderResourceLayoutD3D12 m_StaticResLayout;
+ ShaderResourceCacheD3D12 m_ConstResCache;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h
new file mode 100644
index 00000000..025db186
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h
@@ -0,0 +1,81 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderResourceBindingD3D12Impl class
+
+#include "ShaderResourceBindingD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "ShaderResourceBindingBase.h"
+#include "ShaderBase.h"
+#include "ShaderResourceCacheD3D12.h"
+#include "ShaderResourceLayoutD3D12.h"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+/// Implementation of the Diligent::IShaderResourceBindingD3D12 interface
+class ShaderResourceBindingD3D12Impl : public ShaderResourceBindingBase<IShaderResourceBindingD3D12, FixedBlockMemoryAllocator>
+{
+public:
+ typedef ShaderResourceBindingBase<IShaderResourceBindingD3D12, FixedBlockMemoryAllocator> TBase;
+ ShaderResourceBindingD3D12Impl(FixedBlockMemoryAllocator &SRBAllocator, class PipelineStateD3D12Impl *pPSO, bool IsPSOInternal);
+ ~ShaderResourceBindingD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags)override;
+
+ virtual IShaderVariable *GetVariable(SHADER_TYPE ShaderType, const char *Name)override;
+
+ ShaderResourceLayoutD3D12& GetResourceLayout(SHADER_TYPE ResType)
+ {
+ auto ShaderInd = GetShaderTypeIndex(ResType);
+ auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
+ VERIFY(ResLayoutInd >= 0, "Shader resource layout is not initialized");
+ VERIFY_EXPR(ResLayoutInd < (Int32)m_NumShaders);
+ return m_pResourceLayouts[ResLayoutInd];
+ }
+ ShaderResourceCacheD3D12& GetResourceCache(){return m_ShaderResourceCache;}
+
+#ifdef VERIFY_SHADER_BINDINGS
+ void dbgVerifyResourceBindings(const PipelineStateD3D12Impl *pPSO);
+#endif
+
+ bool StaticResourcesInitialized()const{return m_bStaticResourcesInitialized;}
+ void InitializeStaticResources(const PipelineStateD3D12Impl *pPSO);
+
+private:
+
+ ShaderResourceCacheD3D12 m_ShaderResourceCache;
+ ShaderResourceLayoutD3D12* m_pResourceLayouts = nullptr;
+ // Resource layout index in m_ResourceLayouts[] array for every shader stage
+ Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1};
+ bool m_bStaticResourcesInitialized = false;
+ Uint32 m_NumShaders = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h
new file mode 100644
index 00000000..aed6d32e
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h
@@ -0,0 +1,304 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderResourceCacheD3D12 class
+
+
+// Shader resource cache stores D3D12 resources in a continuous chunk of memory:
+//
+//
+// __________________________________________________________
+// | m_pResources, m_NumResources |
+// m_pMemory | |
+// | | V
+// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] |
+// | A \
+// | | \
+// |________________________________________________| \RefCntAutoPtr
+// m_pResources, m_NumResources \_________
+// | Object |
+// ---------
+//
+// Nrt = m_NumTables
+//
+//
+// The cache is also assigned decriptor heap space to store shader visible descriptor handles (for non-dynamic resources).
+//
+//
+// DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
+// | DescrptHndl[0] ... DescrptHndl[n-1] | DescrptHndl[0] ... DescrptHndl[m-1] |
+// A A
+// | |
+// | TableStartOffset | TableStartOffset
+// | |
+// | RootTable[0] | RootTable[1] | RootTable[2] | .... | RootTable[Nrt] |
+// | |
+// | TableStartOffset | InvalidDescriptorOffset
+// | |
+// V V
+// | DescrptHndl[0] ... DescrptHndl[n-1] | X
+// DESCRIPTOR_HEAP_TYPE_SAMPLER
+//
+//
+//
+// The allocation is inexed by the offset from the beginning of the root table
+// Each root table is assigned the space to store exactly m_NumResources resources
+// Dynamic resources are not assigned space in the descriptor heap allocation.
+//
+//
+//
+// | RootTable[i] | Res[0] ... Res[n-1] |
+// \
+// TableStartOffset\____
+// \
+// V
+// ..... | DescrptHndl[0] ... DescrptHndl[n-1] | ....
+//
+
+#include "DescriptorHeap.h"
+
+namespace Diligent
+{
+
+enum class CachedResourceType : Int32
+{
+ Unknown = -1,
+ CBV = 0,
+ TexSRV,
+ BufSRV,
+ TexUAV,
+ BufUAV,
+ Sampler,
+ NumTypes
+};
+
+class ShaderResourceCacheD3D12
+{
+public:
+ // This enum is used for debug purposes only
+ enum DbgCacheContentType
+ {
+ StaticShaderResources,
+ SRBResources
+ };
+
+ ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType)
+#ifdef _DEBUG
+ : m_DbgContentType(dbgContentType)
+#endif
+ {
+ }
+
+ ~ShaderResourceCacheD3D12();
+
+ void Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, Uint32 TableSizes[]);
+
+ static const Uint32 InvalidDescriptorOffset = static_cast<Uint32>(-1);
+
+ struct Resource
+ {
+ CachedResourceType Type = CachedResourceType::Unknown;
+ // CPU descriptor handle of a cached resource in external descriptor heap
+ // Note that for dynamic resources, this is the only available CPU descriptor handle
+ D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0};
+ RefCntAutoPtr<IDeviceObject> pObject;
+ };
+
+ class RootTable
+ {
+ public:
+ RootTable(Uint32 NumResources, Resource *pResources) :
+ m_NumResources(NumResources),
+ m_pResources(pResources)
+ {}
+
+ inline Resource& GetResource(Uint32 OffsetFromTableStart,
+ const D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,
+ const SHADER_TYPE dbgRefShaderType)
+ {
+ VERIFY(m_dbgHeapType == DescriptorHeapType, "Incosistent descriptor heap type" )
+ VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type" )
+
+ VERIFY(OffsetFromTableStart < m_NumResources, "Root table at index is not large enough to store descriptor at offset ", OffsetFromTableStart );
+ return m_pResources[OffsetFromTableStart];
+ }
+
+ inline Uint32 GetSize()const{return m_NumResources; }
+
+ // Offset from the start of the descriptor heap alloction to the start of the table
+ Uint32 TableStartOffset = InvalidDescriptorOffset;
+
+#ifdef _DEBUG
+ void SetDebugAttribs(Uint32 MaxOffset,
+ const D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,
+ const SHADER_TYPE dbgRefShaderType)
+ {
+ VERIFY_EXPR(m_NumResources == MaxOffset);
+ m_dbgHeapType = DescriptorHeapType;
+ m_dbgShaderType = dbgRefShaderType;
+ }
+
+ D3D12_DESCRIPTOR_HEAP_TYPE DbgGetHeapType()const{return m_dbgHeapType;}
+#endif
+
+ const Uint32 m_NumResources = 0;
+ private:
+
+#ifdef _DEBUG
+ D3D12_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
+ SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN;
+#endif
+
+ Resource* const m_pResources = nullptr;
+ };
+
+ inline RootTable& GetRootTable(Uint32 RootIndex)
+ {
+ VERIFY_EXPR(RootIndex < m_NumTables);
+ return reinterpret_cast<RootTable*>(m_pMemory)[RootIndex];
+ }
+
+ inline Uint32 GetNumRootTables()const{return m_NumTables; }
+
+ void SetDescriptorHeapSpace(DescriptorHeapAllocation &&CbcSrvUavHeapSpace, DescriptorHeapAllocation &&SamplerHeapSpace)
+ {
+ VERIFY(m_SamplerHeapSpace.GetCpuHandle().ptr == 0 && m_CbcSrvUavHeapSpace.GetCpuHandle().ptr == 0, "Space has already been allocated in GPU descriptor heaps");
+#ifdef _DEBUG
+ Uint32 NumSamplerDescriptors = 0, NumSrvCbvUavDescriptors = 0;
+ for (Uint32 rt = 0; rt < m_NumTables; ++rt)
+ {
+ auto &Tbl = GetRootTable(rt);
+ if(Tbl.TableStartOffset != InvalidDescriptorOffset)
+ {
+ if(Tbl.DbgGetHeapType() == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ {
+ VERIFY(Tbl.TableStartOffset == NumSrvCbvUavDescriptors, "Descriptor space allocation is not continuous")
+ NumSrvCbvUavDescriptors = std::max(NumSrvCbvUavDescriptors, Tbl.TableStartOffset + Tbl.GetSize());
+ }
+ else
+ {
+ VERIFY(Tbl.TableStartOffset == NumSamplerDescriptors, "Descriptor space allocation is not continuous")
+ NumSamplerDescriptors = std::max(NumSamplerDescriptors, Tbl.TableStartOffset + Tbl.GetSize());
+ }
+ }
+ }
+ VERIFY(NumSrvCbvUavDescriptors == CbcSrvUavHeapSpace.GetNumHandles() || NumSrvCbvUavDescriptors == 0 && CbcSrvUavHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size" )
+ VERIFY(NumSamplerDescriptors == SamplerHeapSpace.GetNumHandles() || NumSamplerDescriptors == 0 && SamplerHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size" )
+#endif
+
+ m_CbcSrvUavHeapSpace = std::move(CbcSrvUavHeapSpace);
+ m_SamplerHeapSpace = std::move(SamplerHeapSpace);
+ }
+
+ ID3D12DescriptorHeap* GetSrvCbvUavDescriptorHeap(){return m_CbcSrvUavHeapSpace.GetDescriptorHeap();}
+ ID3D12DescriptorHeap* GetSamplerDescriptorHeap(){return m_SamplerHeapSpace.GetDescriptorHeap();}
+
+ // Returns CPU descriptor handle of a shader visible descriptor heap allocation
+ template<D3D12_DESCRIPTOR_HEAP_TYPE HeapType>
+ D3D12_CPU_DESCRIPTOR_HANDLE GetShaderVisibleTableCPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0)
+ {
+ auto &RootParam = GetRootTable(RootParamInd);
+ VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type");
+
+ D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0};
+ // Descriptor heap allocation is not assigned for dynamic resources or
+ // in a special case when resource cache is used to store static
+ // variable assignments for a shader
+ if( RootParam.TableStartOffset != InvalidDescriptorOffset )
+ {
+ VERIFY(RootParam.TableStartOffset + OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range");
+ if( HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER )
+ {
+ VERIFY_EXPR(!m_SamplerHeapSpace.IsNull());
+ CPUDescriptorHandle = m_SamplerHeapSpace.GetCpuHandle(RootParam.TableStartOffset + OffsetFromTableStart);
+ }
+ else if( HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV )
+ {
+ VERIFY_EXPR(!m_CbcSrvUavHeapSpace.IsNull());
+ CPUDescriptorHandle = m_CbcSrvUavHeapSpace.GetCpuHandle(RootParam.TableStartOffset + OffsetFromTableStart);
+ }
+ else
+ {
+ UNEXPECTED("Unexpected descriptor heap type");
+ }
+ }
+
+ return CPUDescriptorHandle;
+ }
+
+ // Returns GPU descriptor handle of a shader visible descriptor table
+ template<D3D12_DESCRIPTOR_HEAP_TYPE HeapType>
+ D3D12_GPU_DESCRIPTOR_HANDLE GetShaderVisibleTableGPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0)
+ {
+ auto &RootParam = GetRootTable(RootParamInd);
+ VERIFY_EXPR(RootParam.TableStartOffset != InvalidDescriptorOffset);
+ VERIFY(RootParam.TableStartOffset + OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range");
+
+ D3D12_GPU_DESCRIPTOR_HANDLE GPUDescriptorHandle = {0};
+ VERIFY( HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type");
+ if( HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER )
+ {
+ VERIFY_EXPR(!m_SamplerHeapSpace.IsNull());
+ GPUDescriptorHandle = m_SamplerHeapSpace.GetGpuHandle(RootParam.TableStartOffset + OffsetFromTableStart);
+ }
+ else if( HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV )
+ {
+ VERIFY_EXPR(!m_CbcSrvUavHeapSpace.IsNull());
+ GPUDescriptorHandle = m_CbcSrvUavHeapSpace.GetGpuHandle(RootParam.TableStartOffset + OffsetFromTableStart);
+ }
+ else
+ {
+ UNEXPECTED("Unexpected descriptor heap type");
+ }
+
+ return GPUDescriptorHandle;
+ }
+
+#ifdef _DEBUG
+ // Only for debug purposes: indicates what types of resources are stored in the cache
+ DbgCacheContentType DbgGetContentType()const{return m_DbgContentType;}
+#endif
+
+private:
+ ShaderResourceCacheD3D12(const ShaderResourceCacheD3D12&) = delete;
+ ShaderResourceCacheD3D12(ShaderResourceCacheD3D12&&) = delete;
+ ShaderResourceCacheD3D12& operator = (const ShaderResourceCacheD3D12&) = delete;
+ ShaderResourceCacheD3D12& operator = (ShaderResourceCacheD3D12&&) = delete;
+
+ DescriptorHeapAllocation m_SamplerHeapSpace;
+ DescriptorHeapAllocation m_CbcSrvUavHeapSpace;
+
+ IMemoryAllocator *m_pAllocator=nullptr;
+ void *m_pMemory = nullptr;
+ Uint32 m_NumTables = 0;
+
+#ifdef _DEBUG
+ // Only for debug purposes: indicates what types of resources are stored in the cache
+ const DbgCacheContentType m_DbgContentType;
+#endif
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h
new file mode 100644
index 00000000..90d1ba27
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h
@@ -0,0 +1,396 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderResourceLayoutD3D12 class
+
+
+// All resources are stored in a single continuous chunk of memory using the following layout:
+//
+// m_ResourceBuffer m_Samplers
+// | |
+// | SRV_CBV_UAV[0] ... SRV_CBV_UAV[s-1] | SRV_CBV_UAV[s] ... SRV_CBV_UAV[s+m-1] | SRV_CBV_UAV[s+m] ... SRV_CBV_UAV[s+m+d-1] || Sampler[0] ... Sampler[s'-1] | Sampler[s'] ... Sampler[s'+m'-1] | Sampler[s'+m'] ... Sampler[s'+m'+d'-1] ||
+// | | | || | | ||
+// | SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC ||
+// | | | ||
+//
+// s == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC]
+// m == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE]
+// d == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC]
+//
+// s' == m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC]
+// m' == m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE]
+// d' == m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC]
+//
+//
+// Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block
+// memory allocator is used. This ensures that all resources from different shader resource bindings reside in
+// continuous memory. If allocation granularity == 1, raw allocator is used.
+//
+//
+// Every SRV_CBV_UAV and Sampler structure holds a reference to D3DShaderResourceAttribs structure from ShaderResources.
+// ShaderResourceLayoutD3D12 holds shared pointer to ShaderResources instance. Note that ShaderResources::SamplerId references
+// a sampler in ShaderResources, while SRV_CBV_UAV::SamplerId references a sampler in ShaderResourceLayoutD3D12, and the
+// two are not the same
+//
+//
+// ________________SamplerId____________________
+// | |
+// _________________ ______________|_____________________________________________V________
+// | | unique_ptr | | | | | | |
+// | ShaderResources |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers |
+// |_________________| |________|___________|___________|___________|___________|____________|
+// A A A A
+// | \ / \
+// |shared_ptr Ref Ref Ref
+// ________|__________________ ________\________________________/_________________________\_________________________________________
+// | | unique_ptr | | | | | | |
+// | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... |
+// |___________________________| |___________________|_________________|_______________|__________________|_________________|__________|
+// | | | A | /
+// | Raw ptr | |___________________SamplerId________________________| | /
+// | | / /
+// | \ / /
+// ________V_________________ ________V_______________________________________________________V____V__
+// | | | |
+// | ShaderResourceCacheD3D12 |---------------->| Resources |
+// |__________________________| |________________________________________________________________________|
+//
+// Resources in the resource cache are identified by the root index and offset in the descriptor table
+//
+//
+// ShaderResourceLayoutD3D12 is used by
+// - ShaderD3D12Impl class instance to hold static resources of a shader; shader resource
+// cache is used to store satatic resource bindings
+// - PipelineStateD3D12Impl class instance to hold all kinds of resources. Root indices and
+// descriptor table offsets are assigned during the initialization; no shader resource cache is used
+// - ShaderResourceBindingD3D12Impl to hold all kind of resources; shader resource cache is assigned
+//
+
+
+// Set this define to 1 to use unordered_map to store shader variables.
+// Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
+#define USE_VARIABLE_HASH_MAP 0
+
+#include "unordered_map"
+
+#include "ShaderD3DBase.h"
+#include "ShaderBase.h"
+#include "HashUtils.h"
+#include "ShaderResourcesD3D12.h"
+#include "ShaderResourceCacheD3D12.h"
+#include "ShaderVariableD3DBase.h"
+
+#ifdef _DEBUG
+# define VERIFY_SHADER_BINDINGS
+#endif
+
+namespace Diligent
+{
+
+/// Diligent::ShaderResourceLayoutD3D12 class
+// sizeof(ShaderResourceLayoutD3D12)==80 (MS compiler, x64)
+class ShaderResourceLayoutD3D12
+{
+public:
+ ShaderResourceLayoutD3D12(IObject &Owner, IMemoryAllocator &ResourceLayoutDataAllocator);
+
+ // This constructor is used by ShaderResourceBindingD3D12Impl to clone layout from the reference layout in PipelineStateD3D12Impl.
+ // Root indices and descriptor table offsets must be correct. Resource cache is not initialized.
+ ShaderResourceLayoutD3D12(IObject &Owner,
+ const ShaderResourceLayoutD3D12& SrcLayout,
+ IMemoryAllocator &ResourceLayoutDataAllocator,
+ const SHADER_VARIABLE_TYPE *AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12 &ResourceCache);
+
+ ShaderResourceLayoutD3D12(const ShaderResourceLayoutD3D12&) = delete;
+ ShaderResourceLayoutD3D12(ShaderResourceLayoutD3D12&&) = delete;
+ ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete;
+ ShaderResourceLayoutD3D12& operator =(ShaderResourceLayoutD3D12&&) = delete;
+
+ ~ShaderResourceLayoutD3D12();
+
+ // The method is called by
+ // - ShaderD3D12Impl class instance to initialize static resource layout and initialize shader resource cache
+ // to hold static resources
+ // - PipelineStateD3D12Impl class instance to hold all kind of resources. Root indices and
+ // descriptor table offsets are assigned during the initialization; no shader resource cache is provided
+ void Initialize(ID3D12Device *pd3d12Device,
+ const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources,
+ IMemoryAllocator &LayoutDataAllocator,
+ const SHADER_VARIABLE_TYPE *VarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12 *pResourceCache,
+ class RootSignature *pRootSig);
+
+ // sizeof(SRV_CBV_UAV) == 32 (x64)
+ struct SRV_CBV_UAV : ShaderVariableD3DBase<ShaderResourceLayoutD3D12>
+ {
+ SRV_CBV_UAV(const SRV_CBV_UAV&) = delete;
+ SRV_CBV_UAV(SRV_CBV_UAV&&) = delete;
+ SRV_CBV_UAV& operator = (const SRV_CBV_UAV&) = delete;
+ SRV_CBV_UAV& operator = (SRV_CBV_UAV&&) = delete;
+
+ static const Uint32 ResTypeBits = 3;
+ static const Uint32 RootIndBits = 16-ResTypeBits;
+ static const Uint32 RootIndMask = (1 << RootIndBits)-1;
+ static const Uint32 ResTypeMask = (1 << ResTypeBits)-1;
+
+ static const Uint16 InvalidRootIndex = RootIndMask;
+ static const Uint16 MaxRootIndex = RootIndMask-1;
+
+ static const Uint32 InvalidSamplerId = 0xFFFF;
+ static const Uint32 MaxSamplerId = InvalidSamplerId-1;
+ static const Uint32 InvalidOffset = static_cast<Uint32>(-1);
+
+ static_assert( static_cast<int>(CachedResourceType::NumTypes) <= ResTypeMask, "3 bits is not enough to store CachedResourceType");
+
+ const Uint32 OffsetFromTableStart;
+
+ SRV_CBV_UAV(ShaderResourceLayoutD3D12 &ParentLayout, const SRV_CBV_UAV &rhs, Uint32 SamId ) :
+ ResType_RootIndex(rhs.ResType_RootIndex),
+ SamplerId(static_cast<Uint16>(SamId)),
+ OffsetFromTableStart(rhs.OffsetFromTableStart),
+ ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, rhs.Attribs)
+ {
+ VERIFY(SamId == InvalidSamplerId || SamId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" )
+ VERIFY(rhs.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references");
+ VERIFY(IsValidOffset(), "Offset must be valid" )
+ VERIFY(IsValidRootIndex(), "Root index must be valid" )
+ }
+
+ SRV_CBV_UAV(ShaderResourceLayoutD3D12 &ParentLayout, const D3DShaderResourceAttribs &_Attribs,
+ CachedResourceType ResType, Uint32 RootIndex, Uint32 _OffsetFromTableStart, Uint32 _SamplerId) :
+ ResType_RootIndex( (static_cast<Uint16>(ResType) << RootIndBits) | (RootIndex & RootIndMask)),
+ SamplerId( static_cast<Uint16>(_SamplerId) ),
+ OffsetFromTableStart(_OffsetFromTableStart),
+ ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, _Attribs)
+ {
+ VERIFY(RootIndex == InvalidRootIndex || RootIndex <= MaxRootIndex, "Root index exceeds max allowed value (", MaxRootIndex, ")" )
+ VERIFY(IsValidOffset(), "Offset must be valid" )
+ VERIFY(SamplerId == InvalidSamplerId || SamplerId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" )
+ }
+
+ bool IsBound(Uint32 ArrayIndex);
+
+ // Non-virtual function
+ void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D12 *dbgResLayout);
+ virtual void Set(IDeviceObject *pObject)override final{ BindResource(pObject, 0, nullptr); }
+
+ virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final
+ {
+ for(Uint32 Elem = 0; Elem < NumElements; ++Elem)
+ BindResource(ppObjects[Elem], FirstElement+Elem, nullptr);
+ }
+
+ bool IsValidSampler()const{return GetSamplerId() != InvalidSamplerId;}
+ bool IsValidRootIndex()const{return GetRootIndex() != InvalidRootIndex;}
+ bool IsValidOffset()const{return OffsetFromTableStart != InvalidOffset;}
+
+ CachedResourceType GetResType()const
+ {
+ return static_cast<CachedResourceType>( (ResType_RootIndex >> RootIndBits) & ResTypeMask );
+ }
+ Uint32 GetRootIndex()const
+ {
+ return ResType_RootIndex & RootIndMask;
+ }
+
+ Uint32 GetSamplerId()const
+ {
+ return SamplerId;
+ }
+
+ private:
+ const Uint16 ResType_RootIndex; // bit
+ // | 0 1 .... 12 | 13 14 15 |
+ // | | |
+ // | Root index | ResType |
+ const Uint16 SamplerId;
+
+ void CacheCB(IDeviceObject *pBuffer, ShaderResourceCacheD3D12::Resource& DstRes, Uint32 ArrayInd, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle);
+
+ template<typename TResourceViewType,
+ typename TViewTypeEnum,
+ typename TBindSamplerProcType>
+ void CacheResourceView(IDeviceObject *pView,
+ ShaderResourceCacheD3D12::Resource& DstRes,
+ Uint32 ArrayIndex,
+ D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle,
+ TViewTypeEnum dbgExpectedViewType,
+ TBindSamplerProcType BindSamplerProc);
+ };
+
+ // sizeof(Sampler) == 24 (x64)
+ struct Sampler
+ {
+ Sampler(const Sampler&) = delete;
+ Sampler(Sampler&&) = delete;
+ Sampler& operator = (const Sampler&) = delete;
+ Sampler& operator = (Sampler&&) = delete;
+
+ const D3DShaderResourceAttribs &Attribs;
+ ShaderResourceLayoutD3D12 &m_ParentResLayout;
+
+ static const Uint32 InvalidRootIndex = static_cast<Uint32>(-1);
+ static const Uint32 InvalidOffset = static_cast<Uint32>(-1);
+
+ const Uint32 RootIndex;
+ const Uint32 OffsetFromTableStart;
+
+ Sampler(ShaderResourceLayoutD3D12 &ParentLayout, const Sampler& Sam):
+ Attribs(Sam.Attribs),
+ m_ParentResLayout(ParentLayout),
+ RootIndex(Sam.RootIndex),
+ OffsetFromTableStart(Sam.OffsetFromTableStart)
+ {
+ VERIFY(Sam.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references");
+ VERIFY(IsValidRootIndex(), "Root index must be valid" )
+ VERIFY(IsValidOffset(), "Offset must be valid" )
+ }
+
+ Sampler(ShaderResourceLayoutD3D12 &ParentResLayout, const D3DShaderResourceAttribs &_Attribs, Uint32 _RootIndex, Uint32 _OffsetFromTableStart) :
+ RootIndex(_RootIndex),
+ OffsetFromTableStart(_OffsetFromTableStart),
+ Attribs(_Attribs),
+ m_ParentResLayout(ParentResLayout)
+ {
+ VERIFY(IsValidRootIndex(), "Root index must be valid" )
+ VERIFY(IsValidOffset(), "Offset must be valid" )
+ }
+
+ bool IsValidRootIndex()const{return RootIndex != InvalidRootIndex;}
+ bool IsValidOffset()const{return OffsetFromTableStart != InvalidOffset;}
+
+ void CacheSampler(class ITextureViewD3D12 *pTexViewD3D12, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle);
+ };
+
+
+ void CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutD3D12 &SrcLayout);
+
+ // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive
+ // while Layout is alive
+ void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D12 *dbgResourceCache );
+
+ IShaderVariable* GetShaderVariable( const Char* Name );
+
+#ifdef VERIFY_SHADER_BINDINGS
+ void dbgVerifyBindings()const;
+#endif
+
+ IObject& GetOwner(){return m_Owner;}
+
+private:
+ void InitVariablesHashMap();
+
+ Sampler &GetAssignedSampler(const SRV_CBV_UAV &TexSrv);
+
+ const Char* GetShaderName()const;
+
+ // There is no need to use shared ptr as referenced resource cache is either part of the
+ // parent ShaderD3D12Impl object or ShaderResourceBindingD3D12Impl object
+ ShaderResourceCacheD3D12 *m_pResourceCache;
+
+ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
+ Sampler* m_Samplers = nullptr;
+ Uint16 m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+ Uint16 m_NumSamplers[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+
+ Uint32 GetSrvCbvUavOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
+ {
+ VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
+ static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected");
+ r += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] : 0;
+ static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected");
+ r += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] : 0;
+ return r;
+ }
+ SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)
+ {
+ VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
+ auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
+ return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)];
+ }
+ const SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
+ {
+ VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
+ auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
+ return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)];
+ }
+ SRV_CBV_UAV& GetSrvCbvUav(Uint32 r)
+ {
+ VERIFY_EXPR( r < GetTotalSrvCbvUavCount() );
+ auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
+ return CbvSrvUav[r];
+ }
+
+ Uint32 GetSamplerOffset(SHADER_VARIABLE_TYPE VarType, Uint32 s)const
+ {
+ VERIFY_EXPR( s < m_NumSamplers[VarType] );
+ static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected");
+ s += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] : 0;
+ static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected");
+ s += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] : 0;
+ return s;
+ }
+ Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)
+ {
+ VERIFY_EXPR( s < m_NumSamplers[VarType] );
+ return m_Samplers[GetSamplerOffset(VarType,s)];
+ }
+ const Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)const
+ {
+ VERIFY_EXPR( s < m_NumSamplers[VarType] );
+ return m_Samplers[GetSamplerOffset(VarType,s)];
+ }
+ Uint32 GetTotalSrvCbvUavCount()const
+ {
+ static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?");
+ return m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC];
+ }
+ Uint32 GetTotalSamplerCount()const
+ {
+ static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?");
+ return m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] + m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC];
+ }
+
+ void AllocateMemory(IMemoryAllocator &Allocator);
+
+#if USE_VARIABLE_HASH_MAP
+ // Hash map to look up shader variables by name.
+ // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
+ typedef std::pair<HashMapStringKey, IShaderVariable*> VariableHashElemType;
+ std::unordered_map<HashMapStringKey, IShaderVariable*, std::hash<HashMapStringKey>, std::equal_to<HashMapStringKey>, STDAllocatorRawMem<VariableHashElemType> > m_VariableHash;
+#endif
+
+ CComPtr<ID3D12Device> m_pd3d12Device;
+ IObject &m_Owner;
+ // We must use shared_ptr to reference ShaderResources instance, because
+ // there may be multiple objects referencing the same set of resources
+ std::shared_ptr<const ShaderResourcesD3D12> m_pResources;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h
new file mode 100644
index 00000000..f58ce20d
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h
@@ -0,0 +1,94 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::ShaderResourcesD3D12 class
+
+// ShaderResourcesD3D12 are created by ShaderD3D12Impl instances. They are then referenced by ShaderResourceLayoutD3D12 objects, which are in turn
+// created by instances of PipelineStatesD3D12Impl and ShaderResourceBindingsD3D12Impl (and ShaderD3D12Impl too)
+//
+// _________________
+// | |
+// | ShaderD3D12Impl |
+// |_________________|
+// |
+// |shared_ptr
+// ________V_____________ _____________________________________________________________________
+// | | unique_ptr | | | | | | |
+// | ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers |
+// |______________________| |________|___________|___________|___________|___________|____________|
+// A A A A
+// | \ / \
+// |shared_ptr Ref Ref Ref
+// ________|__________________ ________\________________________/_________________________\_________________________________________
+// | | unique_ptr | | | | | | |
+// | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... |
+// |___________________________| |___________________|_________________|_______________|__________________|_________________|__________|
+// A | A
+// | |___________________SamplerId________________________|
+// |
+// __________|_____________
+// | |
+// | PipelineStateD3D12Impl |
+// |________________________|
+//
+//
+// One ShaderResources instance can be referenced by multiple objects
+//
+//
+// ________________________ _<m_ShaderResourceLayouts>_ ____<m_pResourceLayouts>___ ________________________________
+// | | | | | | | |
+// | PipelineStateD3D12Impl |-------->| ShaderResourceLayoutD3D12 | ----| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl |
+// |________________________| |___________________________| | |___________________________| |________________________________|
+// | |
+// | shared_ptr |
+// _________________ ___________V__________ | ____<m_pResourceLayouts>___ ________________________________
+// | | shared_ptr | | shared_ptr| | | | |
+// | ShaderD3D12Impl |--------------->| ShaderResourcesD3D12 |<---------------| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl |
+// |_________________| |______________________| | |___________________________| |________________________________|
+// | A |
+// V | |
+// ____<m_StaticResLayout>____ | | ____<m_pResourceLayouts>___ ________________________________
+// | | shared_ptr | | | | | |
+// | ShaderResourceLayoutD3D12 |------------------- ----| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl |
+// |___________________________| |___________________________| |________________________________|
+//
+//
+
+
+#include "ShaderResources.h"
+
+namespace Diligent
+{
+
+/// Diligent::ShaderResources class
+class ShaderResourcesD3D12 : public ShaderResources
+{
+public:
+ // Loads shader resources from the compiled shader bytecode
+ ShaderResourcesD3D12(ID3DBlob *pShaderBytecode, const ShaderDesc &ShdrDesc);
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h
new file mode 100644
index 00000000..e7e8f312
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h
@@ -0,0 +1,69 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::SwapChainD3D12Impl class
+
+#include "SwapChainD3D12.h"
+#include "SwapChainBase.h"
+#include <dxgi1_4.h>
+
+namespace Diligent
+{
+
+class ITextureViewD3D12;
+class IMemoryAllocator;
+/// Implementation of the Diligent::ISwapChainD3D12 interface
+class SwapChainD3D12Impl : public SwapChainBase<ISwapChainD3D12, IMemoryAllocator>
+{
+public:
+ typedef SwapChainBase<ISwapChainD3D12, IMemoryAllocator> TSwapChainBase;
+ SwapChainD3D12Impl(IMemoryAllocator &Allocator,
+ const SwapChainDesc& SwapChainDesc,
+ class RenderDeviceD3D12Impl* pRenderDeviceD3D12,
+ class DeviceContextD3D12Impl* pDeviceContextD3D12,
+ void* pNativeWndHandle);
+ ~SwapChainD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
+
+ virtual void Present();
+ virtual void Resize( Uint32 NewWidth, Uint32 NewHeight );
+
+ virtual IDXGISwapChain *GetDXGISwapChain(){ return m_pSwapChain; }
+ ITextureView *GetCurrentBackBufferRTV();
+ ITextureView *GetDepthBufferDSV(){return m_pDepthBufferDSV;}
+
+private:
+ void InitBuffersAndViews();
+
+ /// DXGI swap chain
+ CComPtr<IDXGISwapChain3> m_pSwapChain;
+
+ std::vector< RefCntAutoPtr<ITextureView>, STDAllocatorRawMem<RefCntAutoPtr<ITextureView>> > m_pBackBufferRTV;
+ RefCntAutoPtr<ITextureView> m_pDepthBufferDSV;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h
new file mode 100644
index 00000000..039de70f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h
@@ -0,0 +1,97 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::TextureD3D12Impl class
+
+#include "TextureD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "TextureBase.h"
+#include "TextureViewD3D12Impl.h"
+#include "D3D12ResourceBase.h"
+
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+
+/// Base implementation of the Diligent::ITextureD3D12 interface
+class TextureD3D12Impl : public TextureBase<ITextureD3D12, TextureViewD3D12Impl, FixedBlockMemoryAllocator, FixedBlockMemoryAllocator>, public D3D12ResourceBase
+{
+public:
+ typedef TextureBase<ITextureD3D12, TextureViewD3D12Impl, FixedBlockMemoryAllocator, FixedBlockMemoryAllocator> TTextureBase;
+
+ TextureD3D12Impl(FixedBlockMemoryAllocator &TexObjAllocator,
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ class RenderDeviceD3D12Impl *pDeviceD3D12,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData = TextureData());
+ TextureD3D12Impl(FixedBlockMemoryAllocator &TexObjAllocator,
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ class RenderDeviceD3D12Impl *pDeviceD3D12,
+ const TextureDesc& TexDesc,
+ ID3D12Resource *pTexture);
+ ~TextureD3D12Impl();
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override;
+
+ //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size);
+ virtual void Map( IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData )override;
+ virtual void Unmap( IDeviceContext *pContext, MAP_TYPE MapType )override;
+
+ virtual ID3D12Resource* GetD3D12Texture(){ return GetD3D12Resource(); }
+
+ void CopyData(IDeviceContext *pContext,
+ ITexture *pSrcTexture,
+ Uint32 SrcMipLevel,
+ Uint32 SrcSlice,
+ const Box *pSrcBox,
+ Uint32 DstMipLevel,
+ Uint32 DstSlice,
+ Uint32 DstX,
+ Uint32 DstY,
+ Uint32 DstZ);
+
+ D3D12_CPU_DESCRIPTOR_HANDLE GetUAVDescriptorHandle(Uint32 Mip, Uint32 Slice);
+
+protected:
+ void CreateViewInternal( const struct TextureViewDesc &ViewDesc, ITextureView **ppView, bool bIsDefaultView )override;
+ //void PrepareD3D12InitData(const TextureData &InitData, Uint32 NumSubresources, std::vector<D3D12_SUBRESOURCE_DATA> &D3D12InitData);
+
+ void CreateSRV( TextureViewDesc &SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle );
+ void CreateRTV( TextureViewDesc &RTVDesc, D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle );
+ void CreateDSV( TextureViewDesc &DSVDesc, D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle );
+ void CreateUAV( TextureViewDesc &UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle );
+
+ // UAVs for every subresource to facilitate mipmap generation
+ DescriptorHeapAllocation m_SubresUAVs;
+
+ friend class RenderDeviceD3D12Impl;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h
new file mode 100644
index 00000000..6256ca0a
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h
@@ -0,0 +1,65 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::TextureViewD3D12Impl class
+
+#include "TextureViewD3D12.h"
+#include "RenderDeviceD3D12.h"
+#include "TextureViewBase.h"
+#include "DescriptorHeap.h"
+
+namespace Diligent
+{
+
+class FixedBlockMemoryAllocator;
+/// Implementation of the Diligent::ITextureViewD3D12 interface
+class TextureViewD3D12Impl : public TextureViewBase<ITextureViewD3D12, FixedBlockMemoryAllocator>
+{
+public:
+ typedef TextureViewBase<ITextureViewD3D12, FixedBlockMemoryAllocator> TTextureViewBase;
+
+ TextureViewD3D12Impl( FixedBlockMemoryAllocator &TexViewObjAllocator,
+ IRenderDevice *pDevice,
+ const TextureViewDesc& ViewDesc,
+ class ITexture *pTexture,
+ DescriptorHeapAllocation &&HandleAlloc,
+ bool bIsDefaultView);
+
+ virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
+
+ //virtual ID3D12View* GetD3D12View()override;
+
+ void GenerateMips( IDeviceContext *pContext )override;
+
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle()override{return m_Descriptor.GetCpuHandle();}
+ //virtual D3D12_GPU_DESCRIPTOR_HANDLE GetGPUDescriptorHandle()override{return m_Descriptor.GetGpuHandle();}
+
+protected:
+ /// D3D12 view descriptor handle
+ DescriptorHeapAllocation m_Descriptor;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/include/d3dx12_win.h b/Graphics/GraphicsEngineD3D12/include/d3dx12_win.h
new file mode 100644
index 00000000..ba59dfc7
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/d3dx12_win.h
@@ -0,0 +1,1508 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+// File: d3dx12.h
+// Content: D3DX12 utility library
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef __D3DX12_H__
+#define __D3DX12_H__
+
+#include "d3d12.h"
+
+#if defined( __cplusplus )
+
+struct CD3DX12_DEFAULT {};
+extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;
+
+//------------------------------------------------------------------------------------------------
+inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )
+{
+ return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&
+ l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;
+}
+
+//------------------------------------------------------------------------------------------------
+inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )
+{ return !( l == r ); }
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RECT : public D3D12_RECT
+{
+ CD3DX12_RECT()
+ {}
+ explicit CD3DX12_RECT( const D3D12_RECT& o ) :
+ D3D12_RECT( o )
+ {}
+ explicit CD3DX12_RECT(
+ LONG Left,
+ LONG Top,
+ LONG Right,
+ LONG Bottom )
+ {
+ left = Left;
+ top = Top;
+ right = Right;
+ bottom = Bottom;
+ }
+ ~CD3DX12_RECT() {}
+ operator const D3D12_RECT&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_BOX : public D3D12_BOX
+{
+ CD3DX12_BOX()
+ {}
+ explicit CD3DX12_BOX( const D3D12_BOX& o ) :
+ D3D12_BOX( o )
+ {}
+ explicit CD3DX12_BOX(
+ LONG Left,
+ LONG Right )
+ {
+ left = Left;
+ top = 0;
+ front = 0;
+ right = Right;
+ bottom = 1;
+ back = 1;
+ }
+ explicit CD3DX12_BOX(
+ LONG Left,
+ LONG Top,
+ LONG Right,
+ LONG Bottom )
+ {
+ left = Left;
+ top = Top;
+ front = 0;
+ right = Right;
+ bottom = Bottom;
+ back = 1;
+ }
+ explicit CD3DX12_BOX(
+ LONG Left,
+ LONG Top,
+ LONG Front,
+ LONG Right,
+ LONG Bottom,
+ LONG Back )
+ {
+ left = Left;
+ top = Top;
+ front = Front;
+ right = Right;
+ bottom = Bottom;
+ back = Back;
+ }
+ ~CD3DX12_BOX() {}
+ operator const D3D12_BOX&() const { return *this; }
+};
+inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )
+{
+ return l.left == r.left && l.top == r.top && l.front == r.front &&
+ l.right == r.right && l.bottom == r.bottom && l.back == r.back;
+}
+inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )
+{ return !( l == r ); }
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC
+{
+ CD3DX12_DEPTH_STENCIL_DESC()
+ {}
+ explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :
+ D3D12_DEPTH_STENCIL_DESC( o )
+ {}
+ explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )
+ {
+ DepthEnable = TRUE;
+ DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ DepthFunc = D3D12_COMPARISON_FUNC_LESS;
+ StencilEnable = FALSE;
+ StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
+ StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
+ const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
+ { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
+ FrontFace = defaultStencilOp;
+ BackFace = defaultStencilOp;
+ }
+ explicit CD3DX12_DEPTH_STENCIL_DESC(
+ BOOL depthEnable,
+ D3D12_DEPTH_WRITE_MASK depthWriteMask,
+ D3D12_COMPARISON_FUNC depthFunc,
+ BOOL stencilEnable,
+ UINT8 stencilReadMask,
+ UINT8 stencilWriteMask,
+ D3D12_STENCIL_OP frontStencilFailOp,
+ D3D12_STENCIL_OP frontStencilDepthFailOp,
+ D3D12_STENCIL_OP frontStencilPassOp,
+ D3D12_COMPARISON_FUNC frontStencilFunc,
+ D3D12_STENCIL_OP backStencilFailOp,
+ D3D12_STENCIL_OP backStencilDepthFailOp,
+ D3D12_STENCIL_OP backStencilPassOp,
+ D3D12_COMPARISON_FUNC backStencilFunc )
+ {
+ DepthEnable = depthEnable;
+ DepthWriteMask = depthWriteMask;
+ DepthFunc = depthFunc;
+ StencilEnable = stencilEnable;
+ StencilReadMask = stencilReadMask;
+ StencilWriteMask = stencilWriteMask;
+ FrontFace.StencilFailOp = frontStencilFailOp;
+ FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;
+ FrontFace.StencilPassOp = frontStencilPassOp;
+ FrontFace.StencilFunc = frontStencilFunc;
+ BackFace.StencilFailOp = backStencilFailOp;
+ BackFace.StencilDepthFailOp = backStencilDepthFailOp;
+ BackFace.StencilPassOp = backStencilPassOp;
+ BackFace.StencilFunc = backStencilFunc;
+ }
+ ~CD3DX12_DEPTH_STENCIL_DESC() {}
+ operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC
+{
+ CD3DX12_BLEND_DESC()
+ {}
+ explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :
+ D3D12_BLEND_DESC( o )
+ {}
+ explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )
+ {
+ AlphaToCoverageEnable = FALSE;
+ IndependentBlendEnable = FALSE;
+ const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
+ {
+ FALSE,FALSE,
+ D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
+ D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
+ D3D12_LOGIC_OP_NOOP,
+ D3D12_COLOR_WRITE_ENABLE_ALL,
+ };
+ for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
+ RenderTarget[ i ] = defaultRenderTargetBlendDesc;
+ }
+ ~CD3DX12_BLEND_DESC() {}
+ operator const D3D12_BLEND_DESC&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC
+{
+ CD3DX12_RASTERIZER_DESC()
+ {}
+ explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :
+ D3D12_RASTERIZER_DESC( o )
+ {}
+ explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )
+ {
+ FillMode = D3D12_FILL_MODE_SOLID;
+ CullMode = D3D12_CULL_MODE_BACK;
+ FrontCounterClockwise = FALSE;
+ DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
+ DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
+ SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
+ DepthClipEnable = TRUE;
+ MultisampleEnable = FALSE;
+ AntialiasedLineEnable = FALSE;
+ ForcedSampleCount = 0;
+ ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+ }
+ explicit CD3DX12_RASTERIZER_DESC(
+ D3D12_FILL_MODE fillMode,
+ D3D12_CULL_MODE cullMode,
+ BOOL frontCounterClockwise,
+ INT depthBias,
+ FLOAT depthBiasClamp,
+ FLOAT slopeScaledDepthBias,
+ BOOL depthClipEnable,
+ BOOL multisampleEnable,
+ BOOL antialiasedLineEnable,
+ UINT forcedSampleCount,
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)
+ {
+ FillMode = fillMode;
+ CullMode = cullMode;
+ FrontCounterClockwise = frontCounterClockwise;
+ DepthBias = depthBias;
+ DepthBiasClamp = depthBiasClamp;
+ SlopeScaledDepthBias = slopeScaledDepthBias;
+ DepthClipEnable = depthClipEnable;
+ MultisampleEnable = multisampleEnable;
+ AntialiasedLineEnable = antialiasedLineEnable;
+ ForcedSampleCount = forcedSampleCount;
+ ConservativeRaster = conservativeRaster;
+ }
+ ~CD3DX12_RASTERIZER_DESC() {}
+ operator const D3D12_RASTERIZER_DESC&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO
+{
+ CD3DX12_RESOURCE_ALLOCATION_INFO()
+ {}
+ explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :
+ D3D12_RESOURCE_ALLOCATION_INFO( o )
+ {}
+ CD3DX12_RESOURCE_ALLOCATION_INFO(
+ UINT64 size,
+ UINT64 alignment )
+ {
+ SizeInBytes = size;
+ Alignment = alignment;
+ }
+ operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES
+{
+ CD3DX12_HEAP_PROPERTIES()
+ {}
+ explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :
+ D3D12_HEAP_PROPERTIES(o)
+ {}
+ CD3DX12_HEAP_PROPERTIES(
+ D3D12_CPU_PAGE_PROPERTY cpuPageProperty,
+ D3D12_MEMORY_POOL memoryPoolPreference,
+ UINT creationNodeMask = 1,
+ UINT nodeMask = 1 )
+ {
+ Type = D3D12_HEAP_TYPE_CUSTOM;
+ CPUPageProperty = cpuPageProperty;
+ MemoryPoolPreference = memoryPoolPreference;
+ CreationNodeMask = creationNodeMask;
+ VisibleNodeMask = nodeMask;
+ }
+ explicit CD3DX12_HEAP_PROPERTIES(
+ D3D12_HEAP_TYPE type,
+ UINT creationNodeMask = 1,
+ UINT nodeMask = 1 )
+ {
+ Type = type;
+ CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ CreationNodeMask = creationNodeMask;
+ VisibleNodeMask = nodeMask;
+ }
+ operator const D3D12_HEAP_PROPERTIES&() const { return *this; }
+ bool IsCPUAccessible() const
+ {
+ return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&
+ (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));
+ }
+};
+inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )
+{
+ return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty &&
+ l.MemoryPoolPreference == r.MemoryPoolPreference &&
+ l.CreationNodeMask == r.CreationNodeMask &&
+ l.VisibleNodeMask == r.VisibleNodeMask;
+}
+inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )
+{ return !( l == r ); }
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC
+{
+ CD3DX12_HEAP_DESC()
+ {}
+ explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :
+ D3D12_HEAP_DESC(o)
+ {}
+ CD3DX12_HEAP_DESC(
+ UINT64 size,
+ D3D12_HEAP_PROPERTIES properties,
+ UINT64 alignment = 0,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = size;
+ Properties = properties;
+ Alignment = alignment;
+ Flags = flags;
+ }
+ CD3DX12_HEAP_DESC(
+ UINT64 size,
+ D3D12_HEAP_TYPE type,
+ UINT64 alignment = 0,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = size;
+ Properties = CD3DX12_HEAP_PROPERTIES( type );
+ Alignment = alignment;
+ Flags = flags;
+ }
+ CD3DX12_HEAP_DESC(
+ UINT64 size,
+ D3D12_CPU_PAGE_PROPERTY cpuPageProperty,
+ D3D12_MEMORY_POOL memoryPoolPreference,
+ UINT64 alignment = 0,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = size;
+ Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );
+ Alignment = alignment;
+ Flags = flags;
+ }
+ CD3DX12_HEAP_DESC(
+ const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,
+ D3D12_HEAP_PROPERTIES properties,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = resAllocInfo.SizeInBytes;
+ Properties = properties;
+ Alignment = resAllocInfo.Alignment;
+ Flags = flags;
+ }
+ CD3DX12_HEAP_DESC(
+ const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,
+ D3D12_HEAP_TYPE type,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = resAllocInfo.SizeInBytes;
+ Properties = CD3DX12_HEAP_PROPERTIES( type );
+ Alignment = resAllocInfo.Alignment;
+ Flags = flags;
+ }
+ CD3DX12_HEAP_DESC(
+ const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,
+ D3D12_CPU_PAGE_PROPERTY cpuPageProperty,
+ D3D12_MEMORY_POOL memoryPoolPreference,
+ D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )
+ {
+ SizeInBytes = resAllocInfo.SizeInBytes;
+ Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );
+ Alignment = resAllocInfo.Alignment;
+ Flags = flags;
+ }
+ operator const D3D12_HEAP_DESC&() const { return *this; }
+ bool IsCPUAccessible() const
+ { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }
+};
+inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )
+{
+ return l.SizeInBytes == r.SizeInBytes &&
+ l.Properties == r.Properties &&
+ l.Alignment == r.Alignment &&
+ l.Flags == r.Flags;
+}
+inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )
+{ return !( l == r ); }
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE
+{
+ CD3DX12_CLEAR_VALUE()
+ {}
+ explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :
+ D3D12_CLEAR_VALUE(o)
+ {}
+ CD3DX12_CLEAR_VALUE(
+ DXGI_FORMAT format,
+ const FLOAT color[4] )
+ {
+ Format = format;
+ memcpy( Color, color, sizeof( Color ) );
+ }
+ CD3DX12_CLEAR_VALUE(
+ DXGI_FORMAT format,
+ FLOAT depth,
+ UINT8 stencil )
+ {
+ Format = format;
+ /* Use memcpy to preserve NAN values */
+ memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );
+ DepthStencil.Stencil = stencil;
+ }
+ operator const D3D12_CLEAR_VALUE&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RANGE : public D3D12_RANGE
+{
+ CD3DX12_RANGE()
+ {}
+ explicit CD3DX12_RANGE(const D3D12_RANGE &o) :
+ D3D12_RANGE(o)
+ {}
+ CD3DX12_RANGE(
+ SIZE_T begin,
+ SIZE_T end )
+ {
+ Begin = begin;
+ End = end;
+ }
+ operator const D3D12_RANGE&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE
+{
+ CD3DX12_TILED_RESOURCE_COORDINATE()
+ {}
+ explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :
+ D3D12_TILED_RESOURCE_COORDINATE(o)
+ {}
+ CD3DX12_TILED_RESOURCE_COORDINATE(
+ UINT x,
+ UINT y,
+ UINT z,
+ UINT subresource )
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ Subresource = subresource;
+ }
+ operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE
+{
+ CD3DX12_TILE_REGION_SIZE()
+ {}
+ explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :
+ D3D12_TILE_REGION_SIZE(o)
+ {}
+ CD3DX12_TILE_REGION_SIZE(
+ UINT numTiles,
+ BOOL useBox,
+ UINT width,
+ UINT16 height,
+ UINT16 depth )
+ {
+ NumTiles = numTiles;
+ UseBox = useBox;
+ Width = width;
+ Height = height;
+ Depth = depth;
+ }
+ operator const D3D12_TILE_REGION_SIZE&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING
+{
+ CD3DX12_SUBRESOURCE_TILING()
+ {}
+ explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :
+ D3D12_SUBRESOURCE_TILING(o)
+ {}
+ CD3DX12_SUBRESOURCE_TILING(
+ UINT widthInTiles,
+ UINT16 heightInTiles,
+ UINT16 depthInTiles,
+ UINT startTileIndexInOverallResource )
+ {
+ WidthInTiles = widthInTiles;
+ HeightInTiles = heightInTiles;
+ DepthInTiles = depthInTiles;
+ StartTileIndexInOverallResource = startTileIndexInOverallResource;
+ }
+ operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE
+{
+ CD3DX12_TILE_SHAPE()
+ {}
+ explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :
+ D3D12_TILE_SHAPE(o)
+ {}
+ CD3DX12_TILE_SHAPE(
+ UINT widthInTexels,
+ UINT heightInTexels,
+ UINT depthInTexels )
+ {
+ WidthInTexels = widthInTexels;
+ HeightInTexels = heightInTexels;
+ DepthInTexels = depthInTexels;
+ }
+ operator const D3D12_TILE_SHAPE&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER
+{
+ CD3DX12_RESOURCE_BARRIER()
+ {}
+ explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :
+ D3D12_RESOURCE_BARRIER(o)
+ {}
+ static inline CD3DX12_RESOURCE_BARRIER Transition(
+ _In_ ID3D12Resource* pResource,
+ D3D12_RESOURCE_STATES stateBefore,
+ D3D12_RESOURCE_STATES stateAfter,
+ UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
+ D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)
+ {
+ CD3DX12_RESOURCE_BARRIER result;
+ ZeroMemory(&result, sizeof(result));
+ D3D12_RESOURCE_BARRIER &barrier = result;
+ result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ result.Flags = flags;
+ barrier.Transition.pResource = pResource;
+ barrier.Transition.StateBefore = stateBefore;
+ barrier.Transition.StateAfter = stateAfter;
+ barrier.Transition.Subresource = subresource;
+ return result;
+ }
+ static inline CD3DX12_RESOURCE_BARRIER Aliasing(
+ _In_ ID3D12Resource* pResourceBefore,
+ _In_ ID3D12Resource* pResourceAfter)
+ {
+ CD3DX12_RESOURCE_BARRIER result;
+ ZeroMemory(&result, sizeof(result));
+ D3D12_RESOURCE_BARRIER &barrier = result;
+ result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
+ barrier.Aliasing.pResourceBefore = pResourceBefore;
+ barrier.Aliasing.pResourceAfter = pResourceAfter;
+ return result;
+ }
+ static inline CD3DX12_RESOURCE_BARRIER UAV(
+ _In_ ID3D12Resource* pResource)
+ {
+ CD3DX12_RESOURCE_BARRIER result;
+ ZeroMemory(&result, sizeof(result));
+ D3D12_RESOURCE_BARRIER &barrier = result;
+ result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+ barrier.UAV.pResource = pResource;
+ return result;
+ }
+ operator const D3D12_RESOURCE_BARRIER&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO
+{
+ CD3DX12_PACKED_MIP_INFO()
+ {}
+ explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :
+ D3D12_PACKED_MIP_INFO(o)
+ {}
+ CD3DX12_PACKED_MIP_INFO(
+ UINT8 numStandardMips,
+ UINT8 numPackedMips,
+ UINT numTilesForPackedMips,
+ UINT startTileIndexInOverallResource )
+ {
+ NumStandardMips = numStandardMips;
+ NumPackedMips = numPackedMips;
+ NumTilesForPackedMips = numTilesForPackedMips;
+ StartTileIndexInOverallResource = startTileIndexInOverallResource;
+ }
+ operator const D3D12_PACKED_MIP_INFO&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT
+{
+ CD3DX12_SUBRESOURCE_FOOTPRINT()
+ {}
+ explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :
+ D3D12_SUBRESOURCE_FOOTPRINT(o)
+ {}
+ CD3DX12_SUBRESOURCE_FOOTPRINT(
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT depth,
+ UINT rowPitch )
+ {
+ Format = format;
+ Width = width;
+ Height = height;
+ Depth = depth;
+ RowPitch = rowPitch;
+ }
+ explicit CD3DX12_SUBRESOURCE_FOOTPRINT(
+ const D3D12_RESOURCE_DESC& resDesc,
+ UINT rowPitch )
+ {
+ Format = resDesc.Format;
+ Width = UINT( resDesc.Width );
+ Height = resDesc.Height;
+ Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);
+ RowPitch = rowPitch;
+ }
+ operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION
+{
+ CD3DX12_TEXTURE_COPY_LOCATION()
+ {}
+ explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :
+ D3D12_TEXTURE_COPY_LOCATION(o)
+ {}
+ CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }
+ CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)
+ {
+ pResource = pRes;
+ Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ PlacedFootprint = Footprint;
+ }
+ CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)
+ {
+ pResource = pRes;
+ Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ SubresourceIndex = Sub;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE
+{
+ CD3DX12_DESCRIPTOR_RANGE() { }
+ explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :
+ D3D12_DESCRIPTOR_RANGE(o)
+ {}
+ CD3DX12_DESCRIPTOR_RANGE(
+ D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
+ UINT numDescriptors,
+ UINT baseShaderRegister,
+ UINT registerSpace = 0,
+ UINT offsetInDescriptorsFromTableStart =
+ D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);
+ }
+
+ inline void Init(
+ D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
+ UINT numDescriptors,
+ UINT baseShaderRegister,
+ UINT registerSpace = 0,
+ UINT offsetInDescriptorsFromTableStart =
+ D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);
+ }
+
+ static inline void Init(
+ _Out_ D3D12_DESCRIPTOR_RANGE &range,
+ D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
+ UINT numDescriptors,
+ UINT baseShaderRegister,
+ UINT registerSpace = 0,
+ UINT offsetInDescriptorsFromTableStart =
+ D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ range.RangeType = rangeType;
+ range.NumDescriptors = numDescriptors;
+ range.BaseShaderRegister = baseShaderRegister;
+ range.RegisterSpace = registerSpace;
+ range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE
+{
+ CD3DX12_ROOT_DESCRIPTOR_TABLE() {}
+ explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :
+ D3D12_ROOT_DESCRIPTOR_TABLE(o)
+ {}
+ CD3DX12_ROOT_DESCRIPTOR_TABLE(
+ UINT numDescriptorRanges,
+ _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)
+ {
+ Init(numDescriptorRanges, _pDescriptorRanges);
+ }
+
+ inline void Init(
+ UINT numDescriptorRanges,
+ _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)
+ {
+ Init(*this, numDescriptorRanges, _pDescriptorRanges);
+ }
+
+ static inline void Init(
+ _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,
+ UINT numDescriptorRanges,
+ _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)
+ {
+ rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;
+ rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS
+{
+ CD3DX12_ROOT_CONSTANTS() {}
+ explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :
+ D3D12_ROOT_CONSTANTS(o)
+ {}
+ CD3DX12_ROOT_CONSTANTS(
+ UINT num32BitValues,
+ UINT shaderRegister,
+ UINT registerSpace = 0)
+ {
+ Init(num32BitValues, shaderRegister, registerSpace);
+ }
+
+ inline void Init(
+ UINT num32BitValues,
+ UINT shaderRegister,
+ UINT registerSpace = 0)
+ {
+ Init(*this, num32BitValues, shaderRegister, registerSpace);
+ }
+
+ static inline void Init(
+ _Out_ D3D12_ROOT_CONSTANTS &rootConstants,
+ UINT num32BitValues,
+ UINT shaderRegister,
+ UINT registerSpace = 0)
+ {
+ rootConstants.Num32BitValues = num32BitValues;
+ rootConstants.ShaderRegister = shaderRegister;
+ rootConstants.RegisterSpace = registerSpace;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR
+{
+ CD3DX12_ROOT_DESCRIPTOR() {}
+ explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :
+ D3D12_ROOT_DESCRIPTOR(o)
+ {}
+ CD3DX12_ROOT_DESCRIPTOR(
+ UINT shaderRegister,
+ UINT registerSpace = 0)
+ {
+ Init(shaderRegister, registerSpace);
+ }
+
+ inline void Init(
+ UINT shaderRegister,
+ UINT registerSpace = 0)
+ {
+ Init(*this, shaderRegister, registerSpace);
+ }
+
+ static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)
+ {
+ table.ShaderRegister = shaderRegister;
+ table.RegisterSpace = registerSpace;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER
+{
+ CD3DX12_ROOT_PARAMETER() {}
+ explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :
+ D3D12_ROOT_PARAMETER(o)
+ {}
+
+ static inline void InitAsDescriptorTable(
+ _Out_ D3D12_ROOT_PARAMETER &rootParam,
+ UINT numDescriptorRanges,
+ _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ rootParam.ShaderVisibility = visibility;
+ CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);
+ }
+
+ static inline void InitAsConstants(
+ _Out_ D3D12_ROOT_PARAMETER &rootParam,
+ UINT num32BitValues,
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ rootParam.ShaderVisibility = visibility;
+ CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);
+ }
+
+ static inline void InitAsConstantBufferView(
+ _Out_ D3D12_ROOT_PARAMETER &rootParam,
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ rootParam.ShaderVisibility = visibility;
+ CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);
+ }
+
+ static inline void InitAsShaderResourceView(
+ _Out_ D3D12_ROOT_PARAMETER &rootParam,
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
+ rootParam.ShaderVisibility = visibility;
+ CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);
+ }
+
+ static inline void InitAsUnorderedAccessView(
+ _Out_ D3D12_ROOT_PARAMETER &rootParam,
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
+ rootParam.ShaderVisibility = visibility;
+ CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);
+ }
+
+ inline void InitAsDescriptorTable(
+ UINT numDescriptorRanges,
+ _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);
+ }
+
+ inline void InitAsConstants(
+ UINT num32BitValues,
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);
+ }
+
+ inline void InitAsConstantBufferView(
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);
+ }
+
+ inline void InitAsShaderResourceView(
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);
+ }
+
+ inline void InitAsUnorderedAccessView(
+ UINT shaderRegister,
+ UINT registerSpace = 0,
+ D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)
+ {
+ InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC
+{
+ CD3DX12_STATIC_SAMPLER_DESC() {}
+ explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :
+ D3D12_STATIC_SAMPLER_DESC(o)
+ {}
+ CD3DX12_STATIC_SAMPLER_DESC(
+ UINT shaderRegister,
+ D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,
+ D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ FLOAT mipLODBias = 0,
+ UINT maxAnisotropy = 16,
+ D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,
+ D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,
+ FLOAT minLOD = 0.f,
+ FLOAT maxLOD = D3D12_FLOAT32_MAX,
+ D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
+ UINT registerSpace = 0)
+ {
+ Init(
+ shaderRegister,
+ filter,
+ addressU,
+ addressV,
+ addressW,
+ mipLODBias,
+ maxAnisotropy,
+ comparisonFunc,
+ borderColor,
+ minLOD,
+ maxLOD,
+ shaderVisibility,
+ registerSpace);
+ }
+
+ static inline void Init(
+ _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,
+ UINT shaderRegister,
+ D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,
+ D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ FLOAT mipLODBias = 0,
+ UINT maxAnisotropy = 16,
+ D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,
+ D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,
+ FLOAT minLOD = 0.f,
+ FLOAT maxLOD = D3D12_FLOAT32_MAX,
+ D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
+ UINT registerSpace = 0)
+ {
+ samplerDesc.ShaderRegister = shaderRegister;
+ samplerDesc.Filter = filter;
+ samplerDesc.AddressU = addressU;
+ samplerDesc.AddressV = addressV;
+ samplerDesc.AddressW = addressW;
+ samplerDesc.MipLODBias = mipLODBias;
+ samplerDesc.MaxAnisotropy = maxAnisotropy;
+ samplerDesc.ComparisonFunc = comparisonFunc;
+ samplerDesc.BorderColor = borderColor;
+ samplerDesc.MinLOD = minLOD;
+ samplerDesc.MaxLOD = maxLOD;
+ samplerDesc.ShaderVisibility = shaderVisibility;
+ samplerDesc.RegisterSpace = registerSpace;
+ }
+ inline void Init(
+ UINT shaderRegister,
+ D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,
+ D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ FLOAT mipLODBias = 0,
+ UINT maxAnisotropy = 16,
+ D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,
+ D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,
+ FLOAT minLOD = 0.f,
+ FLOAT maxLOD = D3D12_FLOAT32_MAX,
+ D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
+ UINT registerSpace = 0)
+ {
+ Init(
+ *this,
+ shaderRegister,
+ filter,
+ addressU,
+ addressV,
+ addressW,
+ mipLODBias,
+ maxAnisotropy,
+ comparisonFunc,
+ borderColor,
+ minLOD,
+ maxLOD,
+ shaderVisibility,
+ registerSpace);
+ }
+
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC
+{
+ CD3DX12_ROOT_SIGNATURE_DESC() {}
+ explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :
+ D3D12_ROOT_SIGNATURE_DESC(o)
+ {}
+ CD3DX12_ROOT_SIGNATURE_DESC(
+ UINT numParameters,
+ _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,
+ UINT numStaticSamplers = 0,
+ _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,
+ D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)
+ {
+ Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);
+ }
+ CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)
+ {
+ Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);
+ }
+
+ inline void Init(
+ UINT numParameters,
+ _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,
+ UINT numStaticSamplers = 0,
+ _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,
+ D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)
+ {
+ Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);
+ }
+
+ static inline void Init(
+ _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,
+ UINT numParameters,
+ _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,
+ UINT numStaticSamplers = 0,
+ _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,
+ D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)
+ {
+ desc.NumParameters = numParameters;
+ desc.pParameters = _pParameters;
+ desc.NumStaticSamplers = numStaticSamplers;
+ desc.pStaticSamplers = _pStaticSamplers;
+ desc.Flags = flags;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE
+{
+ CD3DX12_CPU_DESCRIPTOR_HANDLE() {}
+ explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :
+ D3D12_CPU_DESCRIPTOR_HANDLE(o)
+ {}
+ CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }
+ CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)
+ {
+ InitOffsetted(other, offsetScaledByIncrementSize);
+ }
+ CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);
+ }
+ CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ ptr += offsetInDescriptors * descriptorIncrementSize;
+ return *this;
+ }
+ CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize)
+ {
+ ptr += offsetScaledByIncrementSize;
+ return *this;
+ }
+ bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other)
+ {
+ return (ptr == other.ptr);
+ }
+ bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other)
+ {
+ return (ptr != other.ptr);
+ }
+ CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)
+ {
+ ptr = other.ptr;
+ return *this;
+ }
+
+ inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)
+ {
+ InitOffsetted(*this, base, offsetScaledByIncrementSize);
+ }
+
+ inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);
+ }
+
+ static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)
+ {
+ handle.ptr = base.ptr + offsetScaledByIncrementSize;
+ }
+
+ static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
+{
+ CD3DX12_GPU_DESCRIPTOR_HANDLE() {}
+ explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :
+ D3D12_GPU_DESCRIPTOR_HANDLE(o)
+ {}
+ CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }
+ CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)
+ {
+ InitOffsetted(other, offsetScaledByIncrementSize);
+ }
+ CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);
+ }
+ CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ ptr += offsetInDescriptors * descriptorIncrementSize;
+ return *this;
+ }
+ CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize)
+ {
+ ptr += offsetScaledByIncrementSize;
+ return *this;
+ }
+ inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other)
+ {
+ return (ptr == other.ptr);
+ }
+ inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other)
+ {
+ return (ptr != other.ptr);
+ }
+ CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)
+ {
+ ptr = other.ptr;
+ return *this;
+ }
+
+ inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)
+ {
+ InitOffsetted(*this, base, offsetScaledByIncrementSize);
+ }
+
+ inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);
+ }
+
+ static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)
+ {
+ handle.ptr = base.ptr + offsetScaledByIncrementSize;
+ }
+
+ static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)
+ {
+ handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )
+{
+ return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize;
+}
+
+//------------------------------------------------------------------------------------------------
+template <typename T, typename U, typename V>
+inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )
+{
+ MipSlice = static_cast<T>(Subresource % MipLevels);
+ ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);
+ PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));
+}
+
+//------------------------------------------------------------------------------------------------
+inline UINT8 D3D12GetFormatPlaneCount(
+ _In_ ID3D12Device* pDevice,
+ DXGI_FORMAT Format
+ )
+{
+ D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};
+ if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))
+ {
+ return 0;
+ }
+ return formatInfo.PlaneCount;
+}
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC
+{
+ CD3DX12_RESOURCE_DESC()
+ {}
+ explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :
+ D3D12_RESOURCE_DESC( o )
+ {}
+ CD3DX12_RESOURCE_DESC(
+ D3D12_RESOURCE_DIMENSION dimension,
+ UINT64 alignment,
+ UINT64 width,
+ UINT height,
+ UINT16 depthOrArraySize,
+ UINT16 mipLevels,
+ DXGI_FORMAT format,
+ UINT sampleCount,
+ UINT sampleQuality,
+ D3D12_TEXTURE_LAYOUT layout,
+ D3D12_RESOURCE_FLAGS flags )
+ {
+ Dimension = dimension;
+ Alignment = alignment;
+ Width = width;
+ Height = height;
+ DepthOrArraySize = depthOrArraySize;
+ MipLevels = mipLevels;
+ Format = format;
+ SampleDesc.Count = sampleCount;
+ SampleDesc.Quality = sampleQuality;
+ Layout = layout;
+ Flags = flags;
+ }
+ static inline CD3DX12_RESOURCE_DESC Buffer(
+ const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,
+ D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )
+ {
+ return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes,
+ 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );
+ }
+ static inline CD3DX12_RESOURCE_DESC Buffer(
+ UINT64 width,
+ D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
+ UINT64 alignment = 0 )
+ {
+ return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1,
+ DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );
+ }
+ static inline CD3DX12_RESOURCE_DESC Tex1D(
+ DXGI_FORMAT format,
+ UINT64 width,
+ UINT16 arraySize = 1,
+ UINT16 mipLevels = 0,
+ D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
+ D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
+ UINT64 alignment = 0 )
+ {
+ return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize,
+ mipLevels, format, 1, 0, layout, flags );
+ }
+ static inline CD3DX12_RESOURCE_DESC Tex2D(
+ DXGI_FORMAT format,
+ UINT64 width,
+ UINT height,
+ UINT16 arraySize = 1,
+ UINT16 mipLevels = 0,
+ UINT sampleCount = 1,
+ UINT sampleQuality = 0,
+ D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
+ D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
+ UINT64 alignment = 0 )
+ {
+ return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize,
+ mipLevels, format, sampleCount, sampleQuality, layout, flags );
+ }
+ static inline CD3DX12_RESOURCE_DESC Tex3D(
+ DXGI_FORMAT format,
+ UINT64 width,
+ UINT height,
+ UINT16 depth,
+ UINT16 mipLevels = 0,
+ D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
+ D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
+ UINT64 alignment = 0 )
+ {
+ return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth,
+ mipLevels, format, 1, 0, layout, flags );
+ }
+ inline UINT16 Depth() const
+ { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }
+ inline UINT16 ArraySize() const
+ { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }
+ inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const
+ { return D3D12GetFormatPlaneCount(pDevice, Format); }
+ inline UINT Subresources(_In_ ID3D12Device* pDevice) const
+ { return MipLevels * ArraySize() * PlaneCount(pDevice); }
+ inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)
+ { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }
+ operator const D3D12_RESOURCE_DESC&() const { return *this; }
+};
+inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )
+{
+ return l.Dimension == r.Dimension &&
+ l.Alignment == r.Alignment &&
+ l.Width == r.Width &&
+ l.Height == r.Height &&
+ l.DepthOrArraySize == r.DepthOrArraySize &&
+ l.MipLevels == r.MipLevels &&
+ l.Format == r.Format &&
+ l.SampleDesc.Count == r.SampleDesc.Count &&
+ l.SampleDesc.Quality == r.SampleDesc.Quality &&
+ l.Layout == r.Layout &&
+ l.Flags == r.Flags;
+}
+inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )
+{ return !( l == r ); }
+
+//------------------------------------------------------------------------------------------------
+// Row-by-row memcpy
+inline void MemcpySubresource(
+ _In_ const D3D12_MEMCPY_DEST* pDest,
+ _In_ const D3D12_SUBRESOURCE_DATA* pSrc,
+ SIZE_T RowSizeInBytes,
+ UINT NumRows,
+ UINT NumSlices)
+{
+ for (UINT z = 0; z < NumSlices; ++z)
+ {
+ BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
+ const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;
+ for (UINT y = 0; y < NumRows; ++y)
+ {
+ memcpy(pDestSlice + pDest->RowPitch * y,
+ pSrcSlice + pSrc->RowPitch * y,
+ RowSizeInBytes);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+// Returns required size of a buffer to be used for data upload
+inline UINT64 GetRequiredIntermediateSize(
+ _In_ ID3D12Resource* pDestinationResource,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)
+{
+ D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
+ UINT64 RequiredSize = 0;
+
+ ID3D12Device* pDevice;
+ pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));
+ pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);
+ pDevice->Release();
+
+ return RequiredSize;
+}
+
+//------------------------------------------------------------------------------------------------
+// All arrays must be populated (e.g. by calling GetCopyableFootprints)
+inline UINT64 UpdateSubresources(
+ _In_ ID3D12GraphicsCommandList* pCmdList,
+ _In_ ID3D12Resource* pDestinationResource,
+ _In_ ID3D12Resource* pIntermediate,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
+ UINT64 RequiredSize,
+ _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
+ _In_reads_(NumSubresources) const UINT* pNumRows,
+ _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
+ _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)
+{
+ // Minor validation
+ D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();
+ D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();
+ if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
+ IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
+ RequiredSize > (SIZE_T)-1 ||
+ (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
+ (FirstSubresource != 0 || NumSubresources != 1)))
+ {
+ return 0;
+ }
+
+ BYTE* pData;
+ HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));
+ if (FAILED(hr))
+ {
+ return 0;
+ }
+
+ for (UINT i = 0; i < NumSubresources; ++i)
+ {
+ if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;
+ D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };
+ MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);
+ }
+ pIntermediate->Unmap(0, NULL);
+
+ if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
+ {
+ CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );
+ pCmdList->CopyBufferRegion(
+ pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
+ }
+ else
+ {
+ for (UINT i = 0; i < NumSubresources; ++i)
+ {
+ CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
+ CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
+ pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
+ }
+ }
+ return RequiredSize;
+}
+
+//------------------------------------------------------------------------------------------------
+// Heap-allocating UpdateSubresources implementation
+inline UINT64 UpdateSubresources(
+ _In_ ID3D12GraphicsCommandList* pCmdList,
+ _In_ ID3D12Resource* pDestinationResource,
+ _In_ ID3D12Resource* pIntermediate,
+ UINT64 IntermediateOffset,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
+ _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
+ _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)
+{
+ UINT64 RequiredSize = 0;
+ UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
+ if (MemToAlloc > SIZE_MAX)
+ {
+ return 0;
+ }
+ void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
+ if (pMem == NULL)
+ {
+ return 0;
+ }
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
+ UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
+ UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
+
+ D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
+ ID3D12Device* pDevice;
+ pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));
+ pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
+ pDevice->Release();
+
+ UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);
+ HeapFree(GetProcessHeap(), 0, pMem);
+ return Result;
+}
+
+//------------------------------------------------------------------------------------------------
+// Stack-allocating UpdateSubresources implementation
+template <UINT MaxSubresources>
+inline UINT64 UpdateSubresources(
+ _In_ ID3D12GraphicsCommandList* pCmdList,
+ _In_ ID3D12Resource* pDestinationResource,
+ _In_ ID3D12Resource* pIntermediate,
+ UINT64 IntermediateOffset,
+ _In_range_(0, MaxSubresources) UINT FirstSubresource,
+ _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,
+ _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)
+{
+ UINT64 RequiredSize = 0;
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];
+ UINT NumRows[MaxSubresources];
+ UINT64 RowSizesInBytes[MaxSubresources];
+
+ D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
+ ID3D12Device* pDevice;
+ pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));
+ pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);
+ pDevice->Release();
+
+ return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);
+}
+
+//------------------------------------------------------------------------------------------------
+inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )
+{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }
+
+//------------------------------------------------------------------------------------------------
+inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp)
+{
+ // This cast is useful for passing strongly typed command list pointers into
+ // ExecuteCommandLists.
+ // This cast is valid as long as the const-ness is respected. D3D12 APIs do
+ // respect the const-ness of their arguments.
+ return reinterpret_cast<ID3D12CommandList * const *>(pp);
+}
+
+
+#endif // defined( __cplusplus )
+
+#endif //__D3DX12_H__
+
+
+
diff --git a/Graphics/GraphicsEngineD3D12/include/pch.h b/Graphics/GraphicsEngineD3D12/include/pch.h
new file mode 100644
index 00000000..f2f0b7f4
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/pch.h
@@ -0,0 +1,47 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define NOMINMAX
+
+
+#include <vector>
+#include <exception>
+#include <algorithm>
+#include <d3d12.h>
+
+#include "PlatformDefinitions.h"
+#include "Errors.h"
+#include "RefCntAutoPtr.h"
+#include "DebugUtilities.h"
+#include "D3DErrors.h"
+#include "RenderDeviceBase.h"
+#include "ValidatedCast.h"
+#include <atlcomcli.h> \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h b/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h
new file mode 100644
index 00000000..f3e69a13
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/BufferD3D12.h
@@ -0,0 +1,56 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBufferD3D12 interface
+
+#include "Buffer.h"
+
+namespace Diligent
+{
+
+// {3E9B15ED-A289-48DC-8214-C6E3E6177378}
+static const INTERFACE_ID IID_BufferD3D12 =
+{ 0x3e9b15ed, 0xa289, 0x48dc, { 0x82, 0x14, 0xc6, 0xe3, 0xe6, 0x17, 0x73, 0x78 } };
+
+/// Interface to the buffer object implemented in D3D12
+class IBufferD3D12 : public Diligent::IBuffer
+{
+public:
+
+ /// Returns a pointer to the ID3D12Resource interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ /// \param [in] DataStartByteOffset - Offset from the beginning of the buffer
+ /// to the start of the data. This parameter
+ /// is required for dynamic buffers, which are
+ /// suballocated in a dynamic upload heap
+ /// \param [in] ContextId - Id of the context within which address of the buffer is requested.
+ ///
+ virtual ID3D12Resource *GetD3D12Buffer(size_t &DataStartByteOffset, Uint32 ContextId) = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/BufferViewD3D12.h b/Graphics/GraphicsEngineD3D12/interface/BufferViewD3D12.h
new file mode 100644
index 00000000..7d9e45c9
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/BufferViewD3D12.h
@@ -0,0 +1,47 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IBufferViewD3D12 interface
+
+#include "BufferView.h"
+
+namespace Diligent
+{
+
+// {09643F2F-40D4-4076-B086-9E5CDC2CC4FC}
+static const Diligent::INTERFACE_ID IID_BufferViewD3D12 =
+{ 0x9643f2f, 0x40d4, 0x4076, { 0xb0, 0x86, 0x9e, 0x5c, 0xdc, 0x2c, 0xc4, 0xfc } };
+
+/// Interface to the buffer view object implemented in D3D12
+class IBufferViewD3D12 : public IBufferView
+{
+public:
+
+ /// Returns CPU descriptor handle of the internal Direct3D12 object.
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h b/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h
new file mode 100644
index 00000000..c31ea4cc
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h
@@ -0,0 +1,57 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IPipeplineStateD3D12 interface
+
+#include "PipelineState.h"
+
+namespace Diligent
+{
+
+// {33C9BE4B-6F23-4F83-A665-5AC1836DF35A}
+static const INTERFACE_ID IID_PipelineStateD3D12 =
+{ 0x33c9be4b, 0x6f23, 0x4f83, { 0xa6, 0x65, 0x5a, 0xc1, 0x83, 0x6d, 0xf3, 0x5a } };
+
+
+/// Interface to the blend state object implemented in D3D12
+class IPipelineStateD3D12 : public IPipelineState
+{
+public:
+
+ /// Returns a pointer to the ID3D12PipelineState interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual ID3D12PipelineState *GetD3D12PipelineState()const = 0;
+
+ /// Returns a pointer to the root signature object associated with this pipeline state.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual ID3D12RootSignature *GetD3D12RootSignature()const = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h
new file mode 100644
index 00000000..309d355e
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h
@@ -0,0 +1,49 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IRenderDeviceD3D12 interface
+
+#include "RenderDevice.h"
+
+namespace Diligent
+{
+// {C7987C98-87FE-4309-AE88-E98F044B00F6}
+static const Diligent::INTERFACE_ID IID_RenderDeviceD3D12 =
+{ 0xc7987c98, 0x87fe, 0x4309, { 0xae, 0x88, 0xe9, 0x8f, 0x4, 0x4b, 0x0, 0xf6 } };
+
+/// Interface to the render device object implemented in D3D12
+class IRenderDeviceD3D12 : public Diligent::IRenderDevice
+{
+public:
+
+ /// Returns a pointer to the ID3D12Device interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual ID3D12Device* GetD3D12Device() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h
new file mode 100644
index 00000000..f3aa45f4
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h
@@ -0,0 +1,104 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of functions that initialize Direct3D12-based engine implementation
+
+#include "Errors.h"
+
+extern "C"
+{
+#ifdef ENGINE_DLL
+
+ typedef void (*CreateDeviceAndContextsD3D12Type)(
+ const Diligent::EngineD3D12Attribs& CreationAttribs,
+ Diligent::IRenderDevice **ppDevice,
+ Diligent::IDeviceContext **ppContexts,
+ Diligent::Uint32 NumDeferredContexts );
+
+
+ typedef void (*CreateSwapChainD3D12Type)(
+ Diligent::IRenderDevice *pDevice,
+ Diligent::IDeviceContext *pImmediateContext,
+ const Diligent::SwapChainDesc& SwapChainDesc,
+ void* pNativeWndHandle,
+ Diligent::ISwapChain **ppSwapChain );
+
+ static void LoadGraphicsEngineD3D12(CreateDeviceAndContextsD3D12Type &CreateDeviceFunc, CreateSwapChainD3D12Type &CreateSwapChainFunc)
+ {
+ CreateDeviceFunc = nullptr;
+ CreateSwapChainFunc = nullptr;
+ std::string LibName = "GraphicsEngineD3D12_";
+
+#if _WIN64
+ LibName += "64";
+#else
+ LibName += "32";
+#endif
+
+#ifdef _DEBUG
+ LibName += "d";
+#else
+ LibName += "r";
+#endif
+
+ LibName += ".dll";
+ auto hModule = LoadLibraryA( LibName.c_str() );
+ if( hModule == NULL )
+ {
+ LOG_ERROR_MESSAGE( "Failed to load ", LibName, " library." );
+ return;
+ }
+
+ CreateDeviceFunc = reinterpret_cast<CreateDeviceAndContextsD3D12Type>( GetProcAddress(hModule, "CreateDeviceAndContextsD3D12") );
+ if( CreateDeviceFunc == NULL )
+ {
+ LOG_ERROR_MESSAGE( "Failed to load CreateDeviceAndContextsD3D12() from ", LibName, " library." );
+ FreeLibrary( hModule );
+ return;
+ }
+
+ CreateSwapChainFunc = reinterpret_cast<CreateSwapChainD3D12Type>( GetProcAddress(hModule, "CreateSwapChainD3D12") );
+ if( CreateSwapChainFunc == NULL )
+ {
+ LOG_ERROR_MESSAGE( "Failed to load CreateSwapChainD3D12() from ", LibName, " library." );
+ FreeLibrary( hModule );
+ return;
+ }
+ }
+#else
+
+ void CreateDeviceAndContextsD3D12( const Diligent::EngineD3D12Attribs& CreationAttribs,
+ Diligent::IRenderDevice **ppDevice,
+ Diligent::IDeviceContext **ppContexts,
+ Diligent::Uint32 NumDeferredContexts);
+
+ void CreateSwapChainD3D12( Diligent::IRenderDevice *pDevice,
+ Diligent::IDeviceContext *pImmediateContext,
+ const Diligent::SwapChainDesc& SwapChainDesc,
+ void* pNativeWndHandle,
+ Diligent::ISwapChain **ppSwapChain );
+#endif
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/SamplerD3D12.h b/Graphics/GraphicsEngineD3D12/interface/SamplerD3D12.h
new file mode 100644
index 00000000..4359fdc5
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/SamplerD3D12.h
@@ -0,0 +1,50 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ISamplerD3D12 interface
+
+#include "Sampler.h"
+
+namespace Diligent
+{
+
+// {31A3BFAF-738E-4D8C-AD18-B021C5D948DD}
+static const Diligent::INTERFACE_ID IID_SamplerD3D12 =
+{ 0x31a3bfaf, 0x738e, 0x4d8c, { 0xad, 0x18, 0xb0, 0x21, 0xc5, 0xd9, 0x48, 0xdd } };
+
+/// Interface to the sampler object implemented in D3D12
+class ISamplerD3D12 : public Diligent::ISampler
+{
+public:
+
+ /// Returns a pointer to the ID3D12SamplerState interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderD3D12.h
new file mode 100644
index 00000000..50aa22aa
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/ShaderD3D12.h
@@ -0,0 +1,50 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IShaderD3D12 interface
+
+#include "Shader.h"
+
+namespace Diligent
+{
+
+// {C059B160-7F31-4029-943D-0996B98EE79A}
+static const Diligent::INTERFACE_ID IID_ShaderD3D12 =
+{ 0xc059b160, 0x7f31, 0x4029, { 0x94, 0x3d, 0x9, 0x96, 0xb9, 0x8e, 0xe7, 0x9a } };
+
+/// Interface to the shader object implemented in D3D12
+class IShaderD3D12 : public Diligent::IShader
+{
+public:
+
+ /// Returns a pointer to the ID3D12DeviceChild interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ //virtual ID3D12DeviceChild* GetD3D12Shader() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderResourceBindingD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderResourceBindingD3D12.h
new file mode 100644
index 00000000..6038b88b
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/ShaderResourceBindingD3D12.h
@@ -0,0 +1,45 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::IShaderResourceBindingD3D12 interface and related data structures
+
+#include "ShaderResourceBinding.h"
+
+namespace Diligent
+{
+
+// {70DD5C7C-81FA-4D9A-942F-D1B91423FAAC}
+static const Diligent::INTERFACE_ID IID_ShaderResourceBindingD3D12 =
+{ 0x70dd5c7c, 0x81fa, 0x4d9a, { 0x94, 0x2f, 0xd1, 0xb9, 0x14, 0x23, 0xfa, 0xac } };
+
+/// Shader resource binding interface
+class IShaderResourceBindingD3D12 : public IShaderResourceBinding
+{
+public:
+
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/SwapChainD3D12.h b/Graphics/GraphicsEngineD3D12/interface/SwapChainD3D12.h
new file mode 100644
index 00000000..eacc0ef4
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/SwapChainD3D12.h
@@ -0,0 +1,50 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ISwapChainD3D12 interface
+
+#include "SwapChain.h"
+
+namespace Diligent
+{
+
+// {C9F8384D-A45E-4970-8447-394177E5B0EE}
+static const Diligent::INTERFACE_ID IID_SwapChainD3D12 =
+{ 0xc9f8384d, 0xa45e, 0x4970, { 0x84, 0x47, 0x39, 0x41, 0x77, 0xe5, 0xb0, 0xee } };
+
+/// Interface to the swap chain object implemented in D3D12
+class ISwapChainD3D12 : public Diligent::ISwapChain
+{
+public:
+
+ /// Returns a pointer to the IDXGISwapChain interface of the internal DXGI object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual IDXGISwapChain *GetDXGISwapChain() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/TextureD3D12.h b/Graphics/GraphicsEngineD3D12/interface/TextureD3D12.h
new file mode 100644
index 00000000..2fe585ce
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/TextureD3D12.h
@@ -0,0 +1,50 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ITextureD3D12 interface
+
+#include "Texture.h"
+
+namespace Diligent
+{
+
+// {CF5522EF-8116-4D76-ADF1-5CC8FB31FF66}
+static const Diligent::INTERFACE_ID IID_TextureD3D12 =
+{ 0xcf5522ef, 0x8116, 0x4d76, { 0xad, 0xf1, 0x5c, 0xc8, 0xfb, 0x31, 0xff, 0x66 } };
+
+/// Interface to the texture object implemented in D3D11
+class ITextureD3D12 : public Diligent::ITexture
+{
+public:
+
+ /// Returns a pointer to the ID3D12Resource interface of the internal Direct3D12 object.
+
+ /// The method does *NOT* call AddRef() on the returned interface,
+ /// so Release() must not be called.
+ virtual ID3D12Resource* GetD3D12Texture() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/interface/TextureViewD3D12.h b/Graphics/GraphicsEngineD3D12/interface/TextureViewD3D12.h
new file mode 100644
index 00000000..967d28a1
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/interface/TextureViewD3D12.h
@@ -0,0 +1,47 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Definition of the Diligent::ITextureViewD3D12 interface
+
+#include "TextureView.h"
+
+namespace Diligent
+{
+
+// {BDFBD325-0699-4720-BC0E-BF84086EC033}
+static const Diligent::INTERFACE_ID IID_TextureViewD3D12 =
+{ 0xbdfbd325, 0x699, 0x4720, { 0xbc, 0xe, 0xbf, 0x84, 0x8, 0x6e, 0xc0, 0x33 } };
+
+/// Interface to the texture view object implemented in D3D11
+class ITextureViewD3D12 : public Diligent::ITextureView
+{
+public:
+
+ /// Returns CPU descriptor handle of the internal Direct3D12 object.
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() = 0;
+};
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli
new file mode 100644
index 00000000..3c25ff54
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsCS.hlsli
@@ -0,0 +1,206 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define RootSig \
+ "RootFlags(0), " \
+ "RootConstants(b0, num32BitConstants = 4), " \
+ "DescriptorTable(SRV(t0, numDescriptors = 1))," \
+ "DescriptorTable(UAV(u0, numDescriptors = 4))," \
+ "StaticSampler(s0," \
+ "addressU = TEXTURE_ADDRESS_CLAMP," \
+ "addressV = TEXTURE_ADDRESS_CLAMP," \
+ "addressW = TEXTURE_ADDRESS_CLAMP," \
+ "filter = FILTER_MIN_MAG_MIP_LINEAR)"
+
+#ifndef NON_POWER_OF_TWO
+#define NON_POWER_OF_TWO 0
+#endif
+
+RWTexture2D<float4> OutMip1 : register(u0);
+RWTexture2D<float4> OutMip2 : register(u1);
+RWTexture2D<float4> OutMip3 : register(u2);
+RWTexture2D<float4> OutMip4 : register(u3);
+Texture2D<float4> SrcTex : register(t0);
+SamplerState BilinearClamp : register(s0);
+
+cbuffer CB : register(b0)
+{
+ uint SrcMipLevel; // Texture level of source mip
+ uint NumMipLevels; // Number of OutMips to write: [1, 4]
+ float2 TexelSize; // 1.0 / OutMip1.Dimensions
+}
+
+// The reason for separating channels is to reduce bank conflicts in the
+// local data memory controller. A large stride will cause more threads
+// to collide on the same memory bank.
+groupshared float gs_R[64];
+groupshared float gs_G[64];
+groupshared float gs_B[64];
+groupshared float gs_A[64];
+
+void StoreColor( uint Index, float4 Color )
+{
+ gs_R[Index] = Color.r;
+ gs_G[Index] = Color.g;
+ gs_B[Index] = Color.b;
+ gs_A[Index] = Color.a;
+}
+
+float4 LoadColor( uint Index )
+{
+ return float4( gs_R[Index], gs_G[Index], gs_B[Index], gs_A[Index]);
+}
+
+float3 LinearToSRGB(float3 x)
+{
+ // This is exactly the sRGB curve
+ //return x < 0.0031308 ? 12.92 * x : 1.055 * pow(abs(x), 1.0 / 2.4) - 0.055;
+
+ // This is cheaper but nearly equivalent
+ return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(abs(x - 0.00228)) - 0.13448 * x + 0.005719;
+}
+
+float4 PackColor(float4 Linear)
+{
+#ifdef CONVERT_TO_SRGB
+ return float4(LinearToSRGB(Linear.rgb), Linear.a);
+#else
+ return Linear;
+#endif
+}
+
+[RootSignature(RootSig)]
+[numthreads( 8, 8, 1 )]
+void main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )
+{
+ uint2 DstMipSize;
+ SrcTex.GetDimensions(DstMipSize.x, DstMipSize.y);
+ DstMipSize >>= SrcMipLevel;
+ bool IsValidThread = all(DTid.xy < DstMipSize);
+
+ float4 Src1 = 0;
+ if( IsValidThread )
+ {
+ // One bilinear sample is insufficient when scaling down by more than 2x.
+ // You will slightly undersample in the case where the source dimension
+ // is odd. This is why it's a really good idea to only generate mips on
+ // power-of-two sized textures. Trying to handle the undersampling case
+ // will force this shader to be slower and more complicated as it will
+ // have to take more source texture samples.
+#if NON_POWER_OF_TWO == 0
+ float2 UV = TexelSize * (DTid.xy + 0.5);
+ Src1 = SrcTex.SampleLevel(BilinearClamp, UV, SrcMipLevel);
+#elif NON_POWER_OF_TWO == 1
+ // > 2:1 in X dimension
+ // Use 2 bilinear samples to guarantee we don't undersample when downsizing by more than 2x
+ // horizontally.
+ float2 UV1 = TexelSize * (DTid.xy + float2(0.25, 0.5));
+ float2 Off = TexelSize * float2(0.5, 0.0);
+ Src1 = 0.5 * (SrcTex.SampleLevel(BilinearClamp, UV1, SrcMipLevel) +
+ SrcTex.SampleLevel(BilinearClamp, UV1 + Off, SrcMipLevel));
+#elif NON_POWER_OF_TWO == 2
+ // > 2:1 in Y dimension
+ // Use 2 bilinear samples to guarantee we don't undersample when downsizing by more than 2x
+ // vertically.
+ float2 UV1 = TexelSize * (DTid.xy + float2(0.5, 0.25));
+ float2 Off = TexelSize * float2(0.0, 0.5);
+ Src1 = 0.5 * (SrcTex.SampleLevel(BilinearClamp, UV1, SrcMipLevel) +
+ SrcTex.SampleLevel(BilinearClamp, UV1 + Off, SrcMipLevel));
+#elif NON_POWER_OF_TWO == 3
+ // > 2:1 in in both dimensions
+ // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x
+ // in both directions.
+ float2 UV1 = TexelSize * (DTid.xy + float2(0.25, 0.25));
+ float2 Off = TexelSize * 0.5;
+ Src1 += SrcTex.SampleLevel(BilinearClamp, UV1, SrcMipLevel);
+ Src1 += SrcTex.SampleLevel(BilinearClamp, UV1 + float2(Off.x, 0.0), SrcMipLevel);
+ Src1 += SrcTex.SampleLevel(BilinearClamp, UV1 + float2(0.0, Off.y), SrcMipLevel);
+ Src1 += SrcTex.SampleLevel(BilinearClamp, UV1 + float2(Off.x, Off.y), SrcMipLevel);
+ Src1 *= 0.25;
+#endif
+
+ OutMip1[DTid.xy] = PackColor(Src1);
+ }
+
+ // A scalar (constant) branch can exit all threads coherently.
+ if (NumMipLevels == 1)
+ return;
+
+ if( IsValidThread )
+ {
+ // Without lane swizzle operations, the only way to share data with other
+ // threads is through LDS.
+ StoreColor(GI, Src1);
+ }
+
+ // This guarantees all LDS writes are complete and that all threads have
+ // executed all instructions so far (and therefore have issued their LDS
+ // write instructions.)
+ GroupMemoryBarrierWithGroupSync();
+
+ if( IsValidThread )
+ {
+ // With low three bits for X and high three bits for Y, this bit mask
+ // (binary: 001001) checks that X and Y are even.
+ if ((GI & 0x9) == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x01);
+ float4 Src3 = LoadColor(GI + 0x08);
+ float4 Src4 = LoadColor(GI + 0x09);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip2[DTid.xy / 2] = PackColor(Src1);
+ StoreColor(GI, Src1);
+ }
+ }
+
+ if (NumMipLevels == 2)
+ return;
+
+ GroupMemoryBarrierWithGroupSync();
+
+ if( IsValidThread )
+ {
+ // This bit mask (binary: 011011) checks that X and Y are multiples of four.
+ if ((GI & 0x1B) == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x02);
+ float4 Src3 = LoadColor(GI + 0x10);
+ float4 Src4 = LoadColor(GI + 0x12);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip3[DTid.xy / 4] = PackColor(Src1);
+ StoreColor(GI, Src1);
+ }
+ }
+
+ if (NumMipLevels == 3)
+ return;
+
+ GroupMemoryBarrierWithGroupSync();
+
+ if( IsValidThread )
+ {
+ // This bit mask would be 111111 (X & Y multiples of 8), but only one
+ // thread fits that criteria.
+ if (GI == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x04);
+ float4 Src3 = LoadColor(GI + 0x20);
+ float4 Src4 = LoadColor(GI + 0x24);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip4[DTid.xy / 8] = PackColor(Src1);
+ }
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaCS.hlsl
new file mode 100644
index 00000000..3ed1ca5f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaCS.hlsl
@@ -0,0 +1,15 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define CONVERT_TO_SRGB
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddCS.hlsl
new file mode 100644
index 00000000..4545115f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddCS.hlsl
@@ -0,0 +1,16 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define CONVERT_TO_SRGB
+#define NON_POWER_OF_TWO 3
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddXCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddXCS.hlsl
new file mode 100644
index 00000000..010e98d7
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddXCS.hlsl
@@ -0,0 +1,16 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define CONVERT_TO_SRGB
+#define NON_POWER_OF_TWO 1
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddYCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddYCS.hlsl
new file mode 100644
index 00000000..6bc0d7df
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsGammaOddYCS.hlsl
@@ -0,0 +1,16 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define CONVERT_TO_SRGB
+#define NON_POWER_OF_TWO 2
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearCS.hlsl
new file mode 100644
index 00000000..19d1d90f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearCS.hlsl
@@ -0,0 +1,14 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddCS.hlsl
new file mode 100644
index 00000000..86416514
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddCS.hlsl
@@ -0,0 +1,15 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define NON_POWER_OF_TWO 3
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddXCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddXCS.hlsl
new file mode 100644
index 00000000..ede7b445
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddXCS.hlsl
@@ -0,0 +1,15 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define NON_POWER_OF_TWO 1
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddYCS.hlsl b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddYCS.hlsl
new file mode 100644
index 00000000..afd17ad2
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/shaders/GenerateMips/GenerateMipsLinearOddYCS.hlsl
@@ -0,0 +1,15 @@
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+#define NON_POWER_OF_TWO 2
+#include "GenerateMipsCS.hlsli"
diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
new file mode 100644
index 00000000..c7470492
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
@@ -0,0 +1,373 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "BufferD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+#include "BufferViewD3D12Impl.h"
+#include "GraphicsUtilities.h"
+#include "DXGITypeConversions.h"
+#include "EngineMemory.h"
+
+namespace Diligent
+{
+
+BufferD3D12Impl :: BufferD3D12Impl(FixedBlockMemoryAllocator &BufferObjMemAllocator,
+ FixedBlockMemoryAllocator &BuffViewObjMemAllocator,
+ RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ const BufferDesc& BuffDesc,
+ const BufferData &BuffData /*= BufferData()*/) :
+ TBufferBase(BufferObjMemAllocator, BuffViewObjMemAllocator, pRenderDeviceD3D12, BuffDesc),
+#ifdef _DEBUG
+ m_DbgMapType(1 + pRenderDeviceD3D12->GetNumDeferredContexts(), static_cast<MAP_TYPE>(-1), STD_ALLOCATOR_RAW_MEM(DynamicAllocation, GetRawAllocator(), "Allocator for vector<MAP_TYPE>")),
+#endif
+ m_DynamicData(BuffDesc.Usage == USAGE_DYNAMIC ? (1 + pRenderDeviceD3D12->GetNumDeferredContexts()) : 0, DynamicAllocation(), STD_ALLOCATOR_RAW_MEM(DynamicAllocation, GetRawAllocator(), "Allocator for vector<DynamicAllocation>"))
+{
+#define LOG_BUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Buffer \"", BuffDesc.Name ? BuffDesc.Name : "", "\": ", ##__VA_ARGS__);
+
+ if( m_Desc.Usage == USAGE_STATIC && BuffData.pData == nullptr )
+ LOG_BUFFER_ERROR_AND_THROW("Static buffer must be initialized with data at creation time")
+
+ if( m_Desc.Usage == USAGE_DYNAMIC && BuffData.pData != nullptr )
+ LOG_BUFFER_ERROR_AND_THROW("Dynamic buffer must be initialized via Map()")
+
+ if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER)
+ {
+ Uint32 AlignmentMask = 255;
+ m_Desc.uiSizeInBytes = (m_Desc.uiSizeInBytes + AlignmentMask) & (~AlignmentMask);
+ }
+
+ if(m_Desc.Usage == USAGE_DYNAMIC)
+ {
+ // Dynamic buffers are suballocated in the upload heap when Map() is called.
+ // Dynamic upload heap buffer is always in D3D12_RESOURCE_STATE_GENERIC_READ state
+
+ m_UsageState = D3D12_RESOURCE_STATE_GENERIC_READ;
+ VERIFY_EXPR(m_DynamicData.size() == 1 + pRenderDeviceD3D12->GetNumDeferredContexts());
+ }
+ else
+ {
+ D3D12_RESOURCE_DESC D3D12BuffDesc = {};
+ D3D12BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ D3D12BuffDesc.Alignment = 0;
+ D3D12BuffDesc.Width = m_Desc.uiSizeInBytes;
+ D3D12BuffDesc.Height = 1;
+ D3D12BuffDesc.DepthOrArraySize = 1;
+ D3D12BuffDesc.MipLevels = 1;
+ D3D12BuffDesc.Format = DXGI_FORMAT_UNKNOWN;
+ D3D12BuffDesc.SampleDesc.Count = 1;
+ D3D12BuffDesc.SampleDesc.Quality = 0;
+ // Layout must be D3D12_TEXTURE_LAYOUT_ROW_MAJOR, as buffer memory layouts are
+ // understood by applications and row-major texture data is commonly marshaled through buffers.
+ D3D12BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ if( m_Desc.BindFlags & BIND_UNORDERED_ACCESS )
+ D3D12BuffDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ auto *pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
+
+
+ D3D12_HEAP_PROPERTIES HeapProps;
+ HeapProps.Type = m_Desc.Usage == USAGE_CPU_ACCESSIBLE ? D3D12_HEAP_TYPE_READBACK : D3D12_HEAP_TYPE_DEFAULT;
+ if(HeapProps.Type == D3D12_HEAP_TYPE_READBACK)
+ m_UsageState = D3D12_RESOURCE_STATE_COPY_DEST;
+ else if(HeapProps.Type == D3D12_HEAP_TYPE_UPLOAD)
+ m_UsageState = D3D12_RESOURCE_STATE_GENERIC_READ;
+ HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ HeapProps.CreationNodeMask = 1;
+ HeapProps.VisibleNodeMask = 1;
+
+ bool bInitializeBuffer = (BuffData.pData != nullptr && BuffData.DataSize > 0);
+ if(bInitializeBuffer)
+ m_UsageState = D3D12_RESOURCE_STATE_COPY_DEST;
+
+ auto hr = pd3d12Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE,
+ &D3D12BuffDesc, m_UsageState, nullptr, __uuidof(m_pd3d12Resource), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource)) );
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create D3D12 buffer")
+
+ if( bInitializeBuffer )
+ {
+ D3D12_HEAP_PROPERTIES UploadHeapProps;
+ UploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ UploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ UploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ UploadHeapProps.CreationNodeMask = 1;
+ UploadHeapProps.VisibleNodeMask = 1;
+
+ D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ CComPtr<ID3D12Resource> UploadBuffer;
+ hr = pd3d12Device->CreateCommittedResource( &UploadHeapProps, D3D12_HEAP_FLAG_NONE,
+ &D3D12BuffDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(UploadBuffer),
+ reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&UploadBuffer)) );
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create uload buffer")
+
+ void* DestAddress = nullptr;
+ hr = UploadBuffer->Map(0, nullptr, &DestAddress);
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to map uload buffer")
+ memcpy(DestAddress, BuffData.pData, BuffData.DataSize);
+ UploadBuffer->Unmap(0, nullptr);
+
+ auto *pInitContext = pRenderDeviceD3D12->AllocateCommandContext();
+ // copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default buffer
+ VERIFY_EXPR(m_UsageState == D3D12_RESOURCE_STATE_COPY_DEST);
+ // We MUST NOT call TransitionResource() from here, because
+ // it will call AddRef() and potentially Release(), while
+ // the object is not constructed yet
+ pInitContext->CopyResource(m_pd3d12Resource, UploadBuffer);
+
+ pRenderDeviceD3D12->CloseAndExecuteCommandContext(pInitContext);
+
+ // Add reference to the object to the release queue to keep it alive
+ // until copy operation is complete. This must be done after
+ // submitting command list for execution!
+ pRenderDeviceD3D12->SafeReleaseD3D12Object(UploadBuffer);
+ }
+
+ if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER)
+ {
+ m_CBVDescriptorAllocation = pRenderDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ CreateCBV(m_CBVDescriptorAllocation.GetCpuHandle());
+ }
+ }
+#if 0
+ D3D12BuffDesc.BindFlags = BindFlagsToD3D12BindFlags(BuffDesc.BindFlags);
+ D3D12BuffDesc.ByteWidth =
+ D3D12BuffDesc.MiscFlags = 0;
+ if( BuffDesc.BindFlags & BIND_INDIRECT_DRAW_ARGS )
+ {
+ D3D12BuffDesc.MiscFlags |= D3D12_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+ }
+ D3D12BuffDesc.Usage = UsageToD3D12Usage(BuffDesc.Usage);
+
+ D3D12BuffDesc.StructureByteStride = 0;
+ if( (BuffDesc.BindFlags & BIND_UNORDERED_ACCESS) )
+ {
+ if( BuffDesc.Mode == BUFFER_MODE_STRUCTURED )
+ {
+ D3D12BuffDesc.MiscFlags |= D3D12_RESOURCE_MISC_BUFFER_STRUCTURED;
+ D3D12BuffDesc.StructureByteStride = BuffDesc.ElementByteStride;
+ }
+ else if( BuffDesc.Mode == BUFFER_MODE_FORMATED )
+ {
+ auto ElementStride = GetValueSize( BuffDesc.Format.ValueType ) * BuffDesc.Format.NumComponents;
+ VERIFY( m_Desc.ElementByteStride == 0 || m_Desc.ElementByteStride == ElementStride, "Element byte stride does not match buffer format" );
+ m_Desc.ElementByteStride = ElementStride;
+ if( BuffDesc.Format.ValueType == VT_FLOAT32 || BuffDesc.Format.ValueType == VT_FLOAT16 )
+ m_Desc.Format.IsNormalized = false;
+ }
+ else
+ {
+ UNEXPECTED( "Buffer UAV type is not correct" );
+ }
+ }
+
+ D3D12BuffDesc.CPUAccessFlags = CPUAccessFlagsToD3D12CPUAccessFlags( BuffDesc.CPUAccessFlags );
+
+ D3D12_SUBRESOURCE_DATA InitData;
+ InitData.pSysMem = BuffData.pData;
+ InitData.SysMemPitch = BuffData.DataSize;
+ InitData.SysMemSlicePitch = 0;
+
+ auto *pDeviceD3D12 = pRenderDeviceD3D12->GetD3D12Device();
+ CHECK_D3D_RESULT_THROW( pDeviceD3D12->CreateBuffer(&D3D12BuffDesc, InitData.pSysMem ? &InitData : nullptr, &m_pD3D12Buffer),
+ "Failed to create the Direct3D11 buffer" );
+#endif
+}
+
+BufferD3D12Impl :: ~BufferD3D12Impl()
+{
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12Impl->SafeReleaseD3D12Object(m_pd3d12Resource);
+}
+
+IMPLEMENT_QUERY_INTERFACE( BufferD3D12Impl, IID_BufferD3D12, TBufferBase )
+
+void BufferD3D12Impl::UpdateData( IDeviceContext *pContext, Uint32 Offset, Uint32 Size, const PVoid pData )
+{
+ TBufferBase::UpdateData( pContext, Offset, Size, pData );
+
+ // We must use cmd context from the device context provided, otherwise there will
+ // be resource barrier issues in the cmd list in the device context
+ auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+ pDeviceContextD3D12->UpdateBufferRegion(this, pData, Offset, Size);
+}
+
+void BufferD3D12Impl :: CopyData(IDeviceContext *pContext, IBuffer *pSrcBuffer, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size)
+{
+ TBufferBase::CopyData( pContext, pSrcBuffer, SrcOffset, DstOffset, Size );
+ auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+ pDeviceContextD3D12->CopyBufferRegion(ValidatedCast<BufferD3D12Impl>(pSrcBuffer), this, SrcOffset, DstOffset, Size);
+}
+
+void BufferD3D12Impl :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData)
+{
+ TBufferBase::Map( pContext, MapType, MapFlags, pMappedData );
+ auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+#ifdef _DEBUG
+ m_DbgMapType[pDeviceContextD3D12->GetContextId()] = MapType;
+#endif
+ if (MapType == MAP_READ )
+ {
+ LOG_WARNING_MESSAGE_ONCE("Mapping CPU buffer for reading on D3D12 currently requires flushing context and idling GPU");
+ pDeviceContextD3D12->Flush();
+ auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12->IdleGPU();
+
+ VERIFY(m_Desc.Usage == USAGE_CPU_ACCESSIBLE, "Buffer must be created as USAGE_CPU_ACCESSIBLE to be mapped for reading")
+ D3D12_RANGE MapRange;
+ MapRange.Begin = 0;
+ MapRange.End = m_Desc.uiSizeInBytes;
+ m_pd3d12Resource->Map(0, &MapRange, &pMappedData);
+ }
+ else if(MapType == MAP_WRITE_DISCARD)
+ {
+ auto *pCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+ auto ContextId = pDeviceContextD3D12->GetContextId();
+ m_DynamicData[ContextId] = pCtxD3D12->AllocateDynamicSpace(m_Desc.uiSizeInBytes);
+ pMappedData = m_DynamicData[ContextId].CPUAddress;
+ }
+ else if(MapType == MAP_READ_WRITE || MapType == MAP_WRITE)
+ {
+ LOG_ERROR("D3D12 allows writing to CPU-readable buffer, but it is not accessable by GPU")
+ }
+ else
+ {
+ LOG_ERROR("Only MAP_WRITE_DISCARD and MAP_READ are currently implemented in D3D12")
+ }
+}
+
+void BufferD3D12Impl::Unmap( IDeviceContext *pContext, MAP_TYPE MapType )
+{
+ TBufferBase::Unmap( pContext, MapType );
+ auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+ auto CtxId = pDeviceContextD3D12->GetContextId();
+#ifdef _DEBUG
+ VERIFY(m_DbgMapType[CtxId] == MapType, "Map type provided does not match the type provided to Map()" );
+#endif
+
+ if (MapType == MAP_READ )
+ {
+ D3D12_RANGE MapRange;
+ // It is valid to specify the CPU didn't write any data by passing a range where End is less than or equal to Begin.
+ MapRange.Begin = 1;
+ MapRange.End = 0;
+ m_pd3d12Resource->Unmap(0, &MapRange);
+ }
+ else if(MapType == MAP_WRITE_DISCARD)
+ {
+ // Nothing needs to be done.
+ }
+#ifdef _DEBUG
+ m_DbgMapType[CtxId] = static_cast<MAP_TYPE>(-1);
+#endif
+}
+
+void BufferD3D12Impl::CreateViewInternal( const BufferViewDesc &OrigViewDesc, IBufferView **ppView, bool bIsDefaultView )
+{
+ VERIFY( ppView != nullptr, "Null pointer provided" );
+ if( !ppView )return;
+ VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
+
+ *ppView = nullptr;
+
+ try
+ {
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ auto &BuffViewAllocator = pDeviceD3D12Impl->GetBuffViewObjAllocator();
+ VERIFY( &BuffViewAllocator == &m_dbgBuffViewAllocator, "Buff view allocator does not match allocator provided at buffer initialization" );
+
+ BufferViewDesc ViewDesc = OrigViewDesc;
+ if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS )
+ {
+ auto UAVHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ CreateUAV( ViewDesc, UAVHandleAlloc.GetCpuHandle() );
+ *ppView = NEW(BuffViewAllocator, "BufferViewD3D12Impl instance", BufferViewD3D12Impl, GetDevice(), ViewDesc, this, std::move(UAVHandleAlloc), bIsDefaultView );
+ }
+ else if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
+ {
+ auto SRVHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ CreateSRV( ViewDesc, SRVHandleAlloc.GetCpuHandle() );
+ *ppView = NEW(BuffViewAllocator, "BufferViewD3D12Impl instance", BufferViewD3D12Impl, GetDevice(), ViewDesc, this, std::move(SRVHandleAlloc), bIsDefaultView );
+ }
+
+ if( !bIsDefaultView && *ppView )
+ (*ppView)->AddRef();
+ }
+ catch( const std::runtime_error & )
+ {
+ const auto *ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name, "\"" )
+ }
+}
+
+void BufferD3D12Impl::CreateUAV( BufferViewDesc &UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVDescriptor )
+{
+ CorrectBufferViewDesc( UAVDesc );
+
+ D3D12_UNORDERED_ACCESS_VIEW_DESC D3D12_UAVDesc;
+ BufferViewDesc_to_D3D12_UAV_DESC(m_Desc, UAVDesc, D3D12_UAVDesc);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateUnorderedAccessView( m_pd3d12Resource, nullptr, &D3D12_UAVDesc, UAVDescriptor );
+}
+
+void BufferD3D12Impl::CreateSRV( struct BufferViewDesc &SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVDescriptor )
+{
+ CorrectBufferViewDesc( SRVDesc );
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC D3D12_SRVDesc;
+ BufferViewDesc_to_D3D12_SRV_DESC(m_Desc, SRVDesc, D3D12_SRVDesc);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateShaderResourceView( m_pd3d12Resource, &D3D12_SRVDesc, SRVDescriptor );
+}
+
+void BufferD3D12Impl::CreateCBV(D3D12_CPU_DESCRIPTOR_HANDLE CBVDescriptor)
+{
+ D3D12_CONSTANT_BUFFER_VIEW_DESC D3D12_CBVDesc;
+ D3D12_CBVDesc.BufferLocation = m_pd3d12Resource->GetGPUVirtualAddress();
+ D3D12_CBVDesc.SizeInBytes = m_Desc.uiSizeInBytes;
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateConstantBufferView( &D3D12_CBVDesc, CBVDescriptor );
+}
+
+#ifdef _DEBUG
+void BufferD3D12Impl::DbgVerifyDynamicAllocation(Uint32 ContextId)
+{
+ VERIFY(m_DynamicData[ContextId].GPUAddress != 0, "Dynamic buffer must be mapped before the first use");
+ auto CurrentFrame = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice())->GetCurrentFrame();
+ VERIFY(m_DynamicData[ContextId].FrameNum == CurrentFrame, "Dynamic allocation is out-of-date. Dynamic buffer must be mapped in the same frame it is used.");
+ VERIFY(GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Dynamic buffers are expected to always be in D3D12_RESOURCE_STATE_GENERIC_READ state")
+}
+#endif
+
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp
new file mode 100644
index 00000000..e27c91ea
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp
@@ -0,0 +1,43 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "BufferViewD3D12Impl.h"
+
+namespace Diligent
+{
+
+BufferViewD3D12Impl::BufferViewD3D12Impl( FixedBlockMemoryAllocator &BuffViewAllocator,
+ IRenderDevice *pDevice,
+ const BufferViewDesc& ViewDesc,
+ IBuffer *pBuffer,
+ DescriptorHeapAllocation &&HandleAlloc,
+ bool bIsDefaultView ) :
+ TBufferViewBase( BuffViewAllocator, pDevice, ViewDesc, pBuffer, bIsDefaultView ),
+ m_DescriptorHandle( std::move(HandleAlloc) )
+{
+}
+
+IMPLEMENT_QUERY_INTERFACE( BufferViewD3D12Impl, IID_BufferViewD3D12, TBufferViewBase )
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
new file mode 100644
index 00000000..c123993f
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
@@ -0,0 +1,449 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+// Adapted to Diligent Engine: Egor Yusov
+//
+
+#include "pch.h"
+#include "CommandContext.h"
+#include "TextureD3D12Impl.h"
+#include "BufferD3D12Impl.h"
+#include "CommandListManager.h"
+
+namespace Diligent
+{
+
+CommandContext::CommandContext( IMemoryAllocator &MemAllocator,
+ CommandListManager &CmdListManager,
+ GPUDescriptorHeap GPUDescriptorHeaps[],
+ Uint32 DynamicDescriptorAllocationChunkSize[]) :
+ m_pCurGraphicsRootSignature( nullptr),
+ m_pCurGraphicsPipelineState( nullptr),
+ m_pCurComputeRootSignature( nullptr),
+ m_pCurComputePipelineState( nullptr),
+ m_DynamicGPUDescriptorAllocator
+ {
+ {MemAllocator, GPUDescriptorHeaps[0], DynamicDescriptorAllocationChunkSize[0]},
+ {MemAllocator, GPUDescriptorHeaps[1], DynamicDescriptorAllocationChunkSize[1]}
+ },
+ m_PendingResourceBarriers( STD_ALLOCATOR_RAW_MEM(D3D12_RESOURCE_BARRIER, GetRawAllocator(), "Allocator for vector<D3D12_RESOURCE_BARRIER>") ),
+ m_PendingBarrierObjects( STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<IDeviceObject>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<IDeviceObject>>") )
+{
+ m_PendingResourceBarriers.reserve(MaxPendingBarriers);
+ m_PendingBarrierObjects.reserve(MaxPendingBarriers);
+
+ CmdListManager.CreateNewCommandList(&m_pCommandList, &m_pCurrentAllocator);
+}
+
+CommandContext::~CommandContext( void )
+{
+}
+
+
+
+void CommandContext::Reset( CommandListManager& CmdListManager )
+{
+ // We only call Reset() on previously freed contexts. The command list persists, but we must
+ // request a new allocator.
+ VERIFY_EXPR(m_pCommandList != nullptr && m_pCurrentAllocator == nullptr);
+ m_pCurrentAllocator.Release();
+ CmdListManager.RequestAllocator(&m_pCurrentAllocator);
+ m_pCommandList->Reset(m_pCurrentAllocator, nullptr);
+
+ m_pCurGraphicsRootSignature = nullptr;
+ m_pCurGraphicsPipelineState = nullptr;
+ m_pCurComputeRootSignature = nullptr;
+ m_pCurComputePipelineState = nullptr;
+ m_PendingResourceBarriers.clear();
+ m_PendingBarrierObjects.clear();
+ m_BoundDescriptorHeaps = ShaderDescriptorHeaps();
+
+ m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+#if 0
+ BindDescriptorHeaps();
+#endif
+}
+
+ID3D12GraphicsCommandList* CommandContext::Close(ID3D12CommandAllocator **ppAllocator)
+{
+ FlushResourceBarriers();
+
+ //if (m_ID.length() > 0)
+ // EngineProfiling::EndBlock(this);
+
+ VERIFY_EXPR(m_pCurrentAllocator != nullptr);
+ auto hr = m_pCommandList->Close();
+ VERIFY(SUCCEEDED(hr), "Failed to close the command list");
+
+ *ppAllocator = m_pCurrentAllocator.Detach();
+ return m_pCommandList;
+}
+
+
+#if 0
+void CommandContext::BindDescriptorHeaps( void )
+{
+ UINT NonNullHeaps = 0;
+ ID3D12DescriptorHeap* HeapsToBind[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
+ for (UINT i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++i)
+ {
+ ID3D12DescriptorHeap* HeapIter = m_CurrentDescriptorHeaps[i];
+ if (HeapIter != nullptr)
+ HeapsToBind[NonNullHeaps++] = HeapIter;
+ }
+
+ if (NonNullHeaps > 0)
+ m_pCommandList->SetDescriptorHeaps(NonNullHeaps, HeapsToBind);
+}
+#endif
+
+void GraphicsContext::SetRenderTargets( UINT NumRTVs, ITextureViewD3D12** ppRTVs, ITextureViewD3D12* pDSV )
+{
+ D3D12_CPU_DESCRIPTOR_HANDLE RTVHandles[8]; // Do not waste time initializing array to zero
+
+ for (UINT i = 0; i < NumRTVs; ++i)
+ {
+ auto *pRTV = ppRTVs[i];
+ if( pRTV )
+ {
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pRTV->GetTexture() );
+ TransitionResource(pTexture, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ RTVHandles[i] = pRTV->GetCPUDescriptorHandle();
+ }
+ }
+
+ if (pDSV)
+ {
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pDSV->GetTexture() );
+ //if (bReadOnlyDepth)
+ //{
+ // TransitionResource(*pTexture, D3D12_RESOURCE_STATE_DEPTH_READ);
+ // m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, &DSV->GetDSV_DepthReadOnly() );
+ //}
+ //else
+ {
+ TransitionResource(pTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+ auto DSVHandle = pDSV->GetCPUDescriptorHandle();
+ m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, &DSVHandle );
+ }
+ }
+ else
+ {
+ m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, nullptr );
+ }
+}
+
+void CommandContext::ClearUAVFloat( ITextureViewD3D12 *pTexView, const float* Color )
+{
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pTexView->GetTexture() );
+ TransitionResource(pTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
+
+ // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs
+ // a shader to set all of the values).
+ UNSUPPORTED("Not yet implemented");
+ D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = {};//m_DynamicDescriptorHeap.UploadDirect(Target.GetUAV());
+ m_pCommandList->ClearUnorderedAccessViewFloat(GpuVisibleHandle, pTexView->GetCPUDescriptorHandle(), pTexture->GetD3D12Resource(), Color, 0, nullptr);
+}
+
+void CommandContext::ClearUAVUint( ITextureViewD3D12 *pTexView, const UINT *Color )
+{
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pTexView->GetTexture() );
+ TransitionResource(pTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
+
+ // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs
+ // a shader to set all of the values).
+ UNSUPPORTED("Not yet implemented");
+ D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = {};//m_DynamicDescriptorHeap.UploadDirect(Target.GetUAV());
+ //CD3DX12_RECT ClearRect(0, 0, (LONG)Target.GetWidth(), (LONG)Target.GetHeight());
+
+ //TODO: My Nvidia card is not clearing UAVs with either Float or Uint variants.
+ m_pCommandList->ClearUnorderedAccessViewUint(GpuVisibleHandle, pTexView->GetCPUDescriptorHandle(), pTexture->GetD3D12Resource(), Color, 0, nullptr/*1, &ClearRect*/);
+}
+
+
+void GraphicsContext::ClearRenderTarget( ITextureViewD3D12 *pRTV, const float *Color )
+{
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pRTV->GetTexture() );
+ TransitionResource(pTexture, D3D12_RESOURCE_STATE_RENDER_TARGET, true);
+ m_pCommandList->ClearRenderTargetView(pRTV->GetCPUDescriptorHandle(), Color, 0, nullptr);
+}
+
+void GraphicsContext::ClearDepthStencil( ITextureViewD3D12 *pDSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil )
+{
+ auto *pTexture = ValidatedCast<TextureD3D12Impl>( pDSV->GetTexture() );
+ TransitionResource( pTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);
+ m_pCommandList->ClearDepthStencilView(pDSV->GetCPUDescriptorHandle(), ClearFlags, Depth, Stencil, 0, nullptr);
+}
+
+
+void CommandContext::TransitionResource(ITextureD3D12 *pTexture, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)
+{
+ VERIFY_EXPR( pTexture != nullptr );
+ auto *pTexD3D12 = ValidatedCast<TextureD3D12Impl>(pTexture);
+ TransitionResource(*pTexD3D12, *pTexD3D12, NewState, FlushImmediate);
+}
+
+void CommandContext::TransitionResource(IBufferD3D12 *pBuffer, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)
+{
+ VERIFY_EXPR( pBuffer != nullptr );
+ auto *pBuffD3D12 = ValidatedCast<BufferD3D12Impl>(pBuffer);
+
+#ifdef _DEBUG
+ // Dynamic buffers are suballocated in the upload heap when Map() is called
+ // and must always be in D3D12_RESOURCE_STATE_GENERIC_READ state
+ if(pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ {
+ VERIFY(pBuffD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Dynamic buffers are expected to always be in D3D12_RESOURCE_STATE_GENERIC_READ state")
+ VERIFY( (NewState & D3D12_RESOURCE_STATE_GENERIC_READ) == NewState, "Dynamic buffers can only transition to one of D3D12_RESOURCE_STATE_GENERIC_READ states")
+ }
+#endif
+
+ TransitionResource(*pBuffD3D12, *pBuffD3D12, NewState, FlushImmediate);
+
+#ifdef _DEBUG
+ if(pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ VERIFY(pBuffD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Dynamic buffers are expected to never transition from D3D12_RESOURCE_STATE_GENERIC_READ state")
+#endif
+}
+
+void CommandContext::TransitionResource(D3D12ResourceBase& Resource, IDeviceObject &Object, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)
+{
+ D3D12_RESOURCE_STATES OldState = Resource.GetState();
+
+ // Check if required state is already set
+ if ( (OldState & NewState) != NewState )
+ {
+ // If both old state and new state are read-only states, combine the two
+ if( (OldState & D3D12_RESOURCE_STATE_GENERIC_READ) == OldState &&
+ (NewState & D3D12_RESOURCE_STATE_GENERIC_READ) == NewState )
+ NewState |= OldState;
+
+ m_PendingResourceBarriers.emplace_back();
+ m_PendingBarrierObjects.emplace_back(&Object);
+ D3D12_RESOURCE_BARRIER& BarrierDesc = m_PendingResourceBarriers.back();
+
+ BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ BarrierDesc.Transition.pResource = Resource.GetD3D12Resource();
+ BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ BarrierDesc.Transition.StateBefore = OldState;
+ BarrierDesc.Transition.StateAfter = NewState;
+
+ // Check to see if we already started the transition
+#if 0
+ if (NewState == Resource.m_TransitioningState)
+ {
+ BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_END_ONLY;
+ Resource.m_TransitioningState = (D3D12_RESOURCE_STATES)-1;
+ }
+ else
+#endif
+ BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+
+ Resource.SetState( NewState );
+ }
+ else if (NewState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
+ InsertUAVBarrier(Resource, Object, FlushImmediate);
+
+ if (FlushImmediate || m_PendingResourceBarriers.size() >= MaxPendingBarriers)
+ FlushResourceBarriers();
+}
+
+#if 0
+void CommandContext::BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)
+{
+ // If it's already transitioning, finish that transition
+ if (Resource.m_TransitioningState != (D3D12_RESOURCE_STATES)-1)
+ TransitionResource(Resource, Resource.m_TransitioningState);
+
+ D3D12_RESOURCE_STATES OldState = Resource.m_UsageState;
+
+ if (OldState != NewState)
+ {
+ ASSERT(m_NumBarriersToFlush < 16, "Exceeded arbitrary limit on buffered barriers");
+ D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++];
+
+ BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ BarrierDesc.Transition.pResource = Resource.GetResource();
+ BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ BarrierDesc.Transition.StateBefore = OldState;
+ BarrierDesc.Transition.StateAfter = NewState;
+
+ BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY;
+
+ Resource.m_TransitioningState = NewState;
+ }
+
+ if (FlushImmediate || m_NumBarriersToFlush == 16)
+ {
+ m_pCommandList->ResourceBarrier(m_NumBarriersToFlush, m_ResourceBarrierBuffer);
+ m_NumBarriersToFlush = 0;
+ }
+}
+#endif
+
+void CommandContext::FlushResourceBarriers()
+{
+ if (m_PendingResourceBarriers.empty())
+ {
+ VERIFY_EXPR(m_PendingBarrierObjects.empty());
+ return;
+ }
+
+ m_pCommandList->ResourceBarrier(static_cast<UINT>(m_PendingResourceBarriers.size()), m_PendingResourceBarriers.data());
+ m_PendingResourceBarriers.clear();
+ m_PendingBarrierObjects.clear();
+}
+
+
+void CommandContext::InsertUAVBarrier(D3D12ResourceBase& Resource, IDeviceObject &Object, bool FlushImmediate)
+{
+ m_PendingResourceBarriers.emplace_back();
+ m_PendingBarrierObjects.emplace_back(&Object);
+ D3D12_RESOURCE_BARRIER& BarrierDesc = m_PendingResourceBarriers.back();
+
+ BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+ BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ BarrierDesc.UAV.pResource = Resource.GetD3D12Resource();
+
+ if (FlushImmediate)
+ FlushResourceBarriers();
+}
+
+void CommandContext::InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, IDeviceObject &BeforeObj, IDeviceObject &AfterObj, bool FlushImmediate)
+{
+ m_PendingResourceBarriers.emplace_back();
+ m_PendingBarrierObjects.emplace_back(&BeforeObj);
+ m_PendingBarrierObjects.emplace_back(&AfterObj);
+ D3D12_RESOURCE_BARRIER& BarrierDesc = m_PendingResourceBarriers.back();
+
+ BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
+ BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ BarrierDesc.Aliasing.pResourceBefore = Before.GetD3D12Resource();
+ BarrierDesc.Aliasing.pResourceAfter = After.GetD3D12Resource();
+
+ if (FlushImmediate)
+ FlushResourceBarriers();
+}
+
+void CommandContext::DiscardUsedDescriptorHeaps(Uint64 FrameNumber)
+{
+ for(size_t HeapType = 0; HeapType < _countof(m_DynamicGPUDescriptorAllocator); ++HeapType)
+ m_DynamicGPUDescriptorAllocator[HeapType].DiscardAllocations(FrameNumber);
+}
+
+DescriptorHeapAllocation CommandContext::AllocateDynamicGPUVisibleDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count )
+{
+ VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type");
+ return m_DynamicGPUDescriptorAllocator[Type].Allocate(Count);
+}
+
+#if 0
+
+void CommandContext::FillBuffer( GpuResource& Dest, size_t DestOffset, DWParam Value, size_t NumBytes )
+{
+ DynAlloc TempSpace = m_CpuLinearAllocator.Allocate( NumBytes, 512 );
+ __m128 VectorValue = _mm_set1_ps(Value.Float);
+ SIMDMemFill(TempSpace.DataPtr, VectorValue, Math::DivideByMultiple(NumBytes, 16));
+ CopyBufferRegion(Dest, DestOffset, TempSpace.Buffer, TempSpace.Offset, NumBytes );
+}
+
+void CommandContext::CopySubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex)
+{
+ // TODO: Add a TransitionSubresource()?
+ TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);
+ TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ FlushResourceBarriers();
+
+ D3D12_TEXTURE_COPY_LOCATION DestLocation =
+ {
+ Dest.GetResource(),
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
+ DestSubIndex
+ };
+
+ D3D12_TEXTURE_COPY_LOCATION SrcLocation =
+ {
+ Src.GetResource(),
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
+ SrcSubIndex
+ };
+
+ m_pCommandList->CopyTextureRegion(&DestLocation, 0, 0, 0, &SrcLocation, nullptr);
+}
+
+void CommandContext::InitializeTextureArraySlice(GpuResource& Dest, UINT SliceIndex, GpuResource& Src)
+{
+ CommandContext& Context = CommandContext::Begin();
+
+ Context.TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);
+ Context.TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ Context.FlushResourceBarriers();
+
+ const D3D12_RESOURCE_DESC& DestDesc = Dest.GetResource()->GetDesc();
+ const D3D12_RESOURCE_DESC& SrcDesc = Src.GetResource()->GetDesc();
+
+ ASSERT(SliceIndex < DestDesc.DepthOrArraySize &&
+ SrcDesc.DepthOrArraySize == 1 &&
+ DestDesc.Width == SrcDesc.Width &&
+ DestDesc.Height == SrcDesc.Height &&
+ DestDesc.MipLevels <= SrcDesc.MipLevels
+ );
+
+ UINT SubResourceIndex = SliceIndex * DestDesc.MipLevels;
+
+ for (UINT i = 0; i < DestDesc.MipLevels; ++i)
+ {
+ D3D12_TEXTURE_COPY_LOCATION destCopyLocation =
+ {
+ Dest.GetResource(),
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
+ SubResourceIndex + i
+ };
+
+ D3D12_TEXTURE_COPY_LOCATION srcCopyLocation =
+ {
+ Src.GetResource(),
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
+ i
+ };
+
+ Context.m_pCommandList->CopyTextureRegion(&destCopyLocation, 0, 0, 0, &srcCopyLocation, nullptr);
+ }
+
+ Context.CloseAndExecute();
+}
+#endif
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp b/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp
new file mode 100644
index 00000000..8ffc64ce
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp
@@ -0,0 +1,106 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+// Adapted to Diligent Engine: Egor Yusov
+
+#include "pch.h"
+#include "CommandListManager.h"
+#include "RenderDeviceD3D12Impl.h"
+
+namespace Diligent
+{
+
+CommandListManager::CommandListManager(RenderDeviceD3D12Impl *pDeviceD3D12) :
+ m_pDeviceD3D12(pDeviceD3D12),
+ m_DiscardedAllocators(STD_ALLOCATOR_RAW_MEM(DiscardedAllocatorQueueElemType, GetRawAllocator(), "Allocator for deque<DiscardedAllocatorQueueElemType>"))
+{
+}
+
+CommandListManager::~CommandListManager()
+{
+}
+
+
+void CommandListManager::CreateNewCommandList( ID3D12GraphicsCommandList** List, ID3D12CommandAllocator** Allocator )
+{
+ RequestAllocator(Allocator);
+ auto *pd3d12Device = m_pDeviceD3D12->GetD3D12Device();
+ auto hr = pd3d12Device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, *Allocator, nullptr, __uuidof(*List), reinterpret_cast<void**>(List) );
+ VERIFY(SUCCEEDED(hr), "Failed to create command list");
+ (*List)->SetName(L"CommandList");
+}
+
+
+void CommandListManager::RequestAllocator(ID3D12CommandAllocator** ppAllocator)
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);
+
+ VERIFY( (*ppAllocator) == nullptr, "Allocator pointer is not null" );
+ (*ppAllocator) = nullptr;
+
+ if (!m_DiscardedAllocators.empty())
+ {
+ auto& AllocatorPair = m_DiscardedAllocators.front();
+
+ if (m_pDeviceD3D12->IsFenceComplete(AllocatorPair.first))
+ {
+ *ppAllocator = AllocatorPair.second.Detach();
+ auto hr = (*ppAllocator)->Reset();
+ VERIFY_EXPR(SUCCEEDED(hr));
+ m_DiscardedAllocators.pop_front();
+ }
+ }
+
+ // If no allocators were ready to be reused, create a new one
+ if ((*ppAllocator) == nullptr)
+ {
+ auto *pd3d12Device = m_pDeviceD3D12->GetD3D12Device();
+ auto hr = pd3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(*ppAllocator), reinterpret_cast<void**>(ppAllocator));
+ VERIFY(SUCCEEDED(hr), "Failed to create command allocator")
+ //wchar_t AllocatorName[32];
+ //swprintf(AllocatorName, 32, L"CommandAllocator %zu", m_AllocatorPool.size());
+ //(*ppAllocator)->SetName(AllocatorName);
+ }
+}
+
+void CommandListManager::DiscardAllocator( Uint64 FenceValue, ID3D12CommandAllocator* pAllocator )
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);
+
+ // That fence value indicates we are free to reset the allocator
+ m_DiscardedAllocators.emplace_back( FenceValue, CComPtr<ID3D12CommandAllocator>(pAllocator) );
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12ResourceBase.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12ResourceBase.cpp
new file mode 100644
index 00000000..b2e9f431
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12ResourceBase.cpp
@@ -0,0 +1,30 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "D3D12ResourceBase.h"
+
+namespace Diligent
+{
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
new file mode 100644
index 00000000..738fbc98
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
@@ -0,0 +1,295 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "D3D12TypeConversions.h"
+#include "DXGITypeConversions.h"
+
+#include "D3D12TypeDefinitions.h"
+#include "D3DTypeConversionImpl.h"
+#include "D3DViewDescConversionImpl.h"
+
+namespace Diligent
+{
+
+D3D12_COMPARISON_FUNC ComparisonFuncToD3D12ComparisonFunc(COMPARISON_FUNCTION Func)
+{
+ return ComparisonFuncToD3DComparisonFunc<D3D12_COMPARISON_FUNC>(Func);
+}
+
+D3D12_FILTER FilterTypeToD3D12Filter(FILTER_TYPE MinFilter, FILTER_TYPE MagFilter, FILTER_TYPE MipFilter)
+{
+ return FilterTypeToD3DFilter<D3D12_FILTER>(MinFilter, MagFilter, MipFilter);
+}
+
+D3D12_TEXTURE_ADDRESS_MODE TexAddressModeToD3D12AddressMode(TEXTURE_ADDRESS_MODE Mode)
+{
+ return TexAddressModeToD3DAddressMode<D3D12_TEXTURE_ADDRESS_MODE>(Mode);
+}
+
+void DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(const DepthStencilStateDesc &DepthStencilDesc, D3D12_DEPTH_STENCIL_DESC &d3d12DSSDesc)
+{
+ DepthStencilStateDesc_To_D3D_DEPTH_STENCIL_DESC<D3D12_DEPTH_STENCIL_DESC, D3D12_DEPTH_STENCILOP_DESC, D3D12_STENCIL_OP, D3D12_COMPARISON_FUNC>(DepthStencilDesc, d3d12DSSDesc);
+}
+
+void RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(const RasterizerStateDesc &RasterizerDesc, D3D12_RASTERIZER_DESC &d3d12RSDesc)
+{
+ RasterizerStateDesc_To_D3D_RASTERIZER_DESC<D3D12_RASTERIZER_DESC, D3D12_FILL_MODE, D3D12_CULL_MODE>(RasterizerDesc, d3d12RSDesc);
+
+ // The sample count that is forced while UAV rendering or rasterizing.
+ // Valid values are 0, 1, 2, 4, 8, and optionally 16. 0 indicates that
+ // the sample count is not forced.
+ d3d12RSDesc.ForcedSampleCount = 0;
+
+ d3d12RSDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+}
+
+
+
+D3D12_LOGIC_OP LogicOperationToD3D12LogicOp( LOGIC_OPERATION lo )
+{
+ // Note that this code is safe for multithreaded environments since
+ // bIsInit is set to true only AFTER the entire map is initialized.
+ static bool bIsInit = false;
+ static D3D12_LOGIC_OP D3D12LogicOp[LOGIC_OP_NUM_OPERATIONS] = {};
+ if( !bIsInit )
+ {
+ // In a multithreaded environment, several threads can potentially enter
+ // this block. This is not a problem since they will just initialize the
+ // memory with the same values more than once
+ D3D12LogicOp[ D3D12_LOGIC_OP_CLEAR ] = D3D12_LOGIC_OP_CLEAR;
+ D3D12LogicOp[ D3D12_LOGIC_OP_SET ] = D3D12_LOGIC_OP_SET;
+ D3D12LogicOp[ D3D12_LOGIC_OP_COPY ] = D3D12_LOGIC_OP_COPY;
+ D3D12LogicOp[ D3D12_LOGIC_OP_COPY_INVERTED ] = D3D12_LOGIC_OP_COPY_INVERTED;
+ D3D12LogicOp[ D3D12_LOGIC_OP_NOOP ] = D3D12_LOGIC_OP_NOOP;
+ D3D12LogicOp[ D3D12_LOGIC_OP_INVERT ] = D3D12_LOGIC_OP_INVERT;
+ D3D12LogicOp[ D3D12_LOGIC_OP_AND ] = D3D12_LOGIC_OP_AND;
+ D3D12LogicOp[ D3D12_LOGIC_OP_NAND ] = D3D12_LOGIC_OP_NAND;
+ D3D12LogicOp[ D3D12_LOGIC_OP_OR ] = D3D12_LOGIC_OP_OR;
+ D3D12LogicOp[ D3D12_LOGIC_OP_NOR ] = D3D12_LOGIC_OP_NOR;
+ D3D12LogicOp[ D3D12_LOGIC_OP_XOR ] = D3D12_LOGIC_OP_XOR;
+ D3D12LogicOp[ D3D12_LOGIC_OP_EQUIV ] = D3D12_LOGIC_OP_EQUIV;
+ D3D12LogicOp[ D3D12_LOGIC_OP_AND_REVERSE ] = D3D12_LOGIC_OP_AND_REVERSE;
+ D3D12LogicOp[ D3D12_LOGIC_OP_AND_INVERTED ] = D3D12_LOGIC_OP_AND_INVERTED;
+ D3D12LogicOp[ D3D12_LOGIC_OP_OR_REVERSE ] = D3D12_LOGIC_OP_OR_REVERSE;
+ D3D12LogicOp[ D3D12_LOGIC_OP_OR_INVERTED ] = D3D12_LOGIC_OP_OR_INVERTED;
+
+ bIsInit = true;
+ }
+ if( lo >= LOGIC_OP_CLEAR && lo < LOGIC_OP_NUM_OPERATIONS )
+ {
+ auto d3dlo = D3D12LogicOp[lo];
+ return d3dlo;
+ }
+ else
+ {
+ UNEXPECTED("Incorrect blend factor (", lo, ")" )
+ return static_cast<D3D12_LOGIC_OP>( 0 );
+ }
+}
+
+
+void BlendStateDesc_To_D3D12_BLEND_DESC(const BlendStateDesc &BSDesc, D3D12_BLEND_DESC &d3d12BlendDesc)
+{
+ BlendStateDescToD3DBlendDesc<D3D12_BLEND_DESC, D3D12_BLEND, D3D12_BLEND_OP>(BSDesc, d3d12BlendDesc);
+
+ for( int i = 0; i < 8; ++i )
+ {
+ const auto& SrcRTDesc = BSDesc.RenderTargets[i];
+ auto &DstRTDesc = d3d12BlendDesc.RenderTarget[i];
+
+ // The following members only present in D3D_RENDER_TARGET_BLEND_DESC
+ DstRTDesc.LogicOpEnable = SrcRTDesc.LogicOperationEnable ? TRUE : FALSE;
+ DstRTDesc.LogicOp = LogicOperationToD3D12LogicOp(SrcRTDesc.LogicOp);
+ }
+}
+
+void LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(const std::vector<LayoutElement, STDAllocatorRawMem<LayoutElement>> &LayoutElements,
+ std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC> > &d3d12InputElements)
+{
+ LayoutElements_To_D3D_INPUT_ELEMENT_DESCs<D3D12_INPUT_ELEMENT_DESC>(LayoutElements, d3d12InputElements);
+}
+
+D3D12_PRIMITIVE_TOPOLOGY TopologyToD3D12Topology(PRIMITIVE_TOPOLOGY Topology)
+{
+ return TopologyToD3DTopology<D3D12_PRIMITIVE_TOPOLOGY>(Topology);
+}
+
+
+
+void TextureViewDesc_to_D3D12_SRV_DESC(const TextureViewDesc& SRVDesc, D3D12_SHADER_RESOURCE_VIEW_DESC &D3D12SRVDesc, Uint32 SampleCount)
+{
+ TextureViewDesc_to_D3D_SRV_DESC(SRVDesc, D3D12SRVDesc, SampleCount);
+ D3D12SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ switch (SRVDesc.TextureDim)
+ {
+ case RESOURCE_DIM_TEX_1D:
+ D3D12SRVDesc.Texture1D.ResourceMinLODClamp = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_1D_ARRAY:
+ D3D12SRVDesc.Texture1DArray.ResourceMinLODClamp = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_2D:
+ if( SampleCount > 1 )
+ {
+ }
+ else
+ {
+ D3D12SRVDesc.Texture2D.PlaneSlice = 0;
+ D3D12SRVDesc.Texture2D.ResourceMinLODClamp = 0;
+ }
+ break;
+
+ case RESOURCE_DIM_TEX_2D_ARRAY:
+ if( SampleCount > 1 )
+ {
+ }
+ else
+ {
+ D3D12SRVDesc.Texture2DArray.PlaneSlice = 0;
+ D3D12SRVDesc.Texture2DArray.ResourceMinLODClamp = 0;
+ }
+ break;
+
+ case RESOURCE_DIM_TEX_3D:
+ D3D12SRVDesc.Texture3D.ResourceMinLODClamp = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_CUBE:
+ D3D12SRVDesc.TextureCube.ResourceMinLODClamp = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_CUBE_ARRAY:
+ D3D12SRVDesc.TextureCubeArray.ResourceMinLODClamp = 0;
+ break;
+
+ default:
+ UNEXPECTED( "Unexpected view type" );
+ }
+}
+
+void TextureViewDesc_to_D3D12_RTV_DESC(const TextureViewDesc& RTVDesc, D3D12_RENDER_TARGET_VIEW_DESC &D3D12RTVDesc, Uint32 SampleCount)
+{
+ TextureViewDesc_to_D3D_RTV_DESC(RTVDesc, D3D12RTVDesc, SampleCount);
+ switch (RTVDesc.TextureDim)
+ {
+ case RESOURCE_DIM_TEX_1D:
+ break;
+
+ case RESOURCE_DIM_TEX_1D_ARRAY:
+ break;
+
+ case RESOURCE_DIM_TEX_2D:
+ if( SampleCount > 1 )
+ {
+ }
+ else
+ {
+ D3D12RTVDesc.Texture2D.PlaneSlice = 0;
+ }
+ break;
+
+ case RESOURCE_DIM_TEX_2D_ARRAY:
+ if( SampleCount > 1 )
+ {
+ }
+ else
+ {
+ D3D12RTVDesc.Texture2DArray.PlaneSlice = 0;
+ }
+ break;
+
+ case RESOURCE_DIM_TEX_3D:
+ break;
+
+ default:
+ UNEXPECTED( "Unexpected view type" );
+ }
+}
+
+void TextureViewDesc_to_D3D12_DSV_DESC(const TextureViewDesc& DSVDesc, D3D12_DEPTH_STENCIL_VIEW_DESC &D3D12DSVDesc, Uint32 SampleCount)
+{
+ TextureViewDesc_to_D3D_DSV_DESC(DSVDesc, D3D12DSVDesc, SampleCount);
+ D3D12DSVDesc.Flags = D3D12_DSV_FLAG_NONE;
+}
+
+void TextureViewDesc_to_D3D12_UAV_DESC(const TextureViewDesc& UAVDesc, D3D12_UNORDERED_ACCESS_VIEW_DESC &D3D12UAVDesc)
+{
+ TextureViewDesc_to_D3D_UAV_DESC(UAVDesc, D3D12UAVDesc);
+ switch (UAVDesc.TextureDim)
+ {
+ case RESOURCE_DIM_TEX_1D:
+ break;
+
+ case RESOURCE_DIM_TEX_1D_ARRAY:
+ break;
+
+ case RESOURCE_DIM_TEX_2D:
+ D3D12UAVDesc.Texture2D.PlaneSlice = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_2D_ARRAY:
+ D3D12UAVDesc.Texture2DArray.PlaneSlice = 0;
+ break;
+
+ case RESOURCE_DIM_TEX_3D:
+ break;
+
+ default:
+ UNEXPECTED( "Unexpected view type" );
+ }
+}
+
+
+void BufferViewDesc_to_D3D12_SRV_DESC(const BufferDesc &BuffDesc, const BufferViewDesc& SRVDesc, D3D12_SHADER_RESOURCE_VIEW_DESC &D3D12SRVDesc)
+{
+ BufferViewDesc_to_D3D_SRV_DESC(BuffDesc, SRVDesc, D3D12SRVDesc);
+ D3D12SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ D3D12SRVDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
+}
+
+void BufferViewDesc_to_D3D12_UAV_DESC(const BufferDesc &BuffDesc, const BufferViewDesc& UAVDesc, D3D12_UNORDERED_ACCESS_VIEW_DESC &D3D12UAVDesc)
+{
+ BufferViewDesc_to_D3D_UAV_DESC(BuffDesc, UAVDesc, D3D12UAVDesc);
+ D3D12UAVDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
+}
+
+D3D12_STATIC_BORDER_COLOR BorderColorToD3D12StaticBorderColor(const Float32 BorderColor[])
+{
+ D3D12_STATIC_BORDER_COLOR StaticBorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
+ if(BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0)
+ StaticBorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
+ else if(BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1)
+ StaticBorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
+ else if(BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 0)
+ StaticBorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
+ else
+ {
+ LOG_ERROR_MESSAGE("Static samplers only allow transparent black (0,0,0,1), opaque black (0,0,0,0) or opaque white (1,1,1,0) as border colors.")
+ }
+ return StaticBorderColor;
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp
new file mode 100644
index 00000000..a1f82e1c
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp
@@ -0,0 +1,45 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "D3D12Utils.h"
+
+namespace Diligent
+{
+ const Char* GetD3D12DescriptorHeapTypeLiteralName(D3D12_DESCRIPTOR_HEAP_TYPE Type)
+ {
+ static bool bIsInitialized = false;
+ static const Char* HeapTypeNames[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
+ if (!bIsInitialized)
+ {
+ HeapTypeNames[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] = "D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV";
+ HeapTypeNames[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = "D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER";
+ HeapTypeNames[D3D12_DESCRIPTOR_HEAP_TYPE_RTV] = "D3D12_DESCRIPTOR_HEAP_TYPE_RTV";
+ HeapTypeNames[D3D12_DESCRIPTOR_HEAP_TYPE_DSV] = "D3D12_DESCRIPTOR_HEAP_TYPE_DSV";
+
+ bIsInitialized = true;
+ }
+ VERIFY_EXPR(Type >= 0 && Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES);
+ return HeapTypeNames[Type];
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/DLLMain.cpp b/Graphics/GraphicsEngineD3D12/src/DLLMain.cpp
new file mode 100644
index 00000000..fff890c0
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/DLLMain.cpp
@@ -0,0 +1,49 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+BOOL APIENTRY DllMain(HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ switch( ul_reason_for_call )
+ {
+ case DLL_PROCESS_ATTACH:
+ #if defined(_DEBUG) || defined(DEBUG)
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+ #endif
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+} \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
new file mode 100644
index 00000000..02ea8384
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
@@ -0,0 +1,342 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DescriptorHeap.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "D3D12Utils.h"
+
+namespace Diligent
+{
+
+
+DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12Impl,
+ IDescriptorAllocator *pParentAllocator,
+ size_t ThisManagerId,
+ const D3D12_DESCRIPTOR_HEAP_DESC &HeapDesc) :
+ m_FreeBlockManager(HeapDesc.NumDescriptors, Allocator),
+ m_NumDescriptorsInAllocation(HeapDesc.NumDescriptors),
+ m_HeapDesc(HeapDesc),
+ m_pDeviceD3D12Impl(pDeviceD3D12Impl),
+ m_pParentAllocator(pParentAllocator),
+ m_ThisManagerId(ThisManagerId)
+{
+ auto pDevice = pDeviceD3D12Impl->GetD3D12Device();
+
+ m_FirstCPUHandle.ptr = 0;
+ m_FirstGPUHandle.ptr = 0;
+ m_DescriptorSize = pDevice->GetDescriptorHandleIncrementSize(HeapDesc.Type);
+
+ pDevice->CreateDescriptorHeap(&m_HeapDesc, __uuidof(m_pd3d12DescriptorHeap), reinterpret_cast<void**>(static_cast<ID3D12DescriptorHeap**>(&m_pd3d12DescriptorHeap)));
+ m_FirstCPUHandle = m_pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
+ if(m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ m_FirstGPUHandle = m_pd3d12DescriptorHeap->GetGPUDescriptorHandleForHeapStart();
+}
+
+DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12Impl,
+ IDescriptorAllocator *pParentAllocator,
+ size_t ThisManagerId,
+ ID3D12DescriptorHeap *pd3d12DescriptorHeap,
+ Uint32 FirstDescriptor,
+ Uint32 NumDescriptors):
+ m_FreeBlockManager(NumDescriptors, Allocator),
+ m_NumDescriptorsInAllocation(NumDescriptors),
+ m_pDeviceD3D12Impl(pDeviceD3D12Impl),
+ m_pParentAllocator(pParentAllocator),
+ m_ThisManagerId(ThisManagerId),
+ m_pd3d12DescriptorHeap(pd3d12DescriptorHeap)
+{
+ m_HeapDesc = m_pd3d12DescriptorHeap->GetDesc();
+ m_DescriptorSize = pDeviceD3D12Impl->GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type);
+
+ m_FirstCPUHandle = pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
+ m_FirstCPUHandle.ptr += m_DescriptorSize * FirstDescriptor;
+
+ if (m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ {
+ m_FirstGPUHandle = pd3d12DescriptorHeap->GetGPUDescriptorHandleForHeapStart();
+ m_FirstGPUHandle.ptr += m_DescriptorSize * FirstDescriptor;
+ }
+}
+
+
+DescriptorHeapAllocationManager::~DescriptorHeapAllocationManager()
+{
+ VERIFY(m_FreeBlockManager.GetFreeSize() == m_NumDescriptorsInAllocation, "Not all descriptors were released");
+}
+
+DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Count)
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+
+ auto DescriptorHandleOffset = m_FreeBlockManager.Allocate(Count);
+ if (DescriptorHandleOffset == FreeBlockListManagerGPU::InvalidOffset)
+ {
+ return DescriptorHeapAllocation();
+ }
+
+ auto CPUHandle = m_FirstCPUHandle;
+ CPUHandle.ptr += DescriptorHandleOffset * m_DescriptorSize;
+
+ auto GPUHandle = m_FirstGPUHandle;
+ if(m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ GPUHandle.ptr += DescriptorHandleOffset * m_DescriptorSize;
+
+ VERIFY(m_ThisManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceed allowed limit");
+ DescriptorHeapAllocation Allocation( m_pParentAllocator, m_pd3d12DescriptorHeap, CPUHandle, GPUHandle, Count, static_cast<Uint16>(m_ThisManagerId));
+
+ return Allocation;
+}
+
+void DescriptorHeapAllocationManager::Free(DescriptorHeapAllocation&& Allocation)
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+
+ VERIFY(Allocation.GetAllocationManagerId() == m_ThisManagerId, "Invalid descriptor heap manager Id")
+
+ auto DescriptorOffset = (Allocation.GetCpuHandle().ptr - m_FirstCPUHandle.ptr) / m_DescriptorSize;
+ m_FreeBlockManager.Free(DescriptorOffset, Allocation.GetNumHandles(), m_pDeviceD3D12Impl->GetCurrentFrame());
+ Allocation = DescriptorHeapAllocation();
+}
+
+void DescriptorHeapAllocationManager::ReleaseStaleAllocations(Uint64 NumCompletedFrames)
+{
+ m_FreeBlockManager.ReleaseCompletedFrames(NumCompletedFrames);
+}
+
+
+
+
+//
+// CPUDescriptorHeap implementation
+//
+CPUDescriptorHeap::CPUDescriptorHeap(IMemoryAllocator &Allocator, RenderDeviceD3D12Impl *pDeviceD3D12Impl, Uint32 NumDescriptorsInHeap, D3D12_DESCRIPTOR_HEAP_TYPE Type, D3D12_DESCRIPTOR_HEAP_FLAGS Flags) :
+ m_pDeviceD3D12Impl(pDeviceD3D12Impl),
+ m_MemAllocator(Allocator),
+ m_HeapPool(STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocationManager, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocationManager>")),
+ m_AvailableHeaps(STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for set<size_t>"))
+{
+ m_HeapDesc.Type = Type;
+ m_HeapDesc.NodeMask = 1;
+ m_HeapDesc.NumDescriptors = NumDescriptorsInHeap;
+ m_HeapDesc.Flags = Flags;
+
+ m_DescriptorSize = m_pDeviceD3D12Impl->GetD3D12Device()->GetDescriptorHandleIncrementSize(Type);
+}
+
+CPUDescriptorHeap::~CPUDescriptorHeap()
+{
+ VERIFY(m_CurrentSize == 0, "Not all allocations released" );
+
+ VERIFY(m_AvailableHeaps.size() == m_HeapPool.size(), "Not all descriptor heap pools are released");
+ for (auto HeapPoolIt = m_HeapPool.begin(); HeapPoolIt != m_HeapPool.end(); ++HeapPoolIt)
+ {
+ VERIFY(HeapPoolIt->GetNumAvailableDescriptors() == m_HeapDesc.NumDescriptors, "Not all descriptors in the descriptor pool are released");
+ }
+
+ LOG_INFO_MESSAGE("Max ", GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " CPU heap size: ", m_MaxHeapSize);
+}
+
+DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ DescriptorHeapAllocation Allocation;
+ for (auto AvailableHeapIt = m_AvailableHeaps.begin(); AvailableHeapIt != m_AvailableHeaps.end(); ++AvailableHeapIt)
+ {
+ Allocation = m_HeapPool[*AvailableHeapIt].Allocate(Count);
+ if(m_HeapPool[*AvailableHeapIt].GetNumAvailableDescriptors() == 0)
+ m_AvailableHeaps.erase(*AvailableHeapIt);
+
+ if(Allocation.GetCpuHandle().ptr != 0)
+ break;
+ }
+
+ if(Allocation.GetCpuHandle().ptr == 0)
+ {
+ m_HeapPool.emplace_back(m_MemAllocator, m_pDeviceD3D12Impl, this, m_HeapPool.size(), m_HeapDesc);
+ auto NewHeapIt = m_AvailableHeaps.insert(m_HeapPool.size()-1);
+
+ Allocation = m_HeapPool[*NewHeapIt.first].Allocate(Count);
+ }
+
+ m_CurrentSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
+ m_MaxHeapSize = std::max(m_MaxHeapSize, m_CurrentSize);
+
+ return Allocation;
+}
+
+void CPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation)
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ auto ManagerId = Allocation.GetAllocationManagerId();
+ m_CurrentSize -= static_cast<Uint32>(Allocation.GetNumHandles());
+ m_HeapPool[ManagerId].Free(std::move(Allocation));
+}
+
+void CPUDescriptorHeap::ReleaseStaleAllocations(Uint64 NumCompletedFrames)
+{
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ for (size_t HeapManagerInd = 0; HeapManagerInd < m_HeapPool.size(); ++HeapManagerInd)
+ {
+ m_HeapPool[HeapManagerInd].ReleaseStaleAllocations(NumCompletedFrames);
+ if(m_HeapPool[HeapManagerInd].GetNumAvailableDescriptors() > 0)
+ m_AvailableHeaps.insert(HeapManagerInd);
+ }
+}
+
+
+
+
+GPUDescriptorHeap::GPUDescriptorHeap(IMemoryAllocator &Allocator,
+ RenderDeviceD3D12Impl *pDevice,
+ Uint32 NumDescriptorsInHeap,
+ Uint32 NumDynamicDescriptors,
+ D3D12_DESCRIPTOR_HEAP_TYPE Type,
+ D3D12_DESCRIPTOR_HEAP_FLAGS Flags) :
+ m_pDeviceD3D12(pDevice),
+ m_HeapDesc
+ {
+ Type,
+ NumDescriptorsInHeap + NumDynamicDescriptors,
+ Flags,
+ 1 // UINT NodeMask;
+ },
+ m_pd3d12DescriptorHeap([&]{
+ CComPtr<ID3D12DescriptorHeap> pHeap;
+ pDevice->GetD3D12Device()->CreateDescriptorHeap(&m_HeapDesc, __uuidof(pHeap), reinterpret_cast<void**>(&pHeap));
+ return pHeap;
+ }()),
+ m_DescriptorSize( pDevice->GetD3D12Device()->GetDescriptorHandleIncrementSize(Type) ),
+ m_HeapAllocationManager(Allocator, pDevice, this, 0, m_pd3d12DescriptorHeap, 0, NumDescriptorsInHeap),
+ m_DynamicAllocationsManager(Allocator, pDevice, this, 1, m_pd3d12DescriptorHeap, NumDescriptorsInHeap, NumDynamicDescriptors )
+{
+}
+
+GPUDescriptorHeap::~GPUDescriptorHeap()
+{
+ LOG_INFO_MESSAGE("Max ", GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " GPU heap static/dynamic size: ", m_MaxHeapSize, "/", m_MaxDynamicSize);
+}
+
+DescriptorHeapAllocation GPUDescriptorHeap::Allocate(uint32_t Count)
+{
+ std::lock_guard<std::mutex> LockGuard(m_Mutex);
+ DescriptorHeapAllocation Allocation = m_HeapAllocationManager.Allocate(Count);
+
+ m_CurrentSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
+ m_MaxHeapSize = std::max(m_MaxHeapSize, m_CurrentSize);
+
+ return Allocation;
+}
+
+DescriptorHeapAllocation GPUDescriptorHeap::AllocateDynamic(uint32_t Count)
+{
+ std::lock_guard<std::mutex> LockGuard(m_Mutex);
+ DescriptorHeapAllocation Allocation = m_DynamicAllocationsManager.Allocate(Count);
+
+ m_CurrentDynamicSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
+ m_MaxDynamicSize = std::max(m_MaxDynamicSize, m_CurrentDynamicSize);
+
+ return Allocation;
+}
+
+void GPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation)
+{
+ auto MgrId = Allocation.GetAllocationManagerId();
+ VERIFY(MgrId == 0 || MgrId == 1, "Unexpected allocation manager ID");
+
+ std::lock_guard<std::mutex> LockGuard(m_Mutex);
+
+ if(MgrId == 0)
+ {
+ m_CurrentSize -= static_cast<Uint32>(Allocation.GetNumHandles());
+ m_HeapAllocationManager.Free(std::move(Allocation));
+ }
+ else
+ {
+ m_CurrentDynamicSize -= static_cast<Uint32>(Allocation.GetNumHandles());
+ m_DynamicAllocationsManager.Free(std::move(Allocation));
+ }
+}
+
+void GPUDescriptorHeap::ReleaseStaleAllocations(Uint64 NumCompletedFrames)
+{
+ m_HeapAllocationManager.ReleaseStaleAllocations(NumCompletedFrames);
+ m_DynamicAllocationsManager.ReleaseStaleAllocations(NumCompletedFrames);
+}
+
+
+
+
+
+DynamicSuballocationsManager::DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize) :
+ m_ParentGPUHeap(ParentGPUHeap),
+ m_DynamicChunkSize(DynamicChunkSize),
+ m_Suballocations(STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocation, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocation>"))
+{
+}
+
+void DynamicSuballocationsManager::DiscardAllocations(Uint64 FrameNumber)
+{
+ m_Suballocations.clear();
+}
+
+DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
+{
+ if( m_Suballocations.empty() ||
+ m_CurrentSuballocationOffset + Count > m_Suballocations.back().GetNumHandles() )
+ {
+ auto SuballocationSize = std::max(m_DynamicChunkSize, Count);
+ auto NewDynamicSubAllocation = m_ParentGPUHeap.AllocateDynamic(SuballocationSize);
+ if (NewDynamicSubAllocation.GetCpuHandle().ptr == 0)
+ {
+ LOG_ERROR_MESSAGE("Failed to suballocate region for dynamic descriptors")
+ return DescriptorHeapAllocation();
+ }
+ m_Suballocations.emplace_back(std::move(NewDynamicSubAllocation));
+ m_CurrentSuballocationOffset = 0;
+ }
+
+ auto &CurrentSuballocation = m_Suballocations.back();
+
+ auto ManagerId = CurrentSuballocation.GetAllocationManagerId();
+ VERIFY(ManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceed allowed limit");
+ DescriptorHeapAllocation Allocation( this,
+ CurrentSuballocation.GetDescriptorHeap(),
+ CurrentSuballocation.GetCpuHandle(m_CurrentSuballocationOffset),
+ CurrentSuballocation.GetGpuHandle(m_CurrentSuballocationOffset),
+ Count,
+ static_cast<Uint16>(ManagerId) );
+ m_CurrentSuballocationOffset += Count;
+
+ return Allocation;
+}
+
+void DynamicSuballocationsManager::Free(DescriptorHeapAllocation&& Allocation)
+{
+ // Do nothing
+ Allocation = DescriptorHeapAllocation();
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
new file mode 100644
index 00000000..5ebfb4b4
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -0,0 +1,724 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+#include "SwapChainD3D12Impl.h"
+#include "PipelineStateD3D12Impl.h"
+#include "CommandContext.h"
+#include "TextureD3D12Impl.h"
+#include "BufferD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+#include "d3dx12_win.h"
+#include "DynamicUploadHeap.h"
+#include "CommandListD3D12Impl.h"
+
+namespace Diligent
+{
+
+ DeviceContextD3D12Impl::DeviceContextD3D12Impl( IMemoryAllocator &RawMemAllocator, RenderDeviceD3D12Impl *pDeviceD3D12Impl, bool bIsDeferred, const EngineD3D12Attribs &Attribs, Uint32 ContextId) :
+ TDeviceContextBase(RawMemAllocator, pDeviceD3D12Impl, bIsDeferred),
+ m_pUploadHeap(pDeviceD3D12Impl->RequestUploadHeap() ),
+ m_NumCommandsInCurCtx(0),
+ m_NumCommandsToFlush(bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : Attribs.NumCommandsToFlushCmdList),
+ m_pCurrCmdCtx(pDeviceD3D12Impl->AllocateCommandContext()),
+ m_CommittedIBFormat(VT_UNDEFINED),
+ m_CommittedD3D12IndexDataStartOffset(0),
+ m_MipsGenerator(pDeviceD3D12Impl->GetD3D12Device()),
+ m_CmdListAllocator(GetRawAllocator(), sizeof(CommandListD3D12Impl), 64 ),
+ m_ContextId(ContextId)
+ {
+ m_NumBoundRenderTargets = 0;
+
+ auto *pd3d12Device = pDeviceD3D12Impl->GetD3D12Device();
+
+ D3D12_COMMAND_SIGNATURE_DESC CmdSignatureDesc = {};
+ D3D12_INDIRECT_ARGUMENT_DESC IndirectArg = {};
+ CmdSignatureDesc.NodeMask = 0;
+ CmdSignatureDesc.NumArgumentDescs = 1;
+ CmdSignatureDesc.pArgumentDescs = &IndirectArg;
+
+ CmdSignatureDesc.ByteStride = sizeof(UINT)*4;
+ IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
+ auto hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDrawIndirectSignature), reinterpret_cast<void**>(static_cast<ID3D12CommandSignature**>(&m_pDrawIndirectSignature)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create indirect draw command signature")
+
+ CmdSignatureDesc.ByteStride = sizeof(UINT)*5;
+ IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
+ hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDrawIndexedIndirectSignature), reinterpret_cast<void**>(static_cast<ID3D12CommandSignature**>(&m_pDrawIndexedIndirectSignature)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create draw indexed indirect command signature")
+
+ CmdSignatureDesc.ByteStride = sizeof(UINT)*3;
+ IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
+ hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDispatchIndirectSignature), reinterpret_cast<void**>(static_cast<ID3D12CommandSignature**>(&m_pDispatchIndirectSignature)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create dispatch indirect command signature")
+ }
+
+ DeviceContextD3D12Impl::~DeviceContextD3D12Impl()
+ {
+ if(m_bIsDeferred)
+ ValidatedCast<RenderDeviceD3D12Impl>(m_pDevice.RawPtr())->DisposeCommandContext(m_pCurrCmdCtx);
+ else
+ Flush(false);
+ }
+
+ //IMPLEMENT_QUERY_INTERFACE( DeviceContextD3D12Impl, IID_DeviceContextD3D12, TDeviceContextBase )
+
+ const LONG MaxD3D12TexDim = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ const Uint32 MaxD3D12ScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ static const RECT MaxD3D12TexSizeRects[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] =
+ {
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim},
+ {0,0, MaxD3D12TexDim,MaxD3D12TexDim}
+ };
+
+ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState *pPipelineState)
+ {
+ if (m_NumCommandsInCurCtx >= m_NumCommandsToFlush)
+ {
+ Flush(true);
+ }
+
+ TDeviceContextBase::SetPipelineState( pPipelineState );
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPipelineState);
+
+ auto *pCmdCtx = RequestCmdContext();
+ const auto &Desc = pPipelineStateD3D12->GetDesc();
+ auto *pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState();
+ if (Desc.IsComputePipeline)
+ {
+ pCmdCtx->AsComputeContext().SetPipelineState(pd3d12PSO);
+ }
+ else
+ {
+ auto &GraphicsCtx = pCmdCtx->AsGraphicsContext();
+ GraphicsCtx.SetPipelineState(pd3d12PSO);
+
+ if (Desc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ {
+ // Commit currently set scissor rectangles
+ D3D12_RECT d3d12ScissorRects[MaxD3D12ScissorRects]; // Do not waste time initializing array with zeroes
+ for( Uint32 sr = 0; sr < m_NumScissorRects; ++sr )
+ {
+ d3d12ScissorRects[sr].left = m_ScissorRects[sr].left;
+ d3d12ScissorRects[sr].top = m_ScissorRects[sr].top;
+ d3d12ScissorRects[sr].right = m_ScissorRects[sr].right;
+ d3d12ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
+ }
+ GraphicsCtx.SetScissorRects(m_NumScissorRects, d3d12ScissorRects);
+ }
+ else
+ {
+ // Disable scissor rectangles
+ static_assert(_countof(MaxD3D12TexSizeRects) == MaxD3D12ScissorRects, "Unexpected array size");
+ GraphicsCtx.SetScissorRects(MaxD3D12ScissorRects, MaxD3D12TexSizeRects);
+ }
+
+ GraphicsCtx.SetStencilRef( m_StencilRef );
+ GraphicsCtx.SetBlendFactor( m_BlendFactors );
+ m_CommittedD3D12IndexBuffer = nullptr;
+ m_CommittedD3D12IndexDataStartOffset = 0;
+ m_CommittedIBFormat = VT_UNDEFINED;
+ m_bCommittedD3D12VBsUpToDate = false;
+ m_bCommittedD3D12IBUpToDate = false;
+ RebindRenderTargets();
+ CommitViewports();
+ }
+ m_pCommittedResourceCache = nullptr;
+ }
+
+ void DeviceContextD3D12Impl::TransitionShaderResources(IPipelineState *pPipelineState, IShaderResourceBinding *pShaderResourceBinding)
+ {
+ VERIFY_EXPR(pPipelineState != nullptr);
+
+ auto *pCtx = RequestCmdContext();
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPipelineState);
+ pPipelineStateD3D12->CommitAndTransitionShaderResources(pShaderResourceBinding, *pCtx, false, true);
+ }
+
+ void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding *pShaderResourceBinding, Uint32 Flags)
+ {
+#ifdef _DEBUG
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR("No pipeline state is bound");
+ return;
+ }
+#endif
+
+ auto *pCtx = RequestCmdContext();
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(m_pPipelineState.RawPtr());
+
+ m_pCommittedResourceCache = pPipelineStateD3D12->CommitAndTransitionShaderResources(pShaderResourceBinding, *pCtx, true, (Flags & COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES)!=0);
+ }
+
+ void DeviceContextD3D12Impl::SetStencilRef(Uint32 StencilRef)
+ {
+ if (TDeviceContextBase::SetStencilRef(StencilRef, 0))
+ {
+ RequestCmdContext()->AsGraphicsContext().SetStencilRef( m_StencilRef );
+ }
+ }
+
+ void DeviceContextD3D12Impl::SetBlendFactors(const float* pBlendFactors)
+ {
+ if (TDeviceContextBase::SetBlendFactors(m_BlendFactors, 0))
+ {
+ RequestCmdContext()->AsGraphicsContext().SetBlendFactor( m_BlendFactors );
+ }
+ }
+
+ void DeviceContextD3D12Impl::CommitD3D12IndexBuffer(VALUE_TYPE IndexType)
+ {
+ if( !m_pIndexBuffer )
+ {
+ LOG_ERROR_MESSAGE( "Index buffer is not set up for indexed draw command" );
+ return;
+ }
+
+ D3D12_INDEX_BUFFER_VIEW IBView;
+ BufferD3D12Impl *pBuffD3D12 = static_cast<BufferD3D12Impl *>(m_pIndexBuffer.RawPtr());
+ IBView.BufferLocation = pBuffD3D12->GetGPUAddress(m_ContextId) + m_IndexDataStartOffset;
+ if( IndexType == VT_UINT32 )
+ IBView.Format = DXGI_FORMAT_R32_UINT;
+ else if( IndexType == VT_UINT16 )
+ IBView.Format = DXGI_FORMAT_R16_UINT;
+ else
+ {
+ LOG_ERROR_MESSAGE( "Unsupported index format. Only R16_UINT and R32_UINT are allowed." );
+ return;
+ }
+ // Note that for a dynamic buffer, what we use here is the size of the buffer itself, not the upload heap buffer!
+ IBView.SizeInBytes = pBuffD3D12->GetDesc().uiSizeInBytes - m_IndexDataStartOffset;
+
+ // Device context keeps strong reference to bound index buffer.
+ // When the buffer is unbound, the reference to the D3D12 resource
+ // is added to the context. There is no need to add reference here
+ //auto &GraphicsCtx = RequestCmdContext()->AsGraphicsContext();
+ //auto *pd3d12Resource = pBuffD3D12->GetD3D12Buffer();
+ //GraphicsCtx.AddReferencedObject(pd3d12Resource);
+
+#ifdef _DEBUG
+ if(pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ pBuffD3D12->DbgVerifyDynamicAllocation(m_ContextId);
+#endif
+ auto &GraphicsCtx = RequestCmdContext()->AsGraphicsContext();
+ // Resource transitioning must always be performed!
+ GraphicsCtx.TransitionResource(pBuffD3D12, D3D12_RESOURCE_STATE_INDEX_BUFFER, true);
+
+ size_t BuffDataStartByteOffset;
+ auto *pd3d12Buff = pBuffD3D12->GetD3D12Buffer(BuffDataStartByteOffset, m_ContextId);
+
+ if( m_CommittedD3D12IndexBuffer != pd3d12Buff ||
+ m_CommittedIBFormat != IndexType ||
+ m_CommittedD3D12IndexDataStartOffset != m_IndexDataStartOffset + BuffDataStartByteOffset)
+ {
+ m_CommittedD3D12IndexBuffer = pd3d12Buff;
+ m_CommittedIBFormat = IndexType;
+ m_CommittedD3D12IndexDataStartOffset = m_IndexDataStartOffset + static_cast<Uint32>(BuffDataStartByteOffset);
+ GraphicsCtx.SetIndexBuffer( IBView );
+ }
+ m_bCommittedD3D12IBUpToDate = true;
+ }
+
+ void DeviceContextD3D12Impl::TransitionD3D12VertexBuffers(GraphicsContext &GraphCtx)
+ {
+ for( UINT Buff = 0; Buff < m_NumVertexStreams; ++Buff )
+ {
+ auto &CurrStream = m_VertexStreams[Buff];
+ VERIFY( CurrStream.pBuffer, "Attempting to bind a null buffer for rendering" );
+ auto *pBufferD3D12 = static_cast<BufferD3D12Impl*>(CurrStream.pBuffer.RawPtr());
+ if(!pBufferD3D12->CheckAllStates(D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER))
+ GraphCtx.TransitionResource(pBufferD3D12, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+ }
+ }
+
+ void DeviceContextD3D12Impl::CommitD3D12VertexBuffers(GraphicsContext &GraphCtx)
+ {
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(m_pPipelineState.RawPtr());
+
+ // Do not initialize array with zeroes for performance reasons
+ D3D12_VERTEX_BUFFER_VIEW VBViews[MaxBufferSlots];// = {}
+ VERIFY( m_NumVertexStreams <= MaxBufferSlots, "Too many buffers are being set" );
+ const auto *TightStrides = pPipelineStateD3D12->GetTightStrides();
+ for( UINT Buff = 0; Buff < m_NumVertexStreams; ++Buff )
+ {
+ auto &CurrStream = m_VertexStreams[Buff];
+ auto &VBView = VBViews[Buff];
+ VERIFY( CurrStream.pBuffer, "Attempting to bind a null buffer for rendering" );
+
+ auto *pBufferD3D12 = static_cast<BufferD3D12Impl*>(CurrStream.pBuffer.RawPtr());
+#ifdef _DEBUG
+ if(pBufferD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ pBufferD3D12->DbgVerifyDynamicAllocation(m_ContextId);
+#endif
+
+ GraphCtx.TransitionResource(pBufferD3D12, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+
+ // Device context keeps strong references to all vertex buffers.
+ // When a buffer is unbound, a reference to D3D12 resource is added to the context,
+ // so there is no need to reference the resource here
+ //GraphicsCtx.AddReferencedObject(pd3d12Resource);
+
+ VBView.BufferLocation = pBufferD3D12->GetGPUAddress(m_ContextId) + CurrStream.Offset;
+ VBView.StrideInBytes = CurrStream.Stride ? CurrStream.Stride : TightStrides[Buff];
+ // Note that for a dynamic buffer, what we use here is the size of the buffer itself, not the upload heap buffer!
+ VBView.SizeInBytes = pBufferD3D12->GetDesc().uiSizeInBytes - CurrStream.Offset;
+ }
+
+ GraphCtx.FlushResourceBarriers();
+ GraphCtx.SetVertexBuffers( 0, m_NumVertexStreams, VBViews );
+
+ m_bCommittedD3D12VBsUpToDate = true;
+ }
+
+ void DeviceContextD3D12Impl::Draw( DrawAttribs &DrawAttribs )
+ {
+#ifdef _DEBUG
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR("No pipeline state is bound");
+ return;
+ }
+ if (m_pPipelineState->GetDesc().IsComputePipeline)
+ {
+ LOG_ERROR("No graphics pipeline state is bound");
+ return;
+ }
+#endif
+
+ auto &GraphCtx = RequestCmdContext()->AsGraphicsContext();
+ if( DrawAttribs.IsIndexed )
+ {
+ if( m_CommittedIBFormat != DrawAttribs.IndexType )
+ m_bCommittedD3D12IBUpToDate = false;
+
+ if(m_bCommittedD3D12IBUpToDate)
+ {
+ BufferD3D12Impl *pBuffD3D12 = static_cast<BufferD3D12Impl *>(m_pIndexBuffer.RawPtr());
+ if(!pBuffD3D12->CheckAllStates(D3D12_RESOURCE_STATE_INDEX_BUFFER))
+ GraphCtx.TransitionResource(pBuffD3D12, D3D12_RESOURCE_STATE_INDEX_BUFFER, true);
+ }
+ else
+ CommitD3D12IndexBuffer(DrawAttribs.IndexType);
+ }
+
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(m_pPipelineState.RawPtr());
+
+ auto D3D12Topology = TopologyToD3D12Topology( DrawAttribs.Topology );
+ GraphCtx.SetPrimitiveTopology(D3D12Topology);
+
+ if(m_bCommittedD3D12VBsUpToDate)
+ TransitionD3D12VertexBuffers(GraphCtx);
+ else
+ CommitD3D12VertexBuffers(GraphCtx);
+
+ GraphCtx.SetRootSignature( pPipelineStateD3D12->GetD3D12RootSignature() );
+
+ if(m_pCommittedResourceCache != nullptr)
+ {
+ pPipelineStateD3D12->GetRootSignature().CommitRootViews(*m_pCommittedResourceCache, GraphCtx, false, m_ContextId);
+ }
+#ifdef _DEBUG
+ else
+ {
+ if( pPipelineStateD3D12->dbgContainsShaderResources() )
+ LOG_ERROR_MESSAGE("Pipeline state \"", pPipelineStateD3D12->GetDesc().Name, "\" contains shader resources, but IDeviceContext::CommitShaderResources() was not called" )
+ }
+#endif
+
+
+ if( DrawAttribs.IsIndirect )
+ {
+ if( auto *pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(DrawAttribs.pIndirectDrawAttribs) )
+ {
+#ifdef _DEBUG
+ if(pBufferD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ pBufferD3D12->DbgVerifyDynamicAllocation(m_ContextId);
+#endif
+
+ GraphCtx.TransitionResource(pBufferD3D12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
+ size_t BuffDataStartByteOffset;
+ ID3D12Resource *pd3d12ArgsBuff = pBufferD3D12->GetD3D12Buffer(BuffDataStartByteOffset, m_ContextId);
+ GraphCtx.ExecuteIndirect(DrawAttribs.IsIndexed ? m_pDrawIndexedIndirectSignature : m_pDrawIndirectSignature, pd3d12ArgsBuff, DrawAttribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Valid pIndirectDrawAttribs must be provided for indirect draw command")
+ }
+ }
+ else
+ {
+ if( DrawAttribs.IsIndexed )
+ GraphCtx.DrawIndexed(DrawAttribs.NumIndices, DrawAttribs.NumInstances, DrawAttribs.FirstIndexLocation, DrawAttribs.BaseVertex, DrawAttribs.FirstInstanceLocation);
+ else
+ GraphCtx.Draw(DrawAttribs.NumVertices, DrawAttribs.NumInstances, DrawAttribs.StartVertexLocation, DrawAttribs.FirstInstanceLocation );
+ }
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::DispatchCompute( const DispatchComputeAttribs &DispatchAttrs )
+ {
+#ifdef _DEBUG
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR("No pipeline state is bound");
+ return;
+ }
+ if (!m_pPipelineState->GetDesc().IsComputePipeline)
+ {
+ LOG_ERROR("No compute pipeline state is bound");
+ return;
+ }
+#endif
+
+ auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(m_pPipelineState.RawPtr());
+
+ auto &ComputeCtx = RequestCmdContext()->AsComputeContext();
+ ComputeCtx.SetRootSignature( pPipelineStateD3D12->GetD3D12RootSignature() );
+
+ if(m_pCommittedResourceCache != nullptr)
+ {
+ pPipelineStateD3D12->GetRootSignature().CommitRootViews(*m_pCommittedResourceCache, ComputeCtx, true, m_ContextId);
+ }
+#ifdef _DEBUG
+ else
+ {
+ if( pPipelineStateD3D12->dbgContainsShaderResources() )
+ LOG_ERROR_MESSAGE("Pipeline state \"", pPipelineStateD3D12->GetDesc().Name, "\" contains shader resources, but IDeviceContext::CommitShaderResources() was not called" )
+ }
+#endif
+
+ if( DispatchAttrs.pIndirectDispatchAttribs )
+ {
+ if( auto *pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(DispatchAttrs.pIndirectDispatchAttribs) )
+ {
+#ifdef _DEBUG
+ if(pBufferD3D12->GetDesc().Usage == USAGE_DYNAMIC)
+ pBufferD3D12->DbgVerifyDynamicAllocation(m_ContextId);
+#endif
+
+ ComputeCtx.TransitionResource(pBufferD3D12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
+ size_t BuffDataStartByteOffset;
+ ID3D12Resource *pd3d12ArgsBuff = pBufferD3D12->GetD3D12Buffer(BuffDataStartByteOffset, m_ContextId);
+ ComputeCtx.ExecuteIndirect(m_pDispatchIndirectSignature, pd3d12ArgsBuff, DispatchAttrs.DispatchArgsByteOffset + BuffDataStartByteOffset);
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Valid pIndirectDrawAttribs must be provided for indirect dispatch command")
+ }
+ }
+ else
+ ComputeCtx.Dispatch(DispatchAttrs.ThreadGroupCountX, DispatchAttrs.ThreadGroupCountY, DispatchAttrs.ThreadGroupCountZ);
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil )
+ {
+ ITextureViewD3D12 *pDSVD3D12 = nullptr;
+ if( pView != nullptr )
+ {
+ pDSVD3D12 = ValidatedCast<ITextureViewD3D12>(pView);
+#ifdef _DEBUG
+ const auto& ViewDesc = pDSVD3D12->GetDesc();
+ VERIFY( ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Incorrect view type: depth stencil is expected" );
+#endif
+ }
+ else
+ {
+ auto *pDSV = ValidatedCast<SwapChainD3D12Impl>(m_pSwapChain.RawPtr())->GetDepthBufferDSV();
+ pDSVD3D12 = ValidatedCast<ITextureViewD3D12>(pDSV);
+ }
+ D3D12_CLEAR_FLAGS d3d12ClearFlags = (D3D12_CLEAR_FLAGS)0;
+ if( ClearFlags & CLEAR_DEPTH_FLAG ) d3d12ClearFlags |= D3D12_CLEAR_FLAG_DEPTH;
+ if( ClearFlags & CLEAR_STENCIL_FLAG ) d3d12ClearFlags |= D3D12_CLEAR_FLAG_STENCIL;
+ // The full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied??
+ RequestCmdContext()->AsGraphicsContext().ClearDepthStencil( pDSVD3D12, d3d12ClearFlags, fDepth, Stencil );
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::ClearRenderTarget( ITextureView *pView, const float *RGBA )
+ {
+ ITextureViewD3D12 *pd3d12RTV = nullptr;
+ if( pView != nullptr )
+ {
+#ifdef _DEBUG
+ const auto& ViewDesc = pView->GetDesc();
+ VERIFY( ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET, "Incorrect view type: render target is expected" );
+#endif
+ pd3d12RTV = ValidatedCast<ITextureViewD3D12>(pView);
+ }
+ else
+ {
+ auto *pBackBufferRTV = ValidatedCast<SwapChainD3D12Impl>(m_pSwapChain.RawPtr())->GetCurrentBackBufferRTV();
+ pd3d12RTV = ValidatedCast<ITextureViewD3D12>(pBackBufferRTV);
+ }
+
+ static const float Zero[4] = { 0.f, 0.f, 0.f, 0.f };
+ if( RGBA == nullptr )
+ RGBA = Zero;
+
+ // The full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied??
+ RequestCmdContext()->AsGraphicsContext().ClearRenderTarget( pd3d12RTV, RGBA );
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx)
+ {
+ if( m_pCurrCmdCtx )
+ {
+ VERIFY(!m_bIsDeferred, "Deferred contexts cannot executre command lists directly");
+ ValidatedCast<RenderDeviceD3D12Impl>(m_pDevice.RawPtr())->CloseAndExecuteCommandContext(m_pCurrCmdCtx);
+ }
+
+ m_pCurrCmdCtx = RequestNewCmdCtx ? ValidatedCast<RenderDeviceD3D12Impl>(m_pDevice.RawPtr())->AllocateCommandContext() : nullptr;
+ m_NumCommandsInCurCtx = 0;
+
+ m_pPipelineState.Release();
+ }
+
+ void DeviceContextD3D12Impl::Flush()
+ {
+ VERIFY(!m_bIsDeferred, "Flush() should only be called for immediate contexts");
+ Flush(true);
+ }
+
+ void DeviceContextD3D12Impl::SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer **ppBuffers, Uint32 *pStrides, Uint32 *pOffsets, Uint32 Flags )
+ {
+ TDeviceContextBase::SetVertexBuffers( StartSlot, NumBuffersSet, ppBuffers, pStrides, pOffsets, Flags );
+ m_bCommittedD3D12VBsUpToDate = false;
+ }
+
+ void DeviceContextD3D12Impl::ClearState()
+ {
+ TDeviceContextBase::ClearState();
+ LOG_ERROR_ONCE("DeviceContextD3D12Impl::ClearState() is not implemented");
+ }
+
+ void DeviceContextD3D12Impl::SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset )
+ {
+ TDeviceContextBase::SetIndexBuffer( pIndexBuffer, ByteOffset );
+ m_bCommittedD3D12IBUpToDate = false;
+ }
+
+ void DeviceContextD3D12Impl::CommitViewports()
+ {
+ const Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ D3D12_VIEWPORT d3d12Viewports[MaxViewports]; // Do not waste time initializing array to zero
+
+ for( Uint32 vp = 0; vp < m_NumViewports; ++vp )
+ {
+ d3d12Viewports[vp].TopLeftX = m_Viewports[vp].TopLeftX;
+ d3d12Viewports[vp].TopLeftY = m_Viewports[vp].TopLeftY;
+ d3d12Viewports[vp].Width = m_Viewports[vp].Width;
+ d3d12Viewports[vp].Height = m_Viewports[vp].Height;
+ d3d12Viewports[vp].MinDepth = m_Viewports[vp].MinDepth;
+ d3d12Viewports[vp].MaxDepth = m_Viewports[vp].MaxDepth;
+ }
+ // All viewports must be set atomically as one operation.
+ // Any viewports not defined by the call are disabled.
+ RequestCmdContext()->AsGraphicsContext().SetViewports( m_NumViewports, d3d12Viewports );
+ }
+
+ void DeviceContextD3D12Impl::SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )
+ {
+ const Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ VERIFY( NumViewports < MaxViewports, "Too many viewports are being set" );
+ NumViewports = std::min( NumViewports, MaxViewports );
+
+ TDeviceContextBase::SetViewports( NumViewports, pViewports, RTWidth, RTHeight );
+ VERIFY( NumViewports == m_NumViewports, "Unexpected number of viewports" );
+
+ CommitViewports();
+ }
+
+ void DeviceContextD3D12Impl::SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )
+ {
+ const Uint32 MaxScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ VERIFY( NumRects < MaxScissorRects, "Too many scissor rects are being set" );
+ NumRects = std::min( NumRects, MaxScissorRects );
+
+ TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
+
+ // Only commit scissor rects if scissor test is enabled in the rasterizer state.
+ if( !m_pPipelineState || m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable )
+ {
+ D3D12_RECT d3d12ScissorRects[MaxScissorRects];
+ VERIFY( NumRects == m_NumScissorRects, "Unexpected number of scissor rects" );
+ for( Uint32 sr = 0; sr < NumRects; ++sr )
+ {
+ d3d12ScissorRects[sr].left = m_ScissorRects[sr].left;
+ d3d12ScissorRects[sr].top = m_ScissorRects[sr].top;
+ d3d12ScissorRects[sr].right = m_ScissorRects[sr].right;
+ d3d12ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
+ }
+ RequestCmdContext()->AsGraphicsContext().SetScissorRects(NumRects, d3d12ScissorRects);
+ }
+ }
+
+
+ void DeviceContextD3D12Impl::RebindRenderTargets()
+ {
+ const Uint32 MaxD3D12RTs = D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ Uint32 NumRenderTargets = m_NumBoundRenderTargets;
+ VERIFY( NumRenderTargets <= MaxD3D12RTs, "D3D12 only allows 8 simultaneous render targets" );
+ NumRenderTargets = std::min( MaxD3D12RTs, NumRenderTargets );
+
+ ITextureViewD3D12 *ppRTVs[MaxD3D12RTs]; // Do not initialize with zeroes!
+ ITextureViewD3D12 *pDSV = nullptr;
+ if( NumRenderTargets == 0 && m_pBoundDepthStencil == nullptr )
+ {
+ NumRenderTargets = 1;
+ auto *pSwapChainD3D12 = ValidatedCast<SwapChainD3D12Impl>( m_pSwapChain.RawPtr() );
+ ppRTVs[0] = ValidatedCast<ITextureViewD3D12>(pSwapChainD3D12->GetCurrentBackBufferRTV());
+ pDSV = ValidatedCast<ITextureViewD3D12>(pSwapChainD3D12->GetDepthBufferDSV());
+ }
+ else
+ {
+ for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
+ ppRTVs[rt] = ValidatedCast<ITextureViewD3D12>(m_pBoundRenderTargets[rt].RawPtr());
+ pDSV = ValidatedCast<ITextureViewD3D12>(m_pBoundDepthStencil.RawPtr());
+ }
+ RequestCmdContext()->AsGraphicsContext().SetRenderTargets(NumRenderTargets, ppRTVs, pDSV);
+ }
+
+ void DeviceContextD3D12Impl::SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil )
+ {
+ if( TDeviceContextBase::SetRenderTargets( NumRenderTargets, ppRenderTargets, pDepthStencil ) )
+ {
+ RebindRenderTargets();
+
+ // Set the viewport to match the render target size
+ SetViewports(1, nullptr, 0, 0);
+ }
+ }
+
+ DynamicAllocation DeviceContextD3D12Impl::AllocateDynamicSpace(size_t NumBytes)
+ {
+ return m_pUploadHeap->Allocate(NumBytes);
+ }
+
+ void DeviceContextD3D12Impl::UpdateBufferRegion(BufferD3D12Impl *pBuffD3D12, const void *pData, Uint64 DstOffset, Uint64 NumBytes)
+ {
+ VERIFY(pBuffD3D12->GetDesc().Usage != USAGE_DYNAMIC, "Dynamic buffers must be updated via Map()")
+
+ auto pCmdCtx = RequestCmdContext();
+//#if USE_RING_BUFFER
+ //auto TmpSpace = pCmdCtx->AllocateUploadBuffer(NumBytes);
+ auto TmpSpace = m_pUploadHeap->Allocate(NumBytes);
+ memcpy(TmpSpace.CPUAddress, pData, NumBytes);
+ pCmdCtx->TransitionResource(pBuffD3D12, D3D12_RESOURCE_STATE_COPY_DEST, true);
+ // Source buffer is already in right state, which cannot be changed
+ size_t DstBuffDataStartByteOffset;
+ auto *pd3d12Buff = pBuffD3D12->GetD3D12Buffer(DstBuffDataStartByteOffset, m_ContextId);
+ VERIFY(DstBuffDataStartByteOffset == 0, "Dst buffer must not be suballocated");
+ pCmdCtx->GetCommandList()->CopyBufferRegion( pd3d12Buff, DstOffset + DstBuffDataStartByteOffset, TmpSpace.pBuffer, TmpSpace.Offset, NumBytes);
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::CopyBufferRegion(BufferD3D12Impl *pSrcBuffD3D12, BufferD3D12Impl *pDstBuffD3D12, Uint64 SrcOffset, Uint64 DstOffset, Uint64 NumBytes)
+ {
+ VERIFY(pDstBuffD3D12->GetDesc().Usage != USAGE_DYNAMIC, "Dynamic buffers cannot be copy destinations")
+
+ auto pCmdCtx = RequestCmdContext();
+ pCmdCtx->TransitionResource(pSrcBuffD3D12, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ pCmdCtx->TransitionResource(pDstBuffD3D12, D3D12_RESOURCE_STATE_COPY_DEST, true);
+ size_t DstDataStartByteOffset;
+ auto *pd3d12DstBuff = pDstBuffD3D12->GetD3D12Buffer(DstDataStartByteOffset, m_ContextId);
+ VERIFY(DstDataStartByteOffset == 0, "Dst buffer must not be suballocated");
+
+ size_t SrcDataStartByteOffset;
+ auto *pd3d12SrcBuff = pSrcBuffD3D12->GetD3D12Buffer(SrcDataStartByteOffset, m_ContextId);
+ pCmdCtx->GetCommandList()->CopyBufferRegion( pd3d12DstBuff, DstOffset + DstDataStartByteOffset, pd3d12SrcBuff, SrcOffset+SrcDataStartByteOffset, NumBytes);
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::CopyTextureRegion(TextureD3D12Impl *pSrcTexture, Uint32 SrcSubResIndex, const D3D12_BOX *pD3D12SrcBox,
+ TextureD3D12Impl *pDstTexture, Uint32 DstSubResIndex, Uint32 DstX, Uint32 DstY, Uint32 DstZ)
+ {
+ auto pCmdCtx = RequestCmdContext();
+ pCmdCtx->TransitionResource(pSrcTexture, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ pCmdCtx->TransitionResource(pDstTexture, D3D12_RESOURCE_STATE_COPY_DEST, true);
+
+ D3D12_TEXTURE_COPY_LOCATION DstLocation = {}, SrcLocation = {};
+
+ DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ DstLocation.pResource = pDstTexture->GetD3D12Resource();
+ DstLocation.SubresourceIndex = SrcSubResIndex;
+
+ SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ SrcLocation.pResource = pSrcTexture->GetD3D12Resource();
+ SrcLocation.SubresourceIndex = DstSubResIndex;
+
+ pCmdCtx->GetCommandList()->CopyTextureRegion( &DstLocation, DstX, DstY, DstZ, &SrcLocation, pD3D12SrcBox);
+ ++m_NumCommandsInCurCtx;
+ }
+
+ void DeviceContextD3D12Impl::GenerateMips(TextureViewD3D12Impl *pTexView)
+ {
+ auto *pCtx = RequestCmdContext();
+ m_MipsGenerator.GenerateMips(ValidatedCast<RenderDeviceD3D12Impl>(m_pDevice.RawPtr()), pTexView, *pCtx);
+ }
+
+ void DeviceContextD3D12Impl::FinishCommandList(class ICommandList **ppCommandList)
+ {
+ CommandListD3D12Impl *pCmdListD3D12( NEW(m_CmdListAllocator, "CommandListD3D12Impl instance", CommandListD3D12Impl, m_pDevice, m_pCurrCmdCtx) );
+ pCmdListD3D12->QueryInterface( IID_CommandList, reinterpret_cast<IObject**>(ppCommandList) );
+ m_pCurrCmdCtx = nullptr;
+ Flush(true);
+ }
+
+ void DeviceContextD3D12Impl::ExecuteCommandList(class ICommandList *pCommandList)
+ {
+ if (m_bIsDeferred)
+ {
+ LOG_ERROR("Only immediate context can execute command list");
+ return;
+ }
+ // First execute commands in this context
+ Flush(true);
+
+ CommandListD3D12Impl* pCmdListD3D12 = ValidatedCast<CommandListD3D12Impl>(pCommandList);
+ ValidatedCast<RenderDeviceD3D12Impl>(m_pDevice.RawPtr())->CloseAndExecuteCommandContext(pCmdListD3D12->Close());
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/DynamicUploadHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DynamicUploadHeap.cpp
new file mode 100644
index 00000000..c747a731
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/DynamicUploadHeap.cpp
@@ -0,0 +1,152 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DynamicUploadHeap.h"
+#include "RenderDeviceD3D12Impl.h"
+
+namespace Diligent
+{
+ GPURingBuffer::GPURingBuffer(size_t MaxSize, IMemoryAllocator &Allocator, ID3D12Device *pd3d12Device, bool AllowCPUAccess) :
+ RingBuffer(MaxSize, Allocator),
+ m_CpuVirtualAddress(nullptr),
+ m_GpuVirtualAddress(0)
+ {
+ D3D12_HEAP_PROPERTIES HeapProps;
+ HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ HeapProps.CreationNodeMask = 1;
+ HeapProps.VisibleNodeMask = 1;
+
+ D3D12_RESOURCE_DESC ResourceDesc;
+ ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ ResourceDesc.Alignment = 0;
+ ResourceDesc.Height = 1;
+ ResourceDesc.DepthOrArraySize = 1;
+ ResourceDesc.MipLevels = 1;
+ ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ ResourceDesc.SampleDesc.Count = 1;
+ ResourceDesc.SampleDesc.Quality = 0;
+ ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+
+ D3D12_RESOURCE_STATES DefaultUsage;
+ if (AllowCPUAccess)
+ {
+ HeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ DefaultUsage = D3D12_RESOURCE_STATE_GENERIC_READ;
+ }
+ else
+ {
+ HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+ DefaultUsage = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+ }
+ ResourceDesc.Width = MaxSize;
+
+ auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,
+ DefaultUsage, nullptr, __uuidof(m_pBuffer), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pBuffer)) );
+ if(FAILED(hr))
+ LOG_ERROR("Failed to create new upload ring buffer")
+
+ m_pBuffer->SetName(L"Upload Ring Buffer");
+
+ m_GpuVirtualAddress = m_pBuffer->GetGPUVirtualAddress();
+
+ if (AllowCPUAccess)
+ {
+ m_pBuffer->Map(0, nullptr, &m_CpuVirtualAddress);
+ }
+ }
+
+ void GPURingBuffer::Destroy()
+ {
+ if (m_CpuVirtualAddress)
+ {
+ m_pBuffer->Unmap(0, nullptr);
+ }
+ m_CpuVirtualAddress = 0;
+ m_GpuVirtualAddress = 0;
+ m_pBuffer.Release();
+ }
+
+ GPURingBuffer::~GPURingBuffer()
+ {
+ Destroy();
+ }
+
+ DynamicUploadHeap::DynamicUploadHeap(IMemoryAllocator &Allocator, bool bIsCPUAccessible, class RenderDeviceD3D12Impl* pDevice, size_t InitialSize) :
+ m_Allocator(Allocator),
+ m_pDeviceD3D12(pDevice),
+ m_bIsCPUAccessible(bIsCPUAccessible),
+ m_RingBuffers(STD_ALLOCATOR_RAW_MEM(GPURingBuffer, GetRawAllocator(), "Allocator for vector<GPURingBuffer>"))
+ {
+ m_RingBuffers.emplace_back(InitialSize, Allocator, pDevice->GetD3D12Device(), m_bIsCPUAccessible);
+ }
+
+ DynamicAllocation DynamicUploadHeap::Allocate(size_t SizeInBytes, size_t Alignment /*= DEFAULT_ALIGN*/)
+ {
+ // This is very expensive! Currently other threads cannot allocate dynamic
+ // data while frame is being finished.
+
+ //std::lock_guard<std::mutex> Lock(m_Mutex);
+
+ const size_t AlignmentMask = Alignment - 1;
+ // Assert that it's a power of two.
+ VERIFY_EXPR((AlignmentMask & Alignment) == 0);
+ // Align the allocation
+ const size_t AlignedSize = (SizeInBytes + AlignmentMask) & ~AlignmentMask;
+ auto DynAlloc = m_RingBuffers.back().Allocate(AlignedSize);
+ if (!DynAlloc.pBuffer)
+ {
+ auto NewMaxSize = m_RingBuffers.back().GetMaxSize() * 2;
+ while(NewMaxSize < SizeInBytes)NewMaxSize*=2;
+ m_RingBuffers.emplace_back(NewMaxSize, m_Allocator, m_pDeviceD3D12->GetD3D12Device(), m_bIsCPUAccessible);
+ DynAlloc = m_RingBuffers.back().Allocate(AlignedSize);
+ }
+#ifdef _DEBUG
+ DynAlloc.FrameNum = m_pDeviceD3D12->GetCurrentFrame();
+#endif
+ return DynAlloc;
+ }
+
+ void DynamicUploadHeap::FinishFrame(Uint64 FrameNum, Uint64 NumCompletedFrames)
+ {
+ //std::lock_guard<std::mutex> Lock(m_Mutex);
+
+ size_t NumBuffsToDelete = 0;
+ for(size_t Ind = 0; Ind < m_RingBuffers.size(); ++Ind)
+ {
+ auto &RingBuff = m_RingBuffers[Ind];
+ RingBuff.FinishCurrentFrame(FrameNum);
+ RingBuff.ReleaseCompletedFrames(NumCompletedFrames);
+ if ( NumBuffsToDelete == Ind && Ind < m_RingBuffers.size()-1 && RingBuff.IsEmpty())
+ {
+ ++NumBuffsToDelete;
+ }
+ }
+
+ if(NumBuffsToDelete)
+ m_RingBuffers.erase(m_RingBuffers.begin(), m_RingBuffers.begin()+NumBuffsToDelete);
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
new file mode 100644
index 00000000..ee382930
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp
@@ -0,0 +1,185 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+// The source code in this file is derived from ColorBuffer.cpp and GraphicsCore.cpp developed by Minigraph
+// Original source files header:
+
+//
+// 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.
+//
+// Developed by Minigraph
+//
+// Author: James Stanard
+//
+
+
+#include "pch.h"
+#include "d3dx12_win.h"
+
+#include "RenderDeviceD3D12Impl.h"
+#include "GenerateMips.h"
+#include "CommandContext.h"
+#include "TextureViewD3D12Impl.h"
+#include "TextureD3D12Impl.h"
+
+#include "GenerateMips/GenerateMipsLinearCS.h"
+#include "GenerateMips/GenerateMipsLinearOddCS.h"
+#include "GenerateMips/GenerateMipsLinearOddXCS.h"
+#include "GenerateMips/GenerateMipsLinearOddYCS.h"
+#include "GenerateMips/GenerateMipsGammaCS.h"
+#include "GenerateMips/GenerateMipsGammaOddCS.h"
+#include "GenerateMips/GenerateMipsGammaOddXCS.h"
+#include "GenerateMips/GenerateMipsGammaOddYCS.h"
+
+namespace Diligent
+{
+ GenerateMipsHelper::GenerateMipsHelper(ID3D12Device *pd3d12Device)
+ {
+ CD3DX12_ROOT_PARAMETER Params[3];
+ Params[0].InitAsConstants(4, 0);
+ CD3DX12_DESCRIPTOR_RANGE SRVRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
+ Params[1].InitAsDescriptorTable(1, &SRVRange);
+ CD3DX12_DESCRIPTOR_RANGE UAVRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 4, 0);
+ Params[2].InitAsDescriptorTable(1, &UAVRange);
+ CD3DX12_STATIC_SAMPLER_DESC SamplerLinearClampDesc(
+ 0, D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
+ CD3DX12_ROOT_SIGNATURE_DESC RootSigDesc;
+ RootSigDesc.NumParameters = _countof(Params);
+ RootSigDesc.pParameters = Params;
+ RootSigDesc.NumStaticSamplers = 1;
+ RootSigDesc.pStaticSamplers = &SamplerLinearClampDesc;
+ RootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
+
+ CComPtr<ID3DBlob> signature;
+ CComPtr<ID3DBlob> error;
+ HRESULT hr = D3D12SerializeRootSignature(&RootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
+ hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pGenerateMipsRS), reinterpret_cast<void**>( static_cast<ID3D12RootSignature**>(&m_pGenerateMipsRS)));
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature for mipmap generation")
+
+ D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc = {};
+ PSODesc.pRootSignature = m_pGenerateMipsRS;
+ PSODesc.NodeMask = 0;
+ PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+
+#define CreatePSO(PSO, ShaderByteCode) \
+ PSODesc.CS.pShaderBytecode = ShaderByteCode;\
+ PSODesc.CS.BytecodeLength = sizeof(ShaderByteCode);\
+ hr = pd3d12Device->CreateComputePipelineState(&PSODesc, __uuidof(PSO), reinterpret_cast<void**>( static_cast<ID3D12PipelineState**>(&PSO))); \
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create Pipeline state for mipmap generation")
+
+ CreatePSO(m_pGenerateMipsLinearPSO[0], g_pGenerateMipsLinearCS);
+ CreatePSO(m_pGenerateMipsLinearPSO[1], g_pGenerateMipsLinearOddXCS);
+ CreatePSO(m_pGenerateMipsLinearPSO[2], g_pGenerateMipsLinearOddYCS);
+ CreatePSO(m_pGenerateMipsLinearPSO[3], g_pGenerateMipsLinearOddCS);
+ CreatePSO(m_pGenerateMipsGammaPSO[0], g_pGenerateMipsGammaCS);
+ CreatePSO(m_pGenerateMipsGammaPSO[1], g_pGenerateMipsGammaOddXCS);
+ CreatePSO(m_pGenerateMipsGammaPSO[2], g_pGenerateMipsGammaOddYCS);
+ CreatePSO(m_pGenerateMipsGammaPSO[3], g_pGenerateMipsGammaOddCS);
+ }
+
+ void GenerateMipsHelper::GenerateMips(RenderDeviceD3D12Impl *pRenderDeviceD3D12, TextureViewD3D12Impl *pTexView, CommandContext& Ctx)
+ {
+ auto &ComputeCtx = Ctx.AsComputeContext();
+ ComputeCtx.SetRootSignature(m_pGenerateMipsRS);
+ auto *pTexture = pTexView->GetTexture();
+ auto *pTexD3D12 = ValidatedCast<TextureD3D12Impl>( pTexture );
+ auto &TexDesc = pTexture->GetDesc();
+ auto *pSRV = pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
+ auto *pSRVD3D12Impl = ValidatedCast<TextureViewD3D12Impl>(pSRV);
+ auto SRVDescriptorHandle = pSRVD3D12Impl->GetCPUDescriptorHandle();
+
+ Ctx.TransitionResource(pTexD3D12, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ auto *pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
+
+ for (uint32_t TopMip = 0; TopMip < TexDesc.MipLevels-1; )
+ {
+ uint32_t SrcWidth = TexDesc.Width >> TopMip;
+ uint32_t SrcHeight = TexDesc.Height >> TopMip;
+ uint32_t DstWidth = SrcWidth >> 1;
+ uint32_t DstHeight = SrcHeight >> 1;
+
+ // Determine if the first downsample is more than 2:1. This happens whenever
+ // the source width or height is odd.
+ uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;
+ if (TexDesc.Format == TEX_FORMAT_RGBA8_UNORM_SRGB)
+ ComputeCtx.SetPipelineState(m_pGenerateMipsGammaPSO[NonPowerOfTwo]);
+ else
+ ComputeCtx.SetPipelineState(m_pGenerateMipsLinearPSO[NonPowerOfTwo]);
+
+ // We can downsample up to four times, but if the ratio between levels is not
+ // exactly 2:1, we have to shift our blend weights, which gets complicated or
+ // expensive. Maybe we can update the code later to compute sample weights for
+ // each successive downsample. We use _BitScanForward to count number of zeros
+ // in the low bits. Zeros indicate we can divide by two without truncating.
+ uint32_t AdditionalMips;
+ _BitScanForward((unsigned long*)&AdditionalMips, DstWidth | DstHeight);
+ uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);
+ if (TopMip + NumMips > TexDesc.MipLevels-1)
+ NumMips = TexDesc.MipLevels-1 - TopMip;
+
+ // These are clamped to 1 after computing additional mips because clamped
+ // dimensions should not limit us from downsampling multiple times. (E.g.
+ // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)
+ if (DstWidth == 0)
+ DstWidth = 1;
+ if (DstHeight == 0)
+ DstHeight = 1;
+
+ D3D12_DESCRIPTOR_HEAP_TYPE HeapType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ auto DescriptorAlloc = Ctx.AllocateDynamicGPUVisibleDescriptor(HeapType, 5);
+ CommandContext::ShaderDescriptorHeaps Heaps(DescriptorAlloc.GetDescriptorHeap());
+ ComputeCtx.SetDescriptorHeaps(Heaps);
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(1, DescriptorAlloc.GetGpuHandle(0));
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(2, DescriptorAlloc.GetGpuHandle(1));
+ struct RootCBData
+ {
+ Uint32 SrcMipLevel; // Texture level of source mip
+ Uint32 NumMipLevels; // Number of OutMips to write: [1, 4]
+ float TexelSize[2]; // 1.0 / OutMip1.Dimensions
+ }CBData = {TopMip, NumMips, 1.0f / static_cast<float>(DstWidth), 1.0f / static_cast<float>(DstHeight)};
+ Ctx.GetCommandList()->SetComputeRoot32BitConstants(0, 4, &CBData, 0);
+
+ // TODO: Shouldn't we transition top mip to shader resource state?
+ D3D12_CPU_DESCRIPTOR_HANDLE DstDescriptorRange = DescriptorAlloc.GetCpuHandle();
+ UINT DstRangeSize = 1+NumMips;
+ D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRanges[5] = {};
+ SrcDescriptorRanges[0] = SRVDescriptorHandle;
+ UINT SrcRangeSizes[5] = {1,1,1,1,1};
+ for(Uint32 u=0; u < NumMips; ++u)
+ SrcDescriptorRanges[1+u] = pTexD3D12->GetUAVDescriptorHandle(TopMip+u+1, 0);
+
+ pd3d12Device->CopyDescriptors(1, &DstDescriptorRange, &DstRangeSize, 1+NumMips, SrcDescriptorRanges, SrcRangeSizes, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ ComputeCtx.Dispatch((DstWidth+7)/8, (DstHeight+7)/8);
+
+ Ctx.InsertUAVBarrier(*pTexD3D12, *pTexD3D12);
+
+ TopMip += NumMips;
+ }
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/GraphicsEngineD3D12.def b/Graphics/GraphicsEngineD3D12/src/GraphicsEngineD3D12.def
new file mode 100644
index 00000000..79094c73
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/GraphicsEngineD3D12.def
@@ -0,0 +1,3 @@
+EXPORTS
+ CreateDeviceAndContextsD3D12
+ CreateSwapChainD3D12 \ No newline at end of file
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
new file mode 100644
index 00000000..c2ed2d83
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -0,0 +1,335 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "PipelineStateD3D12Impl.h"
+#include "ShaderD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DXGITypeConversions.h"
+#include "ShaderResourceBindingD3D12Impl.h"
+#include "CommandContext.h"
+#include "EngineMemory.h"
+
+namespace Diligent
+{
+
+D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE( PRIMITIVE_TOPOLOGY_TYPE TopologyType )
+{
+ static bool bIsInit = false;
+ static D3D12_PRIMITIVE_TOPOLOGY_TYPE D3D12TopologyType[PRIMITIVE_TOPOLOGY_TYPE_NUM_TYPES] = {};
+ if( !bIsInit )
+ {
+ D3D12TopologyType[ PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED] = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED;
+ D3D12TopologyType[ PRIMITIVE_TOPOLOGY_TYPE_POINT ] = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
+ D3D12TopologyType[ PRIMITIVE_TOPOLOGY_TYPE_LINE ] = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
+ D3D12TopologyType[ PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE ] = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ D3D12TopologyType[ PRIMITIVE_TOPOLOGY_TYPE_PATCH ] = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
+
+ bIsInit = true;
+ }
+
+ if( TopologyType >= PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED && TopologyType < PRIMITIVE_TOPOLOGY_TYPE_NUM_TYPES )
+ {
+ auto d3d12TopType = D3D12TopologyType[TopologyType];
+ return d3d12TopType;
+ }
+ else
+ {
+ UNEXPECTED( "Incorrect topology type operation (", TopologyType, ")" )
+ return static_cast<D3D12_PRIMITIVE_TOPOLOGY_TYPE>(0);
+ }
+}
+
+void PipelineStateD3D12Impl::ParseShaderResourceLayout(IShader *pShader)
+{
+ VERIFY_EXPR(pShader);
+
+ auto ShaderType = pShader->GetDesc().ShaderType;
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto *pShaderD3D12 = ValidatedCast<ShaderD3D12Impl>(pShader);
+
+ VERIFY(m_pShaderResourceLayouts[ShaderInd] == nullptr, "Shader resource layout has already been initialized");
+
+ auto pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pShaderD3D12->GetDevice());
+ auto &ShaderResLayoutAllocator = GetRawAllocator();
+
+ auto *pRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutD3D12", sizeof(ShaderResourceLayoutD3D12));
+ m_pShaderResourceLayouts[ShaderInd] = new (pRawMem) ShaderResourceLayoutD3D12(*this, GetRawAllocator());
+ m_pShaderResourceLayouts[ShaderInd]->Initialize(pDeviceD3D12Impl->GetD3D12Device(), pShaderD3D12->GetShaderResources(), GetRawAllocator(), nullptr, 0, nullptr, &m_RootSig);
+}
+
+PipelineStateD3D12Impl :: PipelineStateD3D12Impl(FixedBlockMemoryAllocator &PSOAllocator, RenderDeviceD3D12Impl *pDeviceD3D12, const PipelineStateDesc &PipelineDesc) :
+ TPipelineStateBase(PSOAllocator, pDeviceD3D12, PipelineDesc),
+ m_DummyVar(*this),
+ m_ResourceCacheDataAllocator(GetRawAllocator(), PipelineDesc.SRBAllocationGranularity),
+ m_ShaderResLayoutDataAllocators
+ {
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ {GetRawAllocator(), PipelineDesc.SRBAllocationGranularity},
+ },
+ m_pDefaultShaderResBinding(nullptr, STDDeleter<ShaderResourceBindingD3D12Impl, FixedBlockMemoryAllocator>(pDeviceD3D12->GetSRBAllocator()) )
+{
+ auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
+ if (PipelineDesc.IsComputePipeline)
+ {
+ auto &ComputePipeline = PipelineDesc.ComputePipeline;
+
+ if( ComputePipeline.pCS == nullptr )
+ LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
+
+ D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {};
+ d3d12PSODesc.pRootSignature = nullptr;
+
+ auto *pByteCode = ValidatedCast<ShaderD3D12Impl>(ComputePipeline.pCS)->GetShaderByteCode();
+ d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer();
+ d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize();
+
+ // For single GPU operation, set this to zero. If there are multiple GPU nodes,
+ // set bits to identify the nodes (the device's physical adapters) for which the
+ // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node.
+ d3d12PSODesc.NodeMask = 0;
+
+ d3d12PSODesc.CachedPSO.pCachedBlob = nullptr;
+ d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0;
+
+ // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices.
+ d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+
+ ParseShaderResourceLayout(ComputePipeline.pCS);
+ m_RootSig.Finalize(pd3d12Device);
+ d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature();
+
+ HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>( static_cast<ID3D12PipelineState**>(&m_pd3d12PSO)) );
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create pipeline state");
+ }
+ else
+ {
+ const auto& GraphicsPipeline = PipelineDesc.GraphicsPipeline;
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {};
+
+ m_RootSig.AllocateStaticSamplers( GetShaders(), GetNumShaders() );
+
+#define INIT_SHADER(VarName, ExpectedType)\
+ if (GraphicsPipeline.p##VarName) \
+ { \
+ auto ShaderType = GraphicsPipeline.p##VarName->GetDesc().ShaderType; \
+ if( ShaderType != ExpectedType ) \
+ LOG_ERROR_AND_THROW( GetShaderTypeLiteralName(ShaderType), " shader is provided while ", GetShaderTypeLiteralName(ExpectedType), " is expected") \
+ auto *pByteCode = ValidatedCast<ShaderD3D12Impl>(GraphicsPipeline.p##VarName)->GetShaderByteCode(); \
+ d3d12PSODesc.VarName.pShaderBytecode = pByteCode->GetBufferPointer(); \
+ d3d12PSODesc.VarName.BytecodeLength = pByteCode->GetBufferSize(); \
+ ParseShaderResourceLayout(GraphicsPipeline.p##VarName); \
+ } \
+ else \
+ { \
+ d3d12PSODesc.VarName.pShaderBytecode = nullptr; \
+ d3d12PSODesc.VarName.BytecodeLength = 0; \
+ }
+
+ INIT_SHADER(VS, SHADER_TYPE_VERTEX);
+ INIT_SHADER(PS, SHADER_TYPE_PIXEL);
+ INIT_SHADER(GS, SHADER_TYPE_GEOMETRY);
+ INIT_SHADER(DS, SHADER_TYPE_DOMAIN);
+ INIT_SHADER(HS, SHADER_TYPE_HULL);
+#undef INIT_SHADER
+
+ m_RootSig.Finalize(pd3d12Device);
+ d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature();
+
+ memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput));
+
+ BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState);
+ // The sample mask for the blend state.
+ d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask;
+
+ RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState);
+ DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState);
+
+ std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements( STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>") );
+ if (m_LayoutElements.size() > 0)
+ {
+ LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(m_LayoutElements, d312InputElements);
+ d3d12PSODesc.InputLayout.NumElements = static_cast<UINT>(d312InputElements.size());
+ d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data();
+ }
+ else
+ {
+ d3d12PSODesc.InputLayout.NumElements = 0;
+ d3d12PSODesc.InputLayout.pInputElementDescs = nullptr;
+ }
+
+ d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
+ d3d12PSODesc.PrimitiveTopologyType = PrimitiveTopologyType_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE(GraphicsPipeline.PrimitiveTopologyType);
+
+ d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets;
+ for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt)
+ d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]);
+ for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < 8; ++rt)
+ d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]);
+ d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat);
+
+ d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count;
+ d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality;
+
+ // For single GPU operation, set this to zero. If there are multiple GPU nodes,
+ // set bits to identify the nodes (the device's physical adapters) for which the
+ // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node.
+ d3d12PSODesc.NodeMask = 0;
+
+ d3d12PSODesc.CachedPSO.pCachedBlob = nullptr;
+ d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0;
+
+ // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices.
+ d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+
+ HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>( static_cast<ID3D12PipelineState**>(&m_pd3d12PSO)) );
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create pipeline state");
+ }
+
+ auto &SRBAllocator = pDeviceD3D12->GetSRBAllocator();
+ // Default shader resource binding must be initialized after resource layouts are parsed!
+ m_pDefaultShaderResBinding.reset( NEW(SRBAllocator, "ShaderResourceBindingD3D12Impl instance", ShaderResourceBindingD3D12Impl, this, true) );
+}
+
+PipelineStateD3D12Impl::~PipelineStateD3D12Impl()
+{
+ auto &ShaderResLayoutAllocator = GetRawAllocator();
+ for(Int32 l = 0; l < _countof(m_pShaderResourceLayouts); ++l)
+ {
+ if (m_pShaderResourceLayouts[l] != nullptr)
+ {
+ m_pShaderResourceLayouts[l]->~ShaderResourceLayoutD3D12();
+ ShaderResLayoutAllocator.Free(m_pShaderResourceLayouts[l]);
+ }
+ }
+
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12Impl->SafeReleaseD3D12Object(m_pd3d12PSO);
+}
+
+IMPLEMENT_QUERY_INTERFACE( PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase )
+
+void PipelineStateD3D12Impl::BindShaderResources(IResourceMapping *pResourceMapping, Uint32 Flags)
+{
+ if( m_Desc.IsComputePipeline )
+ {
+ if(m_pCS)m_pCS->BindResources(pResourceMapping, Flags);
+ }
+ else
+ {
+ if(m_pVS)m_pVS->BindResources(pResourceMapping, Flags);
+ if(m_pPS)m_pPS->BindResources(pResourceMapping, Flags);
+ if(m_pGS)m_pGS->BindResources(pResourceMapping, Flags);
+ if(m_pDS)m_pDS->BindResources(pResourceMapping, Flags);
+ if(m_pHS)m_pHS->BindResources(pResourceMapping, Flags);
+ }
+}
+
+void PipelineStateD3D12Impl::CreateShaderResourceBinding(IShaderResourceBinding **ppShaderResourceBinding)
+{
+ auto *pRenderDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( GetDevice() );
+ auto &SRBAllocator = pRenderDeviceD3D12->GetSRBAllocator();
+ auto pResBindingD3D12 = NEW(SRBAllocator, "ShaderResourceBindingD3D12Impl instance", ShaderResourceBindingD3D12Impl, this, false);
+ pResBindingD3D12->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(ppShaderResourceBinding));
+}
+
+const ShaderResourceLayoutD3D12& PipelineStateD3D12Impl::GetShaderResLayout(SHADER_TYPE ShaderType)const
+{
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ VERIFY_EXPR(m_pShaderResourceLayouts[ShaderInd] != nullptr)
+ return *m_pShaderResourceLayouts[ShaderInd];
+}
+
+ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResources(IShaderResourceBinding *pShaderResourceBinding,
+ CommandContext &Ctx,
+ bool CommitResources,
+ bool TransitionResources)const
+{
+#ifdef VERIFY_SHADER_BINDINGS
+ if (pShaderResourceBinding == nullptr &&
+ (m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_MUTABLE) != 0 ||
+ m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_DYNAMIC) != 0))
+ {
+ LOG_ERROR_MESSAGE("Pipeline state \"", m_Desc.Name, "\" contains mutable/dynamic shader variables and requires shader resource binding to commit all resources, but none is provided.")
+ }
+#endif
+
+ auto *pResBindingD3D12Impl = pShaderResourceBinding ? ValidatedCast<ShaderResourceBindingD3D12Impl>(pShaderResourceBinding) : m_pDefaultShaderResBinding.get();
+
+#ifdef VERIFY_SHADER_BINDINGS
+ {
+ auto *pRefPSO = pResBindingD3D12Impl->GetPipelineState();
+ if (pRefPSO != this)
+ {
+ LOG_ERROR_MESSAGE("Shader resource binding does not match the pipeline state \"", m_Desc.Name, "\". Operation will be ignored.");
+ return nullptr;
+ }
+ }
+#endif
+
+ if(!pResBindingD3D12Impl->StaticResourcesInitialized())
+ pResBindingD3D12Impl->InitializeStaticResources(this);
+
+#ifdef VERIFY_SHADER_BINDINGS
+ pResBindingD3D12Impl->dbgVerifyResourceBindings(this);
+#endif
+
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>( GetDevice() );
+ auto &ResourceCache = pResBindingD3D12Impl->GetResourceCache();
+ if(CommitResources)
+ {
+ if(m_Desc.IsComputePipeline)
+ Ctx.AsComputeContext().SetRootSignature( GetD3D12RootSignature() );
+ else
+ Ctx.AsGraphicsContext().SetRootSignature( GetD3D12RootSignature() );
+
+ if(TransitionResources)
+ (m_RootSig.*m_RootSig.TransitionAndCommitDescriptorHandles)(pDeviceD3D12Impl, ResourceCache, Ctx, m_Desc.IsComputePipeline);
+ else
+ (m_RootSig.*m_RootSig.CommitDescriptorHandles)(pDeviceD3D12Impl, ResourceCache, Ctx, m_Desc.IsComputePipeline);
+ }
+ else
+ {
+ VERIFY(TransitionResources, "Resources should be transitioned or committed or both")
+ m_RootSig.TransitionResources(ResourceCache, Ctx);
+ }
+ return &ResourceCache;
+}
+
+
+bool PipelineStateD3D12Impl::dbgContainsShaderResources()const
+{
+ return m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_STATIC) != 0 ||
+ m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_MUTABLE) != 0 ||
+ m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_DYNAMIC) != 0;
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
new file mode 100644
index 00000000..51c89306
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -0,0 +1,509 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "PipelineStateD3D12Impl.h"
+#include "ShaderD3D12Impl.h"
+#include "TextureD3D12Impl.h"
+#include "DXGITypeConversions.h"
+#include "SamplerD3D12Impl.h"
+#include "BufferD3D12Impl.h"
+#include "ShaderResourceBindingD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+
+#include "EngineMemory.h"
+namespace Diligent
+{
+
+RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IMemoryAllocator &RawMemAllocator, const EngineD3D12Attribs &CreationAttribs, ID3D12Device *pd3d12Device, ID3D12CommandQueue *pd3d12CmdQueue, Uint32 NumDeferredContexts) :
+ TRenderDeviceBase(RawMemAllocator, NumDeferredContexts, sizeof(TextureD3D12Impl), sizeof(TextureViewD3D12Impl), sizeof(BufferD3D12Impl), sizeof(BufferViewD3D12Impl), sizeof(ShaderD3D12Impl), sizeof(SamplerD3D12Impl), sizeof(PipelineStateD3D12Impl), sizeof(ShaderResourceBindingD3D12Impl)),
+ m_pd3d12Device(pd3d12Device),
+ m_pd3d12CmdQueue(pd3d12CmdQueue),
+ m_EngineAttribs(CreationAttribs),
+ m_NextFenceValue(1),
+ m_LastCompletedFenceValue(0),
+ m_FenceEventHandle( CreateEvent(nullptr, false, false, nullptr) ),
+ m_CmdListManager(this),
+ m_CPUDescriptorHeaps
+ {
+ {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[2], D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[3], D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}
+ },
+ m_GPUDescriptorHeaps
+ {
+ {RawMemAllocator, this, CreationAttribs.GPUDescriptorHeapSize[0], CreationAttribs.GPUDescriptorHeapDynamicSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE},
+ {RawMemAllocator, this, CreationAttribs.GPUDescriptorHeapSize[1], CreationAttribs.GPUDescriptorHeapDynamicSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE}
+ },
+ m_ContextPool(STD_ALLOCATOR_RAW_MEM(ContextPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<CommandContext>>")),
+ m_AvailableContexts(STD_ALLOCATOR_RAW_MEM(CommandContext*, GetRawAllocator(), "Allocator for vector<CommandContext*>")),
+ m_D3D12ObjReleaseQueue(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),
+ m_UploadHeaps(STD_ALLOCATOR_RAW_MEM(UploadHeapPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<DynamicUploadHeap>>"))
+{
+ m_DeviceCaps.DevType = DeviceType::D3D12;
+ m_DeviceCaps.MajorVersion = 12;
+ m_DeviceCaps.MinorVersion = 0;
+ m_DeviceCaps.bSeparableProgramSupported = True;
+ m_DeviceCaps.bMultithreadedResourceCreationSupported = True;
+
+ VERIFY_EXPR(m_FenceEventHandle != INVALID_HANDLE_VALUE);
+
+ auto hr = pd3d12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(m_pFence), reinterpret_cast<void**>(static_cast<ID3D12Fence**>(&m_pFence)));
+ VERIFY(SUCCEEDED(hr), "Failed to create fence");
+ m_pFence->SetName(L"CommandListManager::m_pFence");
+ m_pFence->Signal(m_LastCompletedFenceValue);
+
+ hr = pd3d12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(m_pNumCompletedFramesFence), reinterpret_cast<void**>(static_cast<ID3D12Fence**>(&m_pNumCompletedFramesFence)));
+ VERIFY(SUCCEEDED(hr), "Failed to create fence");
+ m_pNumCompletedFramesFence->SetName(L"Last completed frame fence");
+ m_pNumCompletedFramesFence->Signal(m_NumCompletedFrames);
+}
+
+RenderDeviceD3D12Impl::~RenderDeviceD3D12Impl()
+{
+ // Finish current frame. This will release resources taken by previous frames, and
+ // will signal current frame as completed. If we do not call FinishFrame(), then
+ // current frame will not be signaled as completed and the second call to FinishFrame()
+ // will not release current frame's resources.
+ FinishFrame();
+ // Wait for the GPU to complete all its operations
+ IdleGPU();
+ // Call FinishFrame() again to release all resources associated with the current frame
+ FinishFrame();
+ CloseHandle(m_FenceEventHandle);
+
+ //LinearAllocator::DestroyAll();
+ //DynamicDescriptorHeap::DestroyAll();
+ m_ContextPool.clear();
+}
+
+void RenderDeviceD3D12Impl::DisposeCommandContext(CommandContext* pCtx)
+{
+ std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
+ m_AvailableContexts.push_back(pCtx);
+}
+
+Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(CommandContext *pCtx)
+{
+ CComPtr<ID3D12CommandAllocator> pAllocator;
+ auto *pCmdList = pCtx->Close(&pAllocator);
+
+ uint64_t FenceValue = 0;
+ {
+ std::lock_guard<std::mutex> LockGuard(m_FenceMutex);
+
+ // Kickoff the command list
+ ID3D12CommandList *const ppCmdLists[] = {pCmdList};
+ m_pd3d12CmdQueue->ExecuteCommandLists(1, ppCmdLists);
+
+ // Signal the next fence value (with the GPU)
+ m_pd3d12CmdQueue->Signal(m_pFence, m_NextFenceValue);
+
+ // And increment the fence value.
+ FenceValue = m_NextFenceValue++;
+ }
+
+ m_CmdListManager.DiscardAllocator(FenceValue, pAllocator);
+ pCtx->DiscardUsedDescriptorHeaps(m_CurrentFrame);
+
+ {
+ std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
+ m_AvailableContexts.push_back(pCtx);
+ }
+
+ return FenceValue;
+}
+
+
+Uint64 RenderDeviceD3D12Impl::IncrementFence(void)
+{
+ std::lock_guard<std::mutex> LockGuard(m_FenceMutex);
+ m_pd3d12CmdQueue->Signal(m_pFence, m_NextFenceValue);
+ return m_NextFenceValue++;
+}
+
+void RenderDeviceD3D12Impl::IdleGPU(bool ReleasePendingObjects)
+{
+ auto FenceValue = IncrementFence();
+ WaitForFence(FenceValue);
+ if(ReleasePendingObjects)
+ {
+ // Do not wait until the end of the frame and force deletion.
+ // This is necessary to release outstanding references to the
+ // swap chain buffers when it is resized in the middle of the frame.
+ // Since GPU has been idled, it is safe to do so
+ ProcessReleaseQueue(true);
+ }
+}
+
+
+bool RenderDeviceD3D12Impl::IsFenceComplete(Uint64 FenceValue)
+{
+ // Avoid querying the fence value by testing against the last one seen.
+ // The max() is to protect against an unlikely race condition that could cause the last
+ // completed fence value to regress.
+ if (FenceValue > m_LastCompletedFenceValue)
+ m_LastCompletedFenceValue = std::max(m_LastCompletedFenceValue, m_pFence->GetCompletedValue());
+
+ return FenceValue <= m_LastCompletedFenceValue;
+}
+
+Uint64 RenderDeviceD3D12Impl::FinishFrame()
+{
+ m_NumCompletedFrames = std::max(m_NumCompletedFrames, m_pNumCompletedFramesFence->GetCompletedValue());
+ for (auto &UploadHeap : m_UploadHeaps)
+ {
+ // Currently upload heaps are free-threaded, so other threads must not allocate
+ // resources at the same time
+ UploadHeap->FinishFrame(m_CurrentFrame, m_NumCompletedFrames);
+ }
+
+ for(Uint32 CPUHeap=0; CPUHeap < _countof(m_CPUDescriptorHeaps); ++CPUHeap)
+ {
+ m_CPUDescriptorHeaps[CPUHeap].ReleaseStaleAllocations(m_NumCompletedFrames);
+ }
+
+ for(Uint32 GPUHeap=0; GPUHeap < _countof(m_GPUDescriptorHeaps); ++GPUHeap)
+ {
+ m_GPUDescriptorHeaps[GPUHeap].ReleaseStaleAllocations(m_NumCompletedFrames);
+ }
+
+
+ ProcessReleaseQueue();
+
+ // How does this work in a multi-threaded environment??
+ auto CompletedFrame = m_CurrentFrame++;
+ m_pd3d12CmdQueue->Signal(m_pNumCompletedFramesFence, m_CurrentFrame);
+ return CompletedFrame;
+}
+
+bool RenderDeviceD3D12Impl::IsFrameComplete(Uint64 Frame)
+{
+ // Avoid querying the fence value by testing against the last one seen.
+ // The max() is to protect against an unlikely race condition that could cause the last
+ // completed fence value to regress.
+ if (Frame > m_NumCompletedFrames)
+ m_NumCompletedFrames = std::max(m_NumCompletedFrames, m_pNumCompletedFramesFence->GetCompletedValue());
+
+ return Frame <= m_NumCompletedFrames;
+}
+
+void RenderDeviceD3D12Impl::WaitForFence(Uint64 FenceValue)
+{
+ if (IsFenceComplete(FenceValue))
+ return;
+
+ // TODO: Think about how this might affect a multi-threaded situation. Suppose thread A
+ // wants to wait for fence 100, then thread B comes along and wants to wait for 99. If
+ // the fence can only have one event set on completion, then thread B has to wait for
+ // 100 before it knows 99 is ready. Maybe insert sequential events?
+ {
+ std::lock_guard<std::mutex> LockGuard(m_EventMutex);
+
+ m_pFence->SetEventOnCompletion(FenceValue, m_FenceEventHandle);
+ WaitForSingleObject(m_FenceEventHandle, INFINITE);
+ m_LastCompletedFenceValue = FenceValue;
+ }
+}
+
+DynamicUploadHeap* RenderDeviceD3D12Impl::RequestUploadHeap()
+{
+ std::lock_guard<std::mutex> LockGuard(m_UploadHeapMutex);
+
+#ifdef _DEBUG
+ size_t InitialSize = 1024+64;
+#else
+ size_t InitialSize = 64<<10;//16<<20;
+#endif
+
+ auto &UploadHeapAllocator = GetRawAllocator();
+ auto *pRawMem = ALLOCATE(UploadHeapAllocator, "DynamicUploadHeap instance", sizeof(DynamicUploadHeap));
+ auto *pNewHeap = new (pRawMem) DynamicUploadHeap(GetRawAllocator(), true, this, InitialSize);
+ m_UploadHeaps.emplace_back( pNewHeap, STDDeleterRawMem<DynamicUploadHeap>(UploadHeapAllocator) );
+ return pNewHeap;
+}
+
+void RenderDeviceD3D12Impl::ReleaseUploadHeap(DynamicUploadHeap* pUploadHeap)
+{
+
+}
+
+CommandContext* RenderDeviceD3D12Impl::AllocateCommandContext(const Char *ID)
+{
+ std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
+
+ CommandContext* ret = nullptr;
+ if (m_AvailableContexts.empty())
+ {
+ Uint32 DynamicDescriptorAllocationChunkSize[] = {256, 32};
+ auto &CmdCtxAllocator = GetRawAllocator();
+ auto *pRawMem = ALLOCATE(CmdCtxAllocator, "CommandContext instance", sizeof(CommandContext));
+ ret = new (pRawMem) CommandContext( GetRawAllocator(), m_CmdListManager, m_GPUDescriptorHeaps, DynamicDescriptorAllocationChunkSize);
+ m_ContextPool.emplace_back(ret, STDDeleterRawMem<CommandContext>(CmdCtxAllocator) );
+ }
+ else
+ {
+ ret = m_AvailableContexts.front();
+ m_AvailableContexts.pop_front();
+ ret->Reset(m_CmdListManager);
+ }
+ VERIFY_EXPR(ret != nullptr);
+ ret->SetID(ID);
+ //if ( ID != nullptr && *ID != 0 )
+ // EngineProfiling::BeginBlock(ID, NewContext);
+
+ return ret;
+}
+
+void RenderDeviceD3D12Impl::SafeReleaseD3D12Object(ID3D12Object* pObj)
+{
+ std::lock_guard<std::mutex> LockGuard(m_ReleasedObjectsMutex);
+ m_D3D12ObjReleaseQueue.emplace_back( m_CurrentFrame, CComPtr<ID3D12Object>(pObj) );
+}
+
+void RenderDeviceD3D12Impl::ProcessReleaseQueue(bool ForceRelease)
+{
+ std::lock_guard<std::mutex> LockGuard(m_ReleasedObjectsMutex);
+
+ // Release all objects whose frame number value < number of completed frames
+ while (m_D3D12ObjReleaseQueue.size())
+ {
+ auto &FirstObj = m_D3D12ObjReleaseQueue.front();
+ // GPU must have been idled when ForceRelease == true
+ if (FirstObj.first < m_NumCompletedFrames || ForceRelease)
+ m_D3D12ObjReleaseQueue.pop_front();
+ else
+ break;
+ }
+}
+
+bool CreateTestResource(ID3D12Device *pDevice, const D3D12_RESOURCE_DESC &ResDesc)
+{
+ // Set the texture pointer address to nullptr to validate input parameters
+ // without creating the texture
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899178(v=vs.85).aspx
+
+ D3D12_HEAP_PROPERTIES HeapProps;
+ HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ HeapProps.CreationNodeMask = 1;
+ HeapProps.VisibleNodeMask = 1;
+
+ auto hr = pDevice->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, &ResDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, __uuidof(ID3D12Resource), nullptr );
+ return hr == S_FALSE; // S_FALSE means that input parameters passed validation
+}
+
+void RenderDeviceD3D12Impl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
+{
+ auto &TexFormatInfo = m_TextureFormatsInfo[TexFormat];
+ VERIFY( TexFormatInfo.Supported, "Texture format is not supported" );
+
+ auto DXGIFormat = TexFormatToDXGI_Format(TexFormat);
+ D3D12_RESOURCE_FLAGS DefaultResourceFlags = D3D12_RESOURCE_FLAG_NONE;
+ if( TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL )
+ DefaultResourceFlags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+
+ const int TestTextureDim = 32;
+ const int TestTextureDepth = 8;
+
+ D3D12_RESOURCE_DESC ResDesc =
+ {
+ D3D12_RESOURCE_DIMENSION_TEXTURE1D,
+ 0, // Alignment
+ TestTextureDim,
+ 1, // Height
+ 1, // DepthOrArraySize
+ 1, // MipLevels
+ DXGIFormat,
+ {1, 0},
+ D3D12_TEXTURE_LAYOUT_UNKNOWN,
+ DefaultResourceFlags
+ };
+
+ // Create test texture 1D
+ TexFormatInfo.Tex1DFmt = false;
+ if( TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED )
+ {
+ TexFormatInfo.Tex1DFmt = CreateTestResource(m_pd3d12Device, ResDesc );
+ }
+
+ // Create test texture 2D
+ TexFormatInfo.Tex2DFmt = false;
+ TexFormatInfo.TexCubeFmt = false;
+ TexFormatInfo.ColorRenderable = false;
+ TexFormatInfo.DepthRenderable = false;
+ TexFormatInfo.SupportsMS = false;
+ {
+ ResDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ ResDesc.Height = TestTextureDim;
+ TexFormatInfo.Tex2DFmt = CreateTestResource( m_pd3d12Device, ResDesc );
+
+ if( TexFormatInfo.Tex2DFmt )
+ {
+ {
+ // D3D12_TEXTURE2D_DESC CubeTexDesc = Tex2DDesc;
+ ResDesc.DepthOrArraySize = 6;
+ // CubeTexDesc.MiscFlags = D3D12_RESOURCE_MISC_TEXTURECUBE;
+ TexFormatInfo.TexCubeFmt = CreateTestResource( m_pd3d12Device, ResDesc );
+ ResDesc.DepthOrArraySize = 1;
+ }
+
+ if( TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL )
+ {
+ ResDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ ResDesc.SampleDesc.Count = 1;
+ TexFormatInfo.DepthRenderable = CreateTestResource( m_pd3d12Device, ResDesc );
+
+ if( TexFormatInfo.DepthRenderable )
+ {
+ ResDesc.SampleDesc.Count = 4;
+ TexFormatInfo.SupportsMS = CreateTestResource( m_pd3d12Device, ResDesc );
+ }
+ }
+ else if( TexFormatInfo.ComponentType != COMPONENT_TYPE_COMPRESSED &&
+ TexFormatInfo.Format != DXGI_FORMAT_R9G9B9E5_SHAREDEXP )
+ {
+ ResDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ ResDesc.SampleDesc.Count = 1;
+ TexFormatInfo.ColorRenderable = CreateTestResource( m_pd3d12Device, ResDesc );
+ if( TexFormatInfo.ColorRenderable )
+ {
+ ResDesc.SampleDesc.Count = 4;
+ TexFormatInfo.SupportsMS = CreateTestResource( m_pd3d12Device, ResDesc );
+ }
+ }
+ }
+ }
+
+ // Create test texture 3D
+ TexFormatInfo.Tex3DFmt = false;
+ // 3D textures do not support depth formats
+ if( !(TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH ||
+ TexFormatInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) )
+ {
+ ResDesc.SampleDesc.Count = 1;
+ ResDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
+ ResDesc.Flags = DefaultResourceFlags;
+ ResDesc.DepthOrArraySize = TestTextureDepth;
+ TexFormatInfo.Tex3DFmt = CreateTestResource( m_pd3d12Device, ResDesc );
+ }
+}
+
+
+IMPLEMENT_QUERY_INTERFACE( RenderDeviceD3D12Impl, IID_RenderDeviceD3D12, TRenderDeviceBase )
+
+void RenderDeviceD3D12Impl::CreatePipelineState(const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState)
+{
+ CreateDeviceObject("Pipeline State", PipelineDesc, ppPipelineState,
+ [&]()
+ {
+ PipelineStateD3D12Impl *pPipelineStateD3D12( NEW(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl, this, PipelineDesc ) );
+ pPipelineStateD3D12->QueryInterface( IID_PipelineState, reinterpret_cast<IObject**>(ppPipelineState) );
+ OnCreateDeviceObject( pPipelineStateD3D12 );
+ }
+ );
+}
+
+
+void RenderDeviceD3D12Impl :: CreateBuffer(const BufferDesc& BuffDesc, const BufferData &BuffData, IBuffer **ppBuffer)
+{
+ CreateDeviceObject("buffer", BuffDesc, ppBuffer,
+ [&]()
+ {
+ BufferD3D12Impl *pBufferD3D12( NEW(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl, m_BuffViewObjAllocator, this, BuffDesc, BuffData ) );
+ pBufferD3D12->QueryInterface( IID_Buffer, reinterpret_cast<IObject**>(ppBuffer) );
+ pBufferD3D12->CreateDefaultViews();
+ OnCreateDeviceObject( pBufferD3D12 );
+ }
+ );
+}
+
+
+void RenderDeviceD3D12Impl :: CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader)
+{
+ CreateDeviceObject( "shader", ShaderCreationAttribs.Desc, ppShader,
+ [&]()
+ {
+ ShaderD3D12Impl *pShaderD3D12( NEW(m_ShaderObjAllocator, "ShaderD3D12Impl instance", ShaderD3D12Impl, this, ShaderCreationAttribs ) );
+ pShaderD3D12->QueryInterface( IID_Shader, reinterpret_cast<IObject**>(ppShader) );
+
+ OnCreateDeviceObject( pShaderD3D12 );
+ }
+ );
+}
+
+void RenderDeviceD3D12Impl::CreateTexture(TextureDesc& TexDesc, ID3D12Resource *pd3d12Texture, class TextureD3D12Impl **ppTexture)
+{
+ TextureD3D12Impl *pTextureD3D12 = NEW(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl, m_TexViewObjAllocator, this, TexDesc, pd3d12Texture );
+ pTextureD3D12->QueryInterface( IID_TextureD3D12, reinterpret_cast<IObject**>(ppTexture) );
+}
+
+void RenderDeviceD3D12Impl :: CreateTexture(const TextureDesc& TexDesc, const TextureData &Data, ITexture **ppTexture)
+{
+ CreateDeviceObject( "texture", TexDesc, ppTexture,
+ [&]()
+ {
+ TextureD3D12Impl *pTextureD3D12 = NEW(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl, m_TexViewObjAllocator, this, TexDesc, Data );
+
+ pTextureD3D12->QueryInterface( IID_Texture, reinterpret_cast<IObject**>(ppTexture) );
+ pTextureD3D12->CreateDefaultViews();
+ OnCreateDeviceObject( pTextureD3D12 );
+ }
+ );
+}
+
+void RenderDeviceD3D12Impl :: CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)
+{
+ CreateDeviceObject( "sampler", SamplerDesc, ppSampler,
+ [&]()
+ {
+ m_SamplersRegistry.Find( SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler) );
+ if( *ppSampler == nullptr )
+ {
+ SamplerD3D12Impl *pSamplerD3D12( NEW(m_SamplerObjAllocator, "SamplerD3D12Impl instance", SamplerD3D12Impl, this, SamplerDesc ) );
+ pSamplerD3D12->QueryInterface( IID_Sampler, reinterpret_cast<IObject**>(ppSampler) );
+ OnCreateDeviceObject( pSamplerD3D12 );
+ m_SamplersRegistry.Add( SamplerDesc, *ppSampler );
+ }
+ }
+ );
+}
+
+DescriptorHeapAllocation RenderDeviceD3D12Impl :: AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count /*= 1*/)
+{
+ VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES, "Invalid heap type");
+ return m_CPUDescriptorHeaps[Type].Allocate(Count);
+}
+
+DescriptorHeapAllocation RenderDeviceD3D12Impl :: AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count /*= 1*/)
+{
+ VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type");
+ return m_GPUDescriptorHeaps[Type].Allocate(Count);
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp
new file mode 100644
index 00000000..762e8a03
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp
@@ -0,0 +1,334 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+/// \file
+/// Routines that initialize D3D12-based engine implementation
+
+#include "pch.h"
+#include "RenderDeviceFactoryD3D12.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+#include "SwapChainD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+#include "StringTools.h"
+#include "EngineMemory.h"
+#include <Windows.h>
+#include <dxgi1_4.h>
+
+namespace Diligent
+{
+
+void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter)
+{
+ CComPtr<IDXGIAdapter1> adapter;
+ *ppAdapter = nullptr;
+
+ for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex)
+ {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ {
+ // Don't select the Basic Render Driver adapter.
+ // If you want a software adapter, pass in "/warp" on the command line.
+ continue;
+ }
+
+ // Check to see if the adapter supports Direct3D 12, but don't create the
+ // actual device yet.
+ if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
+ {
+ LOG_INFO_MESSAGE("D3D12-capabale hardware found: ", NarrowString(desc.Description), " (", desc.DedicatedVideoMemory>>20, " MB)");
+ break;
+ }
+ }
+
+ *ppAdapter = adapter.Detach();
+}
+
+/// Creates render device and device contexts for Direct3D12-based engine implementation
+
+/// \param [in] CreationAttribs - Engine creation attributes.
+/// \param [out] ppDevice - Address of the memory location where pointer to
+/// the created device will be written
+/// \param [out] ppContexts - Address of the memory location where pointers to
+/// the contexts will be written. The new immediate
+/// context goes at position 0. If NumDeferredContexts > 0,
+/// pointers to the deferred contexts are written afterwards.
+/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number
+/// of deferred contexts is requested, pointers to the
+/// contexts are written to ppContexts array starting
+/// at position 1
+void CreateDeviceAndContextsD3D12( const EngineD3D12Attribs& CreationAttribs,
+ IRenderDevice **ppDevice,
+ Diligent::IDeviceContext **ppContexts,
+ Diligent::Uint32 NumDeferredContexts)
+{
+ VERIFY( ppDevice && ppContexts, "Null pointer is provided" );
+ if( !ppDevice || !ppContexts )
+ return;
+
+ for(Uint32 Type=D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type)
+ {
+ auto CPUHeapAllocSize = CreationAttribs.CPUDescriptorHeapAllocationSize[Type];
+ Uint32 MaxSize = 1 << 20;
+ if( CPUHeapAllocSize > 1 << 20 )
+ {
+ LOG_ERROR( "CPU Heap allocation size is too large (", CPUHeapAllocSize, "). Max allowed size is ", MaxSize );
+ return;
+ }
+
+ if( (CPUHeapAllocSize % 16) != 0 )
+ {
+ LOG_ERROR( "CPU Heap allocation size (", CPUHeapAllocSize, ") is expected to be multiple of 16" );
+ return;
+ }
+ }
+
+ SetRawAllocator(CreationAttribs.pRawMemAllocator);
+
+ *ppDevice = nullptr;
+ memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts));
+
+ try
+ {
+#if defined(_DEBUG)
+ // Enable the D3D12 debug layer.
+ {
+ CComPtr<ID3D12Debug> debugController;
+ if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), reinterpret_cast<void**>(static_cast<ID3D12Debug**>(&debugController)) )))
+ {
+ debugController->EnableDebugLayer();
+ }
+ }
+#endif
+
+ CComPtr<IDXGIFactory4> factory;
+ HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast<void**>(static_cast<IDXGIFactory4**>(&factory)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory")
+
+ CComPtr<IDXGIAdapter1> hardwareAdapter;
+ GetHardwareAdapter(factory, &hardwareAdapter);
+
+ CComPtr<ID3D12Device> d3d12Device;
+ hr = D3D12CreateDevice(hardwareAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ if( FAILED(hr))
+ {
+ LOG_WARNING_MESSAGE("Failed to create hardware device. Attempting to create WARP device")
+
+ CComPtr<IDXGIAdapter> warpAdapter;
+ hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast<void**>(static_cast<IDXGIAdapter**>(&warpAdapter)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter")
+
+ hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device")
+ }
+
+#if _DEBUG
+ {
+ CComPtr<ID3D12InfoQueue> pInfoQueue;
+ hr = d3d12Device->QueryInterface(__uuidof(pInfoQueue), reinterpret_cast<void**>(static_cast<ID3D12InfoQueue**>(&pInfoQueue)));
+ if( SUCCEEDED(hr) )
+ {
+ // Suppress whole categories of messages
+ //D3D12_MESSAGE_CATEGORY Categories[] = {};
+
+ // Suppress messages based on their severity level
+ D3D12_MESSAGE_SEVERITY Severities[] =
+ {
+ D3D12_MESSAGE_SEVERITY_INFO
+ };
+
+ // Suppress individual messages by their ID
+ //D3D12_MESSAGE_ID DenyIds[] = {};
+
+ D3D12_INFO_QUEUE_FILTER NewFilter = {};
+ //NewFilter.DenyList.NumCategories = _countof(Categories);
+ //NewFilter.DenyList.pCategoryList = Categories;
+ NewFilter.DenyList.NumSeverities = _countof(Severities);
+ NewFilter.DenyList.pSeverityList = Severities;
+ //NewFilter.DenyList.NumIDs = _countof(DenyIds);
+ //NewFilter.DenyList.pIDList = DenyIds;
+
+ hr = pInfoQueue->PushStorageFilter(&NewFilter);
+ VERIFY(SUCCEEDED(hr), "Failed to push storage filter");
+ }
+ }
+#endif
+
+#ifndef RELEASE
+ // Prevent the GPU from overclocking or underclocking to get consistent timings
+ d3d12Device->SetStablePowerState(TRUE);
+#endif
+
+ // Describe and create the command queue.
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+
+ CComPtr<ID3D12CommandQueue> pd3d12CmdQueue;
+ hr = d3d12Device->CreateCommandQueue(&queueDesc, __uuidof(pd3d12CmdQueue), reinterpret_cast<void**>(static_cast<ID3D12CommandQueue**>(&pd3d12CmdQueue)));
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create command queue");
+ hr = pd3d12CmdQueue->SetName(L"Main Command Queue");
+ VERIFY_EXPR(SUCCEEDED(hr));
+
+ auto &RawMemAllocator = GetRawAllocator();
+ RenderDeviceD3D12Impl *pRenderDeviceD3D12( NEW(RawMemAllocator, "RenderDeviceD3D12Impl instance", RenderDeviceD3D12Impl, CreationAttribs, d3d12Device, pd3d12CmdQueue, NumDeferredContexts ) );
+ pRenderDeviceD3D12->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );
+
+ RefCntAutoPtr<DeviceContextD3D12Impl> pImmediateCtxD3D12( NEW(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl, pRenderDeviceD3D12, false, CreationAttribs, 0) );
+ // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will
+ // keep a weak reference to the context
+ pImmediateCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts) );
+ pRenderDeviceD3D12->SetImmediateContext(pImmediateCtxD3D12);
+
+ for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx)
+ {
+ RefCntAutoPtr<DeviceContextD3D12Impl> pDeferredCtxD3D12( NEW(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl, pRenderDeviceD3D12, true, CreationAttribs, 1+DeferredCtx) );
+ // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will
+ // keep a weak reference to the context
+ pDeferredCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts + 1 + DeferredCtx) );
+ pRenderDeviceD3D12->SetDeferredContext(DeferredCtx, pDeferredCtxD3D12);
+ }
+ }
+ catch( const std::runtime_error & )
+ {
+ if( *ppDevice )
+ {
+ (*ppDevice)->Release();
+ *ppDevice = nullptr;
+ }
+ for(Uint32 ctx=0; ctx < 1 + NumDeferredContexts; ++ctx)
+ {
+ if( ppContexts[ctx] != nullptr )
+ {
+ ppContexts[ctx]->Release();
+ ppContexts[ctx] = nullptr;
+ }
+ }
+
+ LOG_ERROR( "Failed to create device and immediate context" );
+ }
+}
+
+
+/// Creates a swap chain for Direct3D12-based engine implementation
+
+/// \param [in] pDevice - Pointer to the render device
+/// \param [in] pImmediateContext - Pointer to the immediate device context
+/// \param [in] SCDesc - Swap chain description
+/// \param [in] pNativeWndHandle - Platform-specific native handle of the window
+/// the swap chain will be associated with:
+/// * On Win32 platform, this should be window handle (HWND)
+/// * On Universal Windows Platform, this should be reference to the
+/// core window (Windows::UI::Core::CoreWindow)
+///
+/// \param [out] ppSwapChain - Address of the memory location where pointer to the new
+/// swap chain will be written
+void CreateSwapChainD3D12( IRenderDevice *pDevice, IDeviceContext *pImmediateContext, const SwapChainDesc& SCDesc, void* pNativeWndHandle, ISwapChain **ppSwapChain )
+{
+ VERIFY( ppSwapChain, "Null pointer is provided" );
+ if( !ppSwapChain )
+ return;
+
+ *ppSwapChain = nullptr;
+
+ try
+ {
+ auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pDevice );
+ auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pImmediateContext);
+ auto &RawMemAllocator = GetRawAllocator();
+ auto *pSwapChainD3D12 = NEW(RawMemAllocator, "SwapChainD3D12Impl instance", SwapChainD3D12Impl, SCDesc, pDeviceD3D12, pDeviceContextD3D12, pNativeWndHandle);
+ pSwapChainD3D12->QueryInterface( IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain) );
+
+ pDeviceContextD3D12->SetSwapChain(pSwapChainD3D12);
+ // Bind default render target
+ pDeviceContextD3D12->SetRenderTargets( 0, nullptr, nullptr );
+ // Set default viewport
+ pDeviceContextD3D12->SetViewports( 1, nullptr, 0, 0 );
+
+ auto NumDeferredCtx = pDeviceD3D12->GetNumDeferredContexts();
+ for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx)
+ {
+ if (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx))
+ {
+ auto *pDeferredCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pDeferredCtx.RawPtr());
+ pDeferredCtxD3D12->SetSwapChain(pSwapChainD3D12);
+ // Bind default render target
+ pDeferredCtxD3D12->SetRenderTargets( 0, nullptr, nullptr );
+ // Set default viewport
+ pDeferredCtxD3D12->SetViewports( 1, nullptr, 0, 0 );
+ }
+ }
+ }
+ catch( const std::runtime_error & )
+ {
+ if( *ppSwapChain )
+ {
+ (*ppSwapChain)->Release();
+ *ppSwapChain = nullptr;
+ }
+
+ LOG_ERROR( "Failed to create the swap chain" );
+ }
+}
+
+
+#ifdef DOXYGEN
+/// Loads Direct3D12-based engine implementation and exports factory functions
+/// \param [out] CreateDeviceFunc - Pointer to the function that creates render device and device contexts.
+/// See CreateDeviceAndContextsD3D12().
+/// \param [out] CreateSwapChainFunc - Pointer to the function that creates swap chain.
+/// See CreateSwapChainD3D12().
+/// \remarks Depending on the configuration and platform, the function loads different dll:
+/// Platform\\Configuration | Debug | Release
+/// --------------------------|-------------------------------|----------------------------
+/// x86 | GraphicsEngineD3D12_32d.dll | GraphicsEngineD3D12_32r.dll
+/// x64 | GraphicsEngineD3D12_64d.dll | GraphicsEngineD3D12_64r.dll
+///
+void LoadGraphicsEngineD3D12(CreateDeviceAndContextsD3D12Type &CreateDeviceFunc, CreateSwapChainD3D12Type &CreateSwapChainFunc)
+{
+ // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO
+ #error This function must never be compiled;
+}
+#endif
+
+
+}
+
+
+using namespace Diligent;
+extern "C"
+{
+ void CreateDeviceAndContextsD3D12(const EngineD3D12Attribs& EngineAttribs, IRenderDevice **ppDevice, IDeviceContext **ppContexts, Uint32 NumDeferredContexts)
+ {
+ Diligent::CreateDeviceAndContextsD3D12(EngineAttribs, ppDevice, ppContexts, NumDeferredContexts);
+ }
+
+
+ void CreateSwapChainD3D12(IRenderDevice *pDevice, IDeviceContext *pImmediateContext, const SwapChainDesc& SwapChainDesc, void* pNativeWndHandle, ISwapChain **ppSwapChain)
+ {
+ Diligent::CreateSwapChainD3D12(pDevice, pImmediateContext, SwapChainDesc, pNativeWndHandle, ppSwapChain);
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
new file mode 100644
index 00000000..272895af
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
@@ -0,0 +1,959 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "RootSignature.h"
+#include "ShaderResourceLayoutD3D12.h"
+#include "D3DShaderResourceLoader.h"
+#include "ShaderD3D12Impl.h"
+#include "CommandContext.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "TextureD3D12Impl.h"
+#include "BufferD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+
+namespace Diligent
+{
+
+RootSignature::RootParamsManager::RootParamsManager(IMemoryAllocator &MemAllocator):
+ m_MemAllocator(MemAllocator),
+ m_pMemory(nullptr, STDDeleter<void, IMemoryAllocator>(MemAllocator))
+{}
+
+size_t RootSignature::RootParamsManager::GetRequiredMemorySize(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges)const
+{
+ return sizeof(RootParameter) * (m_NumRootTables + NumExtraRootTables + m_NumRootViews + NumExtraRootViews) + sizeof(D3D12_DESCRIPTOR_RANGE) * (m_TotalDescriptorRanges + NumExtraDescriptorRanges);
+}
+
+D3D12_DESCRIPTOR_RANGE* RootSignature::RootParamsManager::Extend(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges, Uint32 RootTableToAddRanges)
+{
+ VERIFY(NumExtraRootTables > 0 || NumExtraRootViews > 0 || NumExtraDescriptorRanges > 0, "At least one root table, root view or descriptor range must be added" );
+ auto MemorySize = GetRequiredMemorySize(NumExtraRootTables, NumExtraRootViews, NumExtraDescriptorRanges);
+ VERIFY_EXPR(MemorySize > 0);
+ auto *pNewMemory = ALLOCATE(m_MemAllocator, "Memory buffer for root tables, root views & descriptor ranges", MemorySize);
+ memset(pNewMemory, 0, MemorySize);
+
+ // Note: this order is more efficient than views->tables->ranges
+ auto *pNewRootTables = reinterpret_cast<RootParameter*>(pNewMemory);
+ auto *pNewRootViews = pNewRootTables + (m_NumRootTables + NumExtraRootTables);
+ auto *pCurrDescriptorRangePtr = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pNewRootViews+m_NumRootViews+NumExtraRootViews);
+
+ // Copy existing root tables to new memory
+ for (Uint32 rt = 0; rt < m_NumRootTables; ++rt)
+ {
+ const auto &SrcTbl = GetRootTable(rt);
+ auto &D3D12SrcTbl = static_cast<const D3D12_ROOT_PARAMETER&>(SrcTbl).DescriptorTable;
+ auto NumRanges = D3D12SrcTbl.NumDescriptorRanges;
+ if(rt == RootTableToAddRanges)
+ {
+ VERIFY(NumExtraRootTables == 0 || NumExtraRootTables == 1, "Up to one descriptor table can be extended at a time");
+ NumRanges += NumExtraDescriptorRanges;
+ }
+ new(pNewRootTables + rt) RootParameter(SrcTbl, NumRanges, pCurrDescriptorRangePtr);
+ pCurrDescriptorRangePtr += NumRanges;
+ }
+
+ // Copy existing root view to new memory
+ for (Uint32 rv = 0; rv < m_NumRootViews; ++rv)
+ {
+ const auto &SrcView = GetRootView(rv);
+ new(pNewRootViews + rv) RootParameter(SrcView);
+ }
+
+ m_pMemory.reset(pNewMemory);
+ m_NumRootTables += NumExtraRootTables;
+ m_NumRootViews += NumExtraRootViews;
+ m_TotalDescriptorRanges += NumExtraDescriptorRanges;
+ m_pRootTables = m_NumRootTables != 0 ? pNewRootTables : nullptr;
+ m_pRootViews = m_NumRootViews != 0 ? pNewRootViews : nullptr;
+
+ return pCurrDescriptorRangePtr;
+}
+
+void RootSignature::RootParamsManager::AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, Uint32 RootIndex, UINT Register, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType)
+{
+ auto *pRangePtr = Extend(0, 1, 0);
+ VERIFY_EXPR((char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
+ new(m_pRootViews + m_NumRootViews-1) RootParameter(ParameterType, RootIndex, Register, 0u, Visibility, VarType);
+}
+
+void RootSignature::RootParamsManager::AddRootTable(Uint32 RootIndex, D3D12_SHADER_VISIBILITY Visibility, SHADER_VARIABLE_TYPE VarType, Uint32 NumRangesInNewTable)
+{
+ auto *pRangePtr = Extend(1, 0, NumRangesInNewTable);
+ VERIFY_EXPR( (char*)(pRangePtr + NumRangesInNewTable) == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
+ new(m_pRootTables + m_NumRootTables-1) RootParameter(D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, RootIndex, NumRangesInNewTable, pRangePtr, Visibility, VarType);
+}
+
+void RootSignature::RootParamsManager::AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges)
+{
+ auto *pRangePtr = Extend(0, 0, NumExtraRanges, RootTableInd);
+ VERIFY_EXPR( (char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
+}
+
+
+RootSignature::RootSignature() :
+ m_RootParams(GetRawAllocator()),
+ m_MemAllocator(GetRawAllocator()),
+ m_StaticSamplers( STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector<StaticSamplerAttribs>") )
+{
+ for(size_t s=0; s < SHADER_VARIABLE_TYPE_NUM_TYPES; ++s)
+ {
+ m_TotalSrvCbvUavSlots[s] = 0;
+ m_TotalSamplerSlots[s] = 0;
+ }
+
+ for(size_t i=0; i < _countof(m_SrvCbvUavRootTablesMap); ++i)
+ m_SrvCbvUavRootTablesMap[i] = InvalidRootTableIndex;
+ for(size_t i=0; i < _countof(m_SamplerRootTablesMap); ++i)
+ m_SamplerRootTablesMap[i] = InvalidRootTableIndex;
+
+}
+
+static D3D12_SHADER_VISIBILITY ShaderTypeInd2ShaderVisibilityMap[]
+{
+ D3D12_SHADER_VISIBILITY_VERTEX, // 0
+ D3D12_SHADER_VISIBILITY_PIXEL, // 1
+ D3D12_SHADER_VISIBILITY_GEOMETRY, // 2
+ D3D12_SHADER_VISIBILITY_HULL, // 3
+ D3D12_SHADER_VISIBILITY_DOMAIN, // 4
+ D3D12_SHADER_VISIBILITY_ALL // 5
+};
+D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType)
+{
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ShaderVisibility = ShaderTypeInd2ShaderVisibilityMap[ShaderInd];
+#ifdef _DEBUG
+ switch (ShaderType)
+ {
+ case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX); break;
+ case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL); break;
+ case SHADER_TYPE_GEOMETRY: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_GEOMETRY); break;
+ case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_HULL); break;
+ case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_DOMAIN); break;
+ case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL); break;
+ default: LOG_ERROR("Unknown shader type (", ShaderType, ")"); break;
+ }
+#endif
+ return ShaderVisibility;
+}
+
+static SHADER_TYPE ShaderVisibility2ShaderTypeMap[] =
+{
+ SHADER_TYPE_COMPUTE, // D3D12_SHADER_VISIBILITY_ALL = 0
+ SHADER_TYPE_VERTEX, // D3D12_SHADER_VISIBILITY_VERTEX = 1
+ SHADER_TYPE_HULL, // D3D12_SHADER_VISIBILITY_HULL = 2
+ SHADER_TYPE_DOMAIN, // D3D12_SHADER_VISIBILITY_DOMAIN = 3
+ SHADER_TYPE_GEOMETRY, // D3D12_SHADER_VISIBILITY_GEOMETRY = 4
+ SHADER_TYPE_PIXEL // D3D12_SHADER_VISIBILITY_PIXEL = 5
+};
+SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility)
+{
+ VERIFY_EXPR(ShaderVisibility >= D3D12_SHADER_VISIBILITY_ALL && ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL );
+ auto ShaderType = ShaderVisibility2ShaderTypeMap[ShaderVisibility];
+#ifdef _DEBUG
+ switch (ShaderVisibility)
+ {
+ case D3D12_SHADER_VISIBILITY_VERTEX: VERIFY_EXPR(ShaderType == SHADER_TYPE_VERTEX); break;
+ case D3D12_SHADER_VISIBILITY_PIXEL: VERIFY_EXPR(ShaderType == SHADER_TYPE_PIXEL); break;
+ case D3D12_SHADER_VISIBILITY_GEOMETRY: VERIFY_EXPR(ShaderType == SHADER_TYPE_GEOMETRY); break;
+ case D3D12_SHADER_VISIBILITY_HULL: VERIFY_EXPR(ShaderType == SHADER_TYPE_HULL); break;
+ case D3D12_SHADER_VISIBILITY_DOMAIN: VERIFY_EXPR(ShaderType == SHADER_TYPE_DOMAIN); break;
+ case D3D12_SHADER_VISIBILITY_ALL: VERIFY_EXPR(ShaderType == SHADER_TYPE_COMPUTE); break;
+ default: LOG_ERROR("Unknown shader visibility (", ShaderVisibility, ")"); break;
+ }
+#endif
+ return ShaderType;
+}
+
+
+static D3D12_DESCRIPTOR_HEAP_TYPE RangeType2HeapTypeMap[]
+{
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, //D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, //D3D12_DESCRIPTOR_RANGE_TYPE_UAV = ( D3D12_DESCRIPTOR_RANGE_TYPE_SRV + 1 ) ,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, //D3D12_DESCRIPTOR_RANGE_TYPE_CBV = ( D3D12_DESCRIPTOR_RANGE_TYPE_UAV + 1 ) ,
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER //D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = ( D3D12_DESCRIPTOR_RANGE_TYPE_CBV + 1 )
+};
+D3D12_DESCRIPTOR_HEAP_TYPE HeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE RangeType)
+{
+ VERIFY_EXPR(RangeType >= D3D12_DESCRIPTOR_RANGE_TYPE_SRV && RangeType <= D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER);
+ auto HeapType = RangeType2HeapTypeMap[RangeType];
+
+#ifdef _DEBUG
+ switch (RangeType)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: VERIFY_EXPR(HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: VERIFY_EXPR(HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: VERIFY_EXPR(HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER: VERIFY_EXPR(HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); break;
+ default: UNEXPECTED("Unexpected descriptor range type"); break;
+ }
+#endif
+ return HeapType;
+}
+
+
+void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, const String &TextureName, const D3DShaderResourceAttribs &SamplerAttribs)
+{
+ auto ShaderVisibility = GetShaderVisibility(ShaderType);
+ auto SamplerFound = false;
+ for (auto &StSmplr : m_StaticSamplers)
+ {
+ if (StSmplr.ShaderVisibility == ShaderVisibility &&
+ TextureName.compare(StSmplr.SamplerDesc.TextureName) == 0)
+ {
+ StSmplr.ShaderRegister = SamplerAttribs.BindPoint;
+ StSmplr.ArraySize = SamplerAttribs.BindCount;
+ StSmplr.RegisterSpace = 0;
+ SamplerFound = true;
+ break;
+ }
+ }
+
+ if (!SamplerFound)
+ {
+ LOG_ERROR("Failed to find static sampler for variable \"", TextureName, '\"')
+ }
+}
+
+void RootSignature::AllocateResourceSlot(SHADER_TYPE ShaderType, const D3DShaderResourceAttribs &ShaderResAttribs, D3D12_DESCRIPTOR_RANGE_TYPE RangeType, Uint32 &RootIndex, Uint32 &OffsetFromTableStart)
+{
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ShaderVisibility = GetShaderVisibility(ShaderType);
+ if (RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && ShaderResAttribs.BindCount == 1)
+ {
+ // Allocate CBV directly in the root signature
+ RootIndex = m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews();
+ OffsetFromTableStart = 0;
+
+ m_RootParams.AddRootView(D3D12_ROOT_PARAMETER_TYPE_CBV, RootIndex, ShaderResAttribs.BindPoint, ShaderVisibility, ShaderResAttribs.GetVariableType());
+ }
+ else
+ {
+ // Use the same table for static and mutable resources. Mark table type as static (mutable is an equivalent option)
+ auto RootTableType = (ShaderResAttribs.GetVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC) ? SHADER_VARIABLE_TYPE_DYNAMIC : SHADER_VARIABLE_TYPE_STATIC;
+ auto TableIndKey = ShaderInd * SHADER_VARIABLE_TYPE_NUM_TYPES + RootTableType;
+ auto &RootTableInd = (( RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER ) ? m_SamplerRootTablesMap : m_SrvCbvUavRootTablesMap)[ TableIndKey ];
+ if (RootTableInd == InvalidRootTableIndex)
+ {
+ RootIndex = m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews();
+ VERIFY_EXPR(m_RootParams.GetNumRootTables() < 255);
+ RootTableInd = static_cast<Uint8>( m_RootParams.GetNumRootTables() );
+ m_RootParams.AddRootTable(RootIndex, ShaderVisibility, RootTableType, 1);
+ }
+ else
+ {
+ m_RootParams.AddDescriptorRanges(RootTableInd, 1);
+ }
+
+ auto &CurrParam = m_RootParams.GetRootTable(RootTableInd);
+ RootIndex = CurrParam.GetRootIndex();
+
+ const auto& d3d12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(CurrParam);
+
+ VERIFY( d3d12RootParam.ShaderVisibility == ShaderVisibility, "Shader visibility is not correct" );
+
+ OffsetFromTableStart = CurrParam.GetDescriptorTableSize();
+
+ Uint32 NewDescriptorRangeIndex = d3d12RootParam.DescriptorTable.NumDescriptorRanges-1;
+ CurrParam.SetDescriptorRange(NewDescriptorRangeIndex, RangeType, ShaderResAttribs.BindPoint, ShaderResAttribs.BindCount, 0, OffsetFromTableStart);
+ }
+}
+
+
+#ifdef _DEBUG
+void RootSignature::dbgVerifyRootParameters()const
+{
+ Uint32 dbgTotalSrvCbvUavSlots = 0;
+ Uint32 dbgTotalSamplerSlots = 0;
+ for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
+ {
+ auto &RootTable = m_RootParams.GetRootTable(rt);
+ auto &Param = static_cast<const D3D12_ROOT_PARAMETER&>( RootTable );
+ VERIFY(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table");
+ auto &Table = Param.DescriptorTable;
+ VERIFY(Table.NumDescriptorRanges > 0, "Descriptor table is expected to be non-empty");
+ VERIFY(Table.pDescriptorRanges[0].OffsetInDescriptorsFromTableStart == 0, "Descriptor table is expected to start at 0 offset");
+ bool IsResourceTable = Table.pDescriptorRanges[0].RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ for (Uint32 r = 0; r < Table.NumDescriptorRanges; ++r)
+ {
+ const auto &range = Table.pDescriptorRanges[r];
+ if(IsResourceTable)
+ {
+ VERIFY( range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ||
+ range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV ||
+ range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Resource type is expected to be SRV, CBV or UAV")
+ dbgTotalSrvCbvUavSlots += range.NumDescriptors;
+ }
+ else
+ {
+ VERIFY(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Resource type is expected to be sampler")
+ dbgTotalSamplerSlots += range.NumDescriptors;
+ }
+
+ if(r>0)
+ {
+ VERIFY(Table.pDescriptorRanges[r].OffsetInDescriptorsFromTableStart == Table.pDescriptorRanges[r-1].OffsetInDescriptorsFromTableStart+Table.pDescriptorRanges[r-1].NumDescriptors, "Ranges in a descriptor table are expected to be consequtive");
+ }
+ }
+ }
+
+ for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
+ {
+ auto &RootView = m_RootParams.GetRootView(rv);
+ auto &Param = static_cast<const D3D12_ROOT_PARAMETER&>( RootView );
+ VERIFY(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV, "Root parameter is expected to be a CBV");
+ }
+
+ VERIFY(dbgTotalSrvCbvUavSlots ==
+ m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_STATIC] +
+ m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_MUTABLE] +
+ m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC], "Unexpected number of SRV CBV UAV resource slots")
+ VERIFY(dbgTotalSamplerSlots ==
+ m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_STATIC] +
+ m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_MUTABLE] +
+ m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC], "Unexpected number of sampler slots")
+}
+#endif
+
+void RootSignature::AllocateStaticSamplers(IShader* const*ppShaders, Uint32 NumShaders)
+{
+ Uint32 TotalSamplers = 0;
+ for(Uint32 s=0;s < NumShaders; ++s)
+ TotalSamplers += ppShaders[s]->GetDesc().NumStaticSamplers;
+ if (TotalSamplers > 0)
+ {
+ m_StaticSamplers.reserve(TotalSamplers);
+ for(Uint32 sh=0;sh < NumShaders; ++sh)
+ {
+ const auto &Desc = ppShaders[sh]->GetDesc();
+ for(Uint32 sam=0; sam < Desc.NumStaticSamplers; ++sam)
+ {
+ m_StaticSamplers.emplace_back(Desc.StaticSamplers[sam], GetShaderVisibility(Desc.ShaderType));
+ }
+ }
+ VERIFY_EXPR(m_StaticSamplers.size() == TotalSamplers);
+ }
+}
+
+void RootSignature::Finalize(ID3D12Device *pd3d12Device)
+{
+ for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
+ {
+ auto &RootTbl = m_RootParams.GetRootTable(rt);
+ auto &d3d12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(RootTbl);
+ VERIFY_EXPR(d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE);
+
+ auto TableSize = RootTbl.GetDescriptorTableSize();
+ VERIFY(d3d12RootParam.DescriptorTable.NumDescriptorRanges > 0 && TableSize > 0, "Unexpected empty descriptor table");
+ auto IsSamplerTable = d3d12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ auto VarType = RootTbl.GetShaderVariableType();
+ (IsSamplerTable ? m_TotalSamplerSlots : m_TotalSrvCbvUavSlots)[VarType] += TableSize;
+ }
+
+#ifdef _DEBUG
+ dbgVerifyRootParameters();
+#endif
+
+ D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
+ rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+
+ auto TotalParams = m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews();
+ std::vector<D3D12_ROOT_PARAMETER, STDAllocatorRawMem<D3D12_ROOT_PARAMETER> > D3D12Parameters( TotalParams, D3D12_ROOT_PARAMETER(), STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector<D3D12_ROOT_PARAMETER>") );
+ for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
+ {
+ auto &RootTable = m_RootParams.GetRootTable(rt);
+ const D3D12_ROOT_PARAMETER &SrcParam = RootTable;
+ VERIFY( SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected" )
+ D3D12Parameters[RootTable.GetRootIndex()] = SrcParam;
+ }
+ for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
+ {
+ auto &RootView = m_RootParams.GetRootView(rv);
+ const D3D12_ROOT_PARAMETER &SrcParam = RootView;
+ VERIFY( SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV, "Root CBV is expected" )
+ D3D12Parameters[RootView.GetRootIndex()] = SrcParam;
+ }
+
+
+ rootSignatureDesc.NumParameters = static_cast<UINT>(D3D12Parameters.size());
+ rootSignatureDesc.pParameters = D3D12Parameters.size() ? D3D12Parameters.data() : nullptr;
+
+ UINT TotalD3D12StaticSamplers = 0;
+ for(const auto &StSam : m_StaticSamplers)
+ TotalD3D12StaticSamplers += StSam.ArraySize;
+ rootSignatureDesc.NumStaticSamplers = TotalD3D12StaticSamplers;
+ rootSignatureDesc.pStaticSamplers = nullptr;
+ std::vector<D3D12_STATIC_SAMPLER_DESC, STDAllocatorRawMem<D3D12_STATIC_SAMPLER_DESC> > D3D12StaticSamplers( STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector<D3D12_STATIC_SAMPLER_DESC>") );
+ D3D12StaticSamplers.reserve(TotalD3D12StaticSamplers);
+ if ( !m_StaticSamplers.empty() )
+ {
+ for(size_t s=0; s < m_StaticSamplers.size(); ++s)
+ {
+ const auto &StSmplrDesc = m_StaticSamplers[s];
+ const auto &SamDesc = StSmplrDesc.SamplerDesc.Desc;
+ for(UINT ArrInd = 0; ArrInd < StSmplrDesc.ArraySize; ++ArrInd)
+ {
+ D3D12StaticSamplers.emplace_back(
+ D3D12_STATIC_SAMPLER_DESC{
+ FilterTypeToD3D12Filter(SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter),
+ TexAddressModeToD3D12AddressMode(SamDesc.AddressU),
+ TexAddressModeToD3D12AddressMode(SamDesc.AddressV),
+ TexAddressModeToD3D12AddressMode(SamDesc.AddressW),
+ SamDesc.MipLODBias,
+ SamDesc.MaxAnisotropy,
+ ComparisonFuncToD3D12ComparisonFunc(SamDesc.ComparisonFunc),
+ BorderColorToD3D12StaticBorderColor(SamDesc.BorderColor),
+ SamDesc.MinLOD,
+ SamDesc.MaxLOD,
+ StSmplrDesc.ShaderRegister + ArrInd,
+ StSmplrDesc.RegisterSpace,
+ StSmplrDesc.ShaderVisibility
+ }
+ );
+ }
+ }
+ rootSignatureDesc.pStaticSamplers = D3D12StaticSamplers.data();
+
+ // Release static samplers array, we no longer need it
+ std::vector<StaticSamplerAttribs, STDAllocatorRawMem<StaticSamplerAttribs> > EmptySamplers( STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector<StaticSamplerAttribs>") );
+ m_StaticSamplers.swap( EmptySamplers );
+
+ VERIFY_EXPR(D3D12StaticSamplers.size() == TotalD3D12StaticSamplers);
+ }
+
+
+ CComPtr<ID3DBlob> signature;
+ CComPtr<ID3DBlob> error;
+ HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
+ hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pd3d12RootSignature), reinterpret_cast<void**>( static_cast<ID3D12RootSignature**>(&m_pd3d12RootSignature)));
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature")
+
+
+ bool bHasDynamicResources = m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC]!=0 || m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC]!=0;
+ if(bHasDynamicResources)
+ {
+ CommitDescriptorHandles = &RootSignature::CommitDescriptorHandlesInternal_SMD<false>;
+ TransitionAndCommitDescriptorHandles = &RootSignature::CommitDescriptorHandlesInternal_SMD<true>;
+ }
+ else
+ {
+ CommitDescriptorHandles = &RootSignature::CommitDescriptorHandlesInternal_SM<false>;
+ TransitionAndCommitDescriptorHandles = &RootSignature::CommitDescriptorHandlesInternal_SM<true>;
+ }
+}
+
+void RootSignature::InitResourceCache(RenderDeviceD3D12Impl *pDeviceD3D12Impl, ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator &CacheMemAllocator)const
+{
+ std::vector<Uint32, STDAllocatorRawMem<Uint32> > CacheTableSizes(m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(), 0, STD_ALLOCATOR_RAW_MEM(Uint32, GetRawAllocator(), "Allocator for vector<Uint32>") );
+ for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
+ {
+ auto &RootParam = m_RootParams.GetRootTable(rt);
+ CacheTableSizes[RootParam.GetRootIndex()] = RootParam.GetDescriptorTableSize();
+ }
+
+ for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
+ {
+ auto &RootParam = m_RootParams.GetRootView(rv);
+ CacheTableSizes[RootParam.GetRootIndex()] = 1;
+ }
+ ResourceCache.Initialize(CacheMemAllocator, static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data());
+
+ Uint32 TotalSrvCbvUavDescriptors =
+ m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_STATIC] +
+ m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_MUTABLE];
+ Uint32 TotalSamplerDescriptors =
+ m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_STATIC] +
+ m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_MUTABLE];
+
+ DescriptorHeapAllocation CbcSrvUavHeapSpace, SamplerHeapSpace;
+ if(TotalSrvCbvUavDescriptors)
+ CbcSrvUavHeapSpace = pDeviceD3D12Impl->AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, TotalSrvCbvUavDescriptors);
+
+ if(TotalSamplerDescriptors)
+ SamplerHeapSpace = pDeviceD3D12Impl->AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, TotalSamplerDescriptors);
+
+ Uint32 SrvCbvUavTblStartOffset = 0;
+ Uint32 SamplerTblStartOffset = 0;
+ for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
+ {
+ auto &RootParam = m_RootParams.GetRootTable(rt);
+ const auto& D3D12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(RootParam);
+ auto &RootTableCache = ResourceCache.GetRootTable(RootParam.GetRootIndex());
+
+ SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
+#ifdef _DEBUG
+ dbgShaderType = ShaderTypeFromShaderVisibility(D3D12RootParam.ShaderVisibility);
+#endif
+ VERIFY_EXPR( D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE )
+
+ auto TableSize = RootParam.GetDescriptorTableSize();
+ VERIFY(TableSize > 0, "Unexpected empty descriptor table");
+
+ auto HeapType = HeapTypeFromRangeType(D3D12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType);
+
+#ifdef _DEBUG
+ RootTableCache.SetDebugAttribs( TableSize, HeapType, dbgShaderType );
+#endif
+
+ // Space for dynamic variables is allocated at every draw call
+ if( RootParam.GetShaderVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC )
+ {
+ if( HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV )
+ {
+ RootTableCache.TableStartOffset = SrvCbvUavTblStartOffset;
+ SrvCbvUavTblStartOffset += TableSize;
+ }
+ else
+ {
+ RootTableCache.TableStartOffset = SamplerTblStartOffset;
+ SamplerTblStartOffset += TableSize;
+ }
+ }
+ else
+ {
+ VERIFY_EXPR(RootTableCache.TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset)
+ }
+ }
+
+#ifdef _DEBUG
+ for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
+ {
+ auto &RootParam = m_RootParams.GetRootView(rv);
+ const auto& D3D12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(RootParam);
+ auto &RootTableCache = ResourceCache.GetRootTable(RootParam.GetRootIndex());
+ VERIFY_EXPR(RootTableCache.TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset)
+
+ SHADER_TYPE dbgShaderType = ShaderTypeFromShaderVisibility(D3D12RootParam.ShaderVisibility);
+ VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV);
+ RootTableCache.SetDebugAttribs( 1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType );
+ }
+#endif
+
+ VERIFY_EXPR(SrvCbvUavTblStartOffset == SrvCbvUavTblStartOffset);
+ VERIFY_EXPR(SamplerTblStartOffset == SamplerTblStartOffset);
+
+ ResourceCache.SetDescriptorHeapSpace(std::move(CbcSrvUavHeapSpace), std::move(SamplerHeapSpace));
+}
+
+const D3D12_RESOURCE_STATES D3D12_RESOURCE_STATE_SHADER_RESOURCE = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+
+__forceinline
+void TransitionResource(CommandContext &Ctx,
+ ShaderResourceCacheD3D12::Resource &Res,
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType)
+{
+ switch (Res.Type)
+ {
+ case CachedResourceType::CBV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type");
+ // Not using QueryInterface() for the sake of efficiency
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(Res.pObject.RawPtr());
+ if( !pBuffToTransition->CheckAllStates(D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) )
+ Ctx.TransitionResource(pBuffToTransition, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER );
+ }
+ break;
+
+ case CachedResourceType::BufSRV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
+ auto *pBuffViewD3D12 = ValidatedCast<BufferViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(pBuffViewD3D12->GetBuffer());
+ if( !pBuffToTransition->CheckAllStates(D3D12_RESOURCE_STATE_SHADER_RESOURCE) )
+ Ctx.TransitionResource(pBuffToTransition, D3D12_RESOURCE_STATE_SHADER_RESOURCE );
+ }
+ break;
+
+ case CachedResourceType::BufUAV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type");
+ auto *pBuffViewD3D12 = ValidatedCast<BufferViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(pBuffViewD3D12->GetBuffer());
+ if( !pBuffToTransition->CheckAllStates(D3D12_RESOURCE_STATE_UNORDERED_ACCESS) )
+ Ctx.TransitionResource(pBuffToTransition, D3D12_RESOURCE_STATE_UNORDERED_ACCESS );
+ }
+ break;
+
+ case CachedResourceType::TexSRV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
+ auto *pTexViewD3D12 = ValidatedCast<TextureViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pTexToTransition = ValidatedCast<TextureD3D12Impl>(pTexViewD3D12->GetTexture());
+ if( !pTexToTransition->CheckAllStates(D3D12_RESOURCE_STATE_SHADER_RESOURCE) )
+ Ctx.TransitionResource(pTexToTransition, D3D12_RESOURCE_STATE_SHADER_RESOURCE );
+ }
+ break;
+
+ case CachedResourceType::TexUAV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type");
+ auto *pTexViewD3D12 = ValidatedCast<TextureViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pTexToTransition = ValidatedCast<TextureD3D12Impl>(pTexViewD3D12->GetTexture());
+ if( !pTexToTransition->CheckAllStates(D3D12_RESOURCE_STATE_UNORDERED_ACCESS) )
+ Ctx.TransitionResource(pTexToTransition, D3D12_RESOURCE_STATE_UNORDERED_ACCESS );
+ }
+ break;
+
+ case CachedResourceType::Sampler:
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type");
+ break;
+
+ default:
+ // Resource not bound
+ VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type")
+ VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected")
+ }
+}
+
+
+#ifdef _DEBUG
+void DbgVerifyResourceState(ShaderResourceCacheD3D12::Resource &Res,
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType)
+{
+ switch (Res.Type)
+ {
+ case CachedResourceType::CBV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV, "Unexpected descriptor range type");
+ // Not using QueryInterface() for the sake of efficiency
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(Res.pObject.RawPtr());
+ auto State = pBuffToTransition->GetState();
+ if( (State & D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) != D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER )
+ LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" );
+ }
+ break;
+
+ case CachedResourceType::BufSRV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
+ auto *pBuffViewD3D12 = ValidatedCast<BufferViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(pBuffViewD3D12->GetBuffer());
+ auto State = pBuffToTransition->GetState();
+ if( (State & D3D12_RESOURCE_STATE_SHADER_RESOURCE) != D3D12_RESOURCE_STATE_SHADER_RESOURCE )
+ LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" );
+ }
+ break;
+
+ case CachedResourceType::BufUAV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type");
+ auto *pBuffViewD3D12 = ValidatedCast<BufferViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(pBuffViewD3D12->GetBuffer());
+ auto State = pBuffToTransition->GetState();
+ if( (State & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != D3D12_RESOURCE_STATE_UNORDERED_ACCESS )
+ LOG_ERROR_MESSAGE("Resource \"", pBuffToTransition->GetDesc().Name, "\" is not in D3D12_RESOURCE_STATE_UNORDERED_ACCESS state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" );
+ }
+ break;
+
+ case CachedResourceType::TexSRV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type");
+ auto *pTexViewD3D12 = ValidatedCast<TextureViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pTexToTransition = ValidatedCast<TextureD3D12Impl>(pTexViewD3D12->GetTexture());
+ auto State = pTexToTransition->GetState();
+ if( (State & D3D12_RESOURCE_STATE_SHADER_RESOURCE) != D3D12_RESOURCE_STATE_SHADER_RESOURCE )
+ LOG_ERROR_MESSAGE("Resource \"", pTexToTransition->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" );
+ }
+ break;
+
+ case CachedResourceType::TexUAV:
+ {
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV, "Unexpected descriptor range type");
+ auto *pTexViewD3D12 = ValidatedCast<TextureViewD3D12Impl>(Res.pObject.RawPtr());
+ auto *pTexToTransition = ValidatedCast<TextureD3D12Impl>(pTexViewD3D12->GetTexture());
+ auto State = pTexToTransition->GetState();
+ if( (State & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != D3D12_RESOURCE_STATE_UNORDERED_ACCESS )
+ LOG_ERROR_MESSAGE("Resource \"", pTexToTransition->GetDesc().Name, "\" is not in D3D12_RESOURCE_STATE_UNORDERED_ACCESS state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?" );
+ }
+ break;
+
+ case CachedResourceType::Sampler:
+ VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type");
+ break;
+
+ default:
+ // Resource not bound
+ VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type")
+ VERIFY(Res.pObject == nullptr && Res.CPUDescriptorHandle.ptr == 0, "Bound resource is unexpected")
+ }
+}
+#endif
+
+template<class TOperation>
+__forceinline void RootSignature::RootParamsManager::ProcessRootTables(TOperation Operation)const
+{
+ for(Uint32 rt = 0; rt < m_NumRootTables; ++rt)
+ {
+ auto &RootTable = GetRootTable(rt);
+ auto RootInd = RootTable.GetRootIndex();
+ const D3D12_ROOT_PARAMETER& D3D12Param = RootTable;
+
+ VERIFY_EXPR(D3D12Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE);
+
+ auto &d3d12Table = D3D12Param.DescriptorTable;
+ VERIFY(d3d12Table.NumDescriptorRanges > 0 && RootTable.GetDescriptorTableSize() > 0, "Unexepected empty descriptor table");
+ bool IsResourceTable = d3d12Table.pDescriptorRanges[0].RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
+#ifdef _DEBUG
+ dbgHeapType = IsResourceTable ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
+#endif
+ Operation(RootInd, RootTable, D3D12Param, IsResourceTable, dbgHeapType);
+ }
+}
+
+template<class TOperation>
+__forceinline void ProcessCachedTableResources(Uint32 RootInd,
+ const D3D12_ROOT_PARAMETER& D3D12Param,
+ ShaderResourceCacheD3D12& ResourceCache,
+ D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType,
+ TOperation Operation)
+{
+ for (UINT r = 0; r < D3D12Param.DescriptorTable.NumDescriptorRanges; ++r)
+ {
+ const auto &range = D3D12Param.DescriptorTable.pDescriptorRanges[r];
+ for (UINT d = 0; d < range.NumDescriptors; ++d)
+ {
+ SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
+#ifdef _DEBUG
+ dbgShaderType = ShaderTypeFromShaderVisibility(D3D12Param.ShaderVisibility);
+ VERIFY(dbgHeapType == HeapTypeFromRangeType(range.RangeType), "Mistmatch between descriptor heap type and descriptor range type");
+#endif
+ auto OffsetFromTableStart = range.OffsetInDescriptorsFromTableStart + d;
+ auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(OffsetFromTableStart, dbgHeapType, dbgShaderType);
+
+ Operation(OffsetFromTableStart, range, Res);
+ }
+ }
+}
+
+
+template<bool PerformResourceTransitions>
+void RootSignature::CommitDescriptorHandlesInternal_SMD(RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ CommandContext &Ctx,
+ bool IsCompute)const
+{
+ auto *pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
+
+ Uint32 NumDynamicCbvSrvUavDescriptors = m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC];
+ Uint32 NumDynamicSamplerDescriptors = m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC];
+ VERIFY_EXPR(NumDynamicCbvSrvUavDescriptors > 0 || NumDynamicSamplerDescriptors > 0);
+
+ DescriptorHeapAllocation DynamicCbvSrvUavDescriptors, DynamicSamplerDescriptors;
+ if(NumDynamicCbvSrvUavDescriptors)
+ DynamicCbvSrvUavDescriptors = Ctx.AllocateDynamicGPUVisibleDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, NumDynamicCbvSrvUavDescriptors);
+ if(NumDynamicSamplerDescriptors)
+ DynamicSamplerDescriptors = Ctx.AllocateDynamicGPUVisibleDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, NumDynamicSamplerDescriptors);
+
+ CommandContext::ShaderDescriptorHeaps Heaps(ResourceCache.GetSrvCbvUavDescriptorHeap(), ResourceCache.GetSamplerDescriptorHeap());
+ if(Heaps.pSamplerHeap == nullptr)
+ Heaps.pSamplerHeap = DynamicSamplerDescriptors.GetDescriptorHeap();
+
+ if(Heaps.pSrvCbvUavHeap == nullptr)
+ Heaps.pSrvCbvUavHeap = DynamicCbvSrvUavDescriptors.GetDescriptorHeap();
+
+ if(NumDynamicCbvSrvUavDescriptors)
+ VERIFY(DynamicCbvSrvUavDescriptors.GetDescriptorHeap() == Heaps.pSrvCbvUavHeap, "Inconsistent CbvSrvUav descriptor heaps" )
+ if(NumDynamicSamplerDescriptors)
+ VERIFY(DynamicSamplerDescriptors.GetDescriptorHeap() == Heaps.pSamplerHeap, "Inconsistent Sampler descriptor heaps" )
+
+ if(Heaps)
+ Ctx.SetDescriptorHeaps(Heaps);
+
+ // Offset to the beginning of the current dynamic CBV_SRV_UAV/SAMPLER table from
+ // the start of the allocation
+ Uint32 DynamicCbvSrvUavTblOffset = 0;
+ Uint32 DynamicSamplerTblOffset = 0;
+
+ m_RootParams.ProcessRootTables(
+ [&](Uint32 RootInd, const RootParameter &RootTable, const D3D12_ROOT_PARAMETER& D3D12Param, bool IsResourceTable, D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType )
+ {
+ D3D12_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle;
+ bool IsDynamicTable = RootTable.GetShaderVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC;
+ if (IsDynamicTable)
+ {
+ if( IsResourceTable )
+ RootTableGPUDescriptorHandle = DynamicCbvSrvUavDescriptors.GetGpuHandle(DynamicCbvSrvUavTblOffset);
+ else
+ RootTableGPUDescriptorHandle = DynamicSamplerDescriptors.GetGpuHandle(DynamicSamplerTblOffset);
+ }
+ else
+ {
+ RootTableGPUDescriptorHandle = IsResourceTable ?
+ ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(RootInd) :
+ ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(RootInd);
+ VERIFY(RootTableGPUDescriptorHandle.ptr != 0, "Unexpected null GPU descriptor handle")
+ }
+
+ if(IsCompute)
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
+ else
+ Ctx.GetCommandList()->SetGraphicsRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
+
+ ProcessCachedTableResources(RootInd, D3D12Param, ResourceCache, dbgHeapType,
+ [&](UINT OffsetFromTableStart, const D3D12_DESCRIPTOR_RANGE &range, ShaderResourceCacheD3D12::Resource &Res)
+ {
+ if(PerformResourceTransitions)
+ {
+ TransitionResource(Ctx, Res, range.RangeType);
+ }
+#ifdef _DEBUG
+ else
+ {
+ DbgVerifyResourceState(Res, range.RangeType);
+ }
+#endif
+
+ if(IsDynamicTable)
+ {
+ if (IsResourceTable)
+ {
+ if( Res.CPUDescriptorHandle.ptr == 0 )
+ LOG_ERROR_MESSAGE("No valid CbvSrvUav descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetFromTableStart)
+
+ VERIFY( DynamicCbvSrvUavTblOffset < NumDynamicCbvSrvUavDescriptors, "Not enough space in the descriptor heap allocation")
+
+ pd3d12Device->CopyDescriptorsSimple(1, DynamicCbvSrvUavDescriptors.GetCpuHandle(DynamicCbvSrvUavTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ ++DynamicCbvSrvUavTblOffset;
+ }
+ else
+ {
+ if( Res.CPUDescriptorHandle.ptr == 0 )
+ LOG_ERROR_MESSAGE("No valid sampler descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetFromTableStart)
+
+ VERIFY( DynamicSamplerTblOffset < NumDynamicSamplerDescriptors, "Not enough space in the descriptor heap allocation")
+
+ pd3d12Device->CopyDescriptorsSimple(1, DynamicSamplerDescriptors.GetCpuHandle(DynamicSamplerTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ ++DynamicSamplerTblOffset;
+ }
+ }
+ }
+ );
+ }
+ );
+
+ VERIFY_EXPR( DynamicCbvSrvUavTblOffset == NumDynamicCbvSrvUavDescriptors );
+ VERIFY_EXPR( DynamicSamplerTblOffset == NumDynamicSamplerDescriptors );
+}
+
+template<bool PerformResourceTransitions>
+void RootSignature::CommitDescriptorHandlesInternal_SM(RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ ShaderResourceCacheD3D12& ResourceCache,
+ CommandContext &Ctx,
+ bool IsCompute)const
+{
+ VERIFY_EXPR(m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC] == 0 && m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC] == 0);
+
+ CommandContext::ShaderDescriptorHeaps Heaps(ResourceCache.GetSrvCbvUavDescriptorHeap(), ResourceCache.GetSamplerDescriptorHeap());
+ if(Heaps)
+ Ctx.SetDescriptorHeaps(Heaps);
+
+ m_RootParams.ProcessRootTables(
+ [&](Uint32 RootInd, const RootParameter &RootTable, const D3D12_ROOT_PARAMETER& D3D12Param, bool IsResourceTable, D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType )
+ {
+ VERIFY(RootTable.GetShaderVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC, "Unexpected dynamic resource");
+
+ D3D12_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle = IsResourceTable ?
+ ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(RootInd) :
+ ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(RootInd);
+ VERIFY(RootTableGPUDescriptorHandle.ptr != 0, "Unexpected null GPU descriptor handle")
+
+ if(IsCompute)
+ Ctx.GetCommandList()->SetComputeRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
+ else
+ Ctx.GetCommandList()->SetGraphicsRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
+
+ if(PerformResourceTransitions)
+ {
+ ProcessCachedTableResources(RootInd, D3D12Param, ResourceCache, dbgHeapType,
+ [&](UINT OffsetFromTableStart, const D3D12_DESCRIPTOR_RANGE &range, ShaderResourceCacheD3D12::Resource &Res)
+ {
+ TransitionResource(Ctx, Res, range.RangeType);
+ }
+ );
+ }
+#ifdef _DEBUG
+ else
+ {
+ ProcessCachedTableResources(RootInd, D3D12Param, ResourceCache, dbgHeapType,
+ [&](UINT OffsetFromTableStart, const D3D12_DESCRIPTOR_RANGE &range, ShaderResourceCacheD3D12::Resource &Res)
+ {
+ DbgVerifyResourceState(Res, range.RangeType);
+ }
+ );
+ }
+#endif
+ }
+ );
+}
+
+
+void RootSignature::TransitionResources(ShaderResourceCacheD3D12& ResourceCache,
+ class CommandContext &Ctx)const
+{
+ m_RootParams.ProcessRootTables(
+ [&](Uint32 RootInd, const RootParameter &RootTable, const D3D12_ROOT_PARAMETER& D3D12Param, bool IsResourceTable, D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType )
+ {
+ ProcessCachedTableResources(RootInd, D3D12Param, ResourceCache, dbgHeapType,
+ [&](UINT OffsetFromTableStart, const D3D12_DESCRIPTOR_RANGE &range, ShaderResourceCacheD3D12::Resource &Res)
+ {
+ TransitionResource(Ctx, Res, range.RangeType);
+ }
+ );
+ }
+ );
+}
+
+
+void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache,
+ CommandContext &Ctx,
+ bool IsCompute,
+ Uint32 ContextId)const
+{
+ for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
+ {
+ auto &RootView = m_RootParams.GetRootView(rv);
+ auto RootInd = RootView.GetRootIndex();
+
+ SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
+#ifdef _DEBUG
+ auto &Param = static_cast<const D3D12_ROOT_PARAMETER&>( RootView );
+ VERIFY_EXPR(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV);
+ dbgShaderType = ShaderTypeFromShaderVisibility(Param.ShaderVisibility);
+#endif
+
+ auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType);
+ auto *pBuffToTransition = ValidatedCast<BufferD3D12Impl>(Res.pObject.RawPtr());
+ if( !pBuffToTransition->CheckAllStates(D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) )
+ Ctx.TransitionResource(pBuffToTransition, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+
+ D3D12_GPU_VIRTUAL_ADDRESS CBVAddress = pBuffToTransition->GetGPUAddress(ContextId);
+ if(IsCompute)
+ Ctx.GetCommandList()->SetComputeRootConstantBufferView(RootInd, CBVAddress);
+ else
+ Ctx.GetCommandList()->SetGraphicsRootConstantBufferView(RootInd, CBVAddress);
+ }
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp
new file mode 100644
index 00000000..e6e95bac
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp
@@ -0,0 +1,62 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "SamplerD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+
+namespace Diligent
+{
+
+SamplerD3D12Impl::SamplerD3D12Impl(FixedBlockMemoryAllocator &SamplerObjAllocator, class RenderDeviceD3D12Impl *pRenderDeviceD3D12, const SamplerDesc& SamplerDesc) :
+ TSamplerBase(SamplerObjAllocator, pRenderDeviceD3D12, SamplerDesc)
+{
+ auto *pD3D12Device = pRenderDeviceD3D12->GetD3D12Device();
+ D3D12_SAMPLER_DESC D3D12SamplerDesc =
+ {
+ FilterTypeToD3D12Filter(SamplerDesc.MinFilter, SamplerDesc.MagFilter, SamplerDesc.MipFilter),
+ TexAddressModeToD3D12AddressMode(SamplerDesc.AddressU),
+ TexAddressModeToD3D12AddressMode(SamplerDesc.AddressV),
+ TexAddressModeToD3D12AddressMode(SamplerDesc.AddressW),
+ SamplerDesc.MipLODBias,
+ SamplerDesc.MaxAnisotropy,
+ ComparisonFuncToD3D12ComparisonFunc(SamplerDesc.ComparisonFunc),
+ {SamplerDesc.BorderColor[0], SamplerDesc.BorderColor[1], SamplerDesc.BorderColor[2], SamplerDesc.BorderColor[3]},
+ SamplerDesc.MinLOD,
+ SamplerDesc.MaxLOD
+ };
+
+ auto CPUDescriptorAlloc = pRenderDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ m_Descriptor = std::move(CPUDescriptorAlloc);
+ pD3D12Device->CreateSampler(&D3D12SamplerDesc, m_Descriptor.GetCpuHandle());
+}
+
+SamplerD3D12Impl::~SamplerD3D12Impl()
+{
+
+}
+
+IMPLEMENT_QUERY_INTERFACE( SamplerD3D12Impl, IID_SamplerD3D12, TSamplerBase )
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp
new file mode 100644
index 00000000..fd43fa49
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp
@@ -0,0 +1,81 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include <D3Dcompiler.h>
+
+#include "ShaderD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DataBlobImpl.h"
+#include "D3DShaderResourceLoader.h"
+
+using namespace Diligent;
+
+namespace Diligent
+{
+
+
+ShaderD3D12Impl::ShaderD3D12Impl(FixedBlockMemoryAllocator& ShaderObjAllocator, RenderDeviceD3D12Impl *pRenderDeviceD3D12, const ShaderCreationAttribs &ShaderCreationAttribs) :
+ TShaderBase(ShaderObjAllocator, pRenderDeviceD3D12, ShaderCreationAttribs.Desc),
+ ShaderD3DBase(ShaderCreationAttribs),
+ m_StaticResLayout(*this, GetRawAllocator()),
+ m_DummyShaderVar(*this),
+ m_ConstResCache(ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources)
+{
+ // Load shader resources
+ auto &Allocator = GetRawAllocator();
+ auto *pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(ShaderResourcesD3D12));
+ auto *pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc);
+ m_pShaderResources.reset(pResources, STDDeleterRawMem<ShaderResourcesD3D12>(Allocator));
+
+ // Clone only static resources that will be set directly in the shader
+ SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_STATIC};
+ m_StaticResLayout.Initialize(pRenderDeviceD3D12->GetD3D12Device(), m_pShaderResources, GetRawAllocator(), VarTypes, _countof(VarTypes), &m_ConstResCache, nullptr);
+}
+
+ShaderD3D12Impl::~ShaderD3D12Impl()
+{
+}
+
+void ShaderD3D12Impl::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags)
+{
+ m_StaticResLayout.BindResources(pResourceMapping, Flags, &m_ConstResCache);
+}
+
+IShaderVariable* ShaderD3D12Impl::GetShaderVariable(const Char* Name)
+{
+ auto *pVar = m_StaticResLayout.GetShaderVariable(Name);
+ if(pVar == nullptr)
+ pVar = &m_DummyShaderVar;
+ return pVar;
+}
+
+#ifdef VERIFY_SHADER_BINDINGS
+void ShaderD3D12Impl::DbgVerifyStaticResourceBindings()
+{
+ m_StaticResLayout.dbgVerifyBindings();
+}
+#endif
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp
new file mode 100644
index 00000000..118707a2
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp
@@ -0,0 +1,139 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "ShaderResourceBindingD3D12Impl.h"
+#include "PipelineStateD3D12Impl.h"
+#include "ShaderD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+
+namespace Diligent
+{
+
+ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl( FixedBlockMemoryAllocator &SRBAllocator, PipelineStateD3D12Impl *pPSO, bool IsPSOInternal) :
+ TBase( SRBAllocator, pPSO, IsPSOInternal ),
+ m_ShaderResourceCache(ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources)
+{
+ auto *ppShaders = pPSO->GetShaders();
+ m_NumShaders = pPSO->GetNumShaders();
+
+ auto *pRenderDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pPSO->GetDevice());
+ pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, pPSO->GetResourceCacheDataAllocator());
+
+ auto *pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12", m_NumShaders * sizeof(ShaderResourceLayoutD3D12));
+ m_pResourceLayouts = reinterpret_cast<ShaderResourceLayoutD3D12*>(pResLayoutRawMem);
+
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto *pShader = ppShaders[s];
+ auto ShaderType = pShader->GetDesc().ShaderType;
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+
+ auto &ShaderResLayoutDataAllocator = pPSO->GetShaderResourceLayoutDataAllocator(ShaderInd);
+
+ SHADER_VARIABLE_TYPE Types[] = {SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC};
+ const auto &SrcLayout = pPSO->GetShaderResLayout(ShaderType);
+ new (m_pResourceLayouts + s) ShaderResourceLayoutD3D12(*this, SrcLayout, ShaderResLayoutDataAllocator, Types, _countof(Types), m_ShaderResourceCache);
+
+ m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ }
+}
+
+ShaderResourceBindingD3D12Impl::~ShaderResourceBindingD3D12Impl()
+{
+ for(Uint32 l = 0; l < m_NumShaders; ++l)
+ m_pResourceLayouts[l].~ShaderResourceLayoutD3D12();
+
+ GetRawAllocator().Free(m_pResourceLayouts);
+}
+
+IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingD3D12Impl, IID_ShaderResourceBindingD3D12, TBase )
+
+void ShaderResourceBindingD3D12Impl::BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags)
+{
+ for (auto ShaderInd = 0; ShaderInd <= CSInd; ++ShaderInd )
+ {
+ if (ShaderFlags & GetShaderTypeFromIndex(ShaderInd))
+ {
+ auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
+ if(ResLayoutInd >= 0)
+ {
+ m_pResourceLayouts[ResLayoutInd].BindResources(pResMapping, Flags, &m_ShaderResourceCache);
+ }
+ }
+ }
+}
+
+IShaderVariable *ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderType, const char *Name)
+{
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
+ if (ResLayoutInd < 0)
+ {
+ LOG_ERROR_MESSAGE("Failed to find shader variable \"", Name,"\" in shader resource binding: shader type ", GetShaderTypeLiteralName(ShaderType), " is not initialized");
+ return ValidatedCast<PipelineStateD3D12Impl>(GetPipelineState())->GetDummyShaderVar();
+ }
+ auto *pVar = m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name);
+ if(pVar == nullptr)
+ pVar = ValidatedCast<PipelineStateD3D12Impl>(GetPipelineState())->GetDummyShaderVar();
+
+ return pVar;
+}
+
+#ifdef VERIFY_SHADER_BINDINGS
+void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineStateD3D12Impl *pPSO)
+{
+ auto *pRefPSO = GetPipelineState();
+ if (pRefPSO != pPSO)
+ {
+ LOG_ERROR("Shader resource binding does not match the pipeline state \"", pPSO->GetDesc().Name, '\"');
+ return;
+ }
+ for(Uint32 l = 0; l < m_NumShaders; ++l)
+ m_pResourceLayouts[l].dbgVerifyBindings();
+}
+#endif
+
+
+void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const PipelineStateD3D12Impl *pPSO)
+{
+ VERIFY(!StaticResourcesInitialized(), "Static resources have already been initialized")
+ VERIFY(pPSO == GetPipelineState(), "Invalid pipeline state provided")
+
+ auto NumShaders = pPSO->GetNumShaders();
+ auto ppShaders = pPSO->GetShaders();
+ // Copy static resources
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ auto *pShader = ValidatedCast<ShaderD3D12Impl>( ppShaders[s] );
+#ifdef VERIFY_SHADER_BINDINGS
+ pShader->DbgVerifyStaticResourceBindings();
+#endif
+ auto &ConstResLayout = pShader->GetConstResLayout();
+ GetResourceLayout(pShader->GetDesc().ShaderType).CopyStaticResourceDesriptorHandles(ConstResLayout);
+ }
+
+ m_bStaticResourcesInitialized = true;
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp
new file mode 100644
index 00000000..700b49b5
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp
@@ -0,0 +1,84 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "ShaderResourceCacheD3D12.h"
+
+namespace Diligent
+{
+ void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, Uint32 TableSizes[])
+ {
+ // Memory layout:
+ // __________________________________________________________
+ // | m_pResources, m_NumResources |
+ // m_pMemory | |
+ // | | V
+ // | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] |
+ // | A
+ // | |
+ // |________________________________________________|
+ // m_pResources, m_NumResources
+ //
+
+ VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized")
+ m_pAllocator = &MemAllocator;
+ m_NumTables = NumTables;
+ Uint32 TotalResources = 0;
+ for(Uint32 t=0; t < NumTables; ++t)
+ TotalResources += TableSizes[t];
+ auto MemorySize = NumTables * sizeof(RootTable) + TotalResources * sizeof(Resource);
+ if(MemorySize > 0)
+ {
+ m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize);
+ auto *pTables = reinterpret_cast<RootTable*>(m_pMemory);
+ auto *pCurrResPtr = reinterpret_cast<Resource*>(pTables + m_NumTables);
+ for(Uint32 res=0; res < TotalResources; ++res)
+ new(pCurrResPtr + res) Resource();
+
+ for (Uint32 t = 0; t < NumTables; ++t)
+ {
+ new(&GetRootTable(t)) RootTable(TableSizes[t], TableSizes[t] > 0 ? pCurrResPtr : nullptr);
+ pCurrResPtr += TableSizes[t];
+ }
+ VERIFY_EXPR((char*)pCurrResPtr == (char*)m_pMemory + MemorySize);
+ }
+ }
+
+ ShaderResourceCacheD3D12::~ShaderResourceCacheD3D12()
+ {
+ if (m_pMemory)
+ {
+ Uint32 TotalResources = 0;
+ for (Uint32 t = 0; t < m_NumTables; ++t)
+ TotalResources += GetRootTable(t).GetSize();
+ auto *pResources = reinterpret_cast<Resource*>( reinterpret_cast<RootTable*>(m_pMemory) + m_NumTables);
+ for(Uint32 res=0; res < TotalResources; ++res)
+ pResources[res].~Resource();
+ for (Uint32 t = 0; t < m_NumTables; ++t)
+ GetRootTable(t).~RootTable();
+
+ m_pAllocator->Free(m_pMemory);
+ }
+ }
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
new file mode 100644
index 00000000..e0121db7
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
@@ -0,0 +1,1038 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "ShaderResourceLayoutD3D12.h"
+#include "ShaderResourceCacheD3D12.h"
+#include "D3DShaderResourceLoader.h"
+#include "BufferD3D12Impl.h"
+#include "BufferViewD3D12.h"
+#include "TextureD3D12Impl.h"
+#include "TextureViewD3D12Impl.h"
+#include "SamplerD3D12Impl.h"
+#include "ShaderD3D12Impl.h"
+#include "RootSignature.h"
+#include "PipelineStateD3D12Impl.h"
+
+namespace Diligent
+{
+
+ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject &Owner,
+ IMemoryAllocator &ResourceLayoutDataAllocator) :
+ m_Owner(Owner),
+#if USE_VARIABLE_HASH_MAP
+ m_VariableHash(STD_ALLOCATOR_RAW_MEM(VariableHashElemType, GetRawAllocator(), "Allocator for unordered_map<HashMapStringKey, IShaderVariable*>")),
+#endif
+ m_ResourceBuffer(nullptr, STDDeleterRawMem<void>(ResourceLayoutDataAllocator))
+{
+}
+
+ShaderResourceLayoutD3D12::~ShaderResourceLayoutD3D12()
+{
+ auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
+ for(Uint32 r=0; r < GetTotalSrvCbvUavCount(); ++r)
+ CbvSrvUav[r].~SRV_CBV_UAV();
+
+ for(Uint32 s=0; s < GetTotalSamplerCount(); ++s)
+ m_Samplers[s].~Sampler();
+}
+
+D3D12_DESCRIPTOR_RANGE_TYPE GetDescriptorRangeType(CachedResourceType ResType)
+{
+ static D3D12_DESCRIPTOR_RANGE_TYPE RangeTypes[(size_t)CachedResourceType::NumTypes] = {};
+ static bool Initialized = false;
+ if (!Initialized)
+ {
+ RangeTypes[(size_t)CachedResourceType::CBV] = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
+ RangeTypes[(size_t)CachedResourceType::TexSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ RangeTypes[(size_t)CachedResourceType::BufSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ RangeTypes[(size_t)CachedResourceType::TexUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ RangeTypes[(size_t)CachedResourceType::BufUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ RangeTypes[(size_t)CachedResourceType::Sampler] = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ Initialized = true;
+ }
+ auto Ind = static_cast<size_t>(ResType);
+ VERIFY(Ind >= 0 && Ind < (size_t)CachedResourceType::NumTypes, "Unexpected resource type")
+ return RangeTypes[Ind];
+}
+
+void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator &Allocator)
+{
+ VERIFY( &m_ResourceBuffer.get_deleter().m_Allocator == &Allocator, "Inconsistent memory allocators" )
+ Uint32 TotalSrvCbvUav = GetTotalSrvCbvUavCount();
+ Uint32 TotalSamplers = GetTotalSamplerCount();
+ size_t MemSize = TotalSrvCbvUav * sizeof(SRV_CBV_UAV) + TotalSamplers * sizeof(Sampler);
+ if(MemSize == 0)
+ return;
+
+ auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader resource layout resources", MemSize);
+ m_ResourceBuffer.reset(pRawMem);
+ if(TotalSamplers)
+ m_Samplers = reinterpret_cast<Sampler*>(reinterpret_cast<SRV_CBV_UAV*>(pRawMem) + TotalSrvCbvUav);
+}
+
+// Clones layout from the reference layout
+// Root indices and descriptor table offsets must be correct
+// Resource cache is not initialized.
+ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject &Owner,
+ const ShaderResourceLayoutD3D12& SrcLayout,
+ IMemoryAllocator &ResourceLayoutDataAllocator,
+ const SHADER_VARIABLE_TYPE *AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12 &ResourceCache) :
+ ShaderResourceLayoutD3D12(Owner, ResourceLayoutDataAllocator)
+{
+ m_pd3d12Device = SrcLayout.m_pd3d12Device;
+ m_pResources = SrcLayout.m_pResources;
+ m_pResourceCache = &ResourceCache;
+
+ Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ if( !IsAllowedType(VarType, AllowedTypeBits))
+ continue;
+
+ m_NumCbvSrvUav[VarType] = SrcLayout.m_NumCbvSrvUav[VarType];
+ m_NumSamplers[VarType] = SrcLayout.m_NumSamplers[VarType];
+ }
+
+ AllocateMemory(ResourceLayoutDataAllocator);
+
+ Uint32 CurrCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+ Uint32 CurrSampler[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ if( !IsAllowedType(VarType, AllowedTypeBits))
+ continue;
+
+ Uint32 NumSrcCbvSrvUav = SrcLayout.m_NumCbvSrvUav[VarType];
+ VERIFY_EXPR(NumSrcCbvSrvUav == m_NumCbvSrvUav[VarType]);
+ for( Uint32 r=0; r < NumSrcCbvSrvUav; ++r )
+ {
+ const auto &SrcRes = SrcLayout.GetSrvCbvUav(VarType, r);
+ Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId;
+ if (SrcRes.IsValidSampler())
+ {
+ const auto &SrcSamplerAttribs = SrcLayout.GetSampler(VarType, SrcRes.GetSamplerId());
+ VERIFY(!SrcSamplerAttribs.Attribs.IsStaticSampler(), "Only non-static samplers can be assigned space in shader cache")
+ VERIFY(SrcSamplerAttribs.Attribs.GetVariableType() == SrcRes.Attribs.GetVariableType(), "Inconsistent texture and sampler variable types" );
+ VERIFY(SrcSamplerAttribs.IsValidRootIndex(), "Root index must be valid")
+ VERIFY(SrcSamplerAttribs.IsValidOffset(), "Offset must be valid")
+ VERIFY_EXPR(SrcSamplerAttribs.Attribs.BindCount == SrcRes.Attribs.BindCount || SrcSamplerAttribs.Attribs.BindCount == 1);
+
+ SamplerId = CurrSampler[VarType];
+ VERIFY(SamplerId <= SRV_CBV_UAV::MaxSamplerId, "SamplerId exceeds maximum allowed value (", SRV_CBV_UAV::MaxSamplerId, ")");
+ VERIFY_EXPR(SamplerId == SrcRes.GetSamplerId());
+ ::new (&GetSampler(VarType, CurrSampler[VarType]++)) Sampler( *this, SrcSamplerAttribs );
+ }
+
+ VERIFY(SrcRes.IsValidRootIndex(), "Root index must be valid")
+ VERIFY(SrcRes.IsValidOffset(), "Offset must be valid")
+ ::new (&GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++)) SRV_CBV_UAV( *this, SrcRes, SamplerId );
+ }
+ }
+
+#ifdef _DEBUG
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ VERIFY_EXPR( CurrCbvSrvUav[VarType] == m_NumCbvSrvUav[VarType] );
+ VERIFY_EXPR( CurrSampler[VarType] == m_NumSamplers[VarType] );
+ }
+#endif
+}
+
+void ShaderResourceLayoutD3D12::Initialize(ID3D12Device *pd3d12Device,
+ const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources,
+ IMemoryAllocator &LayoutDataAllocator,
+ const SHADER_VARIABLE_TYPE *AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12* pResourceCache,
+ RootSignature *pRootSig)
+{
+ m_pResources = pSrcResources;
+ m_pResourceCache = pResourceCache;
+ m_pd3d12Device = pd3d12Device;
+
+ VERIFY_EXPR( (pResourceCache != nullptr) ^ (pRootSig != nullptr) );
+
+ Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+
+ m_pResources->ProcessResources(
+ AllowedVarTypes, NumAllowedTypes,
+
+ [&](const D3DShaderResourceAttribs &CB)
+ {
+ VERIFY_EXPR(IsAllowedType(CB.GetVariableType(), AllowedTypeBits));
+ ++m_NumCbvSrvUav[CB.GetVariableType()];
+ },
+ [&](const D3DShaderResourceAttribs& TexSRV)
+ {
+ auto VarType = TexSRV.GetVariableType();
+ VERIFY_EXPR(IsAllowedType(VarType, AllowedTypeBits));
+ ++m_NumCbvSrvUav[VarType];
+ if(TexSRV.IsValidSampler())
+ {
+ auto SamplerId = TexSRV.GetSamplerId();
+ const auto &SamplerAttribs = m_pResources->GetSampler(SamplerId);
+ VERIFY(SamplerAttribs.GetVariableType() == VarType, "Texture and sampler variable types are not conistent");
+ if(!SamplerAttribs.IsStaticSampler())
+ {
+ ++m_NumSamplers[VarType];
+ }
+ }
+ },
+ [&](const D3DShaderResourceAttribs &TexUAV)
+ {
+ VERIFY_EXPR(IsAllowedType(TexUAV.GetVariableType(), AllowedTypeBits));
+ ++m_NumCbvSrvUav[TexUAV.GetVariableType()];
+ },
+ [&](const D3DShaderResourceAttribs &BufSRV)
+ {
+ VERIFY_EXPR(IsAllowedType(BufSRV.GetVariableType(), AllowedTypeBits));
+ ++m_NumCbvSrvUav[BufSRV.GetVariableType()];
+ },
+ [&](const D3DShaderResourceAttribs &BufUAV)
+ {
+ VERIFY_EXPR(IsAllowedType(BufUAV.GetVariableType(), AllowedTypeBits));
+ ++m_NumCbvSrvUav[BufUAV.GetVariableType()];
+ }
+ );
+
+
+ AllocateMemory(LayoutDataAllocator);
+
+ Uint32 CurrCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+ Uint32 CurrSampler[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
+ int MaxBindPoint[4] = {-1, -1, -1, -1};
+
+ auto AddResource = [&](const D3DShaderResourceAttribs &Attribs, CachedResourceType ResType, Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId)
+ {
+ Uint32 RootIndex = SRV_CBV_UAV::InvalidRootIndex;
+ Uint32 Offset = SRV_CBV_UAV::InvalidOffset;
+ D3D12_DESCRIPTOR_RANGE_TYPE DescriptorRangeType = GetDescriptorRangeType(ResType);
+ if (pRootSig)
+ {
+ pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), Attribs, DescriptorRangeType, RootIndex, Offset );
+ VERIFY(RootIndex <= SRV_CBV_UAV::MaxRootIndex, "Root index excceeds allowed limit");
+ }
+ else
+ {
+ // If root signature is not provided - use artifial root signature to store
+ // static shader resources
+ VERIFY_EXPR(m_pResourceCache != nullptr);
+
+ RootIndex = DescriptorRangeType;
+ Offset = Attribs.BindPoint;
+ // Resources in the static resource cache are indexed by the bind point
+ MaxBindPoint[RootIndex] = std::max(MaxBindPoint[RootIndex], static_cast<int>(Offset + Attribs.BindCount));
+ }
+ VERIFY(RootIndex != SRV_CBV_UAV::InvalidRootIndex, "Root index must be valid")
+ VERIFY(Offset != SRV_CBV_UAV::InvalidOffset, "Offset must be valid")
+
+ // Static samplers are never copied, and SamplerId == InvalidSamplerId
+ ::new (&GetSrvCbvUav(Attribs.GetVariableType(), CurrCbvSrvUav[Attribs.GetVariableType()]++)) SRV_CBV_UAV( *this, Attribs, ResType, RootIndex, Offset, SamplerId);
+ };
+
+
+
+ m_pResources->ProcessResources(
+ AllowedVarTypes, NumAllowedTypes,
+
+ [&](const D3DShaderResourceAttribs &CB)
+ {
+ VERIFY_EXPR( IsAllowedType(CB.GetVariableType(), AllowedTypeBits) );
+ AddResource(CB, CachedResourceType::CBV);
+ },
+ [&](const D3DShaderResourceAttribs& TexSRV)
+ {
+ auto VarType = TexSRV.GetVariableType();
+ VERIFY_EXPR(IsAllowedType(VarType, AllowedTypeBits) )
+
+ Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId;
+ if(TexSRV.IsValidSampler())
+ {
+ const auto &SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId());
+ VERIFY(SrcSamplerAttribs.GetVariableType() == VarType, "Inconsistent texture and sampler variable types" );
+
+ if (SrcSamplerAttribs.IsStaticSampler())
+ {
+ if(pRootSig != nullptr)
+ pRootSig->InitStaticSampler(m_pResources->GetShaderType(), TexSRV.Name, SrcSamplerAttribs);
+
+ // Static samplers are never copied, and SamplerId == InvalidSamplerId
+ }
+ else
+ {
+ Uint32 SamplerRootIndex = Sampler::InvalidRootIndex;
+ Uint32 SamplerOffset = Sampler::InvalidOffset;
+ if (pRootSig)
+ {
+ pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), SrcSamplerAttribs, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, SamplerRootIndex, SamplerOffset );
+ }
+ else
+ {
+ // If root signature is not provided, we are initializing resource cache to store
+ // static shader resources.
+ VERIFY_EXPR(m_pResourceCache != nullptr);
+
+ // We use the following artifial root signature:
+ // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
+ // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
+ // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV, and
+ // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER
+ // Every resource is stored at offset that equals its bind point
+ SamplerRootIndex = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ SamplerOffset = SrcSamplerAttribs.BindPoint;
+ // Resources in the static resource cache are indexed by the bind point
+ MaxBindPoint[SamplerRootIndex] = std::max(MaxBindPoint[SamplerRootIndex], static_cast<int>(SamplerOffset + SrcSamplerAttribs.BindCount));
+ }
+ VERIFY(SamplerRootIndex != Sampler::InvalidRootIndex, "Sampler root index must be valid")
+ VERIFY(SamplerOffset != Sampler::InvalidOffset, "Sampler offset must be valid")
+
+ SamplerId = CurrSampler[VarType];
+ VERIFY(SamplerId <= SRV_CBV_UAV::MaxSamplerId, "Sampler index excceeds allowed limit");
+ ::new (&GetSampler(VarType, CurrSampler[VarType]++)) Sampler( *this, SrcSamplerAttribs, SamplerRootIndex, SamplerOffset );
+ }
+ }
+ AddResource(TexSRV, CachedResourceType::TexSRV, SamplerId);
+ },
+ [&](const D3DShaderResourceAttribs &TexUAV)
+ {
+ VERIFY_EXPR( IsAllowedType(TexUAV.GetVariableType(), AllowedTypeBits) );
+ AddResource(TexUAV, CachedResourceType::TexUAV);
+ },
+ [&](const D3DShaderResourceAttribs &BufSRV)
+ {
+ VERIFY_EXPR( IsAllowedType(BufSRV.GetVariableType(), AllowedTypeBits) );
+ AddResource(BufSRV, CachedResourceType::BufSRV);
+ },
+ [&](const D3DShaderResourceAttribs &BufUAV)
+ {
+ VERIFY_EXPR( IsAllowedType(BufUAV.GetVariableType(), AllowedTypeBits) );
+ AddResource(BufUAV, CachedResourceType::BufUAV);
+ }
+ );
+
+#ifdef _DEBUG
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ VERIFY( CurrCbvSrvUav[VarType] == m_NumCbvSrvUav[VarType], "Not all Srv/Cbv/Uavs are initialized, which result in a crash when dtor is called" );
+ VERIFY( CurrSampler[VarType] == m_NumSamplers[VarType], "Not all Samplers are initialized, which result in a crash when dtor is called" );
+ }
+#endif
+
+ if(m_pResourceCache)
+ {
+ VERIFY_EXPR(pRootSig == nullptr);
+ Uint32 CachedTblSizes[4] =
+ {
+ static_cast<Uint32>(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_SRV] + 1),
+ static_cast<Uint32>(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_UAV] + 1),
+ static_cast<Uint32>(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_CBV] + 1),
+ static_cast<Uint32>(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER] + 1)
+ };
+ m_pResourceCache->Initialize(GetRawAllocator(), _countof(CachedTblSizes), CachedTblSizes);
+#ifdef _DEBUG
+ m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_SRV] + 1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType());
+ m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_UAV] + 1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType());
+ m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_CBV] + 1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType());
+ m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(MaxBindPoint[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER] + 1, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType());
+#endif
+ }
+
+ InitVariablesHashMap();
+}
+
+
+void ShaderResourceLayoutD3D12::InitVariablesHashMap()
+{
+#if USE_VARIABLE_HASH_MAP
+ Uint32 TotalResources = GetTotalSrvCbvUavCount();
+ for(Uint32 r=0; r < TotalResources; ++r)
+ {
+ auto &Res = GetSrvCbvUav(r);
+ /* HashMapStringKey will make a copy of the string*/
+ m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(Res.Name), &Res ) );
+ }
+#endif
+}
+
+
+#define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\
+{ \
+ const auto &ResName = pResource->GetDesc().Name; \
+ LOG_ERROR_MESSAGE( "Failed to bind ", ResType, " \"", ResName, "\" to variable \"", VarName, \
+ "\" in shader \"", ShaderName, "\". ", __VA_ARGS__ ); \
+}
+
+
+
+void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheCB(IDeviceObject *pBuffer, ShaderResourceCacheD3D12::Resource& DstRes, Uint32 ArrayInd, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)
+{
+ // We cannot use ValidatedCast<> here as the resource retrieved from the
+ // resource mapping can be of wrong type
+ RefCntAutoPtr<BufferD3D12Impl> pBuffD3D12(pBuffer, IID_BufferD3D12);
+ if( pBuffD3D12 )
+ {
+ if( pBuffD3D12->GetDesc().BindFlags & BIND_UNIFORM_BUFFER )
+ {
+ if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr && DstRes.pObject != pBuffD3D12)
+ {
+ auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType());
+ LOG_ERROR_MESSAGE( "Non-null constant buffer is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayInd), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempring to bind another constant buffer is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." )
+ }
+
+ DstRes.Type = GetResType();
+ DstRes.CPUDescriptorHandle = pBuffD3D12->GetCBVHandle();
+ VERIFY(DstRes.CPUDescriptorHandle.ptr != 0 || pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC, "No relevant CBV CPU descriptor handle")
+
+ if(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0 )
+ {
+ ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device;
+ pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+
+ DstRes.pObject = pBuffD3D12;
+ }
+ else
+ {
+ LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), m_ParentResLayout.GetShaderName(), "Buffer was not created with BIND_UNIFORM_BUFFER flag.")
+ }
+ }
+ else
+ {
+ LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), m_ParentResLayout.GetShaderName(), "Incorrect resource type: buffer is expected.")
+ }
+}
+
+
+template<typename TResourceViewType>
+struct ResourceViewTraits{};
+
+template<>
+struct ResourceViewTraits<ITextureViewD3D12>
+{
+ static const Char *Name;
+ static const INTERFACE_ID &IID;
+};
+const Char *ResourceViewTraits<ITextureViewD3D12>::Name = "texture view";
+const INTERFACE_ID& ResourceViewTraits<ITextureViewD3D12>::IID = IID_TextureViewD3D12;
+
+template<>
+struct ResourceViewTraits<IBufferViewD3D12>
+{
+ static const Char *Name;
+ static const INTERFACE_ID &IID;
+};
+const Char *ResourceViewTraits<IBufferViewD3D12>::Name = "buffer view";
+const INTERFACE_ID& ResourceViewTraits<IBufferViewD3D12>::IID = IID_BufferViewD3D12;
+
+template<typename TResourceViewType, ///< ResType of the view (ITextureViewD3D12 or IBufferViewD3D12)
+ typename TViewTypeEnum, ///< ResType of the expected view type enum (TEXTURE_VIEW_TYPE or BUFFER_VIEW_TYPE)
+ typename TBindSamplerProcType> ///< ResType of the procedure to set sampler
+void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheResourceView(IDeviceObject *pView,
+ ShaderResourceCacheD3D12::Resource& DstRes,
+ Uint32 ArrayIndex,
+ D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle,
+ TViewTypeEnum dbgExpectedViewType,
+ TBindSamplerProcType BindSamplerProc)
+{
+ // We cannot use ValidatedCast<> here as the resource retrieved from the
+ // resource mapping can be of wrong type
+ RefCntAutoPtr<TResourceViewType> pViewD3D12(pView, ResourceViewTraits<TResourceViewType>::IID);
+ if( pViewD3D12 )
+ {
+#ifdef VERIFY_SHADER_BINDINGS
+ const auto& ViewDesc = pViewD3D12->GetDesc();
+ auto ViewType = ViewDesc.ViewType;
+ if( ViewType != dbgExpectedViewType )
+ {
+ const auto *ExpectedViewTypeName = GetViewTypeLiteralName( dbgExpectedViewType );
+ const auto *ActualViewTypeName = GetViewTypeLiteralName( ViewType );
+ LOG_RESOURCE_BINDING_ERROR(ResourceViewTraits<TResourceViewType>::Name, pViewD3D12, Attribs.GetPrintName(ArrayIndex), m_ParentResLayout.GetShaderName(),
+ "Incorrect view type: ", ExpectedViewTypeName, " is expected, ", ActualViewTypeName, " provided." );
+ return;
+ }
+#endif
+ if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr && DstRes.pObject != pViewD3D12)
+ {
+ auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType());
+ LOG_ERROR_MESSAGE( "Non-null resource is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempting to bind another resource is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." );
+ }
+
+ DstRes.Type = GetResType();
+ DstRes.pObject = pViewD3D12;
+ DstRes.CPUDescriptorHandle = pViewD3D12->GetCPUDescriptorHandle();
+ VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 view")
+
+ if(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0)
+ {
+ ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device;
+ pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+
+ BindSamplerProc(pViewD3D12);
+ }
+ else
+ {
+ LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs.GetPrintName(ArrayIndex), m_ParentResLayout.GetShaderName(), "Incorect resource type: ", ResourceViewTraits<TResourceViewType>::Name, " is expected.")
+ }
+}
+
+void ShaderResourceLayoutD3D12::Sampler::CacheSampler(ITextureViewD3D12 *pTexViewD3D12, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)
+{
+ auto &pResourceCache = m_ParentResLayout.m_pResourceCache;
+ VERIFY(pResourceCache, "Resource cache is null");
+ VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point");
+ VERIFY_EXPR(ArrayIndex < Attribs.BindCount);
+
+ auto &DstSam = pResourceCache->GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_ParentResLayout.m_pResources->GetShaderType());
+
+#ifdef _DEBUG
+ {
+ if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space")
+ }
+ else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources)
+ {
+ if(Attribs.GetVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC)
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call")
+ else
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0 || pTexViewD3D12 == nullptr, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space")
+ }
+ else
+ {
+ UNEXPECTED("Unknown content type")
+ }
+ }
+#endif
+
+ if( pTexViewD3D12 )
+ {
+ auto pSampler = pTexViewD3D12->GetSampler();
+ if( pSampler )
+ {
+ if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstSam.pObject != nullptr && DstSam.pObject != pSampler)
+ {
+ auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType());
+ LOG_ERROR_MESSAGE( "Non-null sampler is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempting to bind another sampler is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." )
+ }
+
+ DstSam.Type = CachedResourceType::Sampler;
+
+ auto *pSamplerD3D12 = ValidatedCast<SamplerD3D12Impl>(pSampler);
+ DstSam.CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle();
+ VERIFY(DstSam.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle")
+
+ if(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0)
+ {
+ ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device;
+ pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstSam.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ }
+
+ DstSam.pObject = pSampler;
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", Attribs.Name, ". Sampler is not set in the texture view \"", pTexViewD3D12->GetDesc().Name, "\"" );
+ }
+ }
+ else
+ {
+ DstSam = ShaderResourceCacheD3D12::Resource();
+ }
+}
+
+
+ShaderResourceLayoutD3D12::Sampler &ShaderResourceLayoutD3D12::GetAssignedSampler(const SRV_CBV_UAV &TexSrv)
+{
+ VERIFY(TexSrv.GetResType() == CachedResourceType::TexSRV, "Unexpected resource type: texture SRV is expected")
+ VERIFY(TexSrv.IsValidSampler(), "Texture SRV has no associated sampler")
+ auto &SamInfo = GetSampler(TexSrv.Attribs.GetVariableType(), TexSrv.GetSamplerId());
+ VERIFY(SamInfo.Attribs.GetVariableType() == TexSrv.Attribs.GetVariableType(), "Inconsistent texture and sampler variable types")
+ VERIFY(SamInfo.Attribs.Name == TexSrv.Attribs.Name + D3DSamplerSuffix, "Sampler name \"", SamInfo.Attribs.Name, "\" does not match texture name \"", TexSrv.Attribs.Name, '\"');
+ return SamInfo;
+}
+
+
+void ShaderResourceLayoutD3D12::SRV_CBV_UAV::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, const ShaderResourceLayoutD3D12 *dbgResLayout)
+{
+ auto &pResourceCache = m_ParentResLayout.m_pResourceCache;
+ VERIFY(pResourceCache, "Resource cache is null");
+ VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache");
+ VERIFY_EXPR(ArrayIndex < Attribs.BindCount);
+
+ auto &DstRes = pResourceCache->GetRootTable(GetRootIndex()).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_ParentResLayout.m_pResources->GetShaderType());
+ auto ShdrVisibleHeapCPUDescriptorHandle = pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(GetRootIndex(), OffsetFromTableStart+ArrayIndex);
+
+#ifdef _DEBUG
+ {
+ if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space")
+ }
+ else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources)
+ {
+ if (GetResType() == CachedResourceType::CBV)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Constant buffers are bound as root views and should not be assigned shader visible descriptor space")
+ }
+ else
+ {
+ if(Attribs.GetVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC)
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call")
+ else
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space")
+ }
+ }
+ else
+ {
+ UNEXPECTED("Unknown content type")
+ }
+ }
+#endif
+
+ if( pObj )
+ {
+ switch (GetResType())
+ {
+ case CachedResourceType::CBV:
+ CacheCB(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle);
+ break;
+
+ case CachedResourceType::TexSRV:
+ CacheResourceView<ITextureViewD3D12>(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, TEXTURE_VIEW_SHADER_RESOURCE, [&](ITextureViewD3D12* pTexView)
+ {
+ if(IsValidSampler())
+ {
+ auto &Sam = m_ParentResLayout.GetAssignedSampler(*this);
+ VERIFY( !Sam.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" )
+ VERIFY_EXPR(Attribs.BindCount == Sam.Attribs.BindCount || Sam.Attribs.BindCount == 1);
+ auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0;
+ auto ShdrVisibleSamplerHeapCPUDescriptorHandle = pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(Sam.RootIndex, Sam.OffsetFromTableStart + SamplerArrInd);
+ Sam.CacheSampler(pTexView, SamplerArrInd, ShdrVisibleSamplerHeapCPUDescriptorHandle);
+ }
+ });
+ break;
+
+ case CachedResourceType::TexUAV:
+ CacheResourceView<ITextureViewD3D12>(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, TEXTURE_VIEW_UNORDERED_ACCESS, [](ITextureViewD3D12*){});
+ break;
+
+ case CachedResourceType::BufSRV:
+ CacheResourceView<IBufferViewD3D12>(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, BUFFER_VIEW_SHADER_RESOURCE, [](IBufferViewD3D12*){});
+ break;
+
+ case CachedResourceType::BufUAV:
+ CacheResourceView<IBufferViewD3D12>( pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, BUFFER_VIEW_UNORDERED_ACCESS, [](IBufferViewD3D12*){});
+ break;
+
+ default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(GetResType()))
+ }
+ }
+ else
+ {
+ if (DstRes.pObject && Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC)
+ {
+ LOG_ERROR_MESSAGE( "Shader variable \"", Attribs.Name, "\" in shader \"", m_ParentResLayout.GetShaderName(), "\" is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic if you need to bind another resource." );
+ }
+
+ DstRes = ShaderResourceCacheD3D12::Resource();
+ if(IsValidSampler())
+ {
+ auto &Sam = m_ParentResLayout.GetAssignedSampler(*this);
+ D3D12_CPU_DESCRIPTOR_HANDLE NullHandle = {0};
+ auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0;
+ Sam.CacheSampler(nullptr, SamplerArrInd, NullHandle);
+ }
+ }
+}
+
+bool ShaderResourceLayoutD3D12::SRV_CBV_UAV::IsBound(Uint32 ArrayIndex)
+{
+ auto &pResourceCache = m_ParentResLayout.m_pResourceCache;
+ VERIFY(pResourceCache, "Resource cache is null");
+ VERIFY_EXPR(ArrayIndex < Attribs.BindCount);
+
+ auto RootIndex = GetRootIndex();
+ if( RootIndex < pResourceCache->GetNumRootTables() )
+ {
+ auto &RootTable = pResourceCache->GetRootTable(RootIndex);
+ if(OffsetFromTableStart + ArrayIndex < RootTable.GetSize())
+ {
+ auto &CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_ParentResLayout.m_pResources->GetShaderType());
+ if( CachedRes.pObject != nullptr )
+ {
+ VERIFY(CachedRes.CPUDescriptorHandle.ptr != 0 || ValidatedCast<BufferD3D12Impl>(CachedRes.pObject.RawPtr())->GetDesc().Usage == USAGE_DYNAMIC, "No relevant descriptor handle")
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+void ShaderResourceLayoutD3D12::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D12 *dbgResourceCache )
+{
+ VERIFY(dbgResourceCache == m_pResourceCache, "Resource cache does not match the cache provided at initialization");
+
+ if( !pResourceMapping )
+ {
+ LOG_ERROR_MESSAGE( "Failed to bind resources in shader \"", GetShaderName(), "\": resource mapping is null" );
+ return;
+ }
+
+ // Bind constant buffers
+ Uint32 TotalResources = GetTotalSrvCbvUavCount();
+ for(Uint32 r=0; r < TotalResources; ++r)
+ {
+ auto &Res = GetSrvCbvUav(r);
+ for(Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd)
+ {
+ if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS )
+ Res.BindResource(nullptr, ArrInd, this);
+
+ if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd) )
+ return;
+
+ const auto& VarName = Res.Attribs.Name;
+ RefCntAutoPtr<IDeviceObject> pObj;
+ VERIFY_EXPR(pResourceMapping != nullptr);
+ pResourceMapping->GetResource( VarName.c_str(), &pObj, ArrInd );
+ if( pObj )
+ {
+ // Call non-virtual function
+ Res.BindResource(pObj, ArrInd, this);
+ }
+ else
+ {
+ if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd) )
+ LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.Attribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" )
+ }
+ }
+ }
+}
+
+
+IShaderVariable* ShaderResourceLayoutD3D12::GetShaderVariable(const Char* Name)
+{
+ IShaderVariable* pVar = nullptr;
+#if USE_VARIABLE_HASH_MAP
+ // Name will be implicitly converted to HashMapStringKey without making a copy
+ auto it = m_VariableHash.find( Name );
+ if( it != m_VariableHash.end() )
+ pVar = it->second;
+#else
+ Uint32 TotalResources = GetTotalSrvCbvUavCount();
+ for(Uint32 r=0; r < TotalResources; ++r)
+ {
+ auto &Res = GetSrvCbvUav(r);
+ if(Res.Attribs.Name.compare(Name) == 0)
+ {
+ pVar = &Res;
+ break;
+ }
+ }
+#endif
+
+ if(pVar == nullptr)
+ {
+ LOG_ERROR_MESSAGE( "Shader variable \"", Name, "\" is not found in shader \"", GetShaderName(), "\" (", GetShaderTypeLiteralName(m_pResources->GetShaderType()), "). Attempts to set the variable will be silently ignored." );
+ }
+ return pVar;
+}
+
+
+
+void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutD3D12 &SrcLayout)
+{
+ if (!m_pResourceCache)
+ {
+ LOG_ERROR("Resource layout has no resource cache");
+ return;
+ }
+
+ if (!SrcLayout.m_pResourceCache)
+ {
+ LOG_ERROR("Dst layout has no resource cache");
+ return;
+ }
+
+ // Static shader resources are stored as follows:
+ // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
+ // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
+ // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV, and
+ // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER
+ // Every resource is stored at offset that equals resource bind point
+
+ for(Uint32 r=0; r < m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC]; ++r)
+ {
+ const auto &res = GetSrvCbvUav(SHADER_VARIABLE_TYPE_STATIC, r);
+ VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types")
+ auto RangeType = GetDescriptorRangeType(res.GetResType());
+ for(Uint32 ArrInd = 0; ArrInd < res.Attribs.BindCount; ++ArrInd)
+ {
+ auto BindPoint = res.Attribs.BindPoint + ArrInd;
+ // Static resources are indexed in the resource cache by its bind point
+ const auto &SrcRes = SrcLayout.m_pResourceCache->GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, SrcLayout.m_pResources->GetShaderType());
+ if( !SrcRes.pObject )
+ LOG_ERROR_MESSAGE( "No resource assigned to static shader variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." );
+ auto &DstRes = m_pResourceCache->GetRootTable(res.GetRootIndex()).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType());
+
+ if(DstRes.pObject != SrcRes.pObject)
+ {
+ VERIFY(DstRes.pObject == nullptr, "Static resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource");
+
+ DstRes.pObject = SrcRes.pObject;
+ DstRes.Type = SrcRes.Type;
+ DstRes.CPUDescriptorHandle = SrcRes.CPUDescriptorHandle;
+
+ auto ShdrVisibleHeapCPUDescriptorHandle = m_pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.GetRootIndex(), res.OffsetFromTableStart + ArrInd);
+ VERIFY_EXPR(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0 || DstRes.Type == CachedResourceType::CBV);
+ if (ShdrVisibleHeapCPUDescriptorHandle.ptr != 0)
+ {
+ m_pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, SrcRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+ }
+ else
+ {
+ VERIFY_EXPR(DstRes.pObject == SrcRes.pObject);
+ VERIFY_EXPR(DstRes.Type == SrcRes.Type);
+ VERIFY_EXPR(DstRes.CPUDescriptorHandle.ptr == SrcRes.CPUDescriptorHandle.ptr);
+ }
+ }
+
+ if(res.IsValidSampler())
+ {
+ auto &SamInfo = GetAssignedSampler(res);
+
+ VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache")
+
+ VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid")
+ VERIFY_EXPR(SamInfo.Attribs.BindCount == res.Attribs.BindCount || SamInfo.Attribs.BindCount == 1);
+
+ for(Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd)
+ {
+ auto BindPoint = SamInfo.Attribs.BindPoint + ArrInd;
+ // Static resources are indexed by the bind point in the resource cache
+ auto& SrcSampler = SrcLayout.m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, SrcLayout.m_pResources->GetShaderType());
+ if( !SrcSampler.pObject )
+ LOG_ERROR_MESSAGE( "No sampler assigned to static shader variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." );
+ auto &DstSampler = m_pResourceCache->GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType());
+
+ if(DstSampler.pObject != SrcSampler.pObject)
+ {
+ VERIFY(DstSampler.pObject == nullptr, "Static sampler resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource");
+
+ DstSampler.pObject = SrcSampler.pObject;
+ DstSampler.Type = SrcSampler.Type;
+ DstSampler.CPUDescriptorHandle = SrcSampler.CPUDescriptorHandle;
+
+ auto ShdrVisibleSamplerHeapCPUDescriptorHandle = m_pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(SamInfo.RootIndex, SamInfo.OffsetFromTableStart + ArrInd);
+ VERIFY_EXPR(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0);
+ if (ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0)
+ {
+ m_pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleSamplerHeapCPUDescriptorHandle, SrcSampler.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ }
+ }
+ else
+ {
+ VERIFY_EXPR(DstSampler.pObject == SrcSampler.pObject);
+ VERIFY_EXPR(DstSampler.Type == SrcSampler.Type);
+ VERIFY_EXPR(DstSampler.CPUDescriptorHandle.ptr == SrcSampler.CPUDescriptorHandle.ptr);
+ }
+ }
+ }
+ }
+}
+
+
+#ifdef VERIFY_SHADER_BINDINGS
+void ShaderResourceLayoutD3D12::dbgVerifyBindings()const
+{
+ VERIFY(m_pResourceCache, "Resource cache is null")
+
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ for(Uint32 r=0; r < m_NumCbvSrvUav[VarType]; ++r)
+ {
+ const auto &res = GetSrvCbvUav(VarType, r);
+ VERIFY(res.Attribs.GetVariableType() == VarType, "Unexpected variable type")
+
+ for(Uint32 ArrInd = 0; ArrInd < res.Attribs.BindCount; ++ArrInd)
+ {
+ const auto &CachedRes = m_pResourceCache->GetRootTable(res.GetRootIndex()).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType());
+ if(CachedRes.pObject)
+ VERIFY(CachedRes.Type == res.GetResType(), "Inconsistent cached resource types")
+ else
+ VERIFY(CachedRes.Type == CachedResourceType::Unknown, "Unexpected cached resource types")
+
+ if( !CachedRes.pObject ||
+ (CachedRes.CPUDescriptorHandle.ptr == 0 && ValidatedCast<const BufferD3D12Impl>(CachedRes.pObject.RawPtr())->GetDesc().Usage != USAGE_DYNAMIC) )
+ LOG_ERROR_MESSAGE( "No resource is bound to ", GetShaderVariableTypeLiteralName(res.Attribs.GetVariableType()), " variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"" )
+
+ if (res.Attribs.BindCount > 1 && res.IsValidSampler())
+ {
+ // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent
+ const auto &SamInfo = const_cast<ShaderResourceLayoutD3D12*>(this)->GetAssignedSampler(res);
+ if(SamInfo.Attribs.BindCount == 1)
+ {
+ const auto &CachedSampler = m_pResourceCache->GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType());
+ if( auto *pTexView = ValidatedCast<const ITextureView>(CachedRes.pObject.RawPtr()) )
+ {
+ auto *pSampler = const_cast<ITextureView*>(pTexView)->GetSampler();
+ if (CachedSampler.pObject != pSampler)
+ LOG_ERROR_MESSAGE( "All elements of texture array \"", res.Attribs.Name, "\" in shader \"", GetShaderName(), "\" share the same sampler. However, the sampler set in view for element ", ArrInd, " does not match bound sampler. This may cause incorrect behavior on GL platform." )
+ }
+ }
+ }
+
+#ifdef _DEBUG
+ {
+ auto ShdrVisibleHeapCPUDescriptorHandle = m_pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.GetRootIndex(), res.OffsetFromTableStart + ArrInd);
+ if (m_pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space")
+ }
+ else if (m_pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources)
+ {
+ if (res.GetResType() == CachedResourceType::CBV)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Constant buffers are bound as root views and should not be assigned shader visible descriptor space")
+ }
+ else
+ {
+ if(res.Attribs.GetVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC)
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call")
+ else
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space")
+ }
+ }
+ else
+ {
+ UNEXPECTED("Unknown content type")
+ }
+ }
+#endif
+ }
+
+ if (res.IsValidSampler())
+ {
+ VERIFY(res.GetResType() == CachedResourceType::TexSRV, "Sampler can only be assigned to texture SRV" );
+ const auto &SamInfo = const_cast<ShaderResourceLayoutD3D12*>(this)->GetAssignedSampler(res);
+ VERIFY( !SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" )
+ VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid")
+
+ for(Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd)
+ {
+ const auto &CachedSampler = m_pResourceCache->GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType());
+ if( CachedSampler.pObject )
+ VERIFY(CachedSampler.Type == CachedResourceType::Sampler, "Incorrect cached sampler type")
+ else
+ VERIFY(CachedSampler.Type == CachedResourceType::Unknown, "Unexpected cached sampler type")
+ if( !CachedSampler.pObject || CachedSampler.CPUDescriptorHandle.ptr == 0 )
+ LOG_ERROR_MESSAGE("No sampler is assigned to texture variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"")
+
+ #ifdef _DEBUG
+ {
+ auto ShdrVisibleHeapCPUDescriptorHandle = m_pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(SamInfo.RootIndex, SamInfo.OffsetFromTableStart + ArrInd);
+ if (m_pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources)
+ {
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space")
+ }
+ else if (m_pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources)
+ {
+ if(SamInfo.Attribs.GetVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC)
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call")
+ else
+ VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space")
+ }
+ else
+ {
+ UNEXPECTED("Unknown content type")
+ }
+ }
+ #endif
+ }
+ }
+ }
+
+ for(Uint32 s=0; s < m_NumSamplers[VarType]; ++s)
+ {
+ const auto &sam = GetSampler(VarType, s);
+ VERIFY(sam.Attribs.GetVariableType() == VarType, "Unexpected sampler variable type")
+
+ for(Uint32 ArrInd = 0; ArrInd < sam.Attribs.BindCount; ++ArrInd)
+ {
+ const auto &CachedSampler = m_pResourceCache->GetRootTable(sam.RootIndex).GetResource(sam.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType());
+ if( CachedSampler.pObject )
+ VERIFY(CachedSampler.Type == CachedResourceType::Sampler, "Incorrect cached sampler type")
+ else
+ VERIFY(CachedSampler.Type == CachedResourceType::Unknown, "Unexpected cached sampler type")
+ if( !CachedSampler.pObject || CachedSampler.CPUDescriptorHandle.ptr == 0 )
+ LOG_ERROR_MESSAGE( "No sampler is bound to sampler variable \"", sam.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"" )
+ }
+ }
+ }
+}
+#endif
+
+const Char* ShaderResourceLayoutD3D12::GetShaderName()const
+{
+ RefCntAutoPtr<IShader> pShader(&m_Owner, IID_Shader);
+ if (pShader)
+ {
+ return pShader->GetDesc().Name;
+ }
+ else
+ {
+ RefCntAutoPtr<IShaderResourceBinding> pSRB(&m_Owner, IID_ShaderResourceBinding);
+ if(pSRB)
+ {
+ auto *pPSO = pSRB->GetPipelineState();
+ auto *pPSOD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPSO);
+ auto *ppShaders = pPSOD3D12->GetShaders();
+ auto NumShaders = pPSOD3D12->GetNumShaders();
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ const auto &ShaderDesc = ppShaders[s]->GetDesc();
+ if(ShaderDesc.ShaderType == m_pResources->GetShaderType())
+ return ShaderDesc.Name;
+ }
+ UNEXPECTED("Shader not found")
+ }
+ else
+ {
+ UNEXPECTED("Owner is expected to be a shader or a shader resource binding")
+ }
+ }
+ return "";
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp
new file mode 100644
index 00000000..e7543ce6
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp
@@ -0,0 +1,93 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include <d3dcompiler.h>
+#include "ShaderResourcesD3D12.h"
+#include "ShaderD3DBase.h"
+#include "ShaderBase.h"
+#include "D3DShaderResourceLoader.h"
+
+
+namespace Diligent
+{
+
+
+ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob *pShaderBytecode, const ShaderDesc &ShdrDesc) :
+ ShaderResources(GetRawAllocator(), ShdrDesc.ShaderType)
+{
+ Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0;
+ LoadD3DShaderResources<D3D12_SHADER_DESC, D3D12_SHADER_INPUT_BIND_DESC, ID3D12ShaderReflection>(
+ pShaderBytecode,
+
+ [&](Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers)
+ {
+ Initialize(GetRawAllocator(), NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers);
+ },
+
+ [&](D3DShaderResourceAttribs&& CBAttribs)
+ {
+ new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(std::move(CBAttribs));
+ },
+
+ [&](D3DShaderResourceAttribs &&TexUAV)
+ {
+ new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs( std::move(TexUAV) );
+ },
+
+ [&](D3DShaderResourceAttribs &&BuffUAV)
+ {
+ new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs( std::move(BuffUAV) );
+ },
+
+ [&](D3DShaderResourceAttribs &&BuffSRV)
+ {
+ new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs( std::move(BuffSRV) );
+ },
+
+ [&](D3DShaderResourceAttribs &&SamplerAttribs)
+ {
+ new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs( std::move(SamplerAttribs) );
+ },
+
+ [&](D3DShaderResourceAttribs &&TexAttribs)
+ {
+ VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs" );
+
+ auto SamplerId = FindAssignedSamplerId(TexAttribs);
+ new (&GetTexSRV(CurrTexSRV++)) D3DShaderResourceAttribs( std::move(TexAttribs), SamplerId);
+ },
+
+ ShdrDesc,
+ D3DSamplerSuffix);
+
+ VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called");
+ VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" );
+ VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" );
+ VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" );
+ VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" );
+ VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" );
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp
new file mode 100644
index 00000000..e1be6145
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp
@@ -0,0 +1,262 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "SwapChainD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+#include "DXGITypeConversions.h"
+#include "TextureD3D12Impl.h"
+#include "EngineMemory.h"
+
+namespace Diligent
+{
+
+SwapChainD3D12Impl::SwapChainD3D12Impl(IMemoryAllocator &Allocator,
+ const SwapChainDesc& SCDesc,
+ RenderDeviceD3D12Impl* pRenderDeviceD3D12,
+ DeviceContextD3D12Impl* pDeviceContextD3D12,
+ void* pNativeWndHandle) :
+ TSwapChainBase(Allocator, pRenderDeviceD3D12, pDeviceContextD3D12, SCDesc),
+ m_pBackBufferRTV(STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<ITextureView>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<ITextureView>>"))
+{
+
+#ifdef PLATFORM_WIN32
+ auto hWnd = reinterpret_cast<HWND>(pNativeWndHandle);
+
+ if( m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0 )
+ {
+ RECT rc;
+ GetClientRect( hWnd, &rc );
+ m_SwapChainDesc.Width = rc.right - rc.left;
+ m_SwapChainDesc.Height = rc.bottom - rc.top;
+ }
+#endif
+
+ auto DXGIColorBuffFmt = TexFormatToDXGI_Format(m_SwapChainDesc.ColorBufferFormat);
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = m_SwapChainDesc.Width;
+ swapChainDesc.Height = m_SwapChainDesc.Height;
+ // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats:
+ // - DXGI_FORMAT_R16G16B16A16_FLOAT
+ // - DXGI_FORMAT_B8G8R8A8_UNORM
+ // - DXGI_FORMAT_R8G8B8A8_UNORM
+ // - DXGI_FORMAT_R10G10B10A2_UNORM
+ // If RGBA8_UNORM_SRGB swap chain is required, we will create RGBA8_UNORM swap chain, but
+ // create RGBA8_UNORM_SRGB render target view
+ swapChainDesc.Format = DXGIColorBuffFmt == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGIColorBuffFmt;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = m_SwapChainDesc.BufferCount;
+ swapChainDesc.Scaling = DXGI_SCALING_NONE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used
+ swapChainDesc.Flags = 0;
+
+ CComPtr<IDXGISwapChain1> pSwapChain1;
+ CComPtr<IDXGIFactory4> factory;
+ HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast<void**>(static_cast<IDXGIFactory4**>(&factory)) );
+ CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory")
+
+ auto *pd3d12CmdQueue = pRenderDeviceD3D12->GetCmdQueue();
+#if defined( PLATFORM_WIN32 )
+ hr = factory->CreateSwapChainForHwnd(pd3d12CmdQueue, hWnd, &swapChainDesc, nullptr, nullptr, &pSwapChain1);
+ CHECK_D3D_RESULT_THROW( hr, "Failed to create Swap Chain" );
+
+ // This sample does not support fullscreen transitions.
+ hr = factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
+
+#elif defined( PLATFORM_UNIVERSAL_WINDOWS )
+
+ hr = factory->CreateSwapChainForCoreWindow(
+ pd3d12CmdQueue,
+ reinterpret_cast<IUnknown*>(pNativeWndHandle),
+ &swapChainDesc,
+ nullptr,
+ &pSwapChain1);
+ CHECK_D3D_RESULT_THROW( hr, "Failed to create DXGI swap chain" );
+
+ // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
+ // ensures that the application will only render after each VSync, minimizing power consumption.
+ //pDXGIDevice->SetMaximumFrameLatency( 1 );
+
+#endif
+
+ pSwapChain1->QueryInterface(__uuidof(m_pSwapChain), reinterpret_cast<void**>( static_cast<IDXGISwapChain3**>(&m_pSwapChain) ));
+
+ InitBuffersAndViews();
+}
+
+SwapChainD3D12Impl::~SwapChainD3D12Impl()
+{
+
+}
+
+void SwapChainD3D12Impl::InitBuffersAndViews()
+{
+ m_pBackBufferRTV.resize(m_SwapChainDesc.BufferCount);
+ for(Uint32 backbuff = 0; backbuff < m_SwapChainDesc.BufferCount; ++backbuff)
+ {
+ CComPtr<ID3D12Resource> pBackBuffer;
+ auto hr = m_pSwapChain->GetBuffer(backbuff, __uuidof(pBackBuffer), reinterpret_cast<void**>( static_cast<ID3D12Resource**>(&pBackBuffer) ));
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to get back buffer ", backbuff," from the swap chain");
+
+ TextureDesc BackBufferDesc;
+ BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
+ String Name = "Main back buffer ";
+ Name += std::to_string(backbuff);
+ BackBufferDesc.Name = Name.c_str();
+
+ RefCntAutoPtr<TextureD3D12Impl> pBackBufferTex;
+ ValidatedCast<RenderDeviceD3D12Impl>(m_pRenderDevice.RawPtr())->CreateTexture(BackBufferDesc, pBackBuffer, &pBackBufferTex);
+ TextureViewDesc RTVDesc;
+ RTVDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
+ RefCntAutoPtr<ITextureView> pRTV;
+ pBackBufferTex->CreateView(RTVDesc, &pRTV);
+ m_pBackBufferRTV[backbuff] = pRTV;
+ }
+
+ TextureDesc DepthBufferDesc;
+ DepthBufferDesc.Type = RESOURCE_DIM_TEX_2D;
+ DepthBufferDesc.Width = m_SwapChainDesc.Width;
+ DepthBufferDesc.Height = m_SwapChainDesc.Height;
+ DepthBufferDesc.Format = m_SwapChainDesc.DepthBufferFormat;
+ DepthBufferDesc.SampleCount = m_SwapChainDesc.SamplesCount;
+ DepthBufferDesc.Usage = USAGE_DEFAULT;
+ DepthBufferDesc.BindFlags = BIND_DEPTH_STENCIL;
+
+ DepthBufferDesc.ClearValue.Format = DepthBufferDesc.Format;
+ DepthBufferDesc.ClearValue.DepthStencil.Depth = m_SwapChainDesc.DefaultDepthValue;
+ DepthBufferDesc.ClearValue.DepthStencil.Stencil = m_SwapChainDesc.DefaultStencilValue;
+ String Name = "Main depth buffer";
+ RefCntAutoPtr<ITexture> pDepthBufferTex;
+ m_pRenderDevice->CreateTexture(DepthBufferDesc, TextureData(), static_cast<ITexture**>(&pDepthBufferTex) );
+ m_pDepthBufferDSV = pDepthBufferTex->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL);
+}
+
+IMPLEMENT_QUERY_INTERFACE( SwapChainD3D12Impl, IID_SwapChainD3D12, TSwapChainBase )
+
+
+void SwapChainD3D12Impl::Present()
+{
+ UINT SyncInterval = 0;
+#ifdef PLATFORM_UNIVERSAL_WINDOWS
+ SyncInterval = 1; // Interval 0 is not supported on Windows Phone
+#endif
+
+ auto pDeviceContext = m_wpDeviceContext.Lock();
+ if( !pDeviceContext )
+ {
+ LOG_ERROR_MESSAGE( "Immediate context has been released" );
+ return;
+ }
+
+ auto *pImmediateCtx = pDeviceContext.RawPtr();
+ auto *pImmediateCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>( pImmediateCtx );
+
+ auto *pCmdCtx = pImmediateCtxD3D12->RequestCmdContext();
+ auto *pBackBuffer = ValidatedCast<TextureD3D12Impl>( GetCurrentBackBufferRTV()->GetTexture() );
+ pCmdCtx->TransitionResource( pBackBuffer, D3D12_RESOURCE_STATE_PRESENT);
+
+ pImmediateCtxD3D12->Flush();
+
+ auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pImmediateCtxD3D12->GetDevice() );
+
+ auto hr = m_pSwapChain->Present( SyncInterval, 0 );
+ VERIFY(SUCCEEDED(hr), "Present failed");
+
+ pDeviceD3D12->FinishFrame();
+
+#if 0
+#ifdef PLATFORM_UNIVERSAL_WINDOWS
+ // A successful Present call for DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL SwapChains unbinds
+ // backbuffer 0 from all GPU writeable bind points.
+ // We need to rebind all render targets to make sure that
+ // the back buffer is not unbound
+ pImmediateCtxD3D12->RebindRenderTargets();
+#endif
+#endif
+}
+
+void SwapChainD3D12Impl::Resize( Uint32 NewWidth, Uint32 NewHeight )
+{
+ if( TSwapChainBase::Resize(NewWidth, NewHeight) )
+ {
+ auto pDeviceContext = m_wpDeviceContext.Lock();
+ VERIFY( pDeviceContext, "Immediate context has been released" );
+ if( pDeviceContext )
+ {
+ RenderDeviceD3D12Impl *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>(m_pRenderDevice.RawPtr());
+ pDeviceContext->Flush();
+
+ try
+ {
+ auto *pImmediateCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pDeviceContext.RawPtr());
+ bool bIsDefaultFBBound = pImmediateCtxD3D12->IsDefaultFBBound();
+
+ // All references to the swap chain must be released before it can be resized
+ m_pBackBufferRTV.clear();
+ m_pDepthBufferDSV.Release();
+
+ // This will release references to D3D12 swap chain buffers hold by
+ // m_pBackBufferRTV[]
+ pDeviceD3D12->IdleGPU(true);
+
+ DXGI_SWAP_CHAIN_DESC SCDes;
+ memset( &SCDes, 0, sizeof( SCDes ) );
+ m_pSwapChain->GetDesc( &SCDes );
+ CHECK_D3D_RESULT_THROW( m_pSwapChain->ResizeBuffers(SCDes.BufferCount, m_SwapChainDesc.Width,
+ m_SwapChainDesc.Height, SCDes.BufferDesc.Format,
+ SCDes.Flags),
+ "Failed to resize the DXGI swap chain" );
+
+
+ InitBuffersAndViews();
+
+ if( bIsDefaultFBBound )
+ {
+ // Set default render target and viewport
+ pDeviceContext->SetRenderTargets( 0, nullptr, nullptr );
+ pDeviceContext->SetViewports( 1, nullptr, 0, 0 );
+ }
+ }
+ catch( const std::runtime_error & )
+ {
+ LOG_ERROR( "Failed to resize the swap chain" );
+ }
+ }
+ }
+}
+
+ITextureView *SwapChainD3D12Impl::GetCurrentBackBufferRTV()
+{
+ auto CurrentBackBufferIndex = m_pSwapChain->GetCurrentBackBufferIndex();
+ VERIFY_EXPR(CurrentBackBufferIndex>=0 && CurrentBackBufferIndex < m_SwapChainDesc.BufferCount);
+ return m_pBackBufferRTV[CurrentBackBufferIndex];
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp
new file mode 100644
index 00000000..d59f1947
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp
@@ -0,0 +1,511 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "TextureD3D12Impl.h"
+#include "RenderDeviceD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+#include "D3D12TypeConversions.h"
+#include "TextureViewD3D12Impl.h"
+#include "DXGITypeConversions.h"
+#include "d3dx12_win.h"
+#include "EngineMemory.h"
+
+using namespace Diligent;
+
+namespace Diligent
+{
+
+DXGI_FORMAT GetClearFormat(DXGI_FORMAT Fmt, D3D12_RESOURCE_FLAGS Flags)
+{
+ if( Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL )
+ {
+ switch (Fmt)
+ {
+ case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_D32_FLOAT;
+ case DXGI_FORMAT_R16_TYPELESS: return DXGI_FORMAT_D16_UNORM;
+ case DXGI_FORMAT_R24G8_TYPELESS: return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case DXGI_FORMAT_R32G8X24_TYPELESS: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+ }
+ }
+ else if (Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
+ {
+
+ }
+ return Fmt;
+}
+
+TextureD3D12Impl :: TextureD3D12Impl(FixedBlockMemoryAllocator &TexObjAllocator,
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ RenderDeviceD3D12Impl *pRenderDeviceD3D12,
+ const TextureDesc& TexDesc,
+ const TextureData &InitData /*= TextureData()*/) :
+ TTextureBase(TexObjAllocator, TexViewObjAllocator, pRenderDeviceD3D12, TexDesc)
+{
+ if( m_Desc.Usage == USAGE_STATIC && InitData.pSubResources == nullptr )
+ LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time");
+
+ D3D12_RESOURCE_DESC Desc = {};
+ Desc.Alignment = 0;
+ if(m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ Desc.DepthOrArraySize = (UINT16)m_Desc.ArraySize;
+ else if(m_Desc.Type == RESOURCE_DIM_TEX_3D )
+ Desc.DepthOrArraySize = (UINT16)m_Desc.Depth;
+ else
+ Desc.DepthOrArraySize = 1;
+
+ if( m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY )
+ Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D;
+ else if( m_Desc.Type == RESOURCE_DIM_TEX_2D || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ else if( m_Desc.Type == RESOURCE_DIM_TEX_3D )
+ Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
+ else
+ {
+ LOG_ERROR_AND_THROW("Unknown texture type");
+ }
+
+
+ Desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ if( m_Desc.BindFlags & BIND_RENDER_TARGET )
+ Desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ if( m_Desc.BindFlags & BIND_DEPTH_STENCIL )
+ Desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ if( (m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || (m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) )
+ Desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ Desc.Format = TexFormatToDXGI_Format(m_Desc.Format, m_Desc.BindFlags);;
+ Desc.Height = (UINT)m_Desc.Height;
+ Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ Desc.MipLevels = static_cast<Uint16>(m_Desc.MipLevels);
+ Desc.SampleDesc.Count = m_Desc.SampleCount;
+ Desc.SampleDesc.Quality = 0;
+ Desc.Width = (UINT64)m_Desc.Width;
+
+
+ D3D12_HEAP_PROPERTIES HeapProps;
+ HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ HeapProps.CreationNodeMask = 1;
+ HeapProps.VisibleNodeMask = 1;
+
+ auto *pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
+ D3D12_CLEAR_VALUE ClearValue;
+ D3D12_CLEAR_VALUE *pClearValue = nullptr;
+ if( Desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) )
+ {
+ if(m_Desc.ClearValue.Format != TEX_FORMAT_UNKNOWN)
+ ClearValue.Format = TexFormatToDXGI_Format(m_Desc.ClearValue.Format);
+ else
+ ClearValue.Format = GetClearFormat(Desc.Format, Desc.Flags);
+
+ if (Desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
+ {
+ for(int i=0; i < 4; ++i)
+ ClearValue.Color[i] = m_Desc.ClearValue.Color[i];
+ }
+ else if(Desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
+ {
+ ClearValue.DepthStencil.Depth = m_Desc.ClearValue.DepthStencil.Depth;
+ ClearValue.DepthStencil.Stencil = m_Desc.ClearValue.DepthStencil.Stencil;
+ }
+ pClearValue = &ClearValue;
+ }
+
+ bool bInitializeTexture = (InitData.pSubResources != nullptr && InitData.NumSubresources > 0);
+ if(bInitializeTexture)
+ m_UsageState = D3D12_RESOURCE_STATE_COPY_DEST;
+
+ auto hr = pd3d12Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE,
+ &Desc, m_UsageState, pClearValue, __uuidof(m_pd3d12Resource), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource)) );
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create D3D12 texture")
+
+ if(bInitializeTexture)
+ {
+ Uint32 ExpectedNumSubresources = static_cast<Uint32>(Desc.MipLevels * (Desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? 1 : Desc.DepthOrArraySize) );
+ if( InitData.NumSubresources != ExpectedNumSubresources )
+ LOG_ERROR_AND_THROW("Incorrect number of subresources in init data. ", ExpectedNumSubresources, " expected, while ", InitData.NumSubresources, " provided")
+
+ UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_pd3d12Resource, 0, InitData.NumSubresources);
+
+ D3D12_HEAP_PROPERTIES UploadHeapProps;
+ UploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ UploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ UploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ UploadHeapProps.CreationNodeMask = 1;
+ UploadHeapProps.VisibleNodeMask = 1;
+
+ D3D12_RESOURCE_DESC BufferDesc;
+ BufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ BufferDesc.Alignment = 0;
+ BufferDesc.Width = uploadBufferSize;
+ BufferDesc.Height = 1;
+ BufferDesc.DepthOrArraySize = 1;
+ BufferDesc.MipLevels = 1;
+ BufferDesc.Format = DXGI_FORMAT_UNKNOWN;
+ BufferDesc.SampleDesc.Count = 1;
+ BufferDesc.SampleDesc.Quality = 0;
+ BufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ BufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ CComPtr<ID3D12Resource> UploadBuffer;
+ hr = pd3d12Device->CreateCommittedResource( &UploadHeapProps, D3D12_HEAP_FLAG_NONE,
+ &BufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr, __uuidof(UploadBuffer), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&UploadBuffer)));
+ if(FAILED(hr))
+ LOG_ERROR_AND_THROW("Failed to create committed resource in an upload heap")
+
+ auto *pInitContext = pRenderDeviceD3D12->AllocateCommandContext();
+ // copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default texture
+ VERIFY_EXPR(m_UsageState == D3D12_RESOURCE_STATE_COPY_DEST);
+ std::vector<D3D12_SUBRESOURCE_DATA, STDAllocatorRawMem<D3D12_SUBRESOURCE_DATA> > D3D12SubResData(InitData.NumSubresources, D3D12_SUBRESOURCE_DATA(), STD_ALLOCATOR_RAW_MEM(D3D12_SUBRESOURCE_DATA, GetRawAllocator(), "Allocator for vector<D3D12_SUBRESOURCE_DATA>") );
+ for(size_t subres=0; subres < D3D12SubResData.size(); ++subres)
+ {
+ D3D12SubResData[subres].pData = InitData.pSubResources[subres].pData;
+ D3D12SubResData[subres].RowPitch = InitData.pSubResources[subres].Stride;
+ D3D12SubResData[subres].SlicePitch = InitData.pSubResources[subres].DepthStride;
+ }
+ auto UploadedSize = UpdateSubresources(pInitContext->GetCommandList(), m_pd3d12Resource, UploadBuffer, 0, 0, InitData.NumSubresources, D3D12SubResData.data());
+ VERIFY(UploadedSize == uploadBufferSize, "Incorrect uploaded data size (", UploadedSize, "). ", uploadBufferSize, " is expected");
+
+ pRenderDeviceD3D12->CloseAndExecuteCommandContext(pInitContext);
+
+ // We MUST NOT call TransitionResource() from here, because
+ // it will call AddRef() and potentially Release(), while
+ // the object is not constructed yet
+ // Add reference to the object to the release queue to keep it alive
+ // until copy operation is complete. This must be done after
+ // submitting command list for execution!
+ pRenderDeviceD3D12->SafeReleaseD3D12Object(UploadBuffer);
+ }
+
+ if(m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS)
+ {
+ auto NumSubresources = m_Desc.MipLevels * m_Desc.ArraySize;
+ m_SubresUAVs = pRenderDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, NumSubresources);
+ for(Uint32 Slice = 0; Slice < m_Desc.ArraySize; ++Slice)
+ for (Uint32 MipLevel = 0; MipLevel < m_Desc.MipLevels; ++MipLevel)
+ {
+ auto SubResInd = D3D12CalcSubresource(MipLevel, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize);
+ VERIFY_EXPR(SubResInd < m_SubresUAVs.GetNumHandles());
+
+ TextureViewDesc UAVDesc;
+ if( m_Desc.Type == RESOURCE_DIM_TEX_2D )
+ UAVDesc.TextureDim = RESOURCE_DIM_TEX_2D;
+ else
+ {
+ LOG_ERROR("Mipmap generation is only supported for 2D textures and texture arrays")
+ }
+ UAVDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS;
+ UAVDesc.FirstArraySlice = Slice;
+ UAVDesc.MostDetailedMip = MipLevel;
+ CreateUAV( UAVDesc, m_SubresUAVs.GetCpuHandle(SubResInd) );
+ }
+ }
+}
+
+
+static TextureDesc InitTexDescFromD3D12Resource(ID3D12Resource *pTexture, const TextureDesc& SrcTexDesc)
+{
+ auto ResourceDesc = pTexture->GetDesc();
+
+ TextureDesc TexDesc = SrcTexDesc;
+ if( TexDesc.Width != 0 && TexDesc.Width != ResourceDesc.Width)
+ LOG_WARNING_MESSAGE("Provided texture width (", TexDesc.Width, ") does not match the actual D3D12 resource width (", ResourceDesc.Width, ")");
+ if( TexDesc.Height != 0 && TexDesc.Height != ResourceDesc.Height)
+ LOG_WARNING_MESSAGE("Provided texture height (", TexDesc.Height, ") does not match the actual D3D12 resource height (", ResourceDesc.Height, ")");
+ if( TexDesc.ArraySize != 0 && TexDesc.ArraySize != ResourceDesc.DepthOrArraySize)
+ LOG_WARNING_MESSAGE("Provided texture depth or array size (", TexDesc.ArraySize, ") does not match the actual D3D12 resource depth or array size (", ResourceDesc.DepthOrArraySize, ")");
+ if( TexDesc.MipLevels != 0 && TexDesc.MipLevels != ResourceDesc.MipLevels)
+ LOG_WARNING_MESSAGE("Provided number of mip levels (", TexDesc.MipLevels, ") does not match the actual number of mip levels in D3D12 resource (", ResourceDesc.MipLevels, ")");
+ auto RefDXGIFormat = TexFormatToDXGI_Format(TexDesc.Format);
+ if( RefDXGIFormat != TexDesc.Format)
+ LOG_ERROR_AND_THROW("Incorrect texture format (", GetTextureFormatAttribs(TexDesc.Format).Name, ")");
+
+ TexDesc.Width = static_cast<Uint32>(ResourceDesc.Width);
+ TexDesc.Height = static_cast<Uint32>(ResourceDesc.Height);
+ TexDesc.ArraySize = ResourceDesc.DepthOrArraySize;
+ TexDesc.MipLevels = ResourceDesc.MipLevels;
+ switch(ResourceDesc.Dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D: TexDesc.Type = TexDesc.ArraySize == 1 ? RESOURCE_DIM_TEX_1D : RESOURCE_DIM_TEX_1D_ARRAY; break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D: TexDesc.Type = TexDesc.ArraySize == 1 ? RESOURCE_DIM_TEX_2D : RESOURCE_DIM_TEX_2D_ARRAY; break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D: TexDesc.Type = RESOURCE_DIM_TEX_3D; break;
+ }
+
+ TexDesc.SampleCount = ResourceDesc.SampleDesc.Count;
+
+ TexDesc.Usage = USAGE_DEFAULT;
+ TexDesc.BindFlags = 0;
+ if( ResourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET )
+ TexDesc.BindFlags |= BIND_RENDER_TARGET;
+ if( ResourceDesc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL )
+ TexDesc.BindFlags |= BIND_DEPTH_STENCIL;
+ if( ResourceDesc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS )
+ TexDesc.BindFlags |= BIND_UNORDERED_ACCESS;
+ return TexDesc;
+}
+
+TextureD3D12Impl::TextureD3D12Impl(FixedBlockMemoryAllocator &TexObjAllocator,
+ FixedBlockMemoryAllocator &TexViewObjAllocator,
+ RenderDeviceD3D12Impl *pDeviceD3D12,
+ const TextureDesc& TexDesc,
+ ID3D12Resource *pTexture) :
+ TTextureBase(TexObjAllocator, TexViewObjAllocator, pDeviceD3D12, InitTexDescFromD3D12Resource(pTexture, TexDesc))
+{
+ m_pd3d12Resource = pTexture;
+}
+IMPLEMENT_QUERY_INTERFACE( TextureD3D12Impl, IID_TextureD3D12, TTextureBase )
+
+void TextureD3D12Impl::CreateViewInternal( const struct TextureViewDesc &ViewDesc, ITextureView **ppView, bool bIsDefaultView )
+{
+ VERIFY( ppView != nullptr, "View pointer address is null" );
+ if( !ppView )return;
+ VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
+
+ *ppView = nullptr;
+
+ try
+ {
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ auto &TexViewAllocator = pDeviceD3D12Impl->GetTexViewObjAllocator();
+ VERIFY( &TexViewAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization" );
+
+ auto UpdatedViewDesc = ViewDesc;
+ CorrectTextureViewDesc( UpdatedViewDesc );
+
+ DescriptorHeapAllocation ViewHandleAlloc;
+ switch( ViewDesc.ViewType )
+ {
+ case TEXTURE_VIEW_SHADER_RESOURCE:
+ {
+ VERIFY( m_Desc.BindFlags & BIND_SHADER_RESOURCE, "BIND_SHADER_RESOURCE flag is not set" );
+ ViewHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ CreateSRV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ }
+ break;
+
+ case TEXTURE_VIEW_RENDER_TARGET:
+ {
+ VERIFY( m_Desc.BindFlags & BIND_RENDER_TARGET, "BIND_RENDER_TARGET flag is not set" );
+ ViewHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+ CreateRTV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ }
+ break;
+
+ case TEXTURE_VIEW_DEPTH_STENCIL:
+ {
+ VERIFY( m_Desc.BindFlags & BIND_DEPTH_STENCIL, "BIND_DEPTH_STENCIL is not set" );
+ ViewHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
+ CreateDSV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ }
+ break;
+
+ case TEXTURE_VIEW_UNORDERED_ACCESS:
+ {
+ VERIFY( m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "BIND_UNORDERED_ACCESS flag is not set" );
+ ViewHandleAlloc = pDeviceD3D12Impl->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ CreateUAV( UpdatedViewDesc, ViewHandleAlloc.GetCpuHandle() );
+ }
+ break;
+
+ default: UNEXPECTED( "Unknown view type" ); break;
+ }
+
+ auto pViewD3D12 = NEW(TexViewAllocator, "TextureViewD3D12Impl instance", TextureViewD3D12Impl, GetDevice(), UpdatedViewDesc, this, std::move(ViewHandleAlloc), bIsDefaultView );
+ VERIFY( pViewD3D12->GetDesc().ViewType == ViewDesc.ViewType, "Incorrect view type" );
+
+ if( bIsDefaultView )
+ *ppView = pViewD3D12;
+ else
+ pViewD3D12->QueryInterface(IID_TextureView, reinterpret_cast<IObject**>(ppView) );
+ }
+ catch( const std::runtime_error & )
+ {
+ const auto *ViewTypeName = GetTexViewTypeLiteralName(ViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", ViewDesc.Name ? ViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"" )
+ }
+}
+
+TextureD3D12Impl :: ~TextureD3D12Impl()
+{
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ auto *pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice());
+ pDeviceD3D12Impl->SafeReleaseD3D12Object(m_pd3d12Resource);
+}
+
+void TextureD3D12Impl::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+{
+ TTextureBase::UpdateData( pContext, MipLevel, Slice, DstBox, SubresData );
+ VERIFY( m_Desc.Usage == USAGE_DEFAULT, "Only default usage resiurces can be updated with UpdateData()" );
+
+ LOG_ERROR_ONCE("TextureD3D12Impl::UpdateData() is not implemented");
+#if 0
+ auto *pD3D12DeviceContext = static_cast<DeviceContextD3D12Impl*>(pContext)->GetD3D12DeviceContext();
+
+ D3D12_BOX D3D12Box;
+ D3D12Box.left = DstBox.MinX;
+ D3D12Box.right = DstBox.MaxX;
+ D3D12Box.top = DstBox.MinY;
+ D3D12Box.bottom = DstBox.MaxY;
+ D3D12Box.front = DstBox.MinZ;
+ D3D12Box.back = DstBox.MaxZ;
+ auto SubresIndex = D3D12CalcSubresource(MipLevel, Slice, m_Desc.MipLevels);
+ pD3D12DeviceContext->UpdateSubresource(m_pd3d12Resource, SubresIndex, &D3D12Box, SubresData.pData, SubresData.Stride, SubresData.DepthStride);
+#endif
+}
+
+void TextureD3D12Impl :: CopyData(IDeviceContext *pContext,
+ ITexture *pSrcTexture,
+ Uint32 SrcMipLevel,
+ Uint32 SrcSlice,
+ const Box *pSrcBox,
+ Uint32 DstMipLevel,
+ Uint32 DstSlice,
+ Uint32 DstX,
+ Uint32 DstY,
+ Uint32 DstZ)
+{
+ TTextureBase::CopyData( pContext, pSrcTexture, SrcMipLevel, SrcSlice, pSrcBox,
+ DstMipLevel, DstSlice, DstX, DstY, DstZ );
+
+ auto *pCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext);
+ auto *pSrcTexD3D12 = ValidatedCast<TextureD3D12Impl>( pSrcTexture );
+
+ D3D12_BOX D3D12SrcBox, *pD3D12SrcBox = nullptr;
+ if( pSrcBox )
+ {
+ D3D12SrcBox.left = pSrcBox->MinX;
+ D3D12SrcBox.right = pSrcBox->MaxX;
+ D3D12SrcBox.top = pSrcBox->MinY;
+ D3D12SrcBox.bottom = pSrcBox->MaxY;
+ D3D12SrcBox.front = pSrcBox->MinZ;
+ D3D12SrcBox.back = pSrcBox->MaxZ;
+ pD3D12SrcBox = &D3D12SrcBox;
+ }
+
+ auto DstSubResIndex = D3D12CalcSubresource(DstMipLevel, DstSlice, 0, m_Desc.MipLevels, m_Desc.ArraySize);
+ auto SrcSubResIndex = D3D12CalcSubresource(SrcMipLevel, SrcSlice, 0, pSrcTexD3D12->m_Desc.MipLevels, pSrcTexD3D12->m_Desc.ArraySize);
+ pCtxD3D12->CopyTextureRegion(pSrcTexD3D12, SrcSubResIndex, pD3D12SrcBox, this, DstSubResIndex, DstX, DstY, DstZ);
+}
+
+void TextureD3D12Impl :: Map(IDeviceContext *pContext, MAP_TYPE MapType, Uint32 MapFlags, PVoid &pMappedData)
+{
+ TTextureBase::Map( pContext, MapType, MapFlags, pMappedData );
+ LOG_ERROR_ONCE("TextureD3D12Impl::Map() is not implemented");
+
+ static char TmpDummyBuffer[1024*1024*64];
+ pMappedData = TmpDummyBuffer;
+
+ //auto *pD3D12DeviceContext = static_cast<RenderDeviceD3D12Impl*>( static_cast<CRenderDevice*>(m_pDevice) )->GetD3D12DeviceContext();
+ //auto D3D12MapType = MapTypeToD3D12MapType(MapType);
+ //auto D3D12MapFlags = MapFlagsToD3D12MapFlags(MapFlags);
+
+ //D3D12_MAPPED_SUBRESOURCE MappedBuff;
+ //pD3D12DeviceContext->Map(m_pd3d12Resource, 0, D3D12MapType, D3D12MapFlags, &MappedBuff);
+
+ //pMappedData = MappedBuff.pData;
+
+ //VERIFY( pMappedData, "Map failed" );
+}
+
+void TextureD3D12Impl::Unmap( IDeviceContext *pContext, MAP_TYPE MapType )
+{
+ TTextureBase::Unmap( pContext, MapType );
+ LOG_ERROR_ONCE("TextureD3D12Impl::Unmap() is not implemented");
+ //auto *pD3D12DeviceContext = static_cast<RenderDeviceD3D12Impl*>( static_cast<CRenderDevice*>(m_pDevice) )->GetD3D12DeviceContext();
+ //pD3D12DeviceContext->Unmap(m_pd3d12Resource, 0);
+}
+
+
+void TextureD3D12Impl::CreateSRV( TextureViewDesc &SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle )
+{
+ VERIFY( SRVDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Incorrect view type: shader resource is expected" );
+
+ if( SRVDesc.Format == TEX_FORMAT_UNKNOWN )
+ {
+ SRVDesc.Format = m_Desc.Format;
+ }
+ D3D12_SHADER_RESOURCE_VIEW_DESC D3D12_SRVDesc;
+ TextureViewDesc_to_D3D12_SRV_DESC(SRVDesc, D3D12_SRVDesc, m_Desc.SampleCount);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateShaderResourceView(m_pd3d12Resource, &D3D12_SRVDesc, SRVHandle);
+}
+
+void TextureD3D12Impl::CreateRTV( TextureViewDesc &RTVDesc, D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle )
+{
+ VERIFY( RTVDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET, "Incorrect view type: render target is expected" );
+
+ if( RTVDesc.Format == TEX_FORMAT_UNKNOWN )
+ {
+ RTVDesc.Format = m_Desc.Format;
+ }
+
+ D3D12_RENDER_TARGET_VIEW_DESC D3D12_RTVDesc;
+ TextureViewDesc_to_D3D12_RTV_DESC(RTVDesc, D3D12_RTVDesc, m_Desc.SampleCount);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateRenderTargetView( m_pd3d12Resource, &D3D12_RTVDesc, RTVHandle );
+}
+
+void TextureD3D12Impl::CreateDSV( TextureViewDesc &DSVDesc, D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle )
+{
+ VERIFY( DSVDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Incorrect view type: depth stencil is expected" );
+
+ if( DSVDesc.Format == TEX_FORMAT_UNKNOWN )
+ {
+ DSVDesc.Format = m_Desc.Format;
+ }
+
+ D3D12_DEPTH_STENCIL_VIEW_DESC D3D12_DSVDesc;
+ TextureViewDesc_to_D3D12_DSV_DESC(DSVDesc, D3D12_DSVDesc, m_Desc.SampleCount);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateDepthStencilView( m_pd3d12Resource, &D3D12_DSVDesc, DSVHandle );
+}
+
+void TextureD3D12Impl::CreateUAV( TextureViewDesc &UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle )
+{
+ VERIFY( UAVDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Incorrect view type: unordered access is expected" );
+
+ if( UAVDesc.Format == TEX_FORMAT_UNKNOWN )
+ {
+ UAVDesc.Format = m_Desc.Format;
+ }
+
+ D3D12_UNORDERED_ACCESS_VIEW_DESC D3D12_UAVDesc;
+ TextureViewDesc_to_D3D12_UAV_DESC(UAVDesc, D3D12_UAVDesc);
+
+ auto *pDeviceD3D12 = static_cast<RenderDeviceD3D12Impl*>(GetDevice())->GetD3D12Device();
+ pDeviceD3D12->CreateUnorderedAccessView( m_pd3d12Resource, nullptr, &D3D12_UAVDesc, UAVHandle );
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE TextureD3D12Impl::GetUAVDescriptorHandle(Uint32 Mip, Uint32 Slice)
+{
+ return m_SubresUAVs.GetCpuHandle(D3D12CalcSubresource(Mip, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize));
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp
new file mode 100644
index 00000000..0b93926b
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp
@@ -0,0 +1,61 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "TextureViewD3D12Impl.h"
+#include "DeviceContextD3D12Impl.h"
+
+namespace Diligent
+{
+
+TextureViewD3D12Impl::TextureViewD3D12Impl( FixedBlockMemoryAllocator &TexViewObjAllocator,
+ IRenderDevice *pDevice,
+ const TextureViewDesc& ViewDesc,
+ ITexture *pTexture,
+ DescriptorHeapAllocation &&HandleAlloc,
+ bool bIsDefaultView ) :
+ TTextureViewBase( TexViewObjAllocator, pDevice, ViewDesc, pTexture, bIsDefaultView ),
+ m_Descriptor(std::move(HandleAlloc))
+{
+}
+//
+//ID3D12View* TextureViewD3D12Impl::GetD3D12View()
+//{
+// return m_pD3D12View;
+//}
+
+IMPLEMENT_QUERY_INTERFACE( TextureViewD3D12Impl, IID_TextureViewD3D12, TTextureViewBase )
+
+void TextureViewD3D12Impl::GenerateMips( IDeviceContext *pContext )
+{
+ VERIFY( m_Desc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "GenerateMips() is allowed for shader resource views only, ", GetTexViewTypeLiteralName(m_Desc.ViewType), " is not allowed." );
+ if( m_Desc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE )
+ {
+ LOG_ERROR("GenerateMips() is allowed for shader resource views only, ", GetTexViewTypeLiteralName(m_Desc.ViewType), " is not allowed.");
+ return;
+ }
+ auto *pDeviceCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>( pContext );
+ pDeviceCtxD3D12->GenerateMips(this);
+}
+
+}
diff --git a/Graphics/GraphicsEngineD3D12/src/pch.cpp b/Graphics/GraphicsEngineD3D12/src/pch.cpp
new file mode 100644
index 00000000..997e0f4a
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/pch.cpp
@@ -0,0 +1,24 @@
+/* Copyright 2015-2016 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"