// Copyright Epic Games, Inc. All Rights Reserved. #include "SceneRendering.h" #include "ScenePrivate.h" #include "RenderGraphUtils.h" #include "RenderCurveSceneExtension.h" DECLARE_GPU_STAT(CurveRasterPipeline); static TAutoConsoleVariable CVarRenderCurve( TEXT("r.RenderCurve"), 0, TEXT("Enable render curve raster pipeline. Read-only variable. (experimental)."), ECVF_RenderThreadSafe | ECVF_ReadOnly ); static TAutoConsoleVariable CVarRenderCurveDebug( TEXT("r.RenderCurve.Debug"), 0, TEXT("Enable render curve pipeline debug visualization."), ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarRenderCurveMinCoverage( TEXT("r.RenderCurve.Raster.MinCoverage"), 0.05f, TEXT("Render curve min. coverage before exiting raster work."), ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarRenderCurveNumBinners( TEXT("r.RenderCurve.Raster.NumBinners"), 32, TEXT("Number of Binners used in Binning pass by the render curve pipeline. 32 is default."), ECVF_RenderThreadSafe ); static TAutoConsoleVariable CVarRenderCurveNumRasterizers( TEXT("r.RenderCurve.Raster.NumRasterizers"), 256, TEXT("Number of Rasterizers used in Raster pass by the render curve pipeline. 256 is default."), ECVF_RenderThreadSafe ); ///////////////////////////////////////////////////////////////////////////////////////// // FPackedSegment #define FPackedSegmentType uint4 #define FPackedSegmentSizeInBytes (sizeof(uint32) * 4) ///////////////////////////////////////////////////////////////////////////////////////// bool IsRenderCurveEnabled() { return CVarRenderCurve.GetValueOnAnyThread() > 0; } inline bool IsRenderCurveSupported(EShaderPlatform In) { return IsRenderCurveEnabled() && IsFeatureLevelSupported(In, ERHIFeatureLevel::SM6) && IsHairStrandsSupported(EHairStrandsShaderType::Strands, In) && !IsVulkanPlatform(In) && !IsMetalPlatform(In); } ///////////////////////////////////////////////////////////////////////////////////////// BEGIN_SHADER_PARAMETER_STRUCT(FRenderCurveCommonParameters, ) SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View) SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneUniformParameters, Scene) SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer) SHADER_PARAMETER_STRUCT_INCLUDE(FHZBParameters, HZBParameters) SHADER_PARAMETER(FIntPoint, Resolution) SHADER_PARAMETER(uint32, BinTileSize) SHADER_PARAMETER(uint32, RasterTileSize) SHADER_PARAMETER(uint32, NumBinners) SHADER_PARAMETER(uint32, NumRasterizers) SHADER_PARAMETER(FIntPoint, BinTileRes) SHADER_PARAMETER(FIntPoint, RasterTileRes) SHADER_PARAMETER(uint32, MaxTileDataCount) SHADER_PARAMETER(uint32, MaxSegmentDataCount) SHADER_PARAMETER(uint32, MaxZBinDataCount) SHADER_PARAMETER(uint32, MaxZBinSegmentDataCount) SHADER_PARAMETER(uint32, MaxRasterWorkCount) SHADER_PARAMETER(float, MinCoverageThreshold) END_SHADER_PARAMETER_STRUCT() ///////////////////////////////////////////////////////////////////////////////////////// class FRenderCurveSegmentLUTCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveSegmentLUTCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveSegmentLUTCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View) SHADER_PARAMETER(FIntPoint, DebugOutputResolution) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWSegmentLUT) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDebugOutput) SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetRasterResolution() { return 16u; } static uint32 GetGroupSizeX() { return GetRasterResolution(); } static uint32 GetGroupSizeY() { return GetRasterResolution(); } static uint32 GetGroupSize() { return GetGroupSizeX() * GetGroupSizeY(); } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), GetGroupSizeX()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), GetGroupSizeY()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveSegmentLUTCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "SegmentLUTCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// class FRenderCurveInstanceCullingCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveInstanceCullingCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveInstanceCullingCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, RWVisibleInstanceArgs) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWVisibleInstances) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWMinMaxZ) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSize() { return 64u; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveInstanceCullingCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "InstanceCullingCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// class FRenderCurveClusterCullingCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveClusterCullingCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveClusterCullingCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisibleInstanceArgs) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleInstances) SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, RWVisibleClusterArgs) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWVisibleClusters) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWMinMaxZ) RDG_BUFFER_ACCESS(VisibleInstanceIndirectArgs, ERHIAccess::IndirectArgs) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSize() { return 64u; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveClusterCullingCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "ClusterCullingCS", SF_Compute); /////////////////////////////////////////////////////////////////////////////////////////////////// // Compute depth tile data based on scene data class FRenderCurveSceneTileDepthCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveSceneTileDepthCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveSceneTileDepthCS, FGlobalShader); BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutSceneTileDepthTexture) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSize() { return 32u * 32u; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveSceneTileDepthCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "SceneTileDepthCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// // Bin segments class FRenderCurveBinningCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveBinningCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveBinningCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ViewMinMaxZ) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneTileDepthTexture) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleClusters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleClustersCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer,VisibleClustersQueue) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray, RWTileSegmentCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWTileData) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWSegmentData) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWTileDataAllocatedCount) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSizeX() { return 64u; } static uint32 GetGroupSizeY() { return 16u; } static uint32 GetGroupSize() { return GetGroupSizeX() * GetGroupSizeY(); } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), GetGroupSizeX()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), GetGroupSizeY()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveBinningCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "BinningCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// // Compact binned segments into contiguous list class FRenderCurveCompactionCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveCompactionCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveCompactionCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ViewMinMaxZ) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneTileDepthTexture) SHADER_PARAMETER_RDG_TEXTURE(Texture2DArray, TileSegmentCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, TileData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, SegmentData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, TileDataAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWZBinDataAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWZBinData) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWZBinSegmentAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWZBinSegmentData) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWRasterWorkAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWRasterWork) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSize() { return 1024u; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters &Parameters, FShaderCompilerEnvironment &OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveCompactionCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "CompactionCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// // Compact binned segments into contiguous list class FRenderCurveRasterizerCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveRasterizerCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveRasterizerCS, FGlobalShader); class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG"); using FPermutationDomain = TShaderPermutationDomain; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ViewMinMaxZ) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneTileDepthTexture) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SegmentLUT) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinDataAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinSegmentAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinSegmentData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, RasterWorkAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, RasterWork) SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RasterWorkQueue) SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutputTexture) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSize() { return 1024u; } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters &Parameters, FShaderCompilerEnvironment &OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveRasterizerCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "RasterizerCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// class FRenderCurveDebugDrawingCS : public FGlobalShader { DECLARE_GLOBAL_SHADER(FRenderCurveDebugDrawingCS); SHADER_USE_PARAMETER_STRUCT(FRenderCurveDebugDrawingCS, FGlobalShader); using FPermutationDomain = TShaderPermutationDomain<>; BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) SHADER_PARAMETER(uint32, TotalBufferMemoryInMBytes) SHADER_PARAMETER(uint32, TotalTextureMemoryInMBytes) SHADER_PARAMETER_STRUCT_INCLUDE(FRenderCurveCommonParameters, CommonParameters) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ViewMinMaxZ) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisibleInstanceArgs) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleInstances) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisibleClusterArgs) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisibleClusters) SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneTileDepthTexture) SHADER_PARAMETER_RDG_TEXTURE(Texture2DArray, TileSegmentCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, TileDataAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinData) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, RasterWork) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, RasterWorkAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinSegmentAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinDataAllocatedCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, ZBinSegmentData) END_SHADER_PARAMETER_STRUCT() public: static uint32 GetGroupSizeX() { return 8u; } static uint32 GetGroupSizeY() { return 8u; } static uint32 GetGroupSize() { return GetGroupSizeX() * GetGroupSizeY(); } static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsRenderCurveSupported(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment); OutEnvironment.SetDefine(TEXT("PERMUTATION_DEBUG"), 1); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), GetGroupSizeX()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), GetGroupSizeY()); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize()); } }; IMPLEMENT_GLOBAL_SHADER(FRenderCurveDebugDrawingCS, "/Engine/Private/HairStrands/RenderCurveRaster.usf", "DebugDrawingCS", SF_Compute); ///////////////////////////////////////////////////////////////////////////////////////// struct FRenderCurveTransientData { FRDGBufferSRVRef VisibleInstancesSRV = nullptr; FRDGBufferSRVRef VisibleInstanceArgsSRV = nullptr; FRDGBufferRef VisibleInstanceArgs = nullptr; FRDGBufferSRVRef VisibleClustersSRV = nullptr; FRDGBufferSRVRef VisibleClusterArgsSRV = nullptr; FRDGBufferRef VisibleClusterArgs = nullptr; FRDGTextureRef SceneTileDepth = nullptr; FRDGTextureRef TileSegmentCount = nullptr; FRDGBufferSRVRef TileDataAllocatedCount = nullptr; FRDGBufferSRVRef TileData = nullptr; FRDGBufferSRVRef SegmentData = nullptr; FRDGBufferUAVRef RWMinMaxZ = nullptr; FRDGBufferSRVRef MinMaxZ = nullptr; FRDGBufferSRVRef ZBinData = nullptr; FRDGBufferSRVRef ZBinDataAllocatedCount = nullptr; FRDGBufferSRVRef ZBinSegmentData = nullptr; FRDGBufferSRVRef ZBinSegmentAllocatedCount = nullptr; FRDGBufferSRVRef RasterWork = nullptr; FRDGBufferSRVRef RasterWorkAllocatedCount = nullptr; }; ///////////////////////////////////////////////////////////////////////////////////////// // Memory struct FRenderCurveMemoryTracker { FRenderCurveMemoryTracker() { Infos.Reserve(12u); } void Add(FRDGBufferRef In) { if (In) { FInfo& Info = Infos.AddDefaulted_GetRef(); Info.Size = In->Desc.GetSize(); Info.Name = In->Name; TotalBufferMemoryInBytes += Info.Size; } } void Add(FRDGTextureRef In) { FInfo& Info = Infos.AddDefaulted_GetRef(); Info.Size = In->Desc.CalcMemorySizeEstimate(); Info.Name = In->Name; TotalTextureMemoryInBytes += Info.Size; } struct FInfo { const TCHAR* Name = nullptr; uint64 Size = 0; }; TArray Infos; uint64 TotalBufferMemoryInBytes = 0; uint64 TotalTextureMemoryInBytes = 0; }; ///////////////////////////////////////////////////////////////////////////////////////// void AddRenderCurveRasterPipeline( FRDGBuilder& GraphBuilder, FScene* Scene, const TArray& Views, FRDGTextureRef SceneColorTexture, FRDGTextureRef SceneDepthTexture) { if (Views.Num() == 0 || !IsRenderCurveSupported(Views[0].GetShaderPlatform())) { return; } // Need wave size to be at least 32 if (GRHISupportsWaveOperations && RHISupportsWaveOperations(Views[0].GetShaderPlatform()) && GRHIMinimumWaveSize < 32) { return; } uint32 InstanceCount = 0; uint32 UniqueClusterCount = 0; if (const RenderCurve::FRenderCurveSceneExtension* Extension = Scene->GetExtensionPtr()) { InstanceCount = Extension->GetInstanceCount(); UniqueClusterCount = Extension->GetClusterCount(); } if (InstanceCount == 0) { return; } QUICK_SCOPE_CYCLE_COUNTER(STAT_CLM_CurveRasterPipeline); RDG_EVENT_SCOPE_STAT(GraphBuilder, CurveRasterPipeline, "CurveRasterPipeline"); RDG_GPU_STAT_SCOPE(GraphBuilder, CurveRasterPipeline); const uint32 MaxVisibleClusterCount = 8u * 1024u * InstanceCount; // 1k cluster per instance in average? const uint32 IndirectArgsSizeInBytes = FMath::Max(uint32(sizeof(FRHIDispatchIndirectParameters)), 16u); // Needs at least 4 elements const bool bDebug = CVarRenderCurveDebug.GetValueOnRenderThread() > 0; const FViewInfo& View = Views[0]; auto ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel);//TODO FRenderCurveMemoryTracker MemoryTracker; // Segment LUT generation // This LUT translate a segment (defined by its two points) into a 8x8 bitmask (stored as 2uints) // Disable as we don't use it yet. #if 0 FRDGTextureRef SegmentLUT = nullptr; if (Scene->HairStrandsSceneData.SegmentLUT == nullptr) { const uint32 Res = FRenderCurveSegmentLUTCS::GetRasterResolution(); SegmentLUT = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(FIntPoint(Res*Res, Res*Res), PF_R32G32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV), TEXT("RenderCurve.SegmentLUT")); FRDGTextureUAVRef RWSegmentLUT = GraphBuilder.CreateUAV(SegmentLUT); AddClearUAVPass(GraphBuilder, RWSegmentLUT, 0u); FRenderCurveSegmentLUTCS::FPermutationDomain PermutationVector; TShaderMapRef ComputeShader(ShaderMap, PermutationVector); FRenderCurveSegmentLUTCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->RWSegmentLUT = RWSegmentLUT; Parameters->RWDebugOutput = GraphBuilder.CreateUAV(SceneColorTexture); Parameters->DebugOutputResolution = SceneColorTexture->Desc.Extent; { ShaderPrint::SetEnabled(true); ShaderPrint::RequestSpaceForLines(1024 * 1024); ShaderPrint::RequestSpaceForCharacters(4096 * 128); ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, Parameters->ShaderPrintUniformBuffer); } FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::DebugDrawing"), ComputeShader, Parameters, FIntVector(Res, Res, 1)); GraphBuilder.QueueTextureExtraction(SegmentLUT, &Scene->HairStrandsSceneData.SegmentLUT, ERHIAccess::SRVMask); } else { SegmentLUT = GraphBuilder.RegisterExternalTexture(Scene->HairStrandsSceneData.SegmentLUT); } MemoryTracker.Add(SegmentLUT); #endif // Common parameters FRenderCurveCommonParameters CommonParameters; { TRDGUniformBufferRef SceneUniformParameters = GetSceneUniformBufferRef(GraphBuilder, View); CommonParameters.View = View.ViewUniformBuffer; CommonParameters.Scene = SceneUniformParameters; if (const FViewInfo* ViewInfo = View.bIsViewInfo ? reinterpret_cast(&View) : nullptr) { CommonParameters.HZBParameters = GetHZBParameters(GraphBuilder, View, EHZBType::FurthestHZB); } else { CommonParameters.HZBParameters = GetDummyHZBParameters(GraphBuilder); } CommonParameters.Resolution = SceneDepthTexture->Desc.Extent; // Rect view instead? ViewSizeAndInvSize CommonParameters.BinTileSize = 32; CommonParameters.RasterTileSize = 8; CommonParameters.NumBinners = FMath::Min(FMath::Max(CVarRenderCurveNumBinners.GetValueOnRenderThread(), 1), 256); CommonParameters.NumRasterizers = FMath::Min(FMath::Max(CVarRenderCurveNumRasterizers.GetValueOnRenderThread(), 1), 1024); CommonParameters.BinTileRes = FIntPoint(FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.X), CommonParameters.BinTileSize), FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.Y), CommonParameters.BinTileSize)); CommonParameters.RasterTileRes = FIntPoint(FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.X), CommonParameters.RasterTileSize), FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.Y), CommonParameters.RasterTileSize)); const uint32 MaxVisibleSegmentCountPerTile = FMath::Max(CommonParameters.NumBinners, 8u) * 128u; const uint32 MaxVisibleTileDataPerTile = FMath::Max(CommonParameters.NumBinners, 8u) * 2; CommonParameters.MaxTileDataCount = CommonParameters.BinTileRes.X * CommonParameters.BinTileRes.Y * MaxVisibleTileDataPerTile; CommonParameters.MaxSegmentDataCount = CommonParameters.BinTileRes.X * CommonParameters.BinTileRes.Y * MaxVisibleSegmentCountPerTile; CommonParameters.MaxZBinDataCount = CommonParameters.MaxTileDataCount; CommonParameters.MaxRasterWorkCount = CommonParameters.BinTileRes.X * CommonParameters.BinTileRes.Y; CommonParameters.MaxZBinSegmentDataCount = CommonParameters.MaxSegmentDataCount; CommonParameters.MinCoverageThreshold = FMath::Clamp(CVarRenderCurveMinCoverage.GetValueOnRenderThread(), 0.f, 1.f); if (bDebug) { ShaderPrint::SetEnabled(true); ShaderPrint::RequestSpaceForLines((12u * 1024u + 16u * 2048u) * InstanceCount); ShaderPrint::RequestSpaceForCharacters(4096 * 128); ShaderPrint::RequestSpaceForTriangles(CommonParameters.BinTileRes.X * CommonParameters.BinTileRes.Y * 2u); ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, CommonParameters.ShaderPrintUniformBuffer); } } FRenderCurveTransientData TransientData; // Instance culling { FRDGBufferRef MinMaxZ = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 2), TEXT("RenderCurve.Culling.ZMinMax")); TransientData.MinMaxZ = GraphBuilder.CreateSRV(MinMaxZ); TransientData.RWMinMaxZ = GraphBuilder.CreateUAV(MinMaxZ); MemoryTracker.Add(MinMaxZ); FRDGBufferRef VisibleInstanceArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc(IndirectArgsSizeInBytes, 1u), TEXT("RenderCurve.Culling.VisibleInstanceArgs")); FRDGBufferRef VisibleInstances = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), InstanceCount), TEXT("RenderCurve.Culling.VisibleInstances")); MemoryTracker.Add(VisibleInstanceArgs); MemoryTracker.Add(VisibleInstances); FRDGBufferUAVRef RWVisibleInstances = GraphBuilder.CreateUAV(VisibleInstances, PF_R32_UINT); FRDGBufferUAVRef RWVisibleInstanceArgs = GraphBuilder.CreateUAV(VisibleInstanceArgs, PF_R32_UINT); TransientData.VisibleInstanceArgs = VisibleInstanceArgs; TransientData.VisibleInstanceArgsSRV = GraphBuilder.CreateSRV(VisibleInstanceArgs, PF_R32_UINT); TransientData.VisibleInstancesSRV = GraphBuilder.CreateSRV(VisibleInstances, PF_R32_UINT); AddClearUAVPass(GraphBuilder, RWVisibleInstanceArgs, 0u); FRenderCurveInstanceCullingCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); TShaderMapRef ComputeShaderRaster(ShaderMap, PermutationVector); FRenderCurveInstanceCullingCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->RWVisibleInstanceArgs = RWVisibleInstanceArgs; Parameters->RWVisibleInstances = RWVisibleInstances; Parameters->RWMinMaxZ = TransientData.RWMinMaxZ; FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::InstanceCulling"), ComputeShaderRaster, Parameters, FIntVector(InstanceCount, 1, 1)); } // Cluster culling { FRDGBufferRef VisibleClusterArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc(IndirectArgsSizeInBytes, 1u), TEXT("RenderCurve.Culling.VisibleClusterArgs")); TransientData.VisibleClusterArgs = VisibleClusterArgs; MemoryTracker.Add(VisibleClusterArgs); FRDGBufferRef VisibleClusters = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32) * 2u, MaxVisibleClusterCount), TEXT("RenderCurve.Culling.VisibleClusters")); FRDGBufferUAVRef RWVisibleClusters = GraphBuilder.CreateUAV(VisibleClusters, PF_R32G32_UINT); TransientData.VisibleClustersSRV = GraphBuilder.CreateSRV(VisibleClusters, PF_R32G32_UINT); MemoryTracker.Add(VisibleClusters); FRDGBufferUAVRef RWVisibleClusterArgs = GraphBuilder.CreateUAV(VisibleClusterArgs, PF_R32_UINT); TransientData.VisibleClusterArgsSRV = GraphBuilder.CreateSRV(VisibleClusterArgs, PF_R32_UINT); AddClearUAVPass(GraphBuilder, RWVisibleClusterArgs, 0u); FRenderCurveClusterCullingCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); TShaderMapRef ComputeShaderRaster(ShaderMap, PermutationVector); FRenderCurveClusterCullingCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->VisibleInstanceArgs = TransientData.VisibleInstanceArgsSRV; Parameters->VisibleInstances = TransientData.VisibleInstancesSRV; Parameters->RWVisibleClusterArgs = RWVisibleClusterArgs; Parameters->RWVisibleClusters = RWVisibleClusters; Parameters->RWMinMaxZ = TransientData.RWMinMaxZ; Parameters->VisibleInstanceIndirectArgs = TransientData.VisibleInstanceArgs; FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::ClusterCulling"), ComputeShaderRaster, Parameters, TransientData.VisibleInstanceArgs, 0u); } // Fill in tile depth { TransientData.SceneTileDepth = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(CommonParameters.BinTileRes, PF_R32G32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource), TEXT("RenderCurve.Raster.SceneTileDepth")); TShaderMapRef ComputeShaderRaster(ShaderMap); FRenderCurveSceneTileDepthCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->SceneDepthTexture = SceneDepthTexture; Parameters->OutSceneTileDepthTexture = GraphBuilder.CreateUAV(TransientData.SceneTileDepth); FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::SceneTileDepth"), ComputeShaderRaster, Parameters, FIntVector(CommonParameters.BinTileRes.X, CommonParameters.BinTileRes.Y, 1)); } // Binning { // TODO change cluster culling to output directly into a structure buffer as we don't use the indirect args? FRDGBufferRef VisibleClusterCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Binning.VisibleClusterCount")); AddCopyBufferPass(GraphBuilder, VisibleClusterCount, 0/*DstOffset*/, TransientData.VisibleClusterArgs, sizeof(uint32) * 3u, sizeof(uint32)); // Copy into a Structured buffer for scalar loading MemoryTracker.Add(VisibleClusterCount); FRDGBufferRef VisibleClusterQueue = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Binning.VisibleClusterQueue")); FRDGBufferUAVRef RWVisibleClusterQueue = GraphBuilder.CreateUAV(VisibleClusterQueue, PF_R32_UINT); AddClearUAVPass(GraphBuilder, RWVisibleClusterQueue, 0u); MemoryTracker.Add(VisibleClusterQueue); const uint32 TileSegmentCountNumLayers = CommonParameters.NumBinners * 3; // 3 layers per binner: segment count | last seg. count | tile info FRDGTextureRef TileSegmentCount = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2DArray(CommonParameters.BinTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_ShaderResource | TexCreate_UAV, TileSegmentCountNumLayers), TEXT("RenderCurve.Binning.TileSegmentCount")); FRDGTextureUAVRef RWTileSegmentCount = GraphBuilder.CreateUAV(TileSegmentCount); AddClearUAVPass(GraphBuilder, RWTileSegmentCount, 0u); TransientData.TileSegmentCount = TileSegmentCount; MemoryTracker.Add(TileSegmentCount); FRDGBufferRef TileDataAllocatedCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Binning.TileDataAllocatedCount")); //FRDGBufferRef TileDataArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc(IndirectArgsSizeInBytes, 1u), TEXT("RenderCurve.Binning.TileDataAllocatedCount")); FRDGBufferUAVRef RWTileDataAllocatedCount = GraphBuilder.CreateUAV(TileDataAllocatedCount); AddClearUAVPass(GraphBuilder, RWTileDataAllocatedCount, 0u); TransientData.TileDataAllocatedCount = GraphBuilder.CreateSRV(TileDataAllocatedCount); MemoryTracker.Add(TileDataAllocatedCount); const uint32 EntryPerTileData = 4u; FRDGBufferRef TileData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), EntryPerTileData * CommonParameters.MaxTileDataCount), TEXT("RenderCurve.Binning.TileData")); FRDGBufferRef SegmentData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(FPackedSegmentSizeInBytes, CommonParameters.MaxSegmentDataCount), TEXT("RenderCurve.Binning.SegmentData")); TransientData.TileData = GraphBuilder.CreateSRV(TileData); TransientData.SegmentData = GraphBuilder.CreateSRV(SegmentData); MemoryTracker.Add(TileData); MemoryTracker.Add(SegmentData); FRenderCurveBinningCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->ViewMinMaxZ = TransientData.MinMaxZ; Parameters->SceneTileDepthTexture = TransientData.SceneTileDepth; Parameters->VisibleClusters = TransientData.VisibleClustersSRV; Parameters->VisibleClustersCount = GraphBuilder.CreateSRV(VisibleClusterCount, PF_R32_UINT); Parameters->VisibleClustersQueue = RWVisibleClusterQueue; Parameters->RWTileSegmentCount = RWTileSegmentCount; Parameters->RWTileData = GraphBuilder.CreateUAV(TileData, PF_R32_UINT); Parameters->RWSegmentData = GraphBuilder.CreateUAV(SegmentData); Parameters->RWTileDataAllocatedCount = RWTileDataAllocatedCount; FRenderCurveBinningCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); TShaderMapRef ComputeShaderBinning(ShaderMap, PermutationVector); FComputeShaderUtils::AddPass( GraphBuilder, RDG_EVENT_NAME("RenderCurve::Binning"), ComputeShaderBinning, Parameters, FIntVector(CommonParameters.NumBinners, 1, 1)); } // Compaction // Each tile segments are compacted into a list of ZBins which each contains a list of segments. // A ZBin is defined by a (fixed) depth range. All segments within this Z ranges belongs to this ZBin // _ _ _ _ _ _ _ _ _ _ // | | | | | |--> ZBinOffset|ZBinCount // |_ _|_ _|_ _|_ _|_ _| // | | | | | | // |_ _|_ _|_ _|_ _|_ _| // | | | | | | // |_ _|_ _|_ _|_ _|_ _| // | | | | | | // |_ _|_ _|_ _|_ _|_ _| // // Definitions: // * ZBinData - Compacted/sparse list of ZBin, containing the offset/count of segment belonging to this ZBin // | Depth0 [ZBinSegmentOffset|ZBinSegmentCount] | Depth7 [ZBinSegmentOffset|ZBinSegmentCount] | Depth24 [ZBinSegmentOffset|ZBinSegmentCount] // // * ZBinSegments // v-----Count-----v // [ / / / / / / / ][ / / / ][ / / / / / ][ / / ] ... // ^ ^ ^ // Offset Offset Offset // // * RasterWork - List of work passed to the rasterize. Contains ZBinOffset|ZBinCount|TileCoord. { FRDGBufferRef ZBinData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32)*2, CommonParameters.MaxZBinDataCount), TEXT("RenderCurve.Compaction.ZBinData")); TransientData.ZBinData = GraphBuilder.CreateSRV(ZBinData); MemoryTracker.Add(ZBinData); FRDGBufferRef ZBinDataAllocatedCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Compaction.ZBinDataAllocatedCount")); FRDGBufferUAVRef RWZBinDataAllocatedCount = GraphBuilder.CreateUAV(ZBinDataAllocatedCount); AddClearUAVPass(GraphBuilder, RWZBinDataAllocatedCount, 0u); TransientData.ZBinDataAllocatedCount = GraphBuilder.CreateSRV(ZBinDataAllocatedCount); MemoryTracker.Add(ZBinDataAllocatedCount); FRDGBufferRef RasterWork = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32)*2, CommonParameters.MaxRasterWorkCount), TEXT("RenderCurve.Compaction.RasterWork")); TransientData.RasterWork = GraphBuilder.CreateSRV(RasterWork); MemoryTracker.Add(RasterWork); FRDGBufferRef RasterWorkAllocatedCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Compaction.RasterWorkAllocatedCount")); FRDGBufferUAVRef RWRasterWorkAllocatedCount = GraphBuilder.CreateUAV(RasterWorkAllocatedCount); AddClearUAVPass(GraphBuilder, RWRasterWorkAllocatedCount, 0u); TransientData.RasterWorkAllocatedCount = GraphBuilder.CreateSRV(RasterWorkAllocatedCount); MemoryTracker.Add(RasterWorkAllocatedCount); FRDGBufferRef ZBinSegmentData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(FPackedSegmentSizeInBytes, CommonParameters.MaxZBinSegmentDataCount), TEXT("RenderCurve.Compaction.ZBinSegmentData")); TransientData.ZBinSegmentData = GraphBuilder.CreateSRV(ZBinSegmentData); MemoryTracker.Add(ZBinSegmentData); FRDGBufferRef ZBinSegmentAllocatedCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Compaction.ZBinSegmentAllocatedCount")); FRDGBufferUAVRef RWZBinSegmentAllocatedCount = GraphBuilder.CreateUAV(ZBinSegmentAllocatedCount); AddClearUAVPass(GraphBuilder, RWZBinSegmentAllocatedCount, 0u); TransientData.ZBinSegmentAllocatedCount = GraphBuilder.CreateSRV(ZBinSegmentAllocatedCount); MemoryTracker.Add(ZBinSegmentAllocatedCount); FRenderCurveCompactionCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->ViewMinMaxZ = TransientData.MinMaxZ; Parameters->SceneTileDepthTexture = TransientData.SceneTileDepth; Parameters->TileSegmentCount = TransientData.TileSegmentCount; Parameters->TileData = TransientData.TileData; Parameters->SegmentData = TransientData.SegmentData; Parameters->TileDataAllocatedCount = TransientData.TileDataAllocatedCount; Parameters->RWZBinDataAllocatedCount = RWZBinDataAllocatedCount; Parameters->RWZBinData = GraphBuilder.CreateUAV(ZBinData); Parameters->RWZBinSegmentAllocatedCount = RWZBinSegmentAllocatedCount; Parameters->RWZBinSegmentData = GraphBuilder.CreateUAV(ZBinSegmentData); Parameters->RWRasterWorkAllocatedCount = RWRasterWorkAllocatedCount; Parameters->RWRasterWork = GraphBuilder.CreateUAV(RasterWork); FRenderCurveCompactionCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); TShaderMapRef ComputeShader(ShaderMap, PermutationVector); FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::Compaction"), ComputeShader, Parameters, FIntVector(CommonParameters.BinTileRes.X, CommonParameters.BinTileRes.Y, 1)); } // Rasterizer { FRDGBufferRef RasterWorkQueue = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("RenderCurve.Rasterizer.WorkQueue")); FRDGBufferUAVRef RWRasterWorkQueue = GraphBuilder.CreateUAV(RasterWorkQueue, PF_R32_UINT); AddClearUAVPass(GraphBuilder, RWRasterWorkQueue, 0u); MemoryTracker.Add(RasterWorkQueue); FRenderCurveRasterizerCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->SceneTileDepthTexture = TransientData.SceneTileDepth; Parameters->SceneDepthTexture = SceneDepthTexture; Parameters->SegmentLUT = GSystemTextures.GetBlackDummy(GraphBuilder); Parameters->ViewMinMaxZ = TransientData.MinMaxZ; Parameters->ZBinDataAllocatedCount = TransientData.ZBinDataAllocatedCount; Parameters->ZBinData = TransientData.ZBinData; Parameters->ZBinSegmentAllocatedCount = TransientData.ZBinSegmentAllocatedCount; Parameters->ZBinSegmentData = TransientData.ZBinSegmentData; Parameters->RasterWorkAllocatedCount = TransientData.RasterWorkAllocatedCount; Parameters->RasterWork = TransientData.RasterWork; Parameters->RasterWorkQueue = RWRasterWorkQueue; Parameters->OutputTexture = GraphBuilder.CreateUAV(SceneColorTexture); FRenderCurveRasterizerCS::FPermutationDomain PermutationVector; PermutationVector.Set(bDebug); TShaderMapRef ComputeShader(ShaderMap, PermutationVector); FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::Rasterizer"), ComputeShader, Parameters, FIntVector(CommonParameters.NumRasterizers, 1, 1)); } // Debug drawing if (bDebug) { FRenderCurveDebugDrawingCS::FPermutationDomain PermutationVector; TShaderMapRef ComputeShader(ShaderMap, PermutationVector); FRenderCurveDebugDrawingCS::FParameters* Parameters = GraphBuilder.AllocParameters(); Parameters->CommonParameters = CommonParameters; Parameters->ViewMinMaxZ = TransientData.MinMaxZ; Parameters->VisibleInstanceArgs = TransientData.VisibleInstanceArgsSRV; Parameters->VisibleInstances = TransientData.VisibleInstancesSRV; Parameters->VisibleClusterArgs = TransientData.VisibleClusterArgsSRV; Parameters->VisibleClusters = TransientData.VisibleClustersSRV; Parameters->SceneTileDepthTexture = TransientData.SceneTileDepth; Parameters->TileSegmentCount = TransientData.TileSegmentCount; Parameters->TileDataAllocatedCount = TransientData.TileDataAllocatedCount; Parameters->ZBinData = TransientData.ZBinData; Parameters->RasterWork = TransientData.RasterWork; Parameters->RasterWorkAllocatedCount = TransientData.RasterWorkAllocatedCount; Parameters->ZBinSegmentData = TransientData.ZBinSegmentData; Parameters->TotalBufferMemoryInMBytes = uint32(MemoryTracker.TotalBufferMemoryInBytes>>20); Parameters->TotalTextureMemoryInMBytes = uint32(MemoryTracker.TotalTextureMemoryInBytes>>20); Parameters->ZBinSegmentAllocatedCount = TransientData.ZBinSegmentAllocatedCount; Parameters->ZBinDataAllocatedCount = TransientData.ZBinDataAllocatedCount; //FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::DebugDrawing"), ComputeShader, Parameters, TransientData.VisibleClusterArgs, 0u); FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("RenderCurve::DebugDrawing"), ComputeShader, Parameters, FIntVector( FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.X), FRenderCurveDebugDrawingCS::GetGroupSizeX()), FMath::DivideAndRoundUp(uint32(CommonParameters.Resolution.Y), FRenderCurveDebugDrawingCS::GetGroupSizeY()), 1)); } // Add streaming request { // Smaller allocation: Move root pages down then resize //ClusterPageDataBuffer = GraphBuilder.RegisterExternalBuffer(ClusterPageData.DataBuffer); //AddPass_Memmove(GraphBuilder, GraphBuilder.CreateUAV(ClusterPageDataBuffer), MaxStreamingPages * NANITE_STREAMING_PAGE_GPU_SIZE, OldMaxStreamingPages * NANITE_STREAMING_PAGE_GPU_SIZE, RootPagesDataSize); //ClusterPageDataBuffer = ResizeByteAddressBufferIfNeeded(GraphBuilder, ClusterPageData.DataBuffer, AllocatedPagesSize, TEXT("Nanite.StreamingManager.ClusterPageData")); } }