// Copyright Epic Games, Inc. All Rights Reserved. #pragma once // NiagaraParticleAccess // --------------------- // This header provides helpers for accessing Niagara data from any shader type. By default, it declares the data buffers as globals, // but can be altered with some #defines to re-use with buffers that come from a non-global source (such as Vertex Factory params or // static uniform buffers). // // To provide a custom interface to power these functions, add #define USE_GLOBAL_NIAGARA_DATA_BUFFERS 0 and declare the following global // functions before including this header: // * NiagaraGetFloatBuffer - Gets a Buffer that points to the full 32-bit float particle data // * NiagaraGetHalfBuffer - Gets a Buffer that points to the 16-bit float particle data // * NiagaraGetFloatDataStride - Gets a uint32 that describes the stride between float registers (assumed to be the same for both float and half) // * NiagaraGetIntBuffer - Gets a Buffer that points to the int particle data (Optional, see below) // * NiagaraGetIntDataStride - Gets a uint32 that describes the stride between int registers (Optional, see below) // // You can may opt out of providing or declaring the integer data buffer by adding #define ENABLE_NIAGARA_INTDATA_ACCESS 0 before // including this header. If you are not using global Niagara data buffers, you do not need to define the integer data accessors. #ifndef USE_GLOBAL_NIAGARA_DATA_BUFFERS #define USE_GLOBAL_NIAGARA_DATA_BUFFERS 1 #endif #ifndef ENABLE_NIAGARA_INT_DATA_ACCESS #define ENABLE_NIAGARA_INT_DATA_ACCESS 1 #endif #if USE_GLOBAL_NIAGARA_DATA_BUFFERS Buffer NiagaraParticleDataFloat; Buffer NiagaraParticleDataHalf; uint NiagaraFloatDataStride; // NOTE: NiagarGet*Buffer have to be macros (not functions) to appease certain shader platforms #define NiagaraGetFloatBuffer() (NiagaraParticleDataFloat) #define NiagaraGetHalfBuffer() (NiagaraParticleDataHalf) uint NiagaraGetFloatDataStride() { return NiagaraFloatDataStride; } #if ENABLE_NIAGARA_INT_DATA_ACCESS Buffer NiagaraParticleDataInt; uint NiagaraIntDataStride; #define NiagaraGetIntBuffer() (NiagaraParticleDataInt) uint NiagaraGetIntDataStride() { return NiagaraIntDataStride; } #endif #endif bool NiagaraGetIsHalfAndFixupRegister(inout int RegisterIdx) { // this was originally: bool IsHalf = RegisterIdx & (1 << 31); // but the glsl comes out as -2147483648 and this appears to be upsetting some old android glsl compilers. Doing this forces an // unsigned 2147483648u literal into glsl. FORT-286011. const uint HalfBit = (1 << 31); const bool bIsHalf = RegisterIdx & HalfBit; RegisterIdx &= ~HalfBit; return bIsHalf; } float NiagaraGetFloat_Internal(Buffer FloatBuffer, int RegisterIdx, uint ParticleIdx) { return FloatBuffer[RegisterIdx * NiagaraGetFloatDataStride() + ParticleIdx]; } float2 NiagaraGetVec2_Internal(Buffer FloatBuffer, int RegisterIdx, uint ParticleIdx) { return float2(NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 0, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 1, ParticleIdx)); } float3 NiagaraGetVec3_Internal(Buffer FloatBuffer, int RegisterIdx, uint ParticleIdx) { return float3(NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 0, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 1, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 2, ParticleIdx)); } float4 NiagaraGetVec4_Internal(Buffer FloatBuffer, int RegisterIdx, uint ParticleIdx) { return float4(NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 0, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 1, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 2, ParticleIdx), NiagaraGetFloat_Internal(FloatBuffer, RegisterIdx + 3, ParticleIdx)); } float NiagaraGetFloat(int RegisterIdx, uint ParticleIdx) { BRANCH if (NiagaraGetIsHalfAndFixupRegister(RegisterIdx)) { return NiagaraGetFloat_Internal(NiagaraGetHalfBuffer(), RegisterIdx, ParticleIdx); } else { return NiagaraGetFloat_Internal(NiagaraGetFloatBuffer(), RegisterIdx, ParticleIdx); } } float2 NiagaraGetVec2(int RegisterIdx, uint ParticleIdx) { BRANCH if (NiagaraGetIsHalfAndFixupRegister(RegisterIdx)) { return NiagaraGetVec2_Internal(NiagaraGetHalfBuffer(), RegisterIdx, ParticleIdx); } else { return NiagaraGetVec2_Internal(NiagaraGetFloatBuffer(), RegisterIdx, ParticleIdx); } } float3 NiagaraGetVec3(int RegisterIdx, uint ParticleIdx) { BRANCH if (NiagaraGetIsHalfAndFixupRegister(RegisterIdx)) { return NiagaraGetVec3_Internal(NiagaraGetHalfBuffer(), RegisterIdx, ParticleIdx); } else { return NiagaraGetVec3_Internal(NiagaraGetFloatBuffer(), RegisterIdx, ParticleIdx); } } float4 NiagaraGetVec4(int RegisterIdx, uint ParticleIdx) { BRANCH if (NiagaraGetIsHalfAndFixupRegister(RegisterIdx)) { return NiagaraGetVec4_Internal(NiagaraGetHalfBuffer(), RegisterIdx, ParticleIdx); } else { return NiagaraGetVec4_Internal(NiagaraGetFloatBuffer(), RegisterIdx, ParticleIdx); } } float NiagaraSafeGetFloat(int RegisterIdx, uint ParticleIdx, float Default) { // NOTE: Branch to prevent unnecessary loads BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetFloat(RegisterIdx, ParticleIdx); } } float2 NiagaraSafeGetVec2(int RegisterIdx, uint ParticleIdx, float2 Default) { // NOTE: Branch to prevent unnecessary loads BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetVec2(RegisterIdx, ParticleIdx); } } float3 NiagaraSafeGetVec3(int RegisterIdx, uint ParticleIdx, float3 Default) { // NOTE: Branch to prevent unnecessary loads BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetVec3(RegisterIdx, ParticleIdx); } } float4 NiagaraSafeGetVec4(int RegisterIdx, uint ParticleIdx, float4 Default) { // NOTE: Branch to prevent unnecessary loads BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetVec4(RegisterIdx, ParticleIdx); } } #if ENABLE_NIAGARA_INT_DATA_ACCESS int NiagaraGetInt(int RegisterIdx, uint ParticleIdx) { return NiagaraGetIntBuffer()[RegisterIdx * NiagaraGetIntDataStride() + ParticleIdx]; } int2 NiagaraGetInt2(int RegisterIdx, uint ParticleIdx) { return int2(NiagaraGetInt(RegisterIdx + 0, ParticleIdx), NiagaraGetInt(RegisterIdx + 1, ParticleIdx)); } int3 NiagaraGetInt3(int RegisterIdx, uint ParticleIdx) { return int3(NiagaraGetInt(RegisterIdx + 0, ParticleIdx), NiagaraGetInt(RegisterIdx + 1, ParticleIdx), NiagaraGetInt(RegisterIdx + 2, ParticleIdx)); } int4 NiagaraGetInt4(int RegisterIdx, uint ParticleIdx) { return int4(NiagaraGetInt(RegisterIdx + 0, ParticleIdx), NiagaraGetInt(RegisterIdx + 1, ParticleIdx), NiagaraGetInt(RegisterIdx + 2, ParticleIdx), NiagaraGetInt(RegisterIdx + 3, ParticleIdx)); } int NiagaraSafeGetInt(int RegisterIdx, uint ParticleIdx, int Default) { BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetInt(RegisterIdx, ParticleIdx); } } int2 NiagaraSafeGetInt2(int RegisterIdx, uint ParticleIdx, int2 Default) { BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetInt2(RegisterIdx, ParticleIdx); } } int3 NiagaraSafeGetInt3(int RegisterIdx, uint ParticleIdx, int3 Default) { BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetInt3(RegisterIdx, ParticleIdx); } } int4 NiagaraSafeGetInt4(int RegisterIdx, uint ParticleIdx, int4 Default) { BRANCH if (RegisterIdx == -1) { return Default; } else { return NiagaraGetInt4(RegisterIdx, ParticleIdx); } } #endif // ENABLE_NIAGARA_INT_DATA_ACCESS