diff options
Diffstat (limited to 'src/d3d11/context_d3d11.cpp')
| -rw-r--r-- | src/d3d11/context_d3d11.cpp | 1257 |
1 files changed, 1257 insertions, 0 deletions
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*/ +//////////////////////////////////////////////////////////////////////////////// |