// This code contains NVIDIA Confidential Information and is disclosed to you // under a form of NVIDIA software license agreement provided separately to you. // // Notice // 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. // // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. // // Information and code furnished is believed to be accurate and reliable. // However, 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. 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) 2008-2021 NVIDIA Corporation. All rights reserved. #if SUPPORT_D3D12 #pragma once #include "Common.h" namespace GFSDK { namespace SSAO { namespace D3D12 { //-------------------------------------------------------------------------------- class RTTexture2D { public: ID3D12Resource* pResource; // ID3D12Texture2D* pTexture; ShaderResourceView SRV; RenderTargetView RTV; UINT m_AllocatedSizeInBytes; RTTexture2D() : pResource(nullptr) , m_AllocatedSizeInBytes(0) { RTV.pResource = NULL; SRV.pResource = NULL; #if _WIN64 RTV.CpuHandle.ptr = ~0ull; SRV.GpuHandle.ptr = ~0ull; #else RTV.CpuHandle.ptr = ~0ul; SRV.GpuHandle.ptr = ~0ul; #endif } UINT GetAllocatedSizeInBytes() { return m_AllocatedSizeInBytes; } UINT GetFormatSizeInBytes(DXGI_FORMAT Format) { UINT NumBytes = 0; switch (Format) { case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R32G32_FLOAT: NumBytes = 8; break; case DXGI_FORMAT_R32_FLOAT: case DXGI_FORMAT_R16G16_FLOAT: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R11G11B10_FLOAT: NumBytes = 4; break; case DXGI_FORMAT_R16_FLOAT: NumBytes = 2; break; case DXGI_FORMAT_R8_UNORM: NumBytes = 1; break; default: ASSERT(0); break; } return NumBytes; } void CreateOnce(GFSDK_D3D12_GraphicsContext* pContext, UINT Width, UINT Height, DXGI_FORMAT Format, UINT BaseSRVHeapIndex, UINT BaseRTVHeapIndex, UINT ArraySize = 1) { if (!pResource) { // Create a texture 2D D3D12_RESOURCE_DESC Desc = {}; Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; Desc.Width = Width; Desc.Height = Height; Desc.MipLevels = 1; Desc.DepthOrArraySize = ArraySize; Desc.SampleDesc.Count = 1; Desc.SampleDesc.Quality = 0; Desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; Desc.Format = Format; Desc.Alignment = 0; THROW_IF_FAILED(pContext->pDevice->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT, pContext->NodeMask, pContext->NodeMask), D3D12_HEAP_FLAG_NONE, &Desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&pResource))); // SRV SRV.pResource = pResource; D3D12_SHADER_RESOURCE_VIEW_DESC DescSRV = {}; DescSRV.Format = Format; if (ArraySize > 1) { DescSRV.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; DescSRV.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; DescSRV.Texture2DArray.ArraySize = ArraySize; DescSRV.Texture2DArray.FirstArraySlice = 0; DescSRV.Texture2DArray.MipLevels = 1; DescSRV.Texture2DArray.MostDetailedMip = 0; DescSRV.Texture2DArray.PlaneSlice = 0; DescSRV.Texture2DArray.ResourceMinLODClamp = 0.0f; } else { DescSRV.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; DescSRV.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; DescSRV.Texture2D.MipLevels = 1; DescSRV.Texture2D.MostDetailedMip = 0; // No MIP DescSRV.Texture2D.PlaneSlice = 0; DescSRV.Texture2D.ResourceMinLODClamp = 0.0f; } D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle = pContext->DescHeaps.CBVSRVUAV.GetCPUHandle(BaseSRVHeapIndex); SRV.GpuHandle = pContext->DescHeaps.CBVSRVUAV.GetGPUHandle(BaseSRVHeapIndex); pContext->pDevice->CreateShaderResourceView(pResource, &DescSRV, CpuHandle); // RTV RTV.pResource = pResource; D3D12_RENDER_TARGET_VIEW_DESC DescRTV = {}; DescRTV.Format = Format; if (ArraySize > 1) { DescRTV.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY; DescRTV.Texture2DArray.ArraySize = ArraySize; DescRTV.Texture2DArray.FirstArraySlice = 0; DescRTV.Texture2DArray.MipSlice = 0; DescRTV.Texture2DArray.PlaneSlice = 0; } else { DescRTV.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; DescRTV.Texture2D.MipSlice = 0; DescRTV.Texture2D.PlaneSlice = 0; } RTV.CpuHandle = pContext->DescHeaps.RTV.GetCPUHandle(BaseRTVHeapIndex); // Create the render target view pContext->pDevice->CreateRenderTargetView(pResource, &DescRTV, RTV.CpuHandle); m_AllocatedSizeInBytes = Width * Height * ArraySize * GetFormatSizeInBytes(Format); } } void SafeRelease() { SAFE_RELEASE(pResource); m_AllocatedSizeInBytes = 0; } }; //-------------------------------------------------------------------------------- template class RTTexture2DArray : public RTTexture2D { public: ShaderResourceView SRVs[ARRAY_SIZE]; RenderTargetView RTVs[ARRAY_SIZE]; RTTexture2DArray() : RTTexture2D() { ZERO_ARRAY(SRVs); ZERO_ARRAY(RTVs); } void CreateOnce(GFSDK_D3D12_GraphicsContext* pContext, UINT Width, UINT Height, DXGI_FORMAT Format, UINT BaseSRVHeapIndex, UINT BaseRTVHeapIndex); void SafeRelease(); }; //-------------------------------------------------------------------------------- template void RTTexture2DArray::CreateOnce(GFSDK_D3D12_GraphicsContext* pContext, UINT Width, UINT Height, DXGI_FORMAT Format, UINT BaseSRVHeapIndex, UINT BaseRTVHeapIndex) { if (!pResource) { RTTexture2D::CreateOnce(pContext, Width, Height, Format, BaseSRVHeapIndex, BaseRTVHeapIndex, ARRAY_SIZE); for (UINT SliceId = 0; SliceId < SIZEOF_ARRAY(RTVs); ++SliceId) { RTVs[SliceId].pResource = pResource; #if _WIN64 RTVs[SliceId].CpuHandle.ptr = ~0ull; #else RTVs[SliceId].CpuHandle.ptr = ~0ul; #endif D3D12_RENDER_TARGET_VIEW_DESC Desc = {}; Desc.Format = Format; Desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY; Desc.Texture2DArray.MipSlice = 0; Desc.Texture2DArray.FirstArraySlice = SliceId; Desc.Texture2DArray.ArraySize = 1; RTVs[SliceId].CpuHandle = pContext->DescHeaps.RTV.GetCPUHandle(BaseRTVHeapIndex + 1 + SliceId); pContext->pDevice->CreateRenderTargetView(pResource, &Desc, RTVs[SliceId].CpuHandle); } for (UINT SliceId = 0; SliceId < SIZEOF_ARRAY(SRVs); ++SliceId) { SRVs[SliceId].pResource = pResource; D3D12_SHADER_RESOURCE_VIEW_DESC Desc = {}; Desc.Format = Format; Desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; Desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; Desc.Texture2DArray.MostDetailedMip = 0; Desc.Texture2DArray.MipLevels = 1; Desc.Texture2DArray.ArraySize = 1; Desc.Texture2DArray.FirstArraySlice = SliceId; SRVs[SliceId].GpuHandle = pContext->DescHeaps.CBVSRVUAV.GetGPUHandle(BaseSRVHeapIndex + 1 + SliceId); D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle = pContext->DescHeaps.CBVSRVUAV.GetCPUHandle(BaseSRVHeapIndex + 1 + SliceId); pContext->pDevice->CreateShaderResourceView(pResource, &Desc, CpuHandle); } } } //-------------------------------------------------------------------------------- template void RTTexture2DArray::SafeRelease() { RTTexture2D::SafeRelease(); } //-------------------------------------------------------------------------------- class RenderTargets { public: RenderTargets() : m_pContext(nullptr) , m_FullWidth(0) , m_FullHeight(0) { } void ReleaseResources() { m_FullResAOZTexture.SafeRelease(); m_FullResAOZTexture2.SafeRelease(); m_FullResNormalTexture.SafeRelease(); m_FullResViewDepthTexture.SafeRelease(); m_FullResViewDepthTexture2.SafeRelease(); m_QuarterResAOTextureArray.SafeRelease(); m_QuarterResViewDepthTextureArray.SafeRelease(); } void Release() { ReleaseResources(); SAFE_RELEASE(m_pContext->pDevice); } void SetGraphicsContext(GFSDK_D3D12_GraphicsContext* pContext) { m_pContext = pContext; m_pContext->pDevice->AddRef(); } void SetFullResolution(UINT Width, UINT Height) { m_FullWidth = Width; m_FullHeight = Height; } UINT GetFullWidth() { return m_FullWidth; } UINT GetFullHeight() { return m_FullHeight; } #if ENABLE_DEBUG_NAMES #define SET_TEXTURE_DEBUG_NAME(Name) \ m_##Name.pResource->SetName(L#Name); #else #define SET_TEXTURE_DEBUG_NAME(Name) #endif const RTTexture2D* GetFullResAOZTexture() { m_FullResAOZTexture.CreateOnce(m_pContext, m_FullWidth, m_FullHeight, DXGI_FORMAT_R16G16_FLOAT, eFullResAOZTexture, eFullResAOZTextureRTV); SET_TEXTURE_DEBUG_NAME(FullResAOZTexture); return &m_FullResAOZTexture; } const RTTexture2D* GetFullResAOZTexture2() { m_FullResAOZTexture2.CreateOnce(m_pContext, m_FullWidth, m_FullHeight, DXGI_FORMAT_R16G16_FLOAT, eFullResAOZTexture2, eFullResAOZTexture2RTV); SET_TEXTURE_DEBUG_NAME(FullResAOZTexture2); return &m_FullResAOZTexture2; } const RTTexture2D* GetFullResViewDepthTexture() { m_FullResViewDepthTexture.CreateOnce(m_pContext, m_FullWidth, m_FullHeight, DXGI_FORMAT_R32_FLOAT, eFullResViewDepthTexture, eFullResViewDepthTextureRTV); SET_TEXTURE_DEBUG_NAME(FullResViewDepthTexture); return &m_FullResViewDepthTexture; } const RTTexture2D* GetFullResViewDepthTexture2() { m_FullResViewDepthTexture2.CreateOnce(m_pContext, m_FullWidth, m_FullHeight, DXGI_FORMAT_R32_FLOAT, eFullResViewDepthTexture2, eFullResViewDepthTexture2RTV); SET_TEXTURE_DEBUG_NAME(FullResViewDepthTexture2); return &m_FullResViewDepthTexture2; } DXGI_FORMAT GetViewDepthTextureFormat(GFSDK_SSAO_DepthStorage DepthStorage) { return (DepthStorage == GFSDK_SSAO_FP16_VIEW_DEPTHS) ? DXGI_FORMAT_R16_FLOAT : DXGI_FORMAT_R32_FLOAT; } const RTTexture2DArray<16>* GetQuarterResViewDepthTextureArray(const GFSDK_SSAO_Parameters &Options) { m_QuarterResViewDepthTextureArray.CreateOnce(m_pContext, iDivUp(m_FullWidth, 4), iDivUp(m_FullHeight, 4), Options.EnableDualLayerAO ? DXGI_FORMAT_R16G16_FLOAT : GetViewDepthTextureFormat(Options.DepthStorage), eQuarterResViewDepthTextureArray, eQuarterResViewDepthTextureArrayRTV); SET_TEXTURE_DEBUG_NAME(QuarterResViewDepthTextureArray); return &m_QuarterResViewDepthTextureArray; } const RTTexture2DArray<16>* GetQuarterResAOTextureArray() { m_QuarterResAOTextureArray.CreateOnce(m_pContext, iDivUp(m_FullWidth, 4), iDivUp(m_FullHeight, 4), DXGI_FORMAT_R8_UNORM, eQuarterResAOTextureArray, eQuarterResAOTextureArrayRTV); SET_TEXTURE_DEBUG_NAME(QuarterResAOTextureArray); return &m_QuarterResAOTextureArray; } const RTTexture2D* GetFullResNormalTexture() { m_FullResNormalTexture.CreateOnce(m_pContext, m_FullWidth, m_FullHeight, DXGI_FORMAT_R8G8B8A8_UNORM, eFullResNormalTexture, eFullResNormalTextureRTV); SET_TEXTURE_DEBUG_NAME(FullResNormalTexture); return &m_FullResNormalTexture; } void CreateOnceAll(const GFSDK_SSAO_Parameters &Options) { GetFullResViewDepthTexture(); GetFullResNormalTexture(); GetQuarterResViewDepthTextureArray(Options); GetQuarterResAOTextureArray(); if (Options.EnableDualLayerAO) { GetFullResViewDepthTexture2(); } if (Options.Blur.Enable) { GetFullResAOZTexture(); GetFullResAOZTexture2(); } } GFSDK_SSAO_Status PreCreate(const GFSDK_SSAO_Parameters &Options) { #if ENABLE_EXCEPTIONS try { CreateOnceAll(Options); } catch (...) { ReleaseResources(); return GFSDK_SSAO_D3D_RESOURCE_CREATION_FAILED; } #else CreateOnceAll(Options); #endif return GFSDK_SSAO_OK; } UINT GetCurrentAllocatedVideoMemoryBytes() { return m_FullResAOZTexture.GetAllocatedSizeInBytes() + m_FullResAOZTexture2.GetAllocatedSizeInBytes() + m_FullResNormalTexture.GetAllocatedSizeInBytes() + m_FullResViewDepthTexture.GetAllocatedSizeInBytes() + m_FullResViewDepthTexture2.GetAllocatedSizeInBytes() + m_QuarterResAOTextureArray.GetAllocatedSizeInBytes() + m_QuarterResViewDepthTextureArray.GetAllocatedSizeInBytes(); } private: GFSDK_D3D12_GraphicsContext* m_pContext; UINT m_FullWidth; UINT m_FullHeight; RTTexture2D m_FullResAOZTexture; RTTexture2D m_FullResAOZTexture2; RTTexture2D m_FullResNormalTexture; RTTexture2D m_FullResViewDepthTexture; RTTexture2D m_FullResViewDepthTexture2; RTTexture2DArray<16> m_QuarterResAOTextureArray; RTTexture2DArray<16> m_QuarterResViewDepthTextureArray; }; } // namespace D3D12 } // namespace SSAO } // namespace GFSDK #endif // SUPPORT_D3D12