Files
UnrealEngine/Engine/Plugins/FX/Niagara/Source/NiagaraShader/Private/NiagaraAsyncGpuTraceProviderGsdf.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

162 lines
5.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "NiagaraAsyncGpuTraceProviderGsdf.h"
#include "DataDrivenShaderPlatformInfo.h"
#include "FXRenderingUtils.h"
#include "GlobalShader.h"
#include "NiagaraDistanceFieldHelper.h"
#include "NiagaraGpuComputeDispatchInterface.h"
#include "NiagaraSettings.h"
#include "RenderGraphUtils.h"
#include "SceneInterface.h"
#include "SceneManagement.h"
#include "SceneView.h"
#include "ShaderParameterStruct.h"
static int GNiagaraAsyncGpuTraceGsdfEnabled = 1;
static FAutoConsoleVariableRef CVarNiagaraAsyncGpuTraceGsdfEnabled(
TEXT("fx.Niagara.AsyncGpuTrace.GlobalSdfEnabled"),
GNiagaraAsyncGpuTraceGsdfEnabled,
TEXT("If disabled AsyncGpuTrace will not be supported against Global SDF."),
ECVF_Default
);
class FNiagaraRayMarchGlobalSdfCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FNiagaraRayMarchGlobalSdfCS);
SHADER_USE_PARAMETER_STRUCT(FNiagaraRayMarchGlobalSdfCS, FGlobalShader);
static constexpr uint32 kMaxMarchCount = 16;
static constexpr uint32 kThreadGroupSizeX = 32;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
if (!FGlobalShader::ShouldCompilePermutation(Parameters))
{
return false;
}
if (!DoesPlatformSupportDistanceFields(Parameters.Platform))
{
return false;
}
// the GSDF sampling is only supported with SM5+
if (!IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5))
{
return false;
}
return true;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("MAX_MARCH_COUNT"), kMaxMarchCount);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), kThreadGroupSizeX);
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, NIAGARASHADER_API)
SHADER_PARAMETER_SRV(StructuredBuffer<FNiagaraAsyncGpuTrace>, Traces)
SHADER_PARAMETER_SRV(Buffer<uint>, TraceCounts)
SHADER_PARAMETER_UAV(StructuredBuffer<FNiagaraAsyncGpuTraceResult>, Results)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(FGlobalDistanceFieldParameters2, GlobalDistanceFieldParameters)
SHADER_PARAMETER(uint32, TracesOffset)
SHADER_PARAMETER(uint32, TraceCountsOffset)
SHADER_PARAMETER(uint32, ResultsOffset)
SHADER_PARAMETER(float, DistanceThreshold)
END_SHADER_PARAMETER_STRUCT()
};
IMPLEMENT_GLOBAL_SHADER(FNiagaraRayMarchGlobalSdfCS, "/Plugin/FX/Niagara/Private/NiagaraRayMarchingShaders.usf", "NiagaraRayMarchGlobalSdfCS", SF_Compute);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const FNiagaraAsyncGpuTraceProvider::EProviderType FNiagaraAsyncGpuTraceProviderGsdf::Type = ENDICollisionQuery_AsyncGpuTraceProvider::GSDF;
FNiagaraAsyncGpuTraceProviderGsdf::FNiagaraAsyncGpuTraceProviderGsdf(EShaderPlatform InShaderPlatform, FNiagaraGpuComputeDispatchInterface* Dispatcher)
: FNiagaraAsyncGpuTraceProvider(InShaderPlatform, Dispatcher)
{
}
bool FNiagaraAsyncGpuTraceProviderGsdf::IsSupported()
{
return GNiagaraAsyncGpuTraceGsdfEnabled
&& DoesProjectSupportDistanceFields();
}
bool FNiagaraAsyncGpuTraceProviderGsdf::IsAvailable() const
{
if (!GNiagaraAsyncGpuTraceGsdfEnabled)
{
return false;
}
// check the feature level of the scene. Gsdf sampling requires SM5+
if (Dispatcher->GetSceneInterface()->GetFeatureLevel() < ERHIFeatureLevel::SM5)
{
return false;
}
return true;
}
void FNiagaraAsyncGpuTraceProviderGsdf::PostRenderOpaque(FRHICommandList& RHICmdList, TConstStridedView<FSceneView> Views, TUniformBufferRef<FSceneUniformParameters> SceneUniformBufferRHI, FCollisionGroupHashMap* CollisionGroupHash)
{
if (const FGlobalDistanceFieldParameterData* DistanceFieldData = UE::FXRenderingUtils::GetGlobalDistanceFieldParameterData(Views))
{
m_DistanceFieldData = *DistanceFieldData;
}
else
{
m_DistanceFieldData = {};
}
m_ViewUniformBuffer = Views[0].ViewUniformBuffer;
}
void FNiagaraAsyncGpuTraceProviderGsdf::IssueTraces(FRHICommandList& RHICmdList, const FDispatchRequest& Request, TUniformBufferRef<FSceneUniformParameters> SceneUniformBufferRHI, FCollisionGroupHashMap* CollisionHashMap)
{
check(IsAvailable());
if (Request.MaxTraceCount == 0)
{
return;
}
SCOPED_DRAW_EVENT(RHICmdList, NiagaraIssueTracesGsdf);
TShaderMapRef<FNiagaraRayMarchGlobalSdfCS> TraceShader(GetGlobalShaderMap(ShaderPlatform));
FNiagaraRayMarchGlobalSdfCS::FParameters Params;
Params.View = GetShaderBinding(m_ViewUniformBuffer);
Params.Traces = Request.TracesBuffer->SRV;
Params.TraceCounts = Request.TraceCountsBuffer->SRV;
Params.Results = Request.ResultsBuffer->UAV;
FNiagaraDistanceFieldHelper::SetGlobalDistanceFieldParameters(&m_DistanceFieldData, Params.GlobalDistanceFieldParameters);
Params.TracesOffset = Request.TracesOffset;
Params.TraceCountsOffset = Request.TraceCountsOffset;
Params.ResultsOffset = Request.ResultsOffset;
Params.DistanceThreshold = 1.0f;
SetComputePipelineState(RHICmdList, TraceShader.GetComputeShader());
SetShaderParameters(RHICmdList, TraceShader, TraceShader.GetComputeShader(), Params);
const FIntVector ThreadGroupCount = FComputeShaderUtils::GetGroupCount(Request.MaxTraceCount, FNiagaraRayMarchGlobalSdfCS::kThreadGroupSizeX);
DispatchComputeShader(RHICmdList, TraceShader.GetShader(), ThreadGroupCount.X, ThreadGroupCount.Y, ThreadGroupCount.Z);
UnsetShaderUAVs(RHICmdList, TraceShader, TraceShader.GetComputeShader());
}
void FNiagaraAsyncGpuTraceProviderGsdf::Reset()
{
m_DistanceFieldData = FGlobalDistanceFieldParameterData();
m_ViewUniformBuffer = TUniformBufferRef<FViewUniformShaderParameters>();
}