Files
UnrealEngineUWP/Engine/Shaders/Private/SceneDataMobileWriter.ush
dmitriy dyomin ee2640af09 Fixed instance custom data handling in a mobile specific GPUScene case
[CL 27787969 by dmitriy dyomin in ue5-main branch]
2023-09-12 08:11:04 -04:00

199 lines
6.9 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#ifndef PLATFORM_USES_PRIMITIVE_UBO
#define PLATFORM_USES_PRIMITIVE_UBO 0
#endif
void WriteDataElementUBO(RWStructuredBuffer<float4> Output, uint Offset, uint DataIdx, float4 Data)
{
#if PLATFORM_USES_PRIMITIVE_UBO
uint DataOffset = Offset + DataIdx;
Output[DataOffset] = Data;
#endif
}
//
// Note: layout must match FBatchedPrimitiveShaderData in PrimitiveUniformShaderParameters.cpp
//
void WritePrimitiveDataUBO(RWStructuredBuffer<float4> Output, uint Offset, FPrimitiveSceneData PrimitiveData, uint MeshLODIndex)
{
uint DataIdx = 0;
#if ALLOW_STATIC_LIGHTING
// Pre-computed lighting data
{
float4 LightMapUVScaleBias = float4(1, 1, 0, 0);
float4 ShadowMapUVScaleBias = float4(1, 1, 0, 0);
uint LightmapDataIndex = PrimitiveData.LightmapDataIndex + MeshLODIndex;
if (LightmapDataIndex < GPUSceneNumLightmapDataItems)
{
FLightmapSceneData LightmapData = GetLightmapData(LightmapDataIndex);
LightMapUVScaleBias = LightmapData.LightMapCoordinateScaleBias;
ShadowMapUVScaleBias = LightmapData.ShadowMapCoordinateScaleBias;
}
WriteDataElementUBO(Output, Offset, DataIdx + 0, LightMapUVScaleBias);
WriteDataElementUBO(Output, Offset, DataIdx + 1, ShadowMapUVScaleBias);
WriteDataElementUBO(Output, Offset, DataIdx + 2, float4(asfloat(PrimitiveData.LightmapDataIndex), 0.f, 0.f, 0.f));
DataIdx += 3u;
}
#endif
// TilePosition, Flags
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(LWCGetTile(PrimitiveData.LocalToWorld), asfloat(PrimitiveData.Flags)));
DataIdx += 1u;
}
// LocalToWorld
{
float4x4 LocalToWorld = transpose(PrimitiveData.LocalToWorld.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, LocalToWorld[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, LocalToWorld[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, LocalToWorld[2]);
DataIdx += 3u;
}
// InvNonUniformScale, TODO .w
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.InvNonUniformScale, 0.0));
DataIdx += 1u;
}
// ObjectWorldPosition, Radius
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.ObjectWorldPosition.Offset, PrimitiveData.ObjectRadius));
DataIdx += 1u;
}
// ActorWorldPosition, TODO .w
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.ActorWorldPosition.Offset, 0.0));
DataIdx += 1u;
}
// ObjectOrientation, ObjectBoundsX
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.ObjectOrientation, PrimitiveData.ObjectBoundsX));
DataIdx += 1u;
}
// LocalObjectBoundsMin, ObjectBoundsY
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.LocalObjectBoundsMin, PrimitiveData.ObjectBoundsY));
DataIdx += 1u;
}
// LocalObjectBoundsMax, ObjectBoundsZ
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(PrimitiveData.LocalObjectBoundsMax, PrimitiveData.ObjectBoundsZ));
DataIdx += 1u;
}
// WorldToLocal, TODO compute from LocalToWorld?
{
float4x4 RelativeWorldToLocal = transpose(PrimitiveData.WorldToLocal.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, RelativeWorldToLocal[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, RelativeWorldToLocal[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, RelativeWorldToLocal[2]);
DataIdx += 3u;
}
// PreviousLocalToWorld, TODO make optional
{
float4x4 PreviousLocalToWorld = transpose(PrimitiveData.PreviousLocalToWorld.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, PreviousLocalToWorld[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, PreviousLocalToWorld[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, PreviousLocalToWorld[2]);
DataIdx += 3u;
}
// PreviousWorldToLocal, TODO make optional
{
float4x4 PreviousRelativeWorldToLocal = transpose(PrimitiveData.PreviousWorldToLocal.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, PreviousRelativeWorldToLocal[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, PreviousRelativeWorldToLocal[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, PreviousRelativeWorldToLocal[2]);
DataIdx += 3u;
}
// CustomData, TODO make optional
{
uint NumCustomData = min(NUM_CUSTOM_PRIMITIVE_DATA, BATCHED_PRIMITIVE_DATA_STRIDE_FLOAT4 - DataIdx); //23u
UNROLL
for (uint i = 0; i < NumCustomData; ++i)
{
WriteDataElementUBO(Output, Offset, DataIdx + i, PrimitiveData.CustomPrimitiveData[i]);
}
DataIdx += NumCustomData;
}
}
void WriteInstanceDataUBO(RWStructuredBuffer<float4> Output, uint Offset, uint InstanceId, FInstanceSceneData InstanceData, uint InstanceSceneDataSOAStride)
{
uint DataIdx = 0;
// TilePosition, Flags
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(LWCGetTile(InstanceData.LocalToWorld), asfloat(InstanceData.Flags)));
DataIdx += 1u;
}
// LocalToWorld
{
float4x4 LocalToWorld = transpose(InstanceData.LocalToWorld.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, LocalToWorld[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, LocalToWorld[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, LocalToWorld[2]);
DataIdx += 3u;
}
// InvNonUniformScale, RandomID
{
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(InstanceData.InvNonUniformScale, InstanceData.RandomID));
DataIdx += 1u;
}
// PreviousLocalToWorld
{
float4x4 PrevLocalToWorld = transpose(InstanceData.PrevLocalToWorld.M);
WriteDataElementUBO(Output, Offset, DataIdx + 0, PrevLocalToWorld[0]);
WriteDataElementUBO(Output, Offset, DataIdx + 1, PrevLocalToWorld[1]);
WriteDataElementUBO(Output, Offset, DataIdx + 2, PrevLocalToWorld[2]);
DataIdx += 3u;
}
uint CustomDataCount = 0;
uint InstanceRelativeId = 0;
LoadInstanceRelativeIdAndCustomDataCount(InstanceId, InstanceSceneDataSOAStride, InstanceRelativeId, CustomDataCount);
FInstancePayloadDataOffsets Offsets = GetInstancePayloadDataOffsets(InstanceData.PrimitiveId, InstanceData.Flags, InstanceRelativeId);
#if ALLOW_STATIC_LIGHTING
{
if (Offsets.LightShadowUVBias != INVALID_INSTANCE_PAYLOAD_OFFSET)
{
float4 LightMapAndShadowMapUVBias = LoadInstancePayloadDataElement(Offsets.LightShadowUVBias);
WriteDataElementUBO(Output, Offset, DataIdx + 0, LightMapAndShadowMapUVBias);
}
DataIdx += 1u;
}
#endif
// CustomDataCount, TODO: yzw
{
CustomDataCount = min(CustomDataCount, (BATCHED_INSTANCE_DATA_STRIDE_FLOAT4 - DataIdx - 1u) * 4u);
WriteDataElementUBO(Output, Offset, DataIdx + 0, float4(asfloat(CustomDataCount), 0.f, 0.f, 0.f));
DataIdx += 1u;
}
// TODO: make it optional, doubles instance data size
{
// limited space for instance custom data
InstanceData.CustomDataCount = CustomDataCount;
InstanceData.CustomDataOffset = Offsets.CustomData;
uint CustomDataElements = (CustomDataCount + 3u) >> 2u;
UNROLL
for (uint i = 0; i < CustomDataElements; ++i)
{
float4 CustomData = LoadInstanceCustomDataElement(InstanceData, i);
WriteDataElementUBO(Output, Offset, DataIdx + i, CustomData);
}
}
}