Files
UnrealEngine/Engine/Plugins/PCG/Shaders/Private/PCGSceneWriter.usf
2025-05-18 13:04:45 +08:00

83 lines
3.0 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
// Scene writer - used to inject final instance data into the GPU Scene. Dispatched in the scene update timeline.
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/GPUScene/GPUSceneWriter.ush"
#include "/Engine/Public/Platform.ush"
uint InPrimitiveIndex;
uint InNumInstancesAllocatedInGPUScene;
uint InInstanceOffset;
StructuredBuffer<uint4> InInstanceData;
StructuredBuffer<uint> InInstanceCustomFloatData;
StructuredBuffer<uint> InWriteCounters;
uint InPrimitiveId;
uint InCustomDataCount;
uint InPayloadDataFlags;
void CullInstance(uint InstanceId)
{
// This will minimally initialize the instance data such that it will be ignored and culled
WriteInstancePrimitiveIdAndFlags(InstanceId, InPrimitiveId, INSTANCE_SCENE_DATA_FLAG_HIDDEN);
}
[numthreads(NUM_THREADS_PER_GROUP, 1, 1)]
void SceneWriter_CS(const uint ThreadId : SV_DispatchThreadID)
{
const uint LocalInstanceId = ThreadId;
if (LocalInstanceId >= InNumInstancesAllocatedInGPUScene)
{
return;
}
// Retrieve the primitive data
FPrimitiveSceneData PrimitiveData = GetPrimitiveData(InPrimitiveId);
const uint InstanceId = PrimitiveData.InstanceSceneDataOffset + LocalInstanceId;
// Cull any instances at tail end (assume all valid instances are written).
if (LocalInstanceId >= InWriteCounters[InPrimitiveIndex])
{
CullInstance(InstanceId);
return;
}
const uint StrideFloat4s = 3;
float4x4 LocalToWorld;
LocalToWorld[0] = asfloat(InInstanceData[(InInstanceOffset + LocalInstanceId) * StrideFloat4s + 0]);
LocalToWorld[1] = asfloat(InInstanceData[(InInstanceOffset + LocalInstanceId) * StrideFloat4s + 1]);
LocalToWorld[2] = asfloat(InInstanceData[(InInstanceOffset + LocalInstanceId) * StrideFloat4s + 2]);
LocalToWorld[3] = float4(0.0f, 0.0f, 0.0f, 1.0f);
LocalToWorld = transpose(LocalToWorld);
InitializeInstanceSceneDataWS(
InstanceId,
InPrimitiveId,
LocalInstanceId,
InPayloadDataFlags,
InCustomDataCount,
/*RandomId=*/0.0f,
DFFromTileOffset(LWCPromote(LocalToWorld))
);
// todo_pcg: We should write local space transforms to the instance data buffer from the SM Spawner and use WriteInstanceLocalToRelativeWorld here instead.
const FDFMatrix Transform = MakeDFMatrix4x3((float3)0.0f, LocalToWorld);
WriteInstanceLocalToWorld(InstanceId, InPrimitiveId, Transform, false);
FInstancePayloadDataOffsets PayloadOffsets = GetInstancePayloadDataOffsets(InPrimitiveId, InPayloadDataFlags, LocalInstanceId);
const uint NumCustomFloat4s = (InCustomDataCount + 3) / 4;
for (uint Float4Index = 0; Float4Index < NumCustomFloat4s; ++Float4Index)
{
const uint BaseIndex = (InInstanceOffset + LocalInstanceId) * InCustomDataCount + Float4Index * 4;
uint4 CustomData;
CustomData[0] = InInstanceCustomFloatData[BaseIndex];
CustomData[1] = InInstanceCustomFloatData[BaseIndex + 1];
CustomData[2] = InInstanceCustomFloatData[BaseIndex + 2];
CustomData[3] = InInstanceCustomFloatData[BaseIndex + 3];
WriteInstanceCustomData(PayloadOffsets, Float4Index, asfloat(CustomData));
}
}