739 lines
38 KiB
C++
739 lines
38 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "HairStrandsForwardRaster.h"
|
|
|
|
#include "Shader.h"
|
|
#include "GlobalShader.h"
|
|
#include "ShaderParameters.h"
|
|
#include "ShaderParameterStruct.h"
|
|
#include "SceneTextureParameters.h"
|
|
#include "RenderGraphUtils.h"
|
|
#include "HairStrandsInterface.h"
|
|
#include "SceneRendering.h"
|
|
#include "DataDrivenShaderPlatformInfo.h"
|
|
|
|
extern int32 GHairVisibilityComputeRaster_Culling;
|
|
extern int32 GHairVisibilityComputeRaster_MaxTiles;
|
|
extern int32 GHairVisibilityComputeRaster_TileSize;
|
|
extern int32 GHairVisibility_NumClassifiers;
|
|
extern int32 GHairVisibilityComputeRaster_NumBinners;
|
|
extern int32 GHairVisibilityComputeRaster_NumRasterizers;
|
|
extern int32 GHairVisibilityComputeRaster_NumRasterizersNaive;
|
|
extern int32 GHairVisibilityComputeRaster_Debug;
|
|
|
|
void SetUpViewHairRenderInfo(const FViewInfo& ViewInfo, FVector4f& OutHairRenderInfo, uint32& OutHairRenderInfoBits, uint32& OutHairComponents);
|
|
void SetUpViewHairRenderInfo(const FViewInfo& ViewInfo, bool bEnableMSAA, FVector4f& OutHairRenderInfo, uint32& OutHairRenderInfoBits, uint32& OutHairComponents);
|
|
FMinHairRadiusAtDepth1 ComputeMinStrandRadiusAtDepth1(const FIntPoint& Resolution, const float FOV, const uint32 SampleCount, const float OverrideStrandHairRasterizationScale, const float OrthoWidth);
|
|
|
|
inline bool IsHairStrandsForwardRasterSupported(EShaderPlatform In)
|
|
{
|
|
return IsFeatureLevelSupported(In, ERHIFeatureLevel::SM6) && IsHairStrandsSupported(EHairStrandsShaderType::Strands, In) &&
|
|
!IsVulkanPlatform(In) && !IsMetalPlatform(In); // :todo-jn: fix SPIR-V error during compilation (Mac and Vulkan)
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Culling pass
|
|
|
|
class FHairCullSegmentCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairCullSegmentCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairCullSegmentCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER(FVector2f, OutputResolution)
|
|
SHADER_PARAMETER(uint32, HairMaterialId)
|
|
SHADER_PARAMETER(uint32, ControlPointCount)
|
|
SHADER_PARAMETER(uint32, CurveCount)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FHairStrandsInstanceParameters, HairInstance)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<FPackedHairVis>, RWHairVis)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint2>, RWCoord)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWCounter)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<float4>, RWPoints)
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_CULL"), 1);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairCullSegmentCS, "/Engine/Private/HairStrands/HairStrandsForwardCulling.usf", "CSMain", SF_Compute);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Raster compute common parameters
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FRasterComputeForwardCommonParameters, )
|
|
SHADER_PARAMETER(FIntPoint, OutputResolution)
|
|
SHADER_PARAMETER(FVector2f, OutputResolutionf)
|
|
|
|
SHADER_PARAMETER(FIntPoint, BinTileRes)
|
|
SHADER_PARAMETER(FIntPoint, RasterTileRes)
|
|
|
|
SHADER_PARAMETER(uint32, NumRasterizers)
|
|
SHADER_PARAMETER(float, RcpNumRasterizers)
|
|
|
|
SHADER_PARAMETER(uint32, NumBinners)
|
|
SHADER_PARAMETER(float, RcpNumBinners)
|
|
|
|
SHADER_PARAMETER(float, RadiusAtDepth1)
|
|
SHADER_PARAMETER(uint32, MaxControlPointCount)
|
|
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, ControlPoints)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, ControlPointCount)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Compute depth tile data based on scene data
|
|
|
|
class FHairStrandsForwardRasterPrepareDepthGridCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairStrandsForwardRasterPrepareDepthGridCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairStrandsForwardRasterPrepareDepthGridCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FRasterComputeForwardCommonParameters, Common)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutVisTileDepthGrid)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_DEPTH_GRID"), 1);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairStrandsForwardRasterPrepareDepthGridCS, "/Engine/Private/HairStrands/HairStrandsForwardRaster.usf", "PrepareDepthGridCS", SF_Compute);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Bin strands segments
|
|
|
|
class FHairStrandsForwardRasterBinningCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairStrandsForwardRasterBinningCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairStrandsForwardRasterBinningCS, FGlobalShader);
|
|
|
|
class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG");
|
|
using FPermutationDomain = TShaderPermutationDomain<FDebug>;
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FRasterComputeForwardCommonParameters, Common)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2DArray, VisTileBinningGrid)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutVisTilePrims)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutVisTilePrimDepths)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray, OutVisTileBinningGrid)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray, OutVisTileBinningGridMinZ)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2DArray, OutVisTileBinningGridMaxZ)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, VisTileDepthGrid)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutVisTileArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWByteAddressBuffer, OutVisTileData)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
RDG_TEXTURE_ACCESS(VisTileBinningGridTex, ERHIAccess::UAVCompute)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_BINNING"), 1);
|
|
}
|
|
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
if (PermutationVector.Get<FDebug>())
|
|
{
|
|
return EShaderPermutationPrecacheRequest::NotPrecached;
|
|
}
|
|
return FGlobalShader::ShouldPrecachePermutation(Parameters);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairStrandsForwardRasterBinningCS, "/Engine/Private/HairStrands/HairStrandsForwardRaster.usf", "BinningCS", SF_Compute);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Compacted binned segments into contiguous list
|
|
|
|
class FHairStrandsForwardRasterCompactionCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairStrandsForwardRasterCompactionCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairStrandsForwardRasterCompactionCS, FGlobalShader);
|
|
|
|
class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG");
|
|
using FPermutationDomain = TShaderPermutationDomain<FDebug>;
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FRasterComputeForwardCommonParameters, Common)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, InData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InPrims)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InDepths)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, InArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWByteAddressBuffer, OutData)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutPrims)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutWork)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutDataCount)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, OutWorkCount)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters &Parameters, FShaderCompilerEnvironment &OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_COMPACTION"), 1);
|
|
}
|
|
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
if (PermutationVector.Get<FDebug>())
|
|
{
|
|
return EShaderPermutationPrecacheRequest::NotPrecached;
|
|
}
|
|
return FGlobalShader::ShouldPrecachePermutation(Parameters);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairStrandsForwardRasterCompactionCS, "/Engine/Private/HairStrands/HairStrandsForwardRaster.usf", "CompactionCS", SF_Compute);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Rasterized binned & shaded segements
|
|
|
|
class FHairStrandsForwardRasterRasterizeCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairStrandsForwardRasterRasterizeCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairStrandsForwardRasterRasterizeCS, FGlobalShader);
|
|
|
|
class FDebug : SHADER_PERMUTATION_BOOL("PERMUTATION_DEBUG");
|
|
using FPermutationDomain = TShaderPermutationDomain<FDebug>;
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FRasterComputeForwardCommonParameters, Common)
|
|
SHADER_PARAMETER(FIntPoint, SampleLightingViewportResolution)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SampleLightingTexture)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, SampleVelocityBuffer)
|
|
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisTilePrims)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisTileArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisTileWork)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, VisTileWorkCount)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, VisTileData)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutHairCountTexture_ForDebug)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutHairPixelCountPerTile_ForDebug)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutSceneColorTexture)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, OutSceneVelocityTexture)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer, RWWorkCounter)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
if (PermutationVector.Get<FDebug>())
|
|
{
|
|
return EShaderPermutationPrecacheRequest::NotPrecached;
|
|
}
|
|
|
|
return EShaderPermutationPrecacheRequest::Precached;
|
|
}
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_RASTER"), 1);
|
|
|
|
OutEnvironment.CompilerFlags.Add(CFLAG_AllowTypedUAVLoads);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairStrandsForwardRasterRasterizeCS, "/Engine/Private/HairStrands/HairStrandsForwardRaster.usf", "RasterCS", SF_Compute);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Debug pass
|
|
|
|
class FHairStrandsForwardRasterDebugCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FHairStrandsForwardRasterDebugCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FHairStrandsForwardRasterDebugCS, FGlobalShader);
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<>;
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FRasterComputeForwardCommonParameters, Common)
|
|
SHADER_PARAMETER(uint32, InstanceCount)
|
|
SHADER_PARAMETER(uint32, CPUAllocatedTileCount)
|
|
SHADER_PARAMETER(uint32, CPUAllocatedCompactedTileCount)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairCountTexture_ForDebug)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HairPixelCountPerTile_ForDebug)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, VisTileArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, VisTileData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, CompactedVisTileArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, CompactedVisTileData)
|
|
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintParameters)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsHairStrandsForwardRasterSupported(Parameters.Platform); }
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_RASTERCOMPUTE_DEBUG"), 1);
|
|
}
|
|
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return EShaderPermutationPrecacheRequest::NotPrecached;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FHairStrandsForwardRasterDebugCS, "/Engine/Private/HairStrands/HairStrandsForwardRaster.usf", "MainCS", SF_Compute);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Culling pass
|
|
|
|
FRasterForwardCullingOutput AddHairStrandsForwardCullingPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& ViewInfo,
|
|
const FHairStrandsMacroGroupDatas& MacroGroupDatas,
|
|
const FIntPoint& InResolution,
|
|
const FRDGTextureRef SceneDepthTexture,
|
|
bool bSupportCulling,
|
|
bool bForceRegister)
|
|
{
|
|
if (!IsHairStrandsForwardRasterSupported(ViewInfo.GetShaderPlatform()))
|
|
{
|
|
return FRasterForwardCullingOutput();
|
|
}
|
|
|
|
// Compute maximum number of PrimIDs
|
|
uint32 MaxNumPrimIDs = 0;
|
|
for (const FHairStrandsMacroGroupData &MacroGroup : MacroGroupDatas)
|
|
{
|
|
for (const FHairStrandsMacroGroupData::PrimitiveInfo &PrimitiveInfo : MacroGroup.PrimitivesInfos)
|
|
{
|
|
// If a groom is not visible in primary view, but visible in shadow view, its PrimitiveInfo.Mesh will be null.
|
|
if (PrimitiveInfo.Mesh == nullptr || PrimitiveInfo.Mesh->Elements.Num() == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const FHairGroupPublicData* HairGroupPublicData = reinterpret_cast<const FHairGroupPublicData*>(PrimitiveInfo.Mesh->Elements[0].VertexFactoryUserData);
|
|
check(HairGroupPublicData);
|
|
|
|
const uint32 PointCount = HairGroupPublicData->GetActiveStrandsPointCount();
|
|
// Sanity check
|
|
check(PointCount == HairGroupPublicData->VFInput.Strands.Common.PointCount);
|
|
|
|
MaxNumPrimIDs += PointCount;
|
|
}
|
|
}
|
|
|
|
if (MaxNumPrimIDs == 0)
|
|
{
|
|
return FRasterForwardCullingOutput();
|
|
}
|
|
const uint32 NodeVisInBytes = 8; // See HairStrandsVisibilityInternal::NodeVis in HairStrandsVisibility.cpp
|
|
const EPixelFormat ControlPointFormat = PF_A32B32G32R32F;
|
|
|
|
FRasterForwardCullingOutput Out;
|
|
Out.Resolution = InResolution;
|
|
Out.NodeIndex = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(Out.Resolution, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource), TEXT("Hair.VisibilityCompactNodeIndex"));
|
|
Out.NodeVis = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(NodeVisInBytes, MaxNumPrimIDs), TEXT("Hair.VisibilityNodeVis"));
|
|
Out.NodeCoord = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxNumPrimIDs), TEXT("Hair.VisibilityNodeCoord"));
|
|
Out.Points = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32)*4u, MaxNumPrimIDs), TEXT("Hair.ControlPoints"));
|
|
Out.PointsSRV = GraphBuilder.CreateSRV(Out.Points, ControlPointFormat);
|
|
Out.PointCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Hair.ControlPointCount"));
|
|
Out.RasterizedInstanceCount = 0;
|
|
|
|
FRDGBufferUAVRef PointsUAV = GraphBuilder.CreateUAV(Out.Points, ControlPointFormat);
|
|
|
|
const uint32 ClearValues[4] = { 0u,0u,0u,0u };
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.PointCount), 0u);
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(Out.NodeIndex), ClearValues);
|
|
|
|
// Create and set the uniform buffer
|
|
const bool bEnableMSAA = false;
|
|
TUniformBufferRef<FViewUniformShaderParameters> ViewUniformShaderParameters;
|
|
SetUpViewHairRenderInfo(ViewInfo, bEnableMSAA, ViewInfo.CachedViewUniformShaderParameters->HairRenderInfo, ViewInfo.CachedViewUniformShaderParameters->HairRenderInfoBits, ViewInfo.CachedViewUniformShaderParameters->HairComponents);
|
|
ViewUniformShaderParameters = TUniformBufferRef<FViewUniformShaderParameters>::CreateUniformBufferImmediate(*ViewInfo.CachedViewUniformShaderParameters, UniformBuffer_SingleFrame);
|
|
|
|
TShaderMapRef<FHairCullSegmentCS> CullShader(ViewInfo.ShaderMap);
|
|
for (const FHairStrandsMacroGroupData& MacroGroup : MacroGroupDatas)
|
|
{
|
|
const FHairStrandsMacroGroupData::TPrimitiveInfos& PrimitiveSceneInfos = MacroGroup.PrimitivesInfos;
|
|
|
|
for (const FHairStrandsMacroGroupData::PrimitiveInfo& PrimitiveInfo : PrimitiveSceneInfos)
|
|
{
|
|
// If a groom is not visible in primary view, but visible in shadow view, its PrimitiveInfo.Mesh will be null.
|
|
if (PrimitiveInfo.Mesh == nullptr || PrimitiveInfo.Mesh->Elements.Num() == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const FHairGroupPublicData* HairGroupPublicData = reinterpret_cast<const FHairGroupPublicData*>(PrimitiveInfo.Mesh->Elements[0].VertexFactoryUserData);
|
|
check(HairGroupPublicData);
|
|
|
|
const bool bCullingEnable = false; //bSupportCulling && GHairVisibilityComputeRaster_Culling ? HairGroupPublicData->GetCullingResultAvailable() : false;
|
|
|
|
// calculate current view screen size - which can result in fewer strands rasterized in current view
|
|
const uint32 CurveCount = HairGroupPublicData->GetActiveStrandsCurveCount();
|
|
const uint32 PointCount = HairGroupPublicData->GetActiveStrandsPointCount();
|
|
|
|
// Curve version
|
|
#if 1
|
|
FHairCullSegmentCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairCullSegmentCS::FParameters>();
|
|
Parameters->OutputResolution = Out.Resolution;
|
|
Parameters->HairMaterialId = PrimitiveInfo.MaterialId;
|
|
Parameters->ControlPointCount = PointCount;
|
|
Parameters->CurveCount = CurveCount;
|
|
Parameters->RWHairVis = GraphBuilder.CreateUAV(Out.NodeVis);
|
|
Parameters->RWCoord = GraphBuilder.CreateUAV(Out.NodeCoord, PF_R16G16_UINT);
|
|
Parameters->RWCounter = GraphBuilder.CreateUAV(Out.PointCount);
|
|
Parameters->RWPoints = PointsUAV;
|
|
Parameters->HairInstance = GetHairStrandsInstanceParameters(GraphBuilder, ViewInfo, HairGroupPublicData, bCullingEnable, bForceRegister);
|
|
Parameters->ViewUniformBuffer = ViewUniformShaderParameters;
|
|
Parameters->SceneDepthTexture = SceneDepthTexture;
|
|
|
|
FIntVector DispatchCount = FComputeShaderUtils::GetGroupCount(CurveCount, 1024);
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("HairStrands::CullSegment(Curves)"),
|
|
CullShader,
|
|
Parameters,
|
|
DispatchCount);
|
|
#endif
|
|
|
|
// Vertex version
|
|
#if 0
|
|
FHairCullSegmentCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairCullSegmentCS::FParameters>();
|
|
Parameters->OutputResolution = Out.Resolution;
|
|
Parameters->HairMaterialId = PrimitiveInfo.MaterialId;
|
|
Parameters->ControlPointCount = VertexCount;
|
|
Parameters->CurveCount = CurveCount;
|
|
Parameters->RWHairVis = GraphBuilder.CreateUAV(Out.NodeVis);
|
|
Parameters->RWCoord = GraphBuilder.CreateUAV(Out.NodeCoord, PF_R16G16_UINT);
|
|
Parameters->RWCounter = GraphBuilder.CreateUAV(Out.PointCount);
|
|
Parameters->RWPoints = GraphBuilder.CreateUAV(Out.Points);
|
|
Parameters->HairInstance = GetHairStrandsInstanceParameters(GraphBuilder, ViewInfo, HairGroupPublicData, bCullingEnable, bForceRegister);
|
|
Parameters->ViewUniformBuffer = ViewUniformShaderParameters;
|
|
Parameters->SceneDepthTexture = SceneDepthTexture;
|
|
|
|
FIntVector DispatchCount = FComputeShaderUtils::GetGroupCount(VertexCount, 1024);
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("HairStrands::CullSegment(Points)"),
|
|
CullShader,
|
|
Parameters,
|
|
DispatchCount);
|
|
#endif
|
|
|
|
++Out.RasterizedInstanceCount;
|
|
}
|
|
}
|
|
|
|
return Out;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// Raster pass
|
|
|
|
void AddHairStrandsForwardRasterPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& ViewInfo,
|
|
const FIntPoint& InResolution,
|
|
const FHairStrandsVisibilityData& InData,
|
|
const FRDGTextureRef SceneDepthTexture,
|
|
const FRDGTextureRef SceneColorTexture,
|
|
const FRDGTextureRef SceneVelocityTexture)
|
|
{
|
|
if (!IsHairStrandsForwardRasterSupported(ViewInfo.GetShaderPlatform()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FIntPoint OutResolution = InResolution;
|
|
|
|
// See the comment on the GHairVisibilityComputeRaster_MaxTiles declaration for an explanation for the large upper bound.
|
|
const uint32 NumBinners = FMath::Min(FMath::Max(GHairVisibilityComputeRaster_NumBinners, 1), 256);
|
|
const uint32 NumRasterizers = FMath::Min(FMath::Max(GHairVisibilityComputeRaster_NumRasterizers, 1), 1024);
|
|
|
|
const uint32 BinTileSize = 32;
|
|
const uint32 RasterTileSize = 8;
|
|
|
|
const FIntPoint BinTileRes = FIntPoint(FMath::DivideAndRoundUp(uint32(InResolution.X), BinTileSize), FMath::DivideAndRoundUp(uint32(InResolution.Y), BinTileSize));
|
|
const FIntPoint RasterTileRes = FIntPoint(FMath::DivideAndRoundUp(uint32(InResolution.X), RasterTileSize), FMath::DivideAndRoundUp(uint32(InResolution.Y), RasterTileSize));
|
|
|
|
struct FBinningData
|
|
{
|
|
// Binned segments
|
|
FRDGBufferRef VisTilePrims;
|
|
FRDGBufferSRVRef VisTilePrimsSRV;
|
|
|
|
FRDGBufferRef VisTilePrimDepths;
|
|
FRDGBufferSRVRef VisTilePrimDepthsSRV;
|
|
|
|
FRDGBufferRef VisTileData;
|
|
FRDGBufferSRVRef VisTileDataSRV;
|
|
|
|
FRDGBufferRef VisTileArgs;
|
|
FRDGBufferUAVRef VisTileArgsUAV;
|
|
FRDGBufferSRVRef VisTileArgsSRV;
|
|
|
|
FRDGTextureRef VisTileBinningGrid;
|
|
FRDGTextureUAVRef VisTileBinningGridUAV;
|
|
|
|
// BinZ Min/Max
|
|
FRDGTextureRef VisTileBinningGridMinZ;
|
|
FRDGTextureRef VisTileBinningGridMaxZ;
|
|
FRDGTextureUAVRef VisTileBinningGridMinZUAV;
|
|
FRDGTextureUAVRef VisTileBinningGridMaxZUAV;
|
|
|
|
// Binned & compacted segments
|
|
FRDGBufferRef CompactedVisTilePrims;
|
|
FRDGBufferRef CompactedVisTileData;
|
|
FRDGBufferRef CompactedVisTileArgs;
|
|
FRDGBufferRef CompactedVisTileWork;
|
|
FRDGBufferRef CompactedVisTileDataCount;
|
|
FRDGBufferRef CompactedVisTileWorkCount;
|
|
};
|
|
|
|
const uint32 EntryCount = 5; // See VT_XXX in .usf: PrimOffset / PrimCount / Coord / MaxIndex / MinMaxDepth
|
|
|
|
FBinningData BinData;
|
|
{
|
|
const uint32 MaxPrimPerTile = 1024u;
|
|
const uint32 BinMaxTiles = FMath::Clamp(GHairVisibilityComputeRaster_MaxTiles, MaxPrimPerTile, 262144); //?
|
|
const uint32 MaxTotalPrims = BinMaxTiles * MaxPrimPerTile; // Number of 'binned' primitives. This number can/needs to be higher than the actual number of primitives, since a primitive can be binned into several bins
|
|
|
|
BinData.VisTilePrims = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxTotalPrims), TEXT("Hair.VisTilePrims"));
|
|
BinData.VisTilePrimsSRV = GraphBuilder.CreateSRV(BinData.VisTilePrims, PF_R32_UINT);
|
|
|
|
BinData.VisTilePrimDepths = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxTotalPrims), TEXT("Hair.VisTilePrimDepths"));
|
|
BinData.VisTilePrimDepthsSRV = GraphBuilder.CreateSRV(BinData.VisTilePrimDepths, PF_R32_UINT);
|
|
|
|
FRDGBufferDesc DescTileData = FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), BinMaxTiles * EntryCount);
|
|
DescTileData.Usage = EBufferUsageFlags(DescTileData.Usage | BUF_ByteAddressBuffer);
|
|
BinData.VisTileData = GraphBuilder.CreateBuffer(DescTileData, TEXT("Hair.VisTileData"));
|
|
BinData.VisTileDataSRV = GraphBuilder.CreateSRV(BinData.VisTileData);
|
|
|
|
FRDGBufferDesc VisTileArgsDesc = FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1);
|
|
BinData.VisTileArgs = GraphBuilder.CreateBuffer(VisTileArgsDesc, TEXT("Hair.VisTileArgs"));
|
|
BinData.VisTileArgsUAV = GraphBuilder.CreateUAV(BinData.VisTileArgs, PF_R32_UINT);
|
|
BinData.VisTileArgsSRV = GraphBuilder.CreateSRV(BinData.VisTileArgs, PF_R32_UINT);
|
|
|
|
BinData.VisTileBinningGrid = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2DArray(BinTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource, NumBinners * 3), TEXT("Hair.VisTileBinningGrid"));
|
|
BinData.VisTileBinningGridUAV = GraphBuilder.CreateUAV(BinData.VisTileBinningGrid);
|
|
|
|
// BinZ Min/Max
|
|
BinData.VisTileBinningGridMinZ = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2DArray(BinTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource, NumBinners * 3), TEXT("Hair.VisTileBinningGridMinZ"));
|
|
BinData.VisTileBinningGridMaxZ = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2DArray(BinTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource, NumBinners * 3), TEXT("Hair.VisTileBinningGridMaxZ"));
|
|
BinData.VisTileBinningGridMinZUAV = GraphBuilder.CreateUAV(BinData.VisTileBinningGridMinZ);
|
|
BinData.VisTileBinningGridMaxZUAV = GraphBuilder.CreateUAV(BinData.VisTileBinningGridMaxZ);
|
|
|
|
BinData.CompactedVisTilePrims = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxTotalPrims), TEXT("Hair.CompactedVisTilePrims"));
|
|
BinData.CompactedVisTileData = GraphBuilder.CreateBuffer(DescTileData, TEXT("Hair.CompactedVisTileData"));
|
|
BinData.CompactedVisTileArgs = GraphBuilder.CreateBuffer(VisTileArgsDesc, TEXT("Hair.CompactedVisTileArgs"));
|
|
BinData.CompactedVisTileWork = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), MaxTotalPrims), TEXT("Hair.CompactedVisTileWork"));
|
|
BinData.CompactedVisTileDataCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Hair.CompactedVisTileDataCount"));
|
|
BinData.CompactedVisTileWorkCount = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Hair.CompactedVisTileWorkCount"));
|
|
}
|
|
|
|
// Create and set the uniform buffer
|
|
TUniformBufferRef<FViewUniformShaderParameters> ViewUniformShaderParameters;
|
|
{
|
|
const bool bEnableMSAA = false;
|
|
SetUpViewHairRenderInfo(ViewInfo, bEnableMSAA, ViewInfo.CachedViewUniformShaderParameters->HairRenderInfo, ViewInfo.CachedViewUniformShaderParameters->HairRenderInfoBits, ViewInfo.CachedViewUniformShaderParameters->HairComponents);
|
|
ViewUniformShaderParameters = TUniformBufferRef<FViewUniformShaderParameters>::CreateUniformBufferImmediate(*ViewInfo.CachedViewUniformShaderParameters, UniformBuffer_SingleFrame);
|
|
}
|
|
|
|
// Common parameters
|
|
FRasterComputeForwardCommonParameters Common;
|
|
{
|
|
Common.OutputResolution = OutResolution;
|
|
Common.OutputResolutionf = FVector2f(OutResolution.X, OutResolution.Y);
|
|
|
|
Common.RasterTileRes = RasterTileRes;
|
|
Common.NumRasterizers = NumRasterizers;
|
|
Common.RcpNumRasterizers = 1.0 / NumRasterizers;
|
|
|
|
Common.BinTileRes = BinTileRes;
|
|
Common.NumBinners = NumBinners;
|
|
Common.RcpNumBinners = 1.0 / NumBinners;
|
|
|
|
Common.MaxControlPointCount = InData.MaxControlPointCount;
|
|
Common.ControlPoints = InData.ControlPointsSRV;
|
|
Common.ControlPointCount = InData.ControlPointCount;
|
|
|
|
Common.RadiusAtDepth1 = ComputeMinStrandRadiusAtDepth1(FIntPoint(ViewInfo.UnconstrainedViewRect.Width(), ViewInfo.UnconstrainedViewRect.Height()), ViewInfo.FOV, 1 /*SampleCount*/, 0 /*ScaleOverride*/, ViewInfo.ViewMatrices.GetOrthoDimensions().X).Primary;
|
|
}
|
|
|
|
// Fill in tile depth
|
|
FRDGTextureRef VisTileDepthGrid = nullptr;
|
|
{
|
|
VisTileDepthGrid = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(BinTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource), TEXT("Hair.VisTileDepthGrid"));
|
|
|
|
TShaderMapRef<FHairStrandsForwardRasterPrepareDepthGridCS> ComputeShaderPrepareDepthGrid(ViewInfo.ShaderMap);
|
|
FHairStrandsForwardRasterPrepareDepthGridCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsForwardRasterPrepareDepthGridCS::FParameters>();
|
|
Parameters->Common = Common;
|
|
Parameters->SceneDepthTexture = SceneDepthTexture;
|
|
Parameters->OutVisTileDepthGrid = GraphBuilder.CreateUAV(VisTileDepthGrid);
|
|
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::VisibilityComputeRasterPrepDepthGrid"), ComputeShaderPrepareDepthGrid, Parameters, FIntVector(BinTileRes.X, BinTileRes.Y, 1));
|
|
}
|
|
|
|
const bool bDebugEnabled = GHairVisibilityComputeRaster_Debug > 0;
|
|
uint32 TotalPrimitiveInfoCount = 1; // TODO = total number of groups
|
|
|
|
if (bDebugEnabled)
|
|
{
|
|
ShaderPrint::SetEnabled(true);
|
|
ShaderPrint::RequestSpaceForTriangles(2 * NumBinners * Common.RasterTileRes.X * Common.RasterTileRes.Y + 2 * NumBinners * 10);
|
|
ShaderPrint::RequestSpaceForLines(4 * 2 * NumBinners * 128);
|
|
}
|
|
|
|
// Reset buffers
|
|
{
|
|
// BinZ Min/Max
|
|
uint32 IndexGridClearMinZ[4] = { 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF };
|
|
uint32 IndexGridClearMaxZ[4] = { 0x0,0x0,0x0,0x0 };
|
|
AddClearUAVPass(GraphBuilder, BinData.VisTileBinningGridMinZUAV, IndexGridClearMinZ);
|
|
AddClearUAVPass(GraphBuilder, BinData.VisTileBinningGridMaxZUAV, IndexGridClearMaxZ);
|
|
|
|
uint32 IndexGridClearValues[4] = { 0x0,0x0,0x0,0x0 };
|
|
AddClearUAVPass(GraphBuilder, BinData.VisTileBinningGridUAV, IndexGridClearValues);
|
|
AddClearUAVPass(GraphBuilder, BinData.VisTileArgsUAV, 0u);
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(BinData.CompactedVisTileArgs, PF_R32_UINT), 0u);
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(BinData.CompactedVisTileDataCount, PF_R32_UINT), 0u);
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(BinData.CompactedVisTileWorkCount, PF_R32_UINT), 0u);
|
|
}
|
|
|
|
// Binning pass
|
|
{
|
|
FHairStrandsForwardRasterBinningCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsForwardRasterBinningCS::FParameters>();
|
|
Parameters->Common = Common;
|
|
Parameters->ViewUniformBuffer = ViewUniformShaderParameters;
|
|
Parameters->OutVisTilePrims = GraphBuilder.CreateUAV(BinData.VisTilePrims, PF_R32_UINT);
|
|
Parameters->OutVisTilePrimDepths = GraphBuilder.CreateUAV(BinData.VisTilePrimDepths, PF_R32_UINT);
|
|
Parameters->OutVisTileBinningGrid = BinData.VisTileBinningGridUAV;
|
|
Parameters->OutVisTileBinningGridMinZ = BinData.VisTileBinningGridMinZUAV;
|
|
Parameters->OutVisTileBinningGridMaxZ = BinData.VisTileBinningGridMaxZUAV;
|
|
Parameters->VisTileDepthGrid = VisTileDepthGrid;
|
|
Parameters->OutVisTileArgs = BinData.VisTileArgsUAV;
|
|
Parameters->OutVisTileData = GraphBuilder.CreateUAV(BinData.VisTileData);
|
|
Parameters->VisTileBinningGridTex = BinData.VisTileBinningGrid;
|
|
ShaderPrint::SetParameters(GraphBuilder, ViewInfo.ShaderPrintData, Parameters->ShaderPrintParameters);
|
|
|
|
FHairStrandsForwardRasterBinningCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FHairStrandsForwardRasterBinningCS::FDebug>(bDebugEnabled);
|
|
TShaderMapRef<FHairStrandsForwardRasterBinningCS> ComputeShaderBinning(ViewInfo.ShaderMap, PermutationVector);
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("HairStrands::VisibilityComputeRasterBinning"),
|
|
ComputeShaderBinning,
|
|
Parameters,
|
|
FIntVector(NumBinners, 1, 1));
|
|
}
|
|
|
|
// Compaction
|
|
{
|
|
FHairStrandsForwardRasterCompactionCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsForwardRasterCompactionCS::FParameters>();
|
|
Parameters->Common = Common;
|
|
Parameters->ViewUniformBuffer = ViewUniformShaderParameters;
|
|
Parameters->InData = BinData.VisTileDataSRV;
|
|
Parameters->InPrims = BinData.VisTilePrimsSRV;
|
|
Parameters->InDepths = BinData.VisTilePrimDepthsSRV;
|
|
Parameters->InArgs = BinData.VisTileArgsSRV;
|
|
Parameters->OutData = GraphBuilder.CreateUAV(BinData.CompactedVisTileData);
|
|
Parameters->OutPrims = GraphBuilder.CreateUAV(BinData.CompactedVisTilePrims, PF_R32_UINT);
|
|
Parameters->OutArgs = GraphBuilder.CreateUAV(BinData.CompactedVisTileArgs, PF_R32_UINT);
|
|
Parameters->OutWork = GraphBuilder.CreateUAV(BinData.CompactedVisTileWork, PF_R32_UINT);
|
|
Parameters->OutDataCount = GraphBuilder.CreateUAV(BinData.CompactedVisTileDataCount, PF_R32_UINT);
|
|
Parameters->OutWorkCount = GraphBuilder.CreateUAV(BinData.CompactedVisTileWorkCount, PF_R32_UINT);
|
|
|
|
ShaderPrint::SetParameters(GraphBuilder, ViewInfo.ShaderPrintData, Parameters->ShaderPrintParameters);
|
|
|
|
FHairStrandsForwardRasterCompactionCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FHairStrandsForwardRasterCompactionCS::FDebug>(bDebugEnabled);
|
|
TShaderMapRef<FHairStrandsForwardRasterCompactionCS> ComputeShaderCompaction(ViewInfo.ShaderMap, PermutationVector);
|
|
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::VisibilityComputeRasterCompaction"), ComputeShaderCompaction, Parameters, FIntVector(BinTileRes.X, BinTileRes.Y, 1));
|
|
}
|
|
|
|
// Debug data
|
|
FRDGTextureRef HairPixelCountPerTile_ForDebug = nullptr;
|
|
FRDGTextureRef HairCountTexture_ForDebug = nullptr;
|
|
if (bDebugEnabled)
|
|
{
|
|
HairPixelCountPerTile_ForDebug = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(RasterTileRes, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource | TexCreate_RenderTargetable), TEXT("Hair.HairPixelTileTexture_ForDebug"));
|
|
HairCountTexture_ForDebug = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(OutResolution, PF_R32_UINT, FClearValueBinding::None, TexCreate_UAV | TexCreate_ShaderResource | TexCreate_RenderTargetable), TEXT("Hair.HairCountTexture_ForDebug"));
|
|
|
|
uint32 ClearValues[4] = { 0,0,0,0 };
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(HairCountTexture_ForDebug), ClearValues);
|
|
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(HairPixelCountPerTile_ForDebug), ClearValues);
|
|
}
|
|
|
|
// Raster pass
|
|
{
|
|
FRDGBufferRef WorkCounter = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Hair.RasterWorkCounter"));
|
|
FRDGBufferUAVRef WorkCounterUAV = GraphBuilder.CreateUAV(WorkCounter, PF_R32_UINT);
|
|
AddClearUAVPass(GraphBuilder, WorkCounterUAV, 0);
|
|
|
|
FHairStrandsForwardRasterRasterizeCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsForwardRasterRasterizeCS::FParameters>();
|
|
Parameters->Common = Common;
|
|
Parameters->ViewUniformBuffer = ViewUniformShaderParameters;
|
|
Parameters->SceneDepthTexture = SceneDepthTexture;
|
|
Parameters->OutHairCountTexture_ForDebug = HairCountTexture_ForDebug ? GraphBuilder.CreateUAV(HairCountTexture_ForDebug) : nullptr;
|
|
Parameters->OutHairPixelCountPerTile_ForDebug = HairPixelCountPerTile_ForDebug ? GraphBuilder.CreateUAV(HairPixelCountPerTile_ForDebug) : nullptr;
|
|
Parameters->SampleLightingViewportResolution = InData.SampleLightingViewportResolution;
|
|
Parameters->SampleLightingTexture = InData.SampleLightingTexture;
|
|
Parameters->SampleVelocityBuffer = InData.ControlPointVelocitySRV;
|
|
Parameters->VisTilePrims = GraphBuilder.CreateSRV(BinData.CompactedVisTilePrims, PF_R32_UINT);
|
|
Parameters->VisTileArgs = GraphBuilder.CreateSRV(BinData.CompactedVisTileArgs, PF_R32_UINT);
|
|
Parameters->VisTileWork = GraphBuilder.CreateSRV(BinData.CompactedVisTileWork, PF_R32_UINT);
|
|
Parameters->VisTileWorkCount = GraphBuilder.CreateSRV(BinData.CompactedVisTileWorkCount, PF_R32_UINT);
|
|
Parameters->VisTileData = GraphBuilder.CreateSRV(BinData.CompactedVisTileData);
|
|
Parameters->OutSceneColorTexture = GraphBuilder.CreateUAV(SceneColorTexture);
|
|
Parameters->OutSceneVelocityTexture = GraphBuilder.CreateUAV(SceneVelocityTexture);
|
|
Parameters->RWWorkCounter = WorkCounterUAV;
|
|
ShaderPrint::SetParameters(GraphBuilder, ViewInfo.ShaderPrintData, Parameters->ShaderPrintParameters);
|
|
|
|
FHairStrandsForwardRasterRasterizeCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FHairStrandsForwardRasterRasterizeCS::FDebug>(bDebugEnabled);
|
|
TShaderMapRef<FHairStrandsForwardRasterRasterizeCS> ComputeShaderRaster(ViewInfo.ShaderMap, PermutationVector);
|
|
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::VisibilityComputeRasterRaster(tiled)"), ComputeShaderRaster, Parameters, FIntVector(NumRasterizers, 1, 1));
|
|
}
|
|
|
|
if (bDebugEnabled)
|
|
{
|
|
FHairStrandsForwardRasterDebugCS::FParameters* Parameters = GraphBuilder.AllocParameters<FHairStrandsForwardRasterDebugCS::FParameters>();
|
|
Parameters->Common = Common;
|
|
Parameters->InstanceCount = InData.RasterizedInstanceCount;
|
|
Parameters->CPUAllocatedTileCount = BinData.VisTileData->Desc.NumElements / EntryCount;
|
|
Parameters->CPUAllocatedCompactedTileCount = BinData.CompactedVisTileData->Desc.NumElements / EntryCount;
|
|
Parameters->VisTileData = GraphBuilder.CreateSRV(BinData.CompactedVisTileData);
|
|
Parameters->VisTileArgs = BinData.VisTileArgsSRV;
|
|
Parameters->CompactedVisTileData = GraphBuilder.CreateSRV(BinData.CompactedVisTileData);
|
|
Parameters->CompactedVisTileArgs = GraphBuilder.CreateSRV(BinData.CompactedVisTileArgs, PF_R32_UINT);
|
|
Parameters->HairCountTexture_ForDebug = HairCountTexture_ForDebug;
|
|
Parameters->HairPixelCountPerTile_ForDebug = HairPixelCountPerTile_ForDebug;
|
|
ShaderPrint::SetParameters(GraphBuilder, ViewInfo.ShaderPrintData, Parameters->ShaderPrintParameters);
|
|
|
|
TShaderMapRef<FHairStrandsForwardRasterDebugCS> DebugComputeShader(ViewInfo.ShaderMap);
|
|
FComputeShaderUtils::AddPass(GraphBuilder, RDG_EVENT_NAME("HairStrands::VisibilityComputeRaster(Debug)"), DebugComputeShader, Parameters, FIntVector(FMath::DivideAndRoundUp(Common.BinTileRes.X, 8), FMath::DivideAndRoundUp(Common.BinTileRes.Y, 8), 1));
|
|
}
|
|
}
|