Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/Nanite/Voxel.cpp
2025-05-18 13:04:45 +08:00

562 lines
23 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
// Experimental voxel code
#include "Voxel.h"
#include "CoreMinimal.h"
#include "RHI.h"
#include "SceneUtils.h"
#include "ScenePrivate.h"
#include "SpriteIndexBuffer.h"
#include "ClearQuad.h"
#include "DataDrivenShaderPlatformInfo.h"
static TAutoConsoleVariable<int32> CVarVoxel(
TEXT("r.Voxel"),
0,
TEXT(""),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarVoxelMethod(
TEXT("r.Voxel.Method"),
0,
TEXT(""),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarVoxelLevel2(
TEXT("r.Voxel.Level2"),
1,
TEXT(""),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarVoxelTileSize(
TEXT("r.Voxel.TileSize"),
8,
TEXT(""),
ECVF_RenderThreadSafe
);
DECLARE_GPU_STAT_NAMED(NaniteVoxel, TEXT("Nanite Voxel"));
namespace Nanite
{
#if !UE_BUILD_SHIPPING
TGlobalResource< FSpriteIndexBuffer<64> > GSpriteIndexBuffer;
class FVoxelShader : public FGlobalShader
{
public:
FVoxelShader() {}
FVoxelShader( const ShaderMetaType::CompiledShaderInitializerType& Initializer )
: FGlobalShader( Initializer )
{}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported( Parameters.Platform, ERHIFeatureLevel::SM6 );
}
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment )
{
FGlobalShader::ModifyCompilationEnvironment( Parameters, OutEnvironment );
OutEnvironment.CompilerFlags.Add( CFLAG_WaveOperations );
}
};
BEGIN_SHADER_PARAMETER_STRUCT( FBuildBricksParameters, )
SHADER_PARAMETER_STRUCT_REF( FViewUniformShaderParameters, View )
SHADER_PARAMETER_RDG_UNIFORM_BUFFER( FSceneTextureUniformParameters, SceneTextures )
SHADER_PARAMETER( uint32, HashTableSize )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< uint >, HashTable )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< uint >, IndexBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< FBrick >, BrickBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( ByteAddressBuffer, BlockBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, DispatchIndirectArgs )
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, DrawIndirectArgs )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWStructuredBuffer< uint >, RWHashTable )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWStructuredBuffer< uint >, RWIndexBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWStructuredBuffer< FBrick >, RWBrickBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWByteAddressBuffer, RWBlockBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWBuffer< uint >, RWDispatchIndirectArgs )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWBuffer< uint >, RWDrawIndirectArgs )
SHADER_PARAMETER_STRUCT_INCLUDE( ShaderPrint::FShaderParameters, ShaderPrintStruct )
RDG_BUFFER_ACCESS( IndirectArgs, ERHIAccess::IndirectArgs )
END_SHADER_PARAMETER_STRUCT()
#define IMPLEMENT_GLOBAL_SHADER_STRUCT( ShaderTypeName, StructTypeName, SourceFilename, FunctionName, Frequency ) \
class ShaderTypeName : public FVoxelShader \
{ \
DECLARE_GLOBAL_SHADER( ShaderTypeName ); \
SHADER_USE_PARAMETER_STRUCT( ShaderTypeName, FVoxelShader ); \
using FParameters = StructTypeName; \
}; \
IMPLEMENT_GLOBAL_SHADER( ShaderTypeName, SourceFilename, FunctionName, Frequency )
IMPLEMENT_GLOBAL_SHADER_STRUCT( FVisibleBricksHashCS, FBuildBricksParameters, "/Engine/Private/Nanite/Voxel/AutoVoxel.usf", "VisibleBricksHash", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FFillArgsCS, FBuildBricksParameters, "/Engine/Private/Nanite/Voxel/AutoVoxel.usf", "FillArgs", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FAllocBlocksCS, FBuildBricksParameters, "/Engine/Private/Nanite/Voxel/AutoVoxel.usf", "AllocBlocks", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FFillBlocksCS, FBuildBricksParameters, "/Engine/Private/Nanite/Voxel/AutoVoxel.usf", "FillBlocks", SF_Compute );
#if 1
BEGIN_SHADER_PARAMETER_STRUCT( FTileBricksParameters, )
SHADER_PARAMETER_STRUCT_REF( FViewUniformShaderParameters, View )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< FBrick >, BrickBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( ByteAddressBuffer, BlockBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< FTileListElement >, TileListBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< FTileArrayElement >, TileArrayBuffer )
SHADER_PARAMETER_RDG_TEXTURE( Texture2D< uint >, TileHead )
SHADER_PARAMETER_RDG_TEXTURE( Texture2D< uint >, TileCount )
SHADER_PARAMETER_RDG_TEXTURE( Texture2D< uint >, TileOffset )
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, DispatchIndirectArgs )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWStructuredBuffer< FTileListElement >, RWTileListBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWStructuredBuffer< FTileArrayElement >, RWTileArrayBuffer )
SHADER_PARAMETER_RDG_TEXTURE_UAV( RWTexture2D< uint >, RWTileHead )
SHADER_PARAMETER_RDG_TEXTURE_UAV( RWTexture2D< uint >, RWTileCount )
SHADER_PARAMETER_RDG_TEXTURE_UAV( RWTexture2D< uint >, RWTileOffset )
SHADER_PARAMETER_RDG_BUFFER_UAV( RWBuffer< uint >, RWDispatchIndirectArgs )
SHADER_PARAMETER_RDG_TEXTURE_UAV( RWTexture2D, OutSceneColor )
RDG_BUFFER_ACCESS( IndirectArgs, ERHIAccess::IndirectArgs )
END_SHADER_PARAMETER_STRUCT()
IMPLEMENT_GLOBAL_SHADER_STRUCT( FBinBricksInTilesCS, FTileBricksParameters, "/Engine/Private/Nanite/Voxel/TileBricks.usf", "BinBricksInTiles", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FBuildTileArraysCS, FTileBricksParameters, "/Engine/Private/Nanite/Voxel/TileBricks.usf", "BuildTileArrays", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FRayCastTilesCS, FTileBricksParameters, "/Engine/Private/Nanite/Voxel/TileBricks.usf", "RayCastTiles", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FScatterVoxelsCS, FTileBricksParameters, "/Engine/Private/Nanite/Voxel/ScatterBricks.usf", "ScatterVoxels", SF_Compute );
IMPLEMENT_GLOBAL_SHADER_STRUCT( FScatterResolveCS, FTileBricksParameters, "/Engine/Private/Nanite/Voxel/ScatterBricks.usf", "ScatterResolve", SF_Compute );
#endif
BEGIN_SHADER_PARAMETER_STRUCT( FDrawBricksParameters, )
SHADER_PARAMETER_STRUCT_REF( FViewUniformShaderParameters, View )
SHADER_PARAMETER_RDG_BUFFER_SRV( StructuredBuffer< FBrick >, BrickBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( ByteAddressBuffer, BlockBuffer )
SHADER_PARAMETER_RDG_BUFFER_SRV( Buffer< uint >, DispatchIndirectArgs )
RDG_BUFFER_ACCESS( IndirectArgs, ERHIAccess::IndirectArgs )
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
class FDrawBricksVS : public FVoxelShader
{
DECLARE_GLOBAL_SHADER( FDrawBricksVS );
SHADER_USE_PARAMETER_STRUCT( FDrawBricksVS, FVoxelShader );
using FPermutationDomain = TShaderPermutationDomain<>;
using FParameters = FDrawBricksParameters;
};
class FDrawBricksPS : public FVoxelShader
{
DECLARE_GLOBAL_SHADER( FDrawBricksPS );
SHADER_USE_PARAMETER_STRUCT( FDrawBricksPS, FVoxelShader );
using FPermutationDomain = TShaderPermutationDomain<>;
using FParameters = FDrawBricksParameters;
};
IMPLEMENT_SHADER_TYPE(, FDrawBricksVS, TEXT("/Engine/Private/Nanite/Voxel/RasterizeBricks.usf"), TEXT("DrawBricksVS"), SF_Vertex );
IMPLEMENT_SHADER_TYPE(, FDrawBricksPS, TEXT("/Engine/Private/Nanite/Voxel/RasterizeBricks.usf"), TEXT("DrawBricksPS"), SF_Pixel );
#endif
void DrawVisibleBricks(
FRDGBuilder& GraphBuilder,
FScene& Scene,
const FViewInfo& View,
FMinimalSceneTextures& SceneTextures )
{
#if !UE_BUILD_SHIPPING
if( CVarVoxel.GetValueOnRenderThread() == 0 )
return;
RDG_EVENT_SCOPE( GraphBuilder, "Voxel" );
uint32 HashTableSize = View.ViewRect.Area();
//uint32 HashTableSize = FMath::RoundUpToPowerOfTwo( View.ViewRect.Area() );
FRDGBufferRef HashTable = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 4, HashTableSize ), TEXT("Voxel.HashTable") );
FRDGBufferRef IndexBuffer = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 4, HashTableSize ), TEXT("Voxel.IndexBuffer") );
//FRDGBufferRef BrickBuffer = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 8, HashTableSize ), TEXT("Voxel.BrickBuffer") );
FRDGBufferRef BrickBuffer = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 16, HashTableSize ), TEXT("Voxel.BrickBuffer") );
FRDGBufferRef BlockBufferL1 = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateByteAddressDesc( 8 * HashTableSize ), TEXT("Voxel.BlockBufferL1") );
FRDGBufferRef BlockBufferL2 = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateByteAddressDesc( 8 * 2 * View.ViewRect.Area() ), TEXT("Voxel.BlockBufferL2") );
FRDGBufferRef DispatchIndirectArgs = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateIndirectDesc(4), TEXT("Voxel.DispatchIndirectArgs") );
FRDGBufferRef DrawIndirectArgs = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateIndirectDesc(6), TEXT("Voxel.DrawIndirectArgs") );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( HashTable ), 0 );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( DispatchIndirectArgs ), 0 );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( DrawIndirectArgs ), 0 );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( BlockBufferL1 ), 0 );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( BlockBufferL2 ), 0 );
FRDGBufferUAVDesc BrickUAV( BrickBuffer );
//BrickUAV.bSupportsAtomicCounter = true;
{
FBuildBricksParameters* PassParameters = GraphBuilder.AllocParameters< FBuildBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTextures = SceneTextures.UniformBuffer;
PassParameters->HashTableSize = HashTableSize;
PassParameters->RWHashTable = GraphBuilder.CreateUAV( HashTable );
PassParameters->RWIndexBuffer = GraphBuilder.CreateUAV( IndexBuffer );
PassParameters->RWBrickBuffer = GraphBuilder.CreateUAV( BrickBuffer );
//PassParameters->RWBrickBuffer = GraphBuilder.CreateUAV( BrickUAV, ERDGUnorderedAccessViewFlags::InitializeCount );
PassParameters->RWBlockBuffer = GraphBuilder.CreateUAV( BlockBufferL1 );
PassParameters->RWDispatchIndirectArgs = GraphBuilder.CreateUAV( DispatchIndirectArgs );
auto ComputeShader = View.ShaderMap->GetShader< FVisibleBricksHashCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Visible Bricks Hash"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount( View.ViewRect.Size(), 8 )
);
}
{
FBuildBricksParameters* PassParameters = GraphBuilder.AllocParameters< FBuildBricksParameters >();
PassParameters->RWBrickBuffer = GraphBuilder.CreateUAV( BrickUAV );
PassParameters->RWDispatchIndirectArgs = GraphBuilder.CreateUAV( DispatchIndirectArgs );
PassParameters->RWDrawIndirectArgs = GraphBuilder.CreateUAV( DrawIndirectArgs );
ShaderPrint::SetParameters( GraphBuilder, View.ShaderPrintData, PassParameters->ShaderPrintStruct );
auto ComputeShader = View.ShaderMap->GetShader< FFillArgsCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Fill Args"),
ComputeShader,
PassParameters,
FIntVector( 1, 1, 1 )
);
}
FRDGBufferRef BlockBuffer = BlockBufferL1;
if( CVarVoxelLevel2.GetValueOnRenderThread() )
{
{
FBuildBricksParameters* PassParameters = GraphBuilder.AllocParameters< FBuildBricksParameters >();
PassParameters->RWBrickBuffer = GraphBuilder.CreateUAV( BrickBuffer );
PassParameters->BlockBuffer = GraphBuilder.CreateSRV( BlockBufferL1 );
PassParameters->RWBlockBuffer = GraphBuilder.CreateUAV( BlockBufferL2 );
PassParameters->DispatchIndirectArgs = GraphBuilder.CreateSRV( DispatchIndirectArgs );
PassParameters->RWDrawIndirectArgs = GraphBuilder.CreateUAV( DrawIndirectArgs );
PassParameters->IndirectArgs = DispatchIndirectArgs;
auto ComputeShader = View.ShaderMap->GetShader< FAllocBlocksCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Alloc Blocks"),
ComputeShader,
PassParameters,
PassParameters->IndirectArgs,
0
);
}
{
FBuildBricksParameters* PassParameters = GraphBuilder.AllocParameters< FBuildBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTextures = SceneTextures.UniformBuffer;
PassParameters->HashTableSize = HashTableSize;
PassParameters->HashTable = GraphBuilder.CreateSRV( HashTable );
PassParameters->IndexBuffer = GraphBuilder.CreateSRV( IndexBuffer );
PassParameters->BrickBuffer = GraphBuilder.CreateSRV( BrickBuffer );
PassParameters->RWBlockBuffer = GraphBuilder.CreateUAV( BlockBufferL2 );
auto ComputeShader = View.ShaderMap->GetShader< FFillBlocksCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Fill Blocks"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount( View.ViewRect.Size(), 8 )
);
}
BlockBuffer = BlockBufferL2;
}
RDG_EVENT_SCOPE_STAT(GraphBuilder, NaniteVoxel, "NaniteVoxel");
RDG_GPU_STAT_SCOPE(GraphBuilder, NaniteVoxel);
int32 VoxelMethod = CVarVoxelMethod.GetValueOnRenderThread();
switch( VoxelMethod )
{
default:
case 0: // Rasterize bricks
{
FDrawBricksParameters* PassParameters = GraphBuilder.AllocParameters< FDrawBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->BrickBuffer = GraphBuilder.CreateSRV( BrickBuffer );
PassParameters->BlockBuffer = GraphBuilder.CreateSRV( BlockBuffer );
PassParameters->DispatchIndirectArgs= GraphBuilder.CreateSRV( DispatchIndirectArgs );
PassParameters->IndirectArgs = DrawIndirectArgs;
PassParameters->RenderTargets[0] = FRenderTargetBinding( SceneTextures.Color.Target, ERenderTargetLoadAction::ELoad );
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding( SceneTextures.Depth.Target, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ENoAction, FExclusiveDepthStencil::DepthWrite_StencilNop );
const bool bReverseCulling = View.bReverseCulling;
const FIntRect& ViewRect = View.ViewRect;
auto VertexShader = View.ShaderMap->GetShader< FDrawBricksVS >();
auto PixelShader = View.ShaderMap->GetShader< FDrawBricksPS >();
GraphBuilder.AddPass(
RDG_EVENT_NAME("Draw Bricks"),
PassParameters,
ERDGPassFlags::Raster,
[ VertexShader, PixelShader, PassParameters, bReverseCulling, &ViewRect ]( FRDGAsyncTask, FRHICommandList& RHICmdList )
{
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets( GraphicsPSOInit );
RHICmdList.SetViewport( ViewRect.Min.X, ViewRect.Min.Y, 0.0f, ViewRect.Max.X, ViewRect.Max.Y, 1.0f );
#if 0
GraphicsPSOInit.BlendState = TStaticBlendState< CW_RGBA, BO_Add, BF_One, BF_One >::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
#else
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
GraphicsPSOInit.RasterizerState = bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<true, CF_DepthNearOrEqual>::GetRHI();
#endif
GraphicsPSOInit.PrimitiveType = GRHISupportsRectTopology ? PT_RectList : PT_TriangleList;
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GEmptyVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
SetGraphicsPipelineState( RHICmdList, GraphicsPSOInit, 0 );
SetShaderParameters( RHICmdList, VertexShader, VertexShader.GetVertexShader(), *PassParameters );
SetShaderParameters( RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters );
RHICmdList.SetStreamSource( 0, nullptr, 0 );
if( GRHISupportsRectTopology )
{
RHICmdList.DrawPrimitiveIndirect( PassParameters->IndirectArgs->GetIndirectRHICallBuffer(), 0 );
}
else
{
RHICmdList.DrawIndexedPrimitiveIndirect( GSpriteIndexBuffer.IndexBufferRHI, PassParameters->IndirectArgs->GetIndirectRHICallBuffer(), 0 );
}
} );
}
break;
case 1: // Tiled
{
uint32 TileSize = CVarVoxelTileSize.GetValueOnRenderThread();
uint32 TilesX = FMath::DivideAndRoundUp< uint32 >( View.ViewRect.Size().X, TileSize );
uint32 TilesY = FMath::DivideAndRoundUp< uint32 >( View.ViewRect.Size().Y, TileSize );
uint32 MaxTileElements = View.ViewRect.Area();
FRDGBufferRef TileListBuffer = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 12, MaxTileElements ), TEXT("Voxel.TileListBuffer") );
FRDGBufferRef TileArrayBuffer = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateStructuredDesc( 8, MaxTileElements ), TEXT("Voxel.TileArrayBuffer") );
FRDGBufferRef TileArgs = GraphBuilder.CreateBuffer( FRDGBufferDesc::CreateIndirectDesc(5), TEXT("Voxel.TileArgs") );
FRDGBufferUAVDesc TileListUAV( TileListBuffer );
//TileListUAV.bSupportsAtomicCounter = true;
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( TileArgs ), 0 );
FRDGTextureDesc TileDesc( FRDGTextureDesc::Create2D( FIntPoint( TilesX, TilesY ), PF_R32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV ) );
FRDGTextureRef TileHead = GraphBuilder.CreateTexture( TileDesc, TEXT("TileHead") );
FRDGTextureRef TileCount = GraphBuilder.CreateTexture( TileDesc, TEXT("TileCount") );
FRDGTextureRef TileOffset = GraphBuilder.CreateTexture( TileDesc, TEXT("TileOffset") );
const uint32 ClearValue[4] = { 0, 0, 0, 0 };
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( TileHead ), ClearValue );
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( TileCount ), ClearValue );
FRDGTextureDesc SceneColorDesc = SceneTextures.Color.Target->Desc;
SceneColorDesc.Flags |= TexCreate_UAV;
FRDGTextureRef OutSceneColor = GraphBuilder.CreateTexture( SceneColorDesc, TEXT("SceneColorVoxel") );
{
FTileBricksParameters* PassParameters = GraphBuilder.AllocParameters< FTileBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->BrickBuffer = GraphBuilder.CreateSRV( BrickBuffer );
PassParameters->BlockBuffer = GraphBuilder.CreateSRV( BlockBuffer );
PassParameters->RWTileListBuffer = GraphBuilder.CreateUAV( TileListUAV ); //, ERDGUnorderedAccessViewFlags::InitializeCount );
PassParameters->RWTileHead = GraphBuilder.CreateUAV( TileHead );
PassParameters->RWTileCount = GraphBuilder.CreateUAV( TileCount );
PassParameters->DispatchIndirectArgs = GraphBuilder.CreateSRV( DispatchIndirectArgs );
PassParameters->RWDispatchIndirectArgs = GraphBuilder.CreateUAV( TileArgs );
PassParameters->IndirectArgs = DispatchIndirectArgs;
auto ComputeShader = View.ShaderMap->GetShader< FBinBricksInTilesCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Bin Blocks"),
ComputeShader,
PassParameters,
PassParameters->IndirectArgs,
0
);
}
if(1)
{
FTileBricksParameters* PassParameters = GraphBuilder.AllocParameters< FTileBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->TileListBuffer = GraphBuilder.CreateSRV( TileListBuffer );
PassParameters->RWTileArrayBuffer = GraphBuilder.CreateUAV( TileArrayBuffer );
PassParameters->TileHead = TileHead;
PassParameters->TileCount = TileCount;
PassParameters->RWTileOffset = GraphBuilder.CreateUAV( TileOffset );
PassParameters->RWDispatchIndirectArgs = GraphBuilder.CreateUAV( TileArgs );
auto ComputeShader = View.ShaderMap->GetShader< FBuildTileArraysCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Build Tile Arrays"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount( View.ViewRect.Size(), TileSize )
);
}
{
FTileBricksParameters* PassParameters = GraphBuilder.AllocParameters< FTileBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->BrickBuffer = GraphBuilder.CreateSRV( BrickBuffer );
PassParameters->BlockBuffer = GraphBuilder.CreateSRV( BlockBuffer );
PassParameters->TileListBuffer = GraphBuilder.CreateSRV( TileListBuffer );
PassParameters->TileArrayBuffer = GraphBuilder.CreateSRV( TileArrayBuffer );
PassParameters->TileHead = TileHead;
PassParameters->TileCount = TileCount;
PassParameters->TileOffset = TileOffset;
PassParameters->OutSceneColor = GraphBuilder.CreateUAV( OutSceneColor );
auto ComputeShader = View.ShaderMap->GetShader< FRayCastTilesCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Ray Cast Tiles"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount( View.ViewRect.Size(), TileSize )
);
}
SceneTextures.Color = OutSceneColor;
}
break;
case 2: // Scatter
{
FRDGTextureDesc VisBufferDesc( FRDGTextureDesc::Create2D( View.ViewRect.Size(), PF_R32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV ) );
FRDGTextureRef TileCount = GraphBuilder.CreateTexture( VisBufferDesc, TEXT("TileCount") );
const uint32 ClearValue[4] = { 0, 0, 0, 0 };
AddClearUAVPass( GraphBuilder, GraphBuilder.CreateUAV( TileCount ), ClearValue );
FRDGTextureDesc SceneColorDesc = SceneTextures.Color.Target->Desc;
SceneColorDesc.Flags |= TexCreate_UAV;
FRDGTextureRef OutSceneColor = GraphBuilder.CreateTexture( SceneColorDesc, TEXT("SceneColorVoxel") );
{
FTileBricksParameters* PassParameters = GraphBuilder.AllocParameters< FTileBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->BrickBuffer = GraphBuilder.CreateSRV( BrickBuffer );
PassParameters->BlockBuffer = GraphBuilder.CreateSRV( BlockBufferL1 );
PassParameters->RWTileCount = GraphBuilder.CreateUAV( TileCount );
PassParameters->DispatchIndirectArgs = GraphBuilder.CreateSRV( DispatchIndirectArgs );
PassParameters->IndirectArgs = DispatchIndirectArgs;
auto ComputeShader = View.ShaderMap->GetShader< FScatterVoxelsCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Scatter Voxels"),
ComputeShader,
PassParameters,
PassParameters->IndirectArgs,
0
);
}
{
FTileBricksParameters* PassParameters = GraphBuilder.AllocParameters< FTileBricksParameters >();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->TileCount = TileCount;
PassParameters->OutSceneColor = GraphBuilder.CreateUAV( OutSceneColor );
auto ComputeShader = View.ShaderMap->GetShader< FScatterResolveCS >();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("Scatter Resolve"),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount( View.ViewRect.Size(), 8 )
);
}
SceneTextures.Color = OutSceneColor;
}
break;
}
#endif
}
} // namespace Nanite