diff options
Diffstat (limited to 'src/d3d11')
| -rw-r--r-- | src/d3d11/compiled_shaders_d3d11.cpp | 43 | ||||
| -rw-r--r-- | src/d3d11/compiled_shaders_d3d11.h | 52 | ||||
| -rw-r--r-- | src/d3d11/context_d3d11.cpp | 1257 | ||||
| -rw-r--r-- | src/d3d11/context_d3d11.h | 191 | ||||
| -rw-r--r-- | src/d3d11/d3d11_util.cpp | 347 | ||||
| -rw-r--r-- | src/d3d11/d3d11_util.h | 234 |
6 files changed, 2124 insertions, 0 deletions
diff --git a/src/d3d11/compiled_shaders_d3d11.cpp b/src/d3d11/compiled_shaders_d3d11.cpp new file mode 100644 index 0000000..2a23501 --- /dev/null +++ b/src/d3d11/compiled_shaders_d3d11.cpp @@ -0,0 +1,43 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#include <stdint.h> +namespace d3d11 { namespace shaders { + #include <shaders/Apply_PS.mux.bytecode> + #include <shaders/ComputeLightLUT_CS.mux.bytecode> + #include <shaders/ComputePhaseLookup_PS.mux.bytecode> + #include <shaders/Debug_PS.mux.bytecode> + #include <shaders/DownsampleDepth_PS.mux.bytecode> + #include <shaders/Quad_VS.mux.bytecode> + #include <shaders/RenderVolume_VS.mux.bytecode> + #include <shaders/RenderVolume_HS.mux.bytecode> + #include <shaders/RenderVolume_DS.mux.bytecode> + #include <shaders/RenderVolume_PS.mux.bytecode> + #include <shaders/Resolve_PS.mux.bytecode> + #include <shaders/TemporalFilter_PS.mux.bytecode> +}; /* namespace shaders */ }; /* namespace d3d11 */ diff --git a/src/d3d11/compiled_shaders_d3d11.h b/src/d3d11/compiled_shaders_d3d11.h new file mode 100644 index 0000000..885b1c3 --- /dev/null +++ b/src/d3d11/compiled_shaders_d3d11.h @@ -0,0 +1,52 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#ifndef COMPILED_SHADERS_D3D11_H +#define COMPILED_SHADERS_D3D11_H +//////////////////////////////////////////////////////////////////////////////// +#include <stdint.h> +namespace d3d11 { namespace shaders { + #include <shaders/Apply_PS.mux.h> + #include <shaders/ComputeLightLUT_CS.mux.h> + #include <shaders/ComputePhaseLookup_PS.mux.h> + #include <shaders/Debug_PS.mux.h> + #include <shaders/DownsampleDepth_PS.mux.h> + #include <shaders/Quad_VS.mux.h> + #include <shaders/RenderVolume_VS.mux.h> + #include <shaders/RenderVolume_HS.mux.h> + #include <shaders/RenderVolume_DS.mux.h> + #include <shaders/RenderVolume_PS.mux.h> + #include <shaders/Resolve_PS.mux.h> + #include <shaders/TemporalFilter_PS.mux.h> +}; /* namespace shaders */ }; /* namespace d3d11 */ +// We use the namespaces to avoid conflicts if supporting multiple APIs +// but they aren't needed wherever these would be included. +using namespace d3d11; +using namespace shaders; +//////////////////////////////////////////////////////////////////////////////// +#endif // COMPILED_SHADERS_D3D11_H diff --git a/src/d3d11/context_d3d11.cpp b/src/d3d11/context_d3d11.cpp new file mode 100644 index 0000000..9bb2f4a --- /dev/null +++ b/src/d3d11/context_d3d11.cpp @@ -0,0 +1,1257 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#include "common.h" +#include "context_d3d11.h" +#include "compiled_shaders_d3d11.h" +#include "d3d11_util.h" + +#include <stdint.h> +#include <d3d11.h> + +#pragma warning(disable: 4100) +//////////////////////////////////////////////////////////////////////////////// +namespace Nv { namespace VolumetricLighting { +//////////////////////////////////////////////////////////////////////////////// +const uint8_t STENCIL_REF = 0xFF; + +/*============================================================================== + Create a context and load/allocate/generate resources +==============================================================================*/ + +Status ContextImp_D3D11::Create(ContextImp_D3D11 ** out_ctx, const PlatformDesc * pPlatformDesc, const ContextDesc * pContextDesc) +{ + ID3D11Device * pDevice = pPlatformDesc->d3d11.pDevice; + if (pDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_11_0) + return Status::UNSUPPORTED_DEVICE; + + *out_ctx = new ContextImp_D3D11(pContextDesc); + Status result = (*out_ctx)->CreateResources(pDevice); + if (result != Status::OK) + { + delete *out_ctx; + *out_ctx = nullptr; + return result; + } + else + { + return Status::OK; + } +} + +Status ContextImp_D3D11::CreateResources(ID3D11Device * device) +{ + //-------------------------------------------------------------------------- + // Shaders +# define LOAD_SHADERS(x) LoadShaders(device, ##x##::permutation_code, ##x##::permutation_length, shaders::##x##::PERMUTATION_ENTRY_COUNT, shaders.##x) + VD3D_(LOAD_SHADERS(Apply_PS)); + VD3D_(LOAD_SHADERS(ComputeLightLUT_CS)); + VD3D_(LOAD_SHADERS(ComputePhaseLookup_PS)); + VD3D_(LOAD_SHADERS(Debug_PS)); + VD3D_(LOAD_SHADERS(DownsampleDepth_PS)); + VD3D_(LOAD_SHADERS(Quad_VS)); + VD3D_(LOAD_SHADERS(RenderVolume_VS)); + VD3D_(LOAD_SHADERS(RenderVolume_HS)); + VD3D_(LOAD_SHADERS(RenderVolume_DS)); + VD3D_(LOAD_SHADERS(RenderVolume_PS)); + VD3D_(LOAD_SHADERS(Resolve_PS)); + VD3D_(LOAD_SHADERS(TemporalFilter_PS)); +# undef LOAD_SHADERS + + //-------------------------------------------------------------------------- + // Constant Buffers + V_CREATE(pPerContextCB, ConstantBuffer<PerContextCB>::Create(device)); + V_CREATE(pPerFrameCB, ConstantBuffer<PerFrameCB>::Create(device)); + V_CREATE(pPerVolumeCB, ConstantBuffer<PerVolumeCB>::Create(device)); + V_CREATE(pPerApplyCB, ConstantBuffer<PerApplyCB>::Create(device)); + + //-------------------------------------------------------------------------- + // Shader Resources + V_CREATE(pDepth_, DepthTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), getInternalSampleCount(), DXGI_FORMAT_D24_UNORM_S8_UINT, 1, "NvVl::Depth")); + V_CREATE(pPhaseLUT_, RenderTarget::Create(device, 1, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Phase LUT")); + V_CREATE(pLightLUT_P_[0], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Point [0]")); + V_CREATE(pLightLUT_P_[1], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Point [1]")); + V_CREATE(pLightLUT_S1_[0], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Spot 1 [0]")); + V_CREATE(pLightLUT_S1_[1], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Spot 1 [1]")); + V_CREATE(pLightLUT_S2_[0], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Spot 2 [0]")); + V_CREATE(pLightLUT_S2_[1], RenderTarget::Create(device, LIGHT_LUT_DEPTH_RESOLUTION, LIGHT_LUT_WDOTV_RESOLUTION, 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Light LUT Spot 2 [1]")); + V_CREATE(pAccumulation_, RenderTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), getInternalSampleCount(), DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Accumulation")); + + if (isInternalMSAA() || getFilterMode() == FilterMode::TEMPORAL) + { + V_CREATE(pResolvedAccumulation_, RenderTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Resolved Accumulation")); + V_CREATE(pResolvedDepth_, RenderTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), 1, DXGI_FORMAT_R16G16_FLOAT, "NvVl::Resolved Depth")); + } + + if (getFilterMode() == FilterMode::TEMPORAL) + { + for (int i=0; i<2; ++i) + { + V_CREATE(pFilteredDepth_[i], RenderTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), 1, DXGI_FORMAT_R16G16_FLOAT, "NvVl::Filtered Depth")); + V_CREATE(pFilteredAccumulation_[i], RenderTarget::Create(device, getInternalBufferWidth(), getInternalBufferHeight(), 1, DXGI_FORMAT_R16G16B16A16_FLOAT, "NvVl::Filtered Accumulation")); + } + } + + //-------------------------------------------------------------------------- + // States + // Rasterizer State + { + CD3D11_RASTERIZER_DESC rsDesc((CD3D11_DEFAULT())); + rsDesc.FrontCounterClockwise = TRUE; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.DepthClipEnable = FALSE; + VD3D_(device->CreateRasterizerState(&rsDesc, &states.rs.cull_none)); + } + { + CD3D11_RASTERIZER_DESC rsDesc((CD3D11_DEFAULT())); + rsDesc.FrontCounterClockwise = TRUE; + rsDesc.CullMode = D3D11_CULL_FRONT; + rsDesc.DepthClipEnable = FALSE; + VD3D_(device->CreateRasterizerState(&rsDesc, &states.rs.cull_front)); + } + { + CD3D11_RASTERIZER_DESC rsDesc((CD3D11_DEFAULT())); + rsDesc.FillMode = D3D11_FILL_WIREFRAME; + rsDesc.FrontCounterClockwise = TRUE; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.DepthClipEnable = FALSE; + VD3D_(device->CreateRasterizerState(&rsDesc, &states.rs.wireframe)); + } + // Sampler State + { + CD3D11_SAMPLER_DESC ssDesc((CD3D11_DEFAULT())); + ssDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + VD3D_(device->CreateSamplerState(&ssDesc, &states.ss.point)); + } + { + CD3D11_SAMPLER_DESC ssDesc((CD3D11_DEFAULT())); + ssDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + VD3D_(device->CreateSamplerState(&ssDesc, &states.ss.linear)); + } + // Depth-Stencil + { + // Depth Disabled + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthEnable = FALSE; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.no_depth)); + } + { + // Write-only Depth DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.write_only_depth)); + } + { + // Render Volume DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.StencilEnable = TRUE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.render_volume)); + } + { + // Render Volume Boundary DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.StencilEnable = TRUE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.render_volume_boundary)); + } + { + // Render volume cap DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthEnable = FALSE; + dsDesc.StencilEnable = TRUE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_LESS_EQUAL; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_LESS_EQUAL; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.render_volume_cap)); + } + { + // Finish Volume DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthEnable = FALSE; + dsDesc.StencilEnable = TRUE; + dsDesc.StencilWriteMask = 0x00; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_GREATER; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.finish_volume)); + } + { + // Read-Only Depth DS + CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT())); + dsDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + VD3D_(device->CreateDepthStencilState(&dsDesc, &states.ds.read_only_depth)); + } + // Blend State + { + CD3D11_BLEND_DESC bsDesc((CD3D11_DEFAULT())); + bsDesc.RenderTarget[0].RenderTargetWriteMask = 0x00000000; + VD3D_(device->CreateBlendState(&bsDesc, &states.bs.no_color)); + } + { + CD3D11_BLEND_DESC bsDesc((CD3D11_DEFAULT())); + VD3D_(device->CreateBlendState(&bsDesc, &states.bs.no_blending)); + } + { + CD3D11_BLEND_DESC bsDesc((CD3D11_DEFAULT())); + bsDesc.RenderTarget[0].BlendEnable = TRUE; + bsDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_BLEND_FACTOR; + bsDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; + bsDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_BLEND_FACTOR; + bsDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; + VD3D_(device->CreateBlendState(&bsDesc, &states.bs.additive)); + } + { + CD3D11_BLEND_DESC bsDesc((CD3D11_DEFAULT())); + bsDesc.RenderTarget[0].BlendEnable = TRUE; + bsDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_BLEND_FACTOR; + bsDesc.RenderTarget[0].DestBlend = D3D11_BLEND_SRC1_COLOR; + bsDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; + bsDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; + VD3D_(device->CreateBlendState(&bsDesc, &states.bs.additive_modulate)); + } + { + CD3D11_BLEND_DESC bsDesc((CD3D11_DEFAULT())); + bsDesc.RenderTarget[0].BlendEnable = TRUE; + bsDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + bsDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; + bsDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + bsDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; + bsDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC1_ALPHA; + VD3D_(device->CreateBlendState(&bsDesc, &states.bs.debug_blend)); + } + return Status::OK; +} + +/*============================================================================== + Constructor / Destructor +==============================================================================*/ + +ContextImp_D3D11::ContextImp_D3D11(const ContextDesc * pContextDesc) : ContextImp_Common(pContextDesc) +{ + shaders.Apply_PS = nullptr; + shaders.ComputeLightLUT_CS = nullptr; + shaders.ComputePhaseLookup_PS = nullptr; + shaders.Debug_PS = nullptr; + shaders.DownsampleDepth_PS = nullptr; + shaders.Quad_VS = nullptr; + shaders.RenderVolume_VS = nullptr; + shaders.RenderVolume_HS = nullptr; + shaders.RenderVolume_DS = nullptr; + shaders.RenderVolume_PS = nullptr; + shaders.Resolve_PS = nullptr; + shaders.TemporalFilter_PS = nullptr; + + pPerContextCB = nullptr; + pPerFrameCB = nullptr; + pPerVolumeCB = nullptr; + pPerApplyCB = nullptr; + + pDepth_ = nullptr; + pPhaseLUT_ = nullptr; + pLightLUT_P_[0] = nullptr; + pLightLUT_P_[1] = nullptr; + pLightLUT_S1_[0] = nullptr; + pLightLUT_S1_[1] = nullptr; + pLightLUT_S2_[0] = nullptr; + pLightLUT_S2_[1] = nullptr; + pAccumulation_ = nullptr; + pResolvedAccumulation_ = nullptr; + pResolvedDepth_ = nullptr; + for (int i=0; i<2; ++i) + { + pFilteredAccumulation_[i] = nullptr; + pFilteredDepth_[i] = nullptr; + } + + states.rs.cull_none = nullptr; + states.rs.cull_front = nullptr; + states.rs.wireframe = nullptr; + states.ss.point = nullptr; + states.ss.linear = nullptr; + states.ds.no_depth = nullptr; + states.ds.write_only_depth = nullptr; + states.ds.read_only_depth = nullptr; + states.ds.render_volume = nullptr; + states.ds.render_volume_boundary = nullptr; + states.ds.render_volume_cap = nullptr; + states.ds.finish_volume = nullptr; + states.bs.no_color = nullptr; + states.bs.no_blending = nullptr; + states.bs.additive = nullptr; + states.bs.additive_modulate = nullptr; + states.bs.debug_blend = nullptr; +} + +ContextImp_D3D11::~ContextImp_D3D11() +{ + SAFE_DELETE_ARRAY(shaders.Apply_PS); + SAFE_DELETE_ARRAY(shaders.ComputeLightLUT_CS); + SAFE_DELETE_ARRAY(shaders.ComputePhaseLookup_PS); + SAFE_DELETE_ARRAY(shaders.Debug_PS); + SAFE_DELETE_ARRAY(shaders.DownsampleDepth_PS); + SAFE_DELETE_ARRAY(shaders.Quad_VS); + SAFE_DELETE_ARRAY(shaders.RenderVolume_VS); + SAFE_DELETE_ARRAY(shaders.RenderVolume_HS); + SAFE_DELETE_ARRAY(shaders.RenderVolume_DS); + SAFE_DELETE_ARRAY(shaders.RenderVolume_PS); + SAFE_DELETE_ARRAY(shaders.Resolve_PS); + SAFE_DELETE_ARRAY(shaders.TemporalFilter_PS); + + SAFE_DELETE(pPerContextCB); + SAFE_DELETE(pPerFrameCB); + SAFE_DELETE(pPerVolumeCB); + SAFE_DELETE(pPerApplyCB); + + SAFE_DELETE(pDepth_); + SAFE_DELETE(pPhaseLUT_); + SAFE_DELETE(pLightLUT_P_[0]); + SAFE_DELETE(pLightLUT_P_[1]); + SAFE_DELETE(pLightLUT_S1_[0]); + SAFE_DELETE(pLightLUT_S1_[1]); + SAFE_DELETE(pLightLUT_S2_[0]); + SAFE_DELETE(pLightLUT_S2_[1]); + SAFE_DELETE(pAccumulation_); + SAFE_DELETE(pResolvedAccumulation_); + SAFE_DELETE(pResolvedDepth_); + for (int i = 0; i < 2; ++i) + { + SAFE_DELETE(pFilteredAccumulation_[i]); + SAFE_DELETE(pFilteredDepth_[i]); + } + + SAFE_RELEASE(states.rs.cull_none); + SAFE_RELEASE(states.rs.cull_front); + SAFE_RELEASE(states.rs.wireframe); + SAFE_RELEASE(states.ss.point); + SAFE_RELEASE(states.ss.linear); + SAFE_RELEASE(states.ds.no_depth); + SAFE_RELEASE(states.ds.write_only_depth); + SAFE_RELEASE(states.ds.read_only_depth); + SAFE_RELEASE(states.ds.render_volume); + SAFE_RELEASE(states.ds.render_volume_boundary); + SAFE_RELEASE(states.ds.render_volume_cap); + SAFE_RELEASE(states.ds.finish_volume); + SAFE_RELEASE(states.bs.no_color); + SAFE_RELEASE(states.bs.no_blending); + SAFE_RELEASE(states.bs.additive); + SAFE_RELEASE(states.bs.additive_modulate); + SAFE_RELEASE(states.bs.debug_blend); +} + +/*============================================================================== + BeginAccumulation +==============================================================================*/ + +Status ContextImp_D3D11::BeginAccumulation_Start(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, ViewerDesc const* pViewerDesc, MediumDesc const* pMediumDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + + NV_PERFEVENT_BEGIN(dxCtx, "NvVl::BeginAccumulation"); + + if (!isInitialized_) + { + // Update the per-context constant buffer on the first frame it's used + isInitialized_ = true; + SetupCB_PerContext(pPerContextCB->Map(dxCtx)); + pPerContextCB->Unmap(dxCtx); + } + + // Setup the constant buffer + SetupCB_PerFrame(pViewerDesc, pMediumDesc, pPerFrameCB->Map(dxCtx)); + pPerFrameCB->Unmap(dxCtx); + + ID3D11Buffer* pCBs[] = { + pPerContextCB->getCB(), + pPerFrameCB->getCB(), + nullptr, // pPerVolumeCB - Invalid + nullptr // pPerApplyCB - Invalid + }; + dxCtx->VSSetConstantBuffers(0, 4, pCBs); + dxCtx->PSSetConstantBuffers(0, 4, pCBs); + + ID3D11SamplerState * pSamplers[] = { + states.ss.point, + states.ss.linear + }; + dxCtx->PSSetSamplers(0, 2, pSamplers); + + return Status::OK; +} + +Status ContextImp_D3D11::BeginAccumulation_UpdateMediumLUT(PlatformRenderCtx renderCtx) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + NV_PERFEVENT(dxCtx, "UpdateMediumLUT"); + + FLOAT black[] = {0,0,0,0}; + dxCtx->ClearRenderTargetView(pPhaseLUT_->getRTV(), black); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = 1; + viewport.Height = LIGHT_LUT_WDOTV_RESOLUTION; + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + + ID3D11RenderTargetView * RTVs[] = { pPhaseLUT_->getRTV() }; + dxCtx->OMSetRenderTargets(1, RTVs, nullptr); + dxCtx->OMSetDepthStencilState(states.ds.no_depth, 0); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + dxCtx->PSSetShader(shaders.ComputePhaseLookup_PS[ComputePhaseLookup_PS::SINGLE], nullptr, 0); + V_( DrawFullscreen(dxCtx) ); + return Status::OK; +} + +Status ContextImp_D3D11::BeginAccumulation_CopyDepth(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11ShaderResourceView * sceneDepth_SRV = sceneDepth; + NV_PERFEVENT(dxCtx, "CopyDepth"); + + dxCtx->ClearDepthStencilView(pDepth_->getDSV(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getInternalViewportWidth()); + viewport.Height = static_cast<float>(getInternalViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + + dxCtx->PSSetShaderResources(0, 1, &sceneDepth_SRV); + ID3D11RenderTargetView * NULL_RTVs[] = { nullptr }; + dxCtx->OMSetRenderTargets(1, NULL_RTVs, pDepth_->getDSV()); + dxCtx->OMSetDepthStencilState(states.ds.write_only_depth, 0); + dxCtx->OMSetBlendState(states.bs.no_color, nullptr, 0xFFFFFFFF); + DownsampleDepth_PS::Desc ps_desc = DownsampleDepth_PS::Desc(isOutputMSAA() ? DownsampleDepth_PS::SAMPLEMODE_MSAA : DownsampleDepth_PS::SAMPLEMODE_SINGLE); + dxCtx->PSSetShader(shaders.DownsampleDepth_PS[ps_desc], nullptr, 0); + V_( DrawFullscreen(dxCtx) ); + return Status::OK; +} + +Status ContextImp_D3D11::BeginAccumulation_End(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, ViewerDesc const* pViewerDesc, MediumDesc const* pMediumDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + FLOAT black[] = {0,0,0,0}; + dxCtx->ClearRenderTargetView(pAccumulation_->getRTV(), black); + + NV_PERFEVENT_END(dxCtx); + return Status::OK; +} + +/*============================================================================== + RenderVolume +==============================================================================*/ +Status ContextImp_D3D11::RenderVolume_Start(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + NV_PERFEVENT_BEGIN(dxCtx, "NvVl::RenderVolume"); + + // Setup the constant buffer + SetupCB_PerVolume(pShadowMapDesc, pLightDesc, pVolumeDesc, pPerVolumeCB->Map(dxCtx)); + pPerVolumeCB->Unmap(dxCtx); + + dxCtx->ClearDepthStencilView(pDepth_->getDSV(), D3D11_CLEAR_STENCIL, 1.0f, STENCIL_REF); + + // Set up all the state common for this pass + ID3D11Buffer * pCBs[] = { + pPerContextCB->getCB(), + pPerFrameCB->getCB(), + pPerVolumeCB->getCB(), + nullptr // pPerApplyCB: Invalid + }; + dxCtx->VSSetConstantBuffers(0, 4, pCBs); + dxCtx->HSSetConstantBuffers(0, 4, pCBs); + dxCtx->DSSetConstantBuffers(0, 4, pCBs); + dxCtx->PSSetConstantBuffers(0, 4, pCBs); + dxCtx->CSSetConstantBuffers(0, 4, pCBs); + + ID3D11SamplerState * pSamplers[] = { + states.ss.point, + states.ss.linear + }; + dxCtx->VSSetSamplers(0, 2, pSamplers); + dxCtx->HSSetSamplers(0, 2, pSamplers); + dxCtx->DSSetSamplers(0, 2, pSamplers); + dxCtx->PSSetSamplers(0, 2, pSamplers); + dxCtx->CSSetSamplers(0, 2, pSamplers); + + return Status::OK; +} + +Status ContextImp_D3D11::RenderVolume_DoVolume_Directional(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11ShaderResourceView * pShadowMap_SRV = shadowMap.d3d11; + + NV_PERFEVENT(dxCtx, "Directional"); + + uint32_t mesh_resolution = getCoarseResolution(pVolumeDesc); + + //-------------------------------------------------------------------------- + // Draw tessellated grid + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getInternalViewportWidth()); + viewport.Height = static_cast<float>(getInternalViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + dxCtx->RSSetState(states.rs.cull_none); + dxCtx->OMSetBlendState(states.bs.additive, nullptr, 0xFFFFFFFF); + + ID3D11RenderTargetView * RTVs[] = { pAccumulation_->getRTV() }; + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getDSV()); + + // Determine DS/HS permutation + RenderVolume_HS::Desc hs_desc; + hs_desc.flags.MAXTESSFACTOR = (RenderVolume_HS::eMAXTESSFACTOR) pVolumeDesc->eTessQuality; + + RenderVolume_DS::Desc ds_desc; + + switch (pShadowMapDesc->eType) + { + case ShadowMapLayout::SIMPLE: + case ShadowMapLayout::CASCADE_ATLAS: + hs_desc.flags.SHADOWMAPTYPE = RenderVolume_HS::SHADOWMAPTYPE_ATLAS; + ds_desc.flags.SHADOWMAPTYPE = RenderVolume_DS::SHADOWMAPTYPE_ATLAS; + break; + + case ShadowMapLayout::CASCADE_ARRAY: + hs_desc.flags.SHADOWMAPTYPE = RenderVolume_HS::SHADOWMAPTYPE_ARRAY; + ds_desc.flags.SHADOWMAPTYPE = RenderVolume_DS::SHADOWMAPTYPE_ARRAY; + break; + + default: + return Status::INVALID_PARAMETER; + }; + + switch (pShadowMapDesc->uElementCount) + { + case 0: + if (pShadowMapDesc->eType != ShadowMapLayout::SIMPLE) + { + return Status::INVALID_PARAMETER; + } + case 1: + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_1; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_1; + break; + + case 2: + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_2; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_2; + break; + + case 3: + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_3; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_3; + break; + + case 4: + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_4; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_4; + break; + + default: + return Status::INVALID_PARAMETER; + }; + hs_desc.flags.VOLUMETYPE = RenderVolume_HS::VOLUMETYPE_FRUSTUM; + ds_desc.flags.VOLUMETYPE = RenderVolume_DS::VOLUMETYPE_FRUSTUM; + + // Determine PS permutation + RenderVolume_PS::Desc ps_desc; + ps_desc.flags.SAMPLEMODE = isInternalMSAA() ? RenderVolume_PS::SAMPLEMODE_MSAA : RenderVolume_PS::SAMPLEMODE_SINGLE; + ps_desc.flags.LIGHTMODE = RenderVolume_PS::LIGHTMODE_DIRECTIONAL; + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_GEOMETRY; + ps_desc.flags.ATTENUATIONMODE = RenderVolume_PS::ATTENUATIONMODE_NONE; // unused for directional + + dxCtx->HSSetShader(shaders.RenderVolume_HS[hs_desc], nullptr, 0); + dxCtx->DSSetShader(shaders.RenderVolume_DS[ds_desc], nullptr, 0); + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + + ID3D11ShaderResourceView * SRVs[] = { + nullptr, + pShadowMap_SRV, + nullptr, + nullptr, + pPhaseLUT_->getSRV(), + }; + dxCtx->VSSetShaderResources(0, 5, SRVs); + dxCtx->HSSetShaderResources(0, 5, SRVs); + dxCtx->DSSetShaderResources(0, 5, SRVs); + dxCtx->PSSetShaderResources(0, 5, SRVs); + + dxCtx->OMSetDepthStencilState(states.ds.render_volume, STENCIL_REF); + + DrawFrustumGrid(dxCtx, mesh_resolution); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + + //-------------------------------------------------------------------------- + // Remove the illumination from the base of the scene (re-lit by sky later) + DrawFrustumBase(dxCtx, mesh_resolution); + + //-------------------------------------------------------------------------- + // Render the bounds of the frustum + if (debugFlags_ & (uint32_t)DebugFlags::WIREFRAME) + return Status::OK; + + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_SKY; + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + dxCtx->OMSetDepthStencilState(states.ds.render_volume_boundary, STENCIL_REF); + DrawFullscreen(dxCtx); + + //-------------------------------------------------------------------------- + // Finish the rendering by filling in stenciled gaps + dxCtx->OMSetDepthStencilState(states.ds.finish_volume, STENCIL_REF); + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getReadOnlyDSV()); + SRVs[2] = pDepth_->getSRV(); + dxCtx->PSSetShaderResources(2, 1, &SRVs[2]); + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_FINAL; + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + DrawFullscreen(dxCtx); + + return Status::OK; +} + +Status ContextImp_D3D11::RenderVolume_DoVolume_Spotlight(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11ShaderResourceView * pShadowMap_SRV = shadowMap.d3d11; + + NV_PERFEVENT(dxCtx, "Spotlight"); + + uint32_t mesh_resolution = getCoarseResolution(pVolumeDesc); + + ID3D11ShaderResourceView * SRVs[16] = { nullptr }; + ID3D11UnorderedAccessView * UAVs[16] = { nullptr }; + + //-------------------------------------------------------------------------- + // Create look-up table + if (pLightDesc->Spotlight.eFalloffMode == SpotlightFalloffMode::NONE) + { + NV_PERFEVENT(dxCtx, "Generate Light LUT"); + ComputeLightLUT_CS::Desc cs_desc; + cs_desc.flags.LIGHTMODE = ComputeLightLUT_CS::LIGHTMODE_OMNI; + cs_desc.flags.ATTENUATIONMODE = (ComputeLightLUT_CS::eATTENUATIONMODE) pLightDesc->Spotlight.eAttenuationMode; + + UAVs[0] = pLightLUT_P_[0]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + SRVs[4] = pPhaseLUT_->getSRV(); + dxCtx->CSSetShaderResources(0, 6, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_CALCULATE; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(LIGHT_LUT_DEPTH_RESOLUTION / 32, LIGHT_LUT_WDOTV_RESOLUTION / 8, 1); + + UAVs[0] = pLightLUT_P_[1]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + SRVs[5] = pLightLUT_P_[0]->getSRV(); + dxCtx->CSSetShaderResources(0, 6, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_SUM; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(1, LIGHT_LUT_WDOTV_RESOLUTION / 4, 1); + + dxCtx->CSSetShader(nullptr, nullptr, 0); + UAVs[0] = nullptr; + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + } + else if (pLightDesc->Spotlight.eFalloffMode == SpotlightFalloffMode::FIXED) + { + NV_PERFEVENT(dxCtx, "Generate Light LUT"); + ComputeLightLUT_CS::Desc cs_desc; + cs_desc.flags.LIGHTMODE = ComputeLightLUT_CS::LIGHTMODE_SPOTLIGHT; + cs_desc.flags.ATTENUATIONMODE = (ComputeLightLUT_CS::eATTENUATIONMODE) pLightDesc->Spotlight.eAttenuationMode; + + UAVs[0] = pLightLUT_P_[0]->getUAV(); + UAVs[1] = pLightLUT_S1_[0]->getUAV(); + UAVs[2] = pLightLUT_S2_[0]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 3, UAVs, 0); + SRVs[4] = pPhaseLUT_->getSRV(); + dxCtx->CSSetShaderResources(0, 8, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_CALCULATE; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(LIGHT_LUT_DEPTH_RESOLUTION / 32, LIGHT_LUT_WDOTV_RESOLUTION / 8, 1); + + UAVs[0] = pLightLUT_P_[1]->getUAV(); + UAVs[1] = pLightLUT_S1_[1]->getUAV(); + UAVs[2] = pLightLUT_S2_[1]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 3, UAVs, 0); + SRVs[5] = pLightLUT_P_[0]->getSRV(); + SRVs[6] = pLightLUT_S1_[0]->getSRV(); + SRVs[7] = pLightLUT_S2_[0]->getSRV(); + dxCtx->CSSetShaderResources(0, 8, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_SUM; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(1, LIGHT_LUT_WDOTV_RESOLUTION / 4, 3); + + dxCtx->CSSetShader(nullptr, nullptr, 0); + UAVs[0] = nullptr; + UAVs[1] = nullptr; + UAVs[2] = nullptr; + dxCtx->CSSetUnorderedAccessViews(0, 3, UAVs, 0); + } + + //-------------------------------------------------------------------------- + // Draw tessellated grid + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getInternalViewportWidth()); + viewport.Height = static_cast<float>(getInternalViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + dxCtx->RSSetState(states.rs.cull_none); + dxCtx->OMSetBlendState(states.bs.additive, nullptr, 0xFFFFFFFF); + + ID3D11RenderTargetView * RTVs[] = { pAccumulation_->getRTV() }; + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getDSV()); + + // Determine DS/HS permutation + RenderVolume_HS::Desc hs_desc; + hs_desc.flags.SHADOWMAPTYPE = RenderVolume_HS::SHADOWMAPTYPE_ATLAS; + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_1; + hs_desc.flags.VOLUMETYPE = RenderVolume_HS::VOLUMETYPE_FRUSTUM; + hs_desc.flags.MAXTESSFACTOR = (RenderVolume_HS::eMAXTESSFACTOR) pVolumeDesc->eTessQuality; + + RenderVolume_DS::Desc ds_desc; + ds_desc.flags.SHADOWMAPTYPE = RenderVolume_DS::SHADOWMAPTYPE_ATLAS; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_1; + ds_desc.flags.VOLUMETYPE = RenderVolume_DS::VOLUMETYPE_FRUSTUM; + + // Determine PS permutation + RenderVolume_PS::Desc ps_desc; + ps_desc.flags.SAMPLEMODE = isInternalMSAA() ? RenderVolume_PS::SAMPLEMODE_MSAA : RenderVolume_PS::SAMPLEMODE_SINGLE; + ps_desc.flags.LIGHTMODE = RenderVolume_PS::LIGHTMODE_SPOTLIGHT; + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_GEOMETRY; + ps_desc.flags.ATTENUATIONMODE = (RenderVolume_PS::eATTENUATIONMODE) pLightDesc->Spotlight.eAttenuationMode; + ps_desc.flags.FALLOFFMODE = (RenderVolume_PS::eFALLOFFMODE) pLightDesc->Spotlight.eFalloffMode; + + dxCtx->HSSetShader(shaders.RenderVolume_HS[hs_desc], nullptr, 0); + dxCtx->DSSetShader(shaders.RenderVolume_DS[ds_desc], nullptr, 0); + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + + SRVs[1] = pShadowMap_SRV; + SRVs[4] = pPhaseLUT_->getSRV(); + SRVs[5] = pLightLUT_P_[1]->getSRV(); + SRVs[6] = pLightLUT_S1_[1]->getSRV(); + SRVs[7] = pLightLUT_S2_[1]->getSRV(); + dxCtx->VSSetShaderResources(0, 8, SRVs); + dxCtx->HSSetShaderResources(0, 8, SRVs); + dxCtx->DSSetShaderResources(0, 8, SRVs); + dxCtx->PSSetShaderResources(0, 8, SRVs); + + dxCtx->OMSetDepthStencilState(states.ds.render_volume, STENCIL_REF); + DrawFrustumGrid(dxCtx, mesh_resolution); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + + //-------------------------------------------------------------------------- + // Render the bounds of the spotlight volume + dxCtx->RSSetState(states.rs.cull_front); + DrawFrustumCap(dxCtx, mesh_resolution); + + //-------------------------------------------------------------------------- + // Finish the rendering by filling in stenciled gaps + dxCtx->OMSetDepthStencilState(states.ds.finish_volume, STENCIL_REF); + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getReadOnlyDSV()); + SRVs[2] = pDepth_->getSRV(); + dxCtx->PSSetShaderResources(2, 1, &SRVs[2]); + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_FINAL; + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + DrawFullscreen(dxCtx); + + return Status::OK; +} + +Status ContextImp_D3D11::RenderVolume_DoVolume_Omni(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11ShaderResourceView * pShadowMap_SRV = shadowMap.d3d11; + + NV_PERFEVENT(dxCtx, "Omni"); + + uint32_t mesh_resolution = getCoarseResolution(pVolumeDesc); + + ID3D11ShaderResourceView * SRVs[] = { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }; + + ID3D11UnorderedAccessView * UAVs[] = { + nullptr + }; + + //-------------------------------------------------------------------------- + // Create look-up table + { + NV_PERFEVENT(dxCtx, "Generate Light LUT"); + ComputeLightLUT_CS::Desc cs_desc; + cs_desc.flags.LIGHTMODE = ComputeLightLUT_CS::LIGHTMODE_OMNI; + cs_desc.flags.ATTENUATIONMODE = (ComputeLightLUT_CS::eATTENUATIONMODE) pLightDesc->Omni.eAttenuationMode; + + UAVs[0] = pLightLUT_P_[0]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + SRVs[4] = pPhaseLUT_->getSRV(); + dxCtx->CSSetShaderResources(0, 6, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_CALCULATE; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(LIGHT_LUT_DEPTH_RESOLUTION / 32, LIGHT_LUT_WDOTV_RESOLUTION / 8, 1); + + UAVs[0] = pLightLUT_P_[1]->getUAV(); + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + SRVs[5] = pLightLUT_P_[0]->getSRV(); + dxCtx->CSSetShaderResources(0, 6, SRVs); + cs_desc.flags.COMPUTEPASS = ComputeLightLUT_CS::COMPUTEPASS_SUM; + dxCtx->CSSetShader(shaders.ComputeLightLUT_CS[cs_desc], nullptr, 0); + dxCtx->Dispatch(1, LIGHT_LUT_WDOTV_RESOLUTION / 4, 1); + + dxCtx->CSSetShader(nullptr, nullptr, 0); + UAVs[0] = nullptr; + dxCtx->CSSetUnorderedAccessViews(0, 1, UAVs, 0); + } + + //-------------------------------------------------------------------------- + // Draw tessellated grid + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getInternalViewportWidth()); + viewport.Height = static_cast<float>(getInternalViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + dxCtx->RSSetState(states.rs.cull_none); + dxCtx->OMSetBlendState(states.bs.additive, nullptr, 0xFFFFFFFF); + + ID3D11RenderTargetView * RTVs[] = { pAccumulation_->getRTV() }; + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getDSV()); + + // Determine DS/HS permutation + RenderVolume_HS::Desc hs_desc; + hs_desc.flags.SHADOWMAPTYPE = RenderVolume_HS::SHADOWMAPTYPE_ARRAY; + hs_desc.flags.CASCADECOUNT = RenderVolume_HS::CASCADECOUNT_1; + hs_desc.flags.VOLUMETYPE = RenderVolume_HS::VOLUMETYPE_PARABOLOID; + hs_desc.flags.MAXTESSFACTOR = (RenderVolume_HS::eMAXTESSFACTOR) pVolumeDesc->eTessQuality; + + RenderVolume_DS::Desc ds_desc; + ds_desc.flags.SHADOWMAPTYPE = RenderVolume_DS::SHADOWMAPTYPE_ARRAY; + ds_desc.flags.CASCADECOUNT = RenderVolume_DS::CASCADECOUNT_1; + ds_desc.flags.VOLUMETYPE = RenderVolume_DS::VOLUMETYPE_PARABOLOID; + + // Determine PS permutation + RenderVolume_PS::Desc ps_desc; + ps_desc.flags.SAMPLEMODE = isInternalMSAA() ? RenderVolume_PS::SAMPLEMODE_MSAA : RenderVolume_PS::SAMPLEMODE_SINGLE; + ps_desc.flags.LIGHTMODE = RenderVolume_PS::LIGHTMODE_OMNI; + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_GEOMETRY; + ps_desc.flags.ATTENUATIONMODE = (RenderVolume_PS::eATTENUATIONMODE) pLightDesc->Omni.eAttenuationMode; + + dxCtx->HSSetShader(shaders.RenderVolume_HS[hs_desc], nullptr, 0); + dxCtx->DSSetShader(shaders.RenderVolume_DS[ds_desc], nullptr, 0); + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + + SRVs[1] = pShadowMap_SRV; + SRVs[5] = pLightLUT_P_[1]->getSRV(); + dxCtx->VSSetShaderResources(0, 6, SRVs); + dxCtx->HSSetShaderResources(0, 6, SRVs); + dxCtx->DSSetShaderResources(0, 6, SRVs); + dxCtx->PSSetShaderResources(0, 6, SRVs); + + dxCtx->OMSetDepthStencilState(states.ds.render_volume, STENCIL_REF); + DrawOmniVolume(dxCtx, mesh_resolution); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + + //-------------------------------------------------------------------------- + // Finish the rendering by filling in stenciled gaps + dxCtx->OMSetDepthStencilState(states.ds.finish_volume, STENCIL_REF); + dxCtx->OMSetRenderTargets(1, RTVs, pDepth_->getReadOnlyDSV()); + SRVs[2] = pDepth_->getSRV(); + dxCtx->PSSetShaderResources(2, 1, &SRVs[2]); + ps_desc.flags.PASSMODE = RenderVolume_PS::PASSMODE_FINAL; + dxCtx->PSSetShader(shaders.RenderVolume_PS[ps_desc], nullptr, 0); + DrawFullscreen(dxCtx); + + return Status::OK; +} + +Status ContextImp_D3D11::RenderVolume_End(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11RenderTargetView * NULL_RTV = nullptr; + dxCtx->OMSetRenderTargets(1, &NULL_RTV, nullptr); + NV_PERFEVENT_END(dxCtx); + return Status::OK; +} + +/*============================================================================== + EndAccumulation +==============================================================================*/ +Status ContextImp_D3D11::EndAccumulation_Imp(PlatformRenderCtx renderCtx) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + dxCtx; + return Status::OK; +} + +/*============================================================================== + ApplyLighting +==============================================================================*/ +Status ContextImp_D3D11::ApplyLighting_Start(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + + NV_PERFEVENT_BEGIN(dxCtx, "NvVl::ApplyLighting"); + + // Setup the constant buffer + SetupCB_PerApply(pPostprocessDesc, pPerApplyCB->Map(dxCtx)); + pPerApplyCB->Unmap(dxCtx); + + ID3D11Buffer* pCBs[] = { + pPerContextCB->getCB(), + pPerFrameCB->getCB(), + nullptr, // pPerVolumeCB - Invalid + pPerApplyCB->getCB(), + }; + dxCtx->VSSetConstantBuffers(0, 4, pCBs); + dxCtx->PSSetConstantBuffers(0, 4, pCBs); + + ID3D11SamplerState * pSamplers[] = { + states.ss.point, + states.ss.linear + }; + dxCtx->PSSetSamplers(0, 2, pSamplers); + dxCtx->OMSetDepthStencilState(states.ds.no_depth, 0xFF); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getInternalViewportWidth()); + viewport.Height = static_cast<float>(getInternalViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + + pAccumulatedOutput_ = pAccumulation_; + + return Status::OK; +} + +Status ContextImp_D3D11::ApplyLighting_Resolve(PlatformRenderCtx renderCtx, PostprocessDesc const* pPostprocessDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + + NV_PERFEVENT(dxCtx, "Resolve"); + + Resolve_PS::Desc ps_desc; + ps_desc.flags.SAMPLEMODE = isInternalMSAA() ? Resolve_PS::SAMPLEMODE_MSAA : Resolve_PS::SAMPLEMODE_SINGLE; + dxCtx->PSSetShader(shaders.Resolve_PS[ps_desc], nullptr, 0); + ID3D11ShaderResourceView * SRVs[] = { + pAccumulation_->getSRV(), + pDepth_->getSRV() + }; + dxCtx->PSSetShaderResources(0, 2, SRVs); + ID3D11RenderTargetView * RTVs[] = { + pResolvedAccumulation_->getRTV(), + pResolvedDepth_->getRTV() + }; + dxCtx->OMSetRenderTargets(2, RTVs, nullptr); + DrawFullscreen(dxCtx); + pAccumulatedOutput_ = pResolvedAccumulation_; + ID3D11RenderTargetView * NULL_RTVs[] = { nullptr, nullptr }; + dxCtx->OMSetRenderTargets(2, NULL_RTVs, nullptr); + return Status::OK; +} + +Status ContextImp_D3D11::ApplyLighting_TemporalFilter(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + + NV_PERFEVENT(dxCtx, "TemporalFilter"); + + dxCtx->PSSetShader(shaders.TemporalFilter_PS[TemporalFilter_PS::SINGLE], nullptr, 0); + ID3D11ShaderResourceView * SRVs[] = { + pResolvedAccumulation_->getSRV(), + pFilteredAccumulation_[lastFrameIndex_]->getSRV(), + pResolvedDepth_->getSRV(), + nullptr, + pFilteredDepth_[lastFrameIndex_]->getSRV() + }; + dxCtx->PSSetShaderResources(0, 4, SRVs); + ID3D11RenderTargetView * RTVs[] = { + pFilteredAccumulation_[nextFrameIndex_]->getRTV(), + pFilteredDepth_[nextFrameIndex_]->getRTV() + }; + dxCtx->OMSetRenderTargets(2, RTVs, nullptr); + DrawFullscreen(dxCtx); + pAccumulatedOutput_ = pFilteredAccumulation_[nextFrameIndex_]; + ID3D11RenderTargetView * NULL_RTVs[] = { nullptr, nullptr }; + dxCtx->OMSetRenderTargets(2, NULL_RTVs, nullptr); + return Status::OK; +} + +Status ContextImp_D3D11::ApplyLighting_Composite(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + ID3D11RenderTargetView * pScene_RTV = sceneTarget.d3d11; + ID3D11ShaderResourceView * pSceneDepth_SRV = sceneDepth.d3d11; + + NV_PERFEVENT(dxCtx, "Composite"); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = static_cast<float>(getOutputViewportWidth()); + viewport.Height = static_cast<float>(getOutputViewportHeight()); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + dxCtx->RSSetViewports(1, &viewport); + + if (debugFlags_ & (uint32_t)DebugFlags::NO_BLENDING) + { + dxCtx->OMSetBlendState(states.bs.debug_blend, nullptr, 0xFFFFFFFF); + } + else + { + FLOAT blend_factor[] = { pPostprocessDesc->fBlendfactor, pPostprocessDesc->fBlendfactor, pPostprocessDesc->fBlendfactor, pPostprocessDesc->fBlendfactor }; + dxCtx->OMSetBlendState(states.bs.additive_modulate, blend_factor, 0xFFFFFFFF); + } + dxCtx->OMSetRenderTargets(1, &pScene_RTV, nullptr); + + Apply_PS::Desc ps_desc; + ps_desc.flags.SAMPLEMODE = isOutputMSAA() ? Apply_PS::SAMPLEMODE_MSAA : Apply_PS::SAMPLEMODE_SINGLE; + switch (pPostprocessDesc->eUpsampleQuality) + { + default: + case UpsampleQuality::POINT: + ps_desc.flags.UPSAMPLEMODE = Apply_PS::UPSAMPLEMODE_POINT; + break; + + case UpsampleQuality::BILINEAR: + ps_desc.flags.UPSAMPLEMODE = Apply_PS::UPSAMPLEMODE_BILINEAR; + break; + + case UpsampleQuality::BILATERAL: + ps_desc.flags.UPSAMPLEMODE = Apply_PS::UPSAMPLEMODE_BILATERAL; + break; + } + if (pPostprocessDesc->bDoFog == false) + ps_desc.flags.FOGMODE = Apply_PS::FOGMODE_NONE; + else if (pPostprocessDesc->bIgnoreSkyFog == true) + ps_desc.flags.FOGMODE = Apply_PS::FOGMODE_NOSKY; + else + ps_desc.flags.FOGMODE = Apply_PS::FOGMODE_FULL; + dxCtx->PSSetShader(shaders.Apply_PS[ps_desc], nullptr, 0); + ID3D11ShaderResourceView * SRVs[] = { + pAccumulatedOutput_->getSRV(), + pSceneDepth_SRV, + nullptr, + nullptr, + pPhaseLUT_->getSRV() + }; + if (pFilteredDepth_[nextFrameIndex_]) + SRVs[2] = pFilteredDepth_[nextFrameIndex_]->getSRV(); + dxCtx->PSSetShaderResources(0, 5, SRVs); + DrawFullscreen(dxCtx); + + ID3D11RenderTargetView * NULL_RTV = nullptr; + dxCtx->OMSetRenderTargets(1, &NULL_RTV, nullptr); + return Status::OK; +} + +Status ContextImp_D3D11::ApplyLighting_End(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc) +{ + ID3D11DeviceContext * dxCtx = renderCtx; + dxCtx; + NV_PERFEVENT_END(dxCtx); + return Status::OK; +} + +/*============================================================================== + Utility functions +==============================================================================*/ + +Status ContextImp_D3D11::DrawFullscreen(ID3D11DeviceContext * dxCtx) +{ + NV_PERFEVENT(dxCtx, "DrawFullscreen"); + dxCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + dxCtx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr); + dxCtx->IASetInputLayout(nullptr); + dxCtx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); + dxCtx->RSSetState(states.rs.cull_none); + dxCtx->VSSetShader(shaders.Quad_VS[Quad_VS::SINGLE], nullptr, 0); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + dxCtx->Draw(3, 0); + return Status::OK; +} + +Status ContextImp_D3D11::DrawFrustumGrid(ID3D11DeviceContext * dxCtx, uint32_t resolution) +{ + NV_PERFEVENT(dxCtx, "DrawFrustumGrid"); + dxCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST); + dxCtx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr); + dxCtx->IASetInputLayout(nullptr); + dxCtx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); + RenderVolume_VS::Desc vs_desc; + vs_desc.flags.MESHMODE = RenderVolume_VS::MESHMODE_FRUSTUM_GRID; + dxCtx->VSSetShader(shaders.RenderVolume_VS[vs_desc], nullptr, 0); + + if (debugFlags_ & (uint32_t)DebugFlags::WIREFRAME) + { + dxCtx->RSSetState(states.rs.wireframe); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + dxCtx->PSSetShader(shaders.Debug_PS[Debug_PS::SINGLE], nullptr, 0); + } + + uint32_t vtx_count = 4 * resolution * resolution; + dxCtx->Draw(vtx_count, 0); + return Status::OK; +} + +Status ContextImp_D3D11::DrawFrustumBase(ID3D11DeviceContext * dxCtx, uint32_t resolution) +{ + NV_PERFEVENT(dxCtx, "DrawFrustumBase"); + dxCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + dxCtx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr); + dxCtx->IASetInputLayout(nullptr); + dxCtx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); + RenderVolume_VS::Desc vs_desc; + vs_desc.flags.MESHMODE = RenderVolume_VS::MESHMODE_FRUSTUM_BASE; + dxCtx->VSSetShader(shaders.RenderVolume_VS[vs_desc], nullptr, 0); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + + if (debugFlags_ & (uint32_t)DebugFlags::WIREFRAME) + { + dxCtx->RSSetState(states.rs.wireframe); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + dxCtx->PSSetShader(shaders.Debug_PS[Debug_PS::SINGLE], nullptr, 0); + } + + dxCtx->Draw(6, 0); + return Status::OK; +} + +Status ContextImp_D3D11::DrawFrustumCap(ID3D11DeviceContext * dxCtx, uint32_t resolution) +{ + NV_PERFEVENT(dxCtx, "DrawFrustumCap"); + dxCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + dxCtx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr); + dxCtx->IASetInputLayout(nullptr); + dxCtx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); + RenderVolume_VS::Desc vs_desc; + vs_desc.flags.MESHMODE = RenderVolume_VS::MESHMODE_FRUSTUM_CAP; + dxCtx->VSSetShader(shaders.RenderVolume_VS[vs_desc], nullptr, 0); + dxCtx->HSSetShader(nullptr, nullptr, 0); + dxCtx->DSSetShader(nullptr, nullptr, 0); + + if (debugFlags_ & (uint32_t)DebugFlags::WIREFRAME) + { + dxCtx->RSSetState(states.rs.wireframe); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + dxCtx->PSSetShader(shaders.Debug_PS[Debug_PS::SINGLE], nullptr, 0); + } + + uint32_t vtx_count = 4*3*(resolution+1) + 6; + dxCtx->Draw(vtx_count, 0); + return Status::OK; +} + +Status ContextImp_D3D11::DrawOmniVolume(ID3D11DeviceContext * dxCtx, uint32_t resolution) +{ + NV_PERFEVENT(dxCtx, "DrawOmniVolume"); + dxCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST); + dxCtx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr); + dxCtx->IASetInputLayout(nullptr); + dxCtx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); + RenderVolume_VS::Desc vs_desc; + vs_desc.flags.MESHMODE = RenderVolume_VS::MESHMODE_OMNI_VOLUME; + dxCtx->VSSetShader(shaders.RenderVolume_VS[vs_desc], nullptr, 0); + + if (debugFlags_ & (uint32_t)DebugFlags::WIREFRAME) + { + dxCtx->RSSetState(states.rs.wireframe); + dxCtx->OMSetBlendState(states.bs.no_blending, nullptr, 0xFFFFFFFF); + dxCtx->PSSetShader(shaders.Debug_PS[Debug_PS::SINGLE], nullptr, 0); + } + + uint32_t vtx_count = 6 * 4 * resolution * resolution; + dxCtx->Draw(vtx_count, 0); + return Status::OK; +} +//////////////////////////////////////////////////////////////////////////////// +}; /*namespace Nv*/ }; /*namespace VolumetricLighting*/ +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/d3d11/context_d3d11.h b/src/d3d11/context_d3d11.h new file mode 100644 index 0000000..82a6931 --- /dev/null +++ b/src/d3d11/context_d3d11.h @@ -0,0 +1,191 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#ifndef CONTEXT_D3D11_H +#define CONTEXT_D3D11_H +//////////////////////////////////////////////////////////////////////////////// +#include <Nv/VolumetricLighting/NvVolumetricLighting.h> + +#include <vector> // TODO: remove this dependency +#include "context_common.h" +/*============================================================================== + Forward Declarations +==============================================================================*/ +// D3D11 Types +struct ID3D11VertexShader; +struct ID3D11HullShader; +struct ID3D11DomainShader; +struct ID3D11GeometryShader; +struct ID3D11PixelShader; +struct ID3D11ComputeShader; +struct ID3D11RasterizerState; +struct ID3D11SamplerState; +struct ID3D11DepthStencilState; +struct ID3D11BlendState; +struct ID3D11InputLayout; +struct ID3D11Buffer; + +// Helper Types +class Texture2D; +class RenderTarget; +class DepthTarget; +template <class T> class ConstantBuffer; + +//////////////////////////////////////////////////////////////////////////////// +namespace Nv { namespace VolumetricLighting { +//////////////////////////////////////////////////////////////////////////////// + +class ContextImp_D3D11 : public ContextImp_Common +{ +public: + // Creates the context and resources + static Status Create(ContextImp_D3D11 ** out_ctx, const PlatformDesc * pPlatformDesc, const ContextDesc * pContextDesc); + + // Clean up the context on delete + virtual ~ContextImp_D3D11(); + +protected: + // BeginAccumulation + Status BeginAccumulation_Start(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, ViewerDesc const* pViewerDesc, MediumDesc const* pMediumDesc); + Status BeginAccumulation_UpdateMediumLUT(PlatformRenderCtx renderCtx); + Status BeginAccumulation_CopyDepth(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth); + Status BeginAccumulation_End(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, ViewerDesc const* pViewerDesc, MediumDesc const* pMediumDesc); + + // RenderVolume + Status RenderVolume_Start(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc); + Status RenderVolume_DoVolume_Directional(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc); + Status RenderVolume_DoVolume_Spotlight(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc); + Status RenderVolume_DoVolume_Omni(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc); + Status RenderVolume_End(PlatformRenderCtx renderCtx, PlatformShaderResource shadowMap, ShadowMapDesc const* pShadowMapDesc, LightDesc const* pLightDesc, VolumeDesc const* pVolumeDesc); + + // EndAccumulation + Status EndAccumulation_Imp(PlatformRenderCtx renderCtx); + + // ApplyLighting + Status ApplyLighting_Start(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc); + Status ApplyLighting_Resolve(PlatformRenderCtx renderCtx, PostprocessDesc const* pPostprocessDesc); + Status ApplyLighting_TemporalFilter(PlatformRenderCtx renderCtx, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc); + Status ApplyLighting_Composite(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc); + Status ApplyLighting_End(PlatformRenderCtx renderCtx, PlatformRenderTarget sceneTarget, PlatformShaderResource sceneDepth, PostprocessDesc const* pPostprocessDesc); + +private: + // Private default constructor + // Should never be called + ContextImp_D3D11() {}; + + // Initializing Destructor + // Setup all code that can't fail + ContextImp_D3D11(const ContextDesc * pContextDesc); + + // Called by Create internally + Status CreateResources(ID3D11Device * device); + + // Do a fullscreen pass with the bound pixel-shader + Status DrawFullscreen(ID3D11DeviceContext * dxCtx); + + Status DrawFrustumGrid(ID3D11DeviceContext * dxCtx, uint32_t resolution); + Status DrawFrustumBase(ID3D11DeviceContext * dxCtx, uint32_t resolution); + Status DrawFrustumCap(ID3D11DeviceContext * dxCtx, uint32_t resolution); + Status DrawOmniVolume(ID3D11DeviceContext * dxCtx, uint32_t resolution); + + struct + { + ID3D11PixelShader ** Apply_PS; + ID3D11ComputeShader ** ComputeLightLUT_CS; + ID3D11PixelShader ** ComputePhaseLookup_PS; + ID3D11PixelShader ** Debug_PS; + ID3D11PixelShader ** DownsampleDepth_PS; + ID3D11VertexShader ** Quad_VS; + ID3D11VertexShader ** RenderVolume_VS; + ID3D11HullShader ** RenderVolume_HS; + ID3D11DomainShader ** RenderVolume_DS; + ID3D11PixelShader ** RenderVolume_PS; + ID3D11PixelShader ** Resolve_PS; + ID3D11PixelShader ** TemporalFilter_PS; + } shaders; + + ConstantBuffer<PerContextCB> * pPerContextCB; + ConstantBuffer<PerFrameCB> * pPerFrameCB; + ConstantBuffer<PerVolumeCB> * pPerVolumeCB; + ConstantBuffer<PerApplyCB> * pPerApplyCB; + + DepthTarget * pDepth_; + RenderTarget * pPhaseLUT_; + RenderTarget * pLightLUT_P_[2]; + RenderTarget * pLightLUT_S1_[2]; + RenderTarget * pLightLUT_S2_[2]; + RenderTarget * pAccumulation_; + RenderTarget * pResolvedAccumulation_; + RenderTarget * pResolvedDepth_; + RenderTarget * pFilteredAccumulation_[2]; + RenderTarget * pFilteredDepth_[2]; + + RenderTarget * pAccumulatedOutput_; + + struct + { + struct + { + ID3D11RasterizerState * cull_none; + ID3D11RasterizerState * cull_front; + ID3D11RasterizerState * wireframe; + } rs; + + struct + { + ID3D11SamplerState * point; + ID3D11SamplerState * linear; + } ss; + + struct + { + ID3D11DepthStencilState * no_depth; + ID3D11DepthStencilState * write_only_depth; + ID3D11DepthStencilState * read_only_depth; + ID3D11DepthStencilState * render_volume; + ID3D11DepthStencilState * render_volume_boundary; + ID3D11DepthStencilState * remove_volume_base; + ID3D11DepthStencilState * render_volume_cap; + ID3D11DepthStencilState * finish_volume; + } ds; + + struct + { + ID3D11BlendState * no_color; + ID3D11BlendState * no_blending; + ID3D11BlendState * additive; + ID3D11BlendState * additive_modulate; + ID3D11BlendState * debug_blend; + } bs; + } states; +}; + +//////////////////////////////////////////////////////////////////////////////// +}; /*namespace VolumetricLighting*/ }; /*namespace Nv*/ +//////////////////////////////////////////////////////////////////////////////// +#endif // CONTEXT_D3D11_H diff --git a/src/d3d11/d3d11_util.cpp b/src/d3d11/d3d11_util.cpp new file mode 100644 index 0000000..4226fdb --- /dev/null +++ b/src/d3d11/d3d11_util.cpp @@ -0,0 +1,347 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#include "common.h" +#include "d3d11_util.h" +#include <d3d11.h> + +/*============================================================================== + Overloaded functions to make shader compilation simpler +==============================================================================*/ +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11VertexShader ** out_shader) + { return device->CreateVertexShader(data, length, nullptr, out_shader); } +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11HullShader ** out_shader) + { return device->CreateHullShader(data, length, nullptr, out_shader); } +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11DomainShader ** out_shader) + { return device->CreateDomainShader(data, length, nullptr, out_shader); } +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11GeometryShader ** out_shader) + { return device->CreateGeometryShader(data, length, nullptr, out_shader); } +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11PixelShader ** out_shader) + { return device->CreatePixelShader(data, length, nullptr, out_shader); } +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11ComputeShader ** out_shader) + { return device->CreateComputeShader(data, length, nullptr, out_shader); } +/*============================================================================== + Texture resource management helpers +==============================================================================*/ + +//------------------------------------------------------------------------------ +ShaderResource::ShaderResource(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11UnorderedAccessView * uav) +{ + resource_ = resource; + srv_ = srv; + uav_ = uav; +} + +ShaderResource::~ShaderResource() +{ + SAFE_RELEASE(resource_); + SAFE_RELEASE(srv_); + SAFE_RELEASE(uav_); +} + +//------------------------------------------------------------------------------ +RenderTarget * RenderTarget::Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, const char * debug_name) +{ + ID3D11Texture2D * tex = nullptr; + ID3D11ShaderResourceView * srv = nullptr; + ID3D11RenderTargetView * rtv = nullptr; + ID3D11UnorderedAccessView * uav = nullptr; + + CD3D11_TEXTURE2D_DESC texDesc; + texDesc.ArraySize = 1; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + if (samples == 1) + texDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + texDesc.CPUAccessFlags = 0; + texDesc.Format = format; + texDesc.Width = width; + texDesc.Height = height; + texDesc.MipLevels = 1; + texDesc.MiscFlags = 0; + if (samples > 1) + { + texDesc.SampleDesc.Count = samples; + texDesc.SampleDesc.Quality = 0;//static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN); + } + else + { + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0; + } + texDesc.Usage = D3D11_USAGE_DEFAULT; + device->CreateTexture2D(&texDesc, nullptr, &tex); + if (tex == nullptr) + { + return nullptr; + } + + CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = texDesc.Format; + if (samples > 1) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + } + device->CreateShaderResourceView(tex, &srvDesc, &srv); + if (srv == nullptr) + { + tex->Release(); + return nullptr; + } + + CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = texDesc.Format; + if (samples > 1) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + } + else + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + } + device->CreateRenderTargetView(tex, &rtvDesc, &rtv); + if (rtv == nullptr) + { + tex->Release(); + srv->Release(); + return nullptr; + } + + if (samples == 1) + { + CD3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = texDesc.Format; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + device->CreateUnorderedAccessView(tex, &uavDesc, &uav); + if (uav == nullptr) + { + tex->Release(); + srv->Release(); + rtv->Release(); + return nullptr; + } + } +#if (NV_DEBUG || NV_PROFILE) + if (debug_name) + { + tex->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(debug_name), debug_name); + } +#else + debug_name; +#endif + return new RenderTarget(tex, srv, rtv, uav); +} + +RenderTarget::RenderTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11RenderTargetView * rtv, ID3D11UnorderedAccessView * uav) + : ShaderResource(resource, srv, uav) +{ + rtv_ = rtv; +} + +RenderTarget::~RenderTarget() +{ + SAFE_RELEASE(rtv_); +} + +//------------------------------------------------------------------------------ +DepthTarget * DepthTarget::Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, uint32_t slices, char * debug_name) +{ + ID3D11Texture2D * tex = nullptr; + ID3D11ShaderResourceView * srv = nullptr; + ID3D11DepthStencilView * dsv = nullptr; + ID3D11DepthStencilView * dsv_ro = nullptr; + + DXGI_FORMAT tex_format; + DXGI_FORMAT srv_format; + DXGI_FORMAT dsv_format; + switch (format) + { + case DXGI_FORMAT_D32_FLOAT: + tex_format = DXGI_FORMAT_R32_TYPELESS; + srv_format = DXGI_FORMAT_R32_FLOAT; + dsv_format = DXGI_FORMAT_D32_FLOAT; + break; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + tex_format = DXGI_FORMAT_R24G8_TYPELESS; + srv_format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + dsv_format = DXGI_FORMAT_D24_UNORM_S8_UINT; + break; + + case DXGI_FORMAT_D16_UNORM: + tex_format = DXGI_FORMAT_R16_TYPELESS; + srv_format = DXGI_FORMAT_R16_UNORM; + dsv_format = DXGI_FORMAT_D16_UNORM; + break; + + default: + return nullptr; + } + + CD3D11_TEXTURE2D_DESC texDesc; + texDesc.ArraySize = slices; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + texDesc.CPUAccessFlags = 0; + texDesc.Format = tex_format; + texDesc.Width = width; + texDesc.Height = height; + texDesc.MipLevels = 1; + texDesc.MiscFlags = 0; + if (samples > 1) + { + texDesc.SampleDesc.Count = samples; + texDesc.SampleDesc.Quality = 0;//static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN); + } + else + { + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0; + } + texDesc.Usage = D3D11_USAGE_DEFAULT; + device->CreateTexture2D(&texDesc, nullptr, &tex); + if (tex == nullptr) + { + return nullptr; + } + + CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = srv_format; + if (slices == 1) + { + if (samples > 1) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + } + } + else + { + if (samples > 1) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY; + srvDesc.Texture2DMSArray.FirstArraySlice = 0; + srvDesc.Texture2DMSArray.ArraySize = slices; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = 0; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = slices; + } + } + device->CreateShaderResourceView(tex, &srvDesc, &srv); + + if (srv == nullptr) + { + tex->Release(); + return nullptr; + } + + CD3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Flags = 0; + dsvDesc.Format = dsv_format; + if (slices == 1) + { + if (samples > 1) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = 0; + } + } + else + { + if (samples > 1) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; + dsvDesc.Texture2DMSArray.FirstArraySlice = 0; + dsvDesc.Texture2DMSArray.ArraySize = slices; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.MipSlice = 0; + dsvDesc.Texture2DArray.FirstArraySlice = 0; + dsvDesc.Texture2DArray.ArraySize = slices; + } + } + + device->CreateDepthStencilView(tex, &dsvDesc, &dsv); + dsvDesc.Flags |= D3D11_DSV_READ_ONLY_DEPTH; + if (dsv_format == DXGI_FORMAT_D24_UNORM_S8_UINT) + dsvDesc.Flags |= D3D11_DSV_READ_ONLY_STENCIL; + device->CreateDepthStencilView(tex, &dsvDesc, &dsv_ro); + if (dsv == nullptr || dsv_ro == nullptr) + { + tex->Release(); + srv->Release(); + return nullptr; + } + +#if (NV_DEBUG || NV_PROFILE) + if (debug_name) + { + tex->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(debug_name), debug_name); + } +#else + debug_name; +#endif + + return new DepthTarget(tex, srv, dsv, dsv_ro, nullptr); +} + +DepthTarget::DepthTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11DepthStencilView * dsv, ID3D11DepthStencilView * readonly_dsv, ID3D11UnorderedAccessView * uav) + : ShaderResource(resource, srv, uav) +{ + dsv_ = dsv; + readonly_dsv_ = readonly_dsv; +} + +DepthTarget::~DepthTarget() +{ + SAFE_RELEASE(dsv_); + SAFE_RELEASE(readonly_dsv_); +} + diff --git a/src/d3d11/d3d11_util.h b/src/d3d11/d3d11_util.h new file mode 100644 index 0000000..e9322cf --- /dev/null +++ b/src/d3d11/d3d11_util.h @@ -0,0 +1,234 @@ +// This code contains NVIDIA Confidential Information and is disclosed +// under the Mutual Non-Disclosure Agreement. +// +// Notice +// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES +// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// +// NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless +// expressly authorized by NVIDIA. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved. +// +// NVIDIA Corporation and its licensors retain all intellectual property and proprietary +// rights in and to this software and related documentation and any modifications thereto. +// Any use, reproduction, disclosure or distribution of this software and related +// documentation without an express license agreement from NVIDIA Corporation is +// strictly prohibited. +// + +#ifndef D3D11_UTIL_H +#define D3D11_UTIL_H +//////////////////////////////////////////////////////////////////////////////// +#include "common.h" + +#include <d3d11.h> +#include <d3d11_1.h> + +#pragma warning( disable: 4127 ) + +//////////////////////////////////////////////////////////////////////////////// +/*============================================================================== + Overloaded functions to make shader compilation simpler +==============================================================================*/ +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11VertexShader ** out_shader); +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11HullShader ** out_shader); +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11DomainShader ** out_shader); +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11GeometryShader ** out_shader); +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11PixelShader ** out_shader); +HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11ComputeShader ** out_shader); + + +template <class T> +NV_FORCE_INLINE HRESULT LoadShaders(ID3D11Device * device, const void ** shader_codes, const uint32_t * shader_lengths, UINT count, T ** &out_shaders) +{ + HRESULT hr = S_OK; + out_shaders = new T*[count]; + for (UINT i = 0; i < count; ++i) + { + const void * code = shader_codes[i]; + uint32_t length = shader_lengths[i]; + if (code == nullptr) + { + out_shaders[i] = nullptr; + continue; + } + hr = CompileShader(device, code, length, &out_shaders[i]); + ASSERT_LOG(hr == S_OK, "Failure loading shader"); + if (FAILED(hr)) + break; + } + return hr; +} + +/*============================================================================== + Perf Events +==============================================================================*/ + +class ScopedPerfEvent +{ +public: + ScopedPerfEvent(ID3D11DeviceContext * ctx, const wchar_t * msg) + { + ctx->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf)); + if (pPerf) + { + pPerf->BeginEvent(msg); + } + } + + ~ScopedPerfEvent() + { + if (pPerf) + { + pPerf->EndEvent(); + SAFE_RELEASE(pPerf); + } + }; + +private: + ScopedPerfEvent() : pPerf(nullptr) {}; + ID3DUserDefinedAnnotation * pPerf; +}; + +#if (NV_PROFILE) +# define NV_PERFEVENT(c, t) ScopedPerfEvent perfevent_##__COUNTER__##(c, L##t) +# define NV_PERFEVENT_BEGIN(c, t) { \ + ID3DUserDefinedAnnotation * pPerf_##__COUNTER__ ; \ + c->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf_##__COUNTER__##)); \ + if (pPerf_##__COUNTER__##) { pPerf_##__COUNTER__##->BeginEvent(L##t); pPerf_##__COUNTER__##->Release(); } } +# define NV_PERFEVENT_END(c) { \ + ID3DUserDefinedAnnotation * pPerf_##__COUNTER__ ; \ + c->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf_##__COUNTER__##)); \ + if (pPerf_##__COUNTER__##) { pPerf_##__COUNTER__##->EndEvent(); pPerf_##__COUNTER__##->Release(); } } +#else +# define NV_PERFEVENT(c, t) +# define NV_PERFEVENT_BEGIN(c, t) +# define NV_PERFEVENT_END(c) +#endif + +/*============================================================================== + Constant buffer management +==============================================================================*/ + +template <class T> +class ConstantBuffer +{ +public: + static ConstantBuffer<T> * Create(ID3D11Device * device) + { + HRESULT hr; + ID3D11Buffer * cb = nullptr; + + static_assert((sizeof(T) % 16) == 0, "Constant buffer size must be 16-byte aligned"); + + CD3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = sizeof(T); + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + cbDesc.StructureByteStride = 1; + hr = device->CreateBuffer(&cbDesc, nullptr, &cb); + if (cb == nullptr) + return nullptr; + return new ConstantBuffer<T>(cb); + } + + ConstantBuffer(ID3D11Buffer * b) + { + buffer_ = b; + } + + ~ConstantBuffer() + { + SAFE_RELEASE(buffer_); + } + + T * Map(ID3D11DeviceContext * ctx) + { + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE data; + hr = ctx->Map(buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &data); + return static_cast<T*>(data.pData); + } + + void Unmap(ID3D11DeviceContext * ctx) + { + ctx->Unmap(buffer_, 0); + } + + ID3D11Buffer * getCB() { return buffer_; } + +private: + ConstantBuffer() {}; + + ID3D11Buffer *buffer_; +}; + +/*============================================================================== + Texture resource management helpers +==============================================================================*/ + +//------------------------------------------------------------------------------ +class ShaderResource +{ +public: + ShaderResource(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11UnorderedAccessView * uav); + ~ShaderResource(); + + ID3D11Resource * getResource() { return resource_; } + ID3D11ShaderResourceView * getSRV() { return srv_; } + ID3D11UnorderedAccessView * getUAV() { return uav_; } + +protected: + ShaderResource() {}; + + ID3D11Resource * resource_; + ID3D11ShaderResourceView * srv_; + ID3D11UnorderedAccessView * uav_; +}; + +//------------------------------------------------------------------------------ +class RenderTarget : public ShaderResource +{ +public: + static RenderTarget * Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, const char * debug_name=nullptr); + RenderTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11RenderTargetView * rtv, ID3D11UnorderedAccessView * uav); + ~RenderTarget(); + + ID3D11RenderTargetView * getRTV() { return rtv_; } + +protected: + RenderTarget() {}; + ID3D11RenderTargetView * rtv_; +}; + +//------------------------------------------------------------------------------ +class DepthTarget : public ShaderResource +{ +public: + static DepthTarget * Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, uint32_t slices=1, char * debug_name=nullptr); + DepthTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11DepthStencilView * dsv, ID3D11DepthStencilView * readonly_dsv, ID3D11UnorderedAccessView * uav); + ~DepthTarget(); + + ID3D11DepthStencilView * getDSV() { return dsv_; } + ID3D11DepthStencilView * getReadOnlyDSV() { return readonly_dsv_; } + +protected: + DepthTarget() {}; + ID3D11DepthStencilView * dsv_; + ID3D11DepthStencilView * readonly_dsv_; +}; + +//////////////////////////////////////////////////////////////////////////////// +#endif // D3D11_UTIL_H
\ No newline at end of file |