// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= ShaderParameterMacros.h: Macros to builds shader parameter structures and their metadata. =============================================================================*/ #pragma once #include "ShaderParameterStructDeclaration.h" #include "ShaderParameterMetadata.h" #include "RenderGraphAllocator.h" #include "Algo/Reverse.h" #include "Templates/IsArrayOrRefOfTypeByPredicate.h" #include "Traits/IsCharEncodingCompatibleWith.h" #include "Misc/AssertionMacros.h" #include "RHICommandList.h" #include "RenderGraphTextureSubresource.h" PRAGMA_DISABLE_BUFFER_OVERRUN_WARNING class FRDGTexture; class FRDGTextureSRV; class FRDGTextureUAV; class FRDGBuffer; class FRDGBufferSRV; class FRDGBufferUAV; class FRDGUniformBuffer; enum class EShaderBindingLayoutFlags : uint8; class FShaderBindingLayoutContainer; template class TRDGUniformBuffer; /** Alignements tools because alignas() does not work on type in clang. */ template class TAlignedTypedef; #define IMPLEMENT_ALIGNED_TYPE(Alignment) \ template \ class TAlignedTypedef \ { \ public: \ typedef MS_ALIGN(Alignment) T Type GCC_ALIGN(Alignment); \ }; IMPLEMENT_ALIGNED_TYPE(1); IMPLEMENT_ALIGNED_TYPE(2); IMPLEMENT_ALIGNED_TYPE(4); IMPLEMENT_ALIGNED_TYPE(8); IMPLEMENT_ALIGNED_TYPE(16); #undef IMPLEMENT_ALIGNED_TYPE #if PLATFORM_64BITS /** Fixed 8bytes sized and aligned pointer for shader parameters. */ template using TAlignedShaderParameterPtr = typename TAlignedTypedef::Type; static_assert(sizeof(void*) == 8, "Wrong PLATFORM_64BITS settings."); #else //!PLATFORM_64BITS /** Fixed 8bytes sized pointer for shader parameters. */ template class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) TAlignedShaderParameterPtr { public: TAlignedShaderParameterPtr() { } TAlignedShaderParameterPtr(const PtrType& Other) : Ref(Other) { } TAlignedShaderParameterPtr(const TAlignedShaderParameterPtr& Other) : Ref(Other.Ref) { } FORCEINLINE void operator=(const PtrType& Other) { Ref = Other; } FORCEINLINE operator PtrType&() { return Ref; } FORCEINLINE operator const PtrType&() const { return Ref; } FORCEINLINE const PtrType& operator->() const { return Ref; } private: PtrType Ref; #if !PLATFORM_64BITS uint32 _Padding; static_assert(sizeof(void*) == 4, "Wrong PLATFORM_64BITS settings."); #endif static_assert(sizeof(PtrType) == sizeof(void*), "T should be a pointer."); }; #endif // !PLATFORM_64BITS /** Retrieve the metadata of a UB type */ template struct TUniformBufferMetadataHelper { static const FShaderParametersMetadata* GetStructMetadata() { // This uses ADL rather than templates, because template specializations can't be defined in a different namespace return GetForwardDeclaredShaderParametersStructMetadata((UniformBufferStructType*)nullptr); } }; template struct TUniformBufferMetadataHelper::value>::type> { static const FShaderParametersMetadata* GetStructMetadata() { return UniformBufferStructType::FTypeInfo::GetStructMetadata(); } }; /** A reference to a uniform buffer RHI resource with a specific structure. */ template class TUniformBufferRef : public FUniformBufferRHIRef { static_assert(!TIsUECoreVariant::Value, "UniformBufferRHIRef cannot be double core variants! Switch to float variant."); public: /** Initializes the reference to null. */ TUniformBufferRef() = default; /** Construct an instance from an existing RHI uniform buffer pointer. Validates at runtime that the type of the uniform buffer matches the template struct type. */ explicit TUniformBufferRef(FRHIUniformBuffer* InRHIRef) : FUniformBufferRHIRef(InRHIRef) { checkf(!InRHIRef || TUniformBufferMetadataHelper::GetStructMetadata()->GetLayoutPtr() == InRHIRef->GetLayoutPtr(), TEXT("Attempted to create a uniform buffer of type '%s' from uniform buffer pointer of type '%s'"), *TUniformBufferMetadataHelper::GetStructMetadata()->GetLayout().Name, *InRHIRef->GetLayout().Name); } /** Creates a uniform buffer with the given value, and returns a structured reference to it. */ static TUniformBufferRef CreateUniformBufferImmediate(const TBufferStruct& Value, EUniformBufferUsage Usage, EUniformBufferValidation Validation = EUniformBufferValidation::ValidateResources) { return TUniformBufferRef(RHICreateUniformBuffer(&Value, TUniformBufferMetadataHelper::GetStructMetadata()->GetLayoutPtr(), Usage, Validation)); } /** Creates a uniform buffer with the given value, and returns a structured reference to it. */ static TUniformBufferRef CreateEmptyUniformBufferImmediate(EUniformBufferUsage Usage) { return TUniformBufferRef(RHICreateUniformBuffer(nullptr, TUniformBufferMetadataHelper::GetStructMetadata()->GetLayoutPtr(), Usage, EUniformBufferValidation::ValidateResources)); } UE_DEPRECATED(5.3, "UpdateUniformBufferImmediate requires a command list.") void UpdateUniformBufferImmediate(const TBufferStruct& Value) { PRAGMA_DISABLE_DEPRECATION_WARNINGS RHIUpdateUniformBuffer(GetReference(), &Value); PRAGMA_ENABLE_DEPRECATION_WARNINGS } void UpdateUniformBufferImmediate(FRHICommandListBase& RHICmdList, const TBufferStruct& Value) { RHICmdList.UpdateUniformBuffer(GetReference(), &Value); } private: template friend class TUniformBuffer; friend class TRDGUniformBuffer; }; class alignas(SHADER_PARAMETER_STRUCT_ALIGNMENT) FUniformBufferBinding { public: FUniformBufferBinding() = default; FORCEINLINE FRHIUniformBuffer* GetUniformBuffer() const { return UniformBuffer; } FORCEINLINE EUniformBufferBindingFlags GetBindingFlags() const { return BindingFlags; } FORCEINLINE bool IsStatic() const { return EnumHasAnyFlags(BindingFlags, EUniformBufferBindingFlags::Static); } FORCEINLINE bool IsShader() const { return EnumHasAnyFlags(BindingFlags, EUniformBufferBindingFlags::Shader); } FORCEINLINE operator bool() const { return UniformBuffer != nullptr; } protected: FORCEINLINE FUniformBufferBinding(const FUniformBufferRHIRef& InUniformBuffer, EUniformBufferBindingFlags InBindingFlags) : UniformBuffer(InUniformBuffer) , BindingFlags(InBindingFlags) {} private: FRHIUniformBuffer* UniformBuffer = nullptr; EUniformBufferBindingFlags BindingFlags = EUniformBufferBindingFlags::Shader; }; template class alignas(SHADER_PARAMETER_STRUCT_ALIGNMENT) TUniformBufferBinding : public FUniformBufferBinding { public: TUniformBufferBinding() = default; TUniformBufferBinding(const TUniformBufferRef& InUniformBuffer) : FUniformBufferBinding(InUniformBuffer, TUniformBufferMetadataHelper::GetStructMetadata()->GetPreferredBindingFlag()) {} TUniformBufferBinding(const TUniformBufferRef& InUniformBuffer, EUniformBufferBindingFlags InBindingFlags) : FUniformBufferBinding(InUniformBuffer, InBindingFlags) { #if DO_CHECK const auto* StructMetadata = TUniformBufferMetadataHelper::GetStructMetadata(); checkf( EnumHasAllFlags(StructMetadata->GetBindingFlags(), GetBindingFlags()), TEXT("Uniform buffer binding flags don't match those supported by the uniform buffer layout '%s."), StructMetadata->GetStructTypeName()); #endif } FORCEINLINE TUniformBufferRef GetUniformBufferRef() const { return TUniformBufferRef(FUniformBufferBinding::GetUniformBuffer()); } FORCEINLINE TRDGUniformBuffer* operator->() const { return GetUniformBuffer(); } }; template inline TUniformBufferBinding GetStaticBinding(const TUniformBufferRef& InUniformBuffer) { return TUniformBufferBinding(InUniformBuffer, EUniformBufferBindingFlags::Static); } template inline TUniformBufferBinding GetShaderBinding(const TUniformBufferRef& InUniformBuffer) { return TUniformBufferBinding(InUniformBuffer, EUniformBufferBindingFlags::Shader); } class alignas(SHADER_PARAMETER_STRUCT_ALIGNMENT) FRDGUniformBufferBinding { public: FRDGUniformBufferBinding() = default; FORCEINLINE FRDGUniformBuffer* GetUniformBuffer() const { return UniformBuffer; } FORCEINLINE EUniformBufferBindingFlags GetBindingFlags() const { return BindingFlags; } FORCEINLINE bool IsStatic() const { return EnumHasAnyFlags(BindingFlags, EUniformBufferBindingFlags::Static); } FORCEINLINE bool IsShader() const { return EnumHasAnyFlags(BindingFlags, EUniformBufferBindingFlags::Shader); } FORCEINLINE operator bool() const { return UniformBuffer != nullptr; } FORCEINLINE FRDGUniformBuffer* operator->() const { return UniformBuffer; } protected: FRDGUniformBufferBinding(FRDGUniformBuffer* InUniformBuffer, EUniformBufferBindingFlags InBindingFlags) : UniformBuffer(InUniformBuffer) , BindingFlags(InBindingFlags) {} private: FRDGUniformBuffer* UniformBuffer = nullptr; EUniformBufferBindingFlags BindingFlags = EUniformBufferBindingFlags::Shader; }; template class alignas(SHADER_PARAMETER_STRUCT_ALIGNMENT) TRDGUniformBufferBinding : public FRDGUniformBufferBinding { public: TRDGUniformBufferBinding() = default; TRDGUniformBufferBinding(TRDGUniformBuffer* InUniformBuffer) : FRDGUniformBufferBinding(InUniformBuffer, TUniformBufferMetadataHelper::GetStructMetadata()->GetPreferredBindingFlag()) {} TRDGUniformBufferBinding(TRDGUniformBuffer* InUniformBuffer, EUniformBufferBindingFlags InBindingFlags) : FRDGUniformBufferBinding(InUniformBuffer, InBindingFlags) { #if DO_CHECK const auto* StructMetadata = TUniformBufferMetadataHelper::GetStructMetadata(); checkf( EnumHasAllFlags(StructMetadata->GetBindingFlags(), GetBindingFlags()), TEXT("RDG uniform buffer binding flags don't match those supported by the uniform buffer layout '%s."), StructMetadata->GetStructTypeName()); #endif } FORCEINLINE TRDGUniformBuffer* GetUniformBuffer() const { return static_cast*>(FRDGUniformBufferBinding::GetUniformBuffer()); } FORCEINLINE TRDGUniformBuffer* operator->() const { return GetUniformBuffer(); } }; /** Constructs a uniform buffer binding that will utilize the shader binding model. */ template inline TRDGUniformBufferBinding GetShaderBinding(TRDGUniformBuffer* InUniformBuffer) { return TRDGUniformBufferBinding(InUniformBuffer, EUniformBufferBindingFlags::Shader); } /** Constructs a uniform buffer binding that will utilize the static binding model. */ template inline TRDGUniformBufferBinding GetStaticBinding(TRDGUniformBuffer* InUniformBuffer) { return TRDGUniformBufferBinding(InUniformBuffer, EUniformBufferBindingFlags::Static); } class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) FRDGBufferAccess { public: FRDGBufferAccess() = default; FRDGBufferAccess(FRDGBuffer* InBuffer, ERHIAccess InAccess) : Buffer(InBuffer) , Access(InAccess) { check(IsValidAccess(InAccess)); } FORCEINLINE FRDGBuffer* GetBuffer() const { return Buffer; } FORCEINLINE ERHIAccess GetAccess() const { return Access; } FORCEINLINE operator bool() const { return Buffer != nullptr; } FORCEINLINE FRDGBuffer* operator->() const { check(Buffer); return Buffer; } FORCEINLINE operator FRDGBuffer*() const { return Buffer; } FORCEINLINE bool operator==(const FRDGBufferAccess& RHS) const { return Buffer == RHS.Buffer && Access == RHS.Access; } FORCEINLINE bool operator!=(const FRDGBufferAccess& RHS) const { return Buffer != RHS.Buffer || Access != RHS.Access; } private: TAlignedShaderParameterPtr Buffer = nullptr; ERHIAccess Access = ERHIAccess::Unknown; }; template class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) TRDGBufferAccess : public FRDGBufferAccess { public: static_assert(IsValidAccess(InAccess), "Buffer access is invalid."); TRDGBufferAccess() : FRDGBufferAccess(nullptr, InAccess) { check(IsValidAccess(InAccess)); } TRDGBufferAccess(FRDGBuffer* InBuffer) : FRDGBufferAccess(InBuffer, InAccess) {} }; class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) FRDGTextureAccess { public: FRDGTextureAccess() = default; FRDGTextureAccess(FRDGTexture* InTexture, FRDGTextureSubresourceRange InSubresourceRange, ERHIAccess InAccess) : Texture(InTexture) , SubresourceRange(InSubresourceRange) , Access(InAccess) {} RENDERCORE_API FRDGTextureAccess(FRDGTexture* InTexture, ERHIAccess InAccess); RENDERCORE_API FRDGTextureAccess(FRDGTextureSRV* InTextureSRV, ERHIAccess InAccess); RENDERCORE_API FRDGTextureAccess(FRDGTextureUAV* InTextureUAV, ERHIAccess InAccess); FORCEINLINE FRDGTexture* GetTexture() const { return Texture; } FORCEINLINE FRDGTextureSubresourceRange GetSubresourceRange() const { return SubresourceRange; } FORCEINLINE ERHIAccess GetAccess() const { return Access; } FORCEINLINE operator bool() const { return Texture != nullptr; } FORCEINLINE FRDGTexture* operator->() const { check(Texture); return Texture; } FORCEINLINE operator FRDGTexture*() const { return Texture; } FORCEINLINE bool operator==(const FRDGTextureAccess& RHS) const { return Texture == RHS.Texture && Access == RHS.Access; } FORCEINLINE bool operator!=(const FRDGTextureAccess& RHS) const { return Texture != RHS.Texture || Access != RHS.Access; } private: TAlignedShaderParameterPtr Texture = nullptr; FRDGTextureSubresourceRange SubresourceRange; ERHIAccess Access = ERHIAccess::Unknown; }; template class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) TRDGTextureAccess : public FRDGTextureAccess { public: static_assert(IsValidAccess(InAccess), "Texture access is invalid."); TRDGTextureAccess() = default; TRDGTextureAccess(FRDGTexture* InTexture, FRDGTextureSubresourceRange InSubresourceRange) : FRDGTextureAccess(InTexture, InSubresourceRange, InAccess) {} TRDGTextureAccess(FRDGTexture* InTexture) : FRDGTextureAccess(InTexture, InAccess) {} TRDGTextureAccess(FRDGTextureSRV* InTextureSRV) : FRDGTextureAccess(InTextureSRV, InAccess) {} TRDGTextureAccess(FRDGTextureUAV* InTextureUAV) : FRDGTextureAccess(InTextureUAV, InAccess) {} }; template class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) TRDGResourceAccessArray : public TArray { using Super = TArray; public: using Super::Super; private: #if !PLATFORM_64BITS uint32 _Padding; #endif }; using FRDGBufferAccessArray = TRDGResourceAccessArray; using FRDGTextureAccessArray = TRDGResourceAccessArray; /** Render graph information about how to bind a render target. */ struct FRenderTargetBinding { FRenderTargetBinding() = default; FRenderTargetBinding(FRDGTexture* InTexture, ERenderTargetLoadAction InLoadAction, uint8 InMipIndex = 0, int16 InArraySlice = -1) : Texture(InTexture) , LoadAction(InLoadAction) , MipIndex(InMipIndex) , ArraySlice(InArraySlice) { check(Validate()); } FRenderTargetBinding(FRDGTexture* InTexture, FRDGTexture* InResolveTexture, ERenderTargetLoadAction InLoadAction, uint8 InMipIndex = 0, int16 InArraySlice = -1) : Texture(InTexture) , ResolveTexture(InResolveTexture) , LoadAction(InLoadAction) , MipIndex(InMipIndex) , ArraySlice(InArraySlice) { check(Validate()); } FRDGTexture* GetTexture() const { return Texture; } FRDGTexture* GetResolveTexture() const { return ResolveTexture; } ERenderTargetLoadAction GetLoadAction() const { return LoadAction; } uint8 GetMipIndex() const { return MipIndex; } int16 GetArraySlice() const { return ArraySlice; } /** Whether we can merge a render pass using Other into a render pass using this render target binding. */ inline bool CanMergeBefore(const FRenderTargetBinding& Other) const { return Texture == Other.Texture && ResolveTexture == Other.ResolveTexture && Other.LoadAction != ERenderTargetLoadAction::EClear && MipIndex == Other.MipIndex && ArraySlice == Other.ArraySlice; } void SetTexture(FRDGTexture* InTexture) { Texture = InTexture; check(Validate()); } void SetResolveTexture(FRDGTexture* InTexture) { ResolveTexture = InTexture; check(Validate()); } void SetLoadAction(ERenderTargetLoadAction InLoadAction) { LoadAction = InLoadAction; check(Validate()); } void SetMipIndex(uint8 InMipIndex) { MipIndex = InMipIndex; check(Validate()); } void SetArraySlice(int16 InArraySlice) { ArraySlice = InArraySlice; check(Validate()); } UE_DEPRECATED(5.1, "GetMipIndex has been renamed to SetMipIndex.") void GetMipIndex(uint8 InMipIndex) { SetMipIndex(InMipIndex); } private: /** Intentionally kept private to force setting the load action in the constructor. */ TAlignedShaderParameterPtr Texture = nullptr; TAlignedShaderParameterPtr ResolveTexture = nullptr; ERenderTargetLoadAction LoadAction = ERenderTargetLoadAction::ENoAction; uint8 MipIndex = 0; int16 ArraySlice = -1; RENDERCORE_API bool Validate() const; }; /** Render graph information about how to bind a depth-stencil render target. */ struct FDepthStencilBinding { FDepthStencilBinding() = default; /** * Creates a render target binding informations for a depth/stencil texture. * * Notes: Load and store action are on explicit without default values, to force the user to not forget one of these. */ FORCEINLINE FDepthStencilBinding( FRDGTexture* InTexture, ERenderTargetLoadAction InDepthLoadAction, ERenderTargetLoadAction InStencilLoadAction, FExclusiveDepthStencil InDepthStencilAccess) : Texture(InTexture) , ResolveTexture(nullptr) , DepthLoadAction(InDepthLoadAction) , StencilLoadAction(InStencilLoadAction) , DepthStencilAccess(InDepthStencilAccess) { check(Validate()); } FORCEINLINE FDepthStencilBinding( FRDGTexture* InTexture, FRDGTexture* InResolveTexture, ERenderTargetLoadAction InDepthLoadAction, ERenderTargetLoadAction InStencilLoadAction, FExclusiveDepthStencil InDepthStencilAccess) : Texture(InTexture) , ResolveTexture(InResolveTexture) , DepthLoadAction(InDepthLoadAction) , StencilLoadAction(InStencilLoadAction) , DepthStencilAccess(InDepthStencilAccess) { check(Validate()); } FORCEINLINE FDepthStencilBinding( FRDGTexture* InTexture, ERenderTargetLoadAction InDepthLoadAction, FExclusiveDepthStencil InDepthStencilAccess) : Texture(InTexture) , ResolveTexture(nullptr) , DepthLoadAction(InDepthLoadAction) , DepthStencilAccess(InDepthStencilAccess) { check(Validate()); } FORCEINLINE FDepthStencilBinding( FRDGTexture* InTexture, FRDGTexture* InResolveTexture, ERenderTargetLoadAction InDepthLoadAction, FExclusiveDepthStencil InDepthStencilAccess) : Texture(InTexture) , ResolveTexture(InResolveTexture) , DepthLoadAction(InDepthLoadAction) , DepthStencilAccess(InDepthStencilAccess) { check(Validate()); } FORCEINLINE FRDGTexture* GetTexture() const { return Texture; } FORCEINLINE FRDGTexture* GetResolveTexture() const { return ResolveTexture; } FORCEINLINE ERenderTargetLoadAction GetDepthLoadAction() const { return DepthLoadAction; } FORCEINLINE ERenderTargetLoadAction GetStencilLoadAction() const { return StencilLoadAction; } FORCEINLINE FExclusiveDepthStencil GetDepthStencilAccess() const { return DepthStencilAccess; } // Whether we can merge a render pass using @ref Other into a render pass using this depth stencil binding. inline bool CanMergeBefore(const FDepthStencilBinding& Other) const { return Texture == Other.Texture && ResolveTexture == Other.ResolveTexture && Other.DepthLoadAction != ERenderTargetLoadAction::EClear && Other.StencilLoadAction != ERenderTargetLoadAction::EClear && DepthStencilAccess == Other.DepthStencilAccess; } void SetTexture(FRDGTexture* InTexture) { Texture = InTexture; check(Validate()); } void SetResolveTexture(FRDGTexture* InTexture) { ResolveTexture = InTexture; check(Validate()); } void SetDepthStencilAccess(FExclusiveDepthStencil InAccess) { DepthStencilAccess = InAccess; check(Validate()); } void SetDepthLoadAction(ERenderTargetLoadAction InAction) { DepthLoadAction = InAction; check(Validate()); } void SetStencilLoadAction(ERenderTargetLoadAction InAction) { StencilLoadAction = InAction; check(Validate()); } private: /** * All parameters required to bind a depth render target deferred. This are purposefully private to * force the user to call FDepthStencilBinding() constructors. No defaults allowed. */ TAlignedShaderParameterPtr Texture = nullptr; TAlignedShaderParameterPtr ResolveTexture = nullptr; ERenderTargetLoadAction DepthLoadAction = ERenderTargetLoadAction::ENoAction; ERenderTargetLoadAction StencilLoadAction = ERenderTargetLoadAction::ENoAction; FExclusiveDepthStencil DepthStencilAccess = FExclusiveDepthStencil::DepthNop_StencilNop; RENDERCORE_API bool Validate() const; }; /** Special shader parameters type for a pass parameter to setup render targets. */ struct alignas(SHADER_PARAMETER_STRUCT_ALIGNMENT) FRenderTargetBindingSlots { TStaticArray Output; FDepthStencilBinding DepthStencil; FResolveRect ResolveRect; uint32 NumOcclusionQueries = 0; ESubpassHint SubpassHint = ESubpassHint::None; uint8 MultiViewCount = 0; FRDGTexture* ShadingRateTexture = nullptr; /** Accessors for regular output to simplify the syntax to: * * FRenderTargetParameters PassParameters; * PassParameters.RenderTargets.DepthStencil = ... ; * PassParameters.RenderTargets[0] = ... ; */ FRenderTargetBinding& operator[](uint32 Index) { return Output[Index]; } const FRenderTargetBinding& operator[](uint32 Index) const { return Output[Index]; } template void Enumerate(TFunction Function) { for (int32 Index = 0; Index < Output.Num(); Index++) { if (Output[Index].GetTexture()) { Function(Output[Index]); } else { break; } } } template void Enumerate(TFunction Function) const { for (int32 Index = 0; Index < Output.Num(); Index++) { if (Output[Index].GetTexture()) { Function(Output[Index]); } else { break; } } } uint32 GetActiveCount() const { uint32 Count = 0; for (; Output[Count].GetTexture() != nullptr; ++Count) {}; return Count; } bool CanMergeBefore(const FRenderTargetBindingSlots& Other) const { for (int32 Index = 0; Index < MaxSimultaneousRenderTargets; ++Index) { if (!Output[Index].CanMergeBefore(Other.Output[Index])) { return false; } } if (!DepthStencil.CanMergeBefore(Other.DepthStencil)) { return false; } if (ResolveRect != Other.ResolveRect || (NumOcclusionQueries != Other.NumOcclusionQueries && Other.NumOcclusionQueries != 0) || SubpassHint != Other.SubpassHint || MultiViewCount != Other.MultiViewCount || ShadingRateTexture != Other.ShadingRateTexture) { return false; } return true; } struct FTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = FRenderTargetBindingSlots; static inline const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; }; static_assert(sizeof(FRenderTargetBindingSlots) == 256, "FRenderTargetBindingSlots needs to be same size on all platforms."); /** Static array of shader resource shader that is initialized to nullptr. */ template class alignas(SHADER_PARAMETER_POINTER_ALIGNMENT) TShaderResourceParameterArray : public TStaticArray { public: FORCEINLINE TShaderResourceParameterArray() { for (uint32 i = 0; i < NumElements; i++) { (*this)[i] = nullptr; } } }; /** Template to transcode some meta data information for a type not specific to shader parameters API. */ template struct TShaderParameterTypeInfo { /** Defines what the type actually is. */ static constexpr EUniformBufferBaseType BaseType = UBMT_INVALID; /** Defines the number rows and columns for vector or matrix based data typed. */ static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; /** Defines the number of elements in an array fashion. 0 means this is not a TStaticArray, * which therefor means there is 1 element. */ static constexpr int32 NumElements = 0; /** Defines the alignment of the elements in bytes. */ static constexpr int32 Alignment = alignof(TypeParameter); /** Defines whether this element is stored in constant buffer or not. * This informations is usefull to ensure at compile time everything in the * structure get defined at the end of the structure, to reduce as much as possible * the size of the constant buffer. */ static constexpr bool bIsStoredInConstantBuffer = true; /** Type that is actually alligned. */ using TAlignedType = TypeParameter; /** Type that has a multiple of 4 components. */ using TInstancedType = TypeParameter; static const FShaderParametersMetadata* GetStructMetadata() { return TypeParameter::FTypeInfo::GetStructMetadata(); } }; // Compile SHADER_PARAMETER(bool, MyBool), just to give good error message to programmer why they shouldn't do that. template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_BOOL; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 4; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FUintVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_UINT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 4; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FUintVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_INT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 4; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FIntVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 4; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FVector4f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 2; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 8; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FVector4f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 3; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FVector4f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FVector4f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FLinearColor; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_INT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 2; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 8; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FIntVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_UINT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 2; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 8; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FUintVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_INT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 3; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FIntVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_UINT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 3; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FUintVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_INT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FIntVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_UINT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FUintVector4; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_INT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FIntRect; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FQuat4f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template<> struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = UBMT_FLOAT32; static constexpr int32 NumRows = 4; static constexpr int32 NumColumns = 4; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = 16; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TAlignedTypedef::Type; using TInstancedType = FMatrix44f; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template struct TRDGResourceAccessTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_POINTER_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = BufferAccessType; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } static_assert(sizeof(TAlignedType) == SHADER_PARAMETER_POINTER_ALIGNMENT * 2, "Uniform buffer layout must not be platform dependent."); }; template struct TRDGTextureAccessTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_POINTER_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TextureAccessType; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } static_assert(sizeof(TAlignedType) == SHADER_PARAMETER_POINTER_ALIGNMENT * 3, "Uniform buffer layout must not be platform dependent."); }; template struct TShaderParameterTypeInfo { static constexpr EUniformBufferBaseType BaseType = TShaderParameterTypeInfo::BaseType; static constexpr int32 NumRows = TShaderParameterTypeInfo::NumRows; static constexpr int32 NumColumns = TShaderParameterTypeInfo::NumColumns; static constexpr int32 NumElements = InNumElements; static constexpr int32 Alignment = SHADER_PARAMETER_ARRAY_ELEMENT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = TShaderParameterTypeInfo::bIsStoredInConstantBuffer; using TAlignedType = TStaticArray; using TInstancedType = T; static const FShaderParametersMetadata* GetStructMetadata() { return TShaderParameterTypeInfo::GetStructMetadata(); } static_assert(((sizeof(T) % 16) == 0), "Array element size does not satisfy 16 byte alignment requirements. Try packing it with other values in a vector or using SHADER_PARAMETER_SCALAR_ARRAY."); }; template struct TShaderParameterTypeInfo> { static constexpr EUniformBufferBaseType BaseType = TShaderParameterTypeInfo::BaseType; static constexpr int32 NumRows = TShaderParameterTypeInfo::NumRows; static constexpr int32 NumColumns = TShaderParameterTypeInfo::NumColumns; static constexpr int32 NumElements = InNumElements; static constexpr int32 Alignment = SHADER_PARAMETER_ARRAY_ELEMENT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = TShaderParameterTypeInfo::bIsStoredInConstantBuffer; using TAlignedType = TStaticArray; using TInstancedType = T; static const FShaderParametersMetadata* GetStructMetadata() { return TShaderParameterTypeInfo::GetStructMetadata(); } static_assert(((sizeof(T) % 16) == 0), "Array element size does not satisfy 16 byte alignment requirements. Try packing it with other values in a vector or using SHADER_PARAMETER_SCALAR_ARRAY."); }; template struct TShaderResourceParameterTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_POINTER_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TAlignedShaderParameterPtr; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } static_assert(sizeof(TAlignedType) == SHADER_PARAMETER_POINTER_ALIGNMENT, "Uniform buffer layout must not be platform dependent."); }; template struct TShaderResourceParameterTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = InNumElements; static constexpr int32 Alignment = SHADER_PARAMETER_POINTER_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TShaderResourceParameterArray; static const FShaderParametersMetadata* GetStructMetadata() { return nullptr; } }; template struct TShaderParameterTypeInfo> { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_POINTER_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TAlignedShaderParameterPtr>; using TInstancedType = UniformBufferStructType; static const FShaderParametersMetadata* GetStructMetadata() { return TUniformBufferMetadataHelper::GetStructMetadata(); } }; template struct TShaderParameterTypeInfo> { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TUniformBufferBinding; using TInstancedType = UniformBufferStructType; static const FShaderParametersMetadata* GetStructMetadata() { return TUniformBufferMetadataHelper::GetStructMetadata(); } }; template struct TShaderParameterTypeInfo> { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = false; using TAlignedType = TRDGUniformBufferBinding; using TInstancedType = UniformBufferStructType; static const FShaderParametersMetadata* GetStructMetadata() { return TUniformBufferMetadataHelper::GetStructMetadata(); } }; template struct TShaderParameterStructTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = 0; static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = StructType; static const FShaderParametersMetadata* GetStructMetadata() { return StructType::FTypeInfo::GetStructMetadata(); } }; template struct TShaderParameterStructTypeInfo { static constexpr int32 NumRows = 1; static constexpr int32 NumColumns = 1; static constexpr int32 NumElements = InNumElements; static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; static constexpr bool bIsStoredInConstantBuffer = true; using TAlignedType = TStaticArray; static const FShaderParametersMetadata* GetStructMetadata() { return StructType::FTypeInfo::GetStructMetadata(); } }; #define INTERNAL_BEGIN_UNIFORM_BUFFER_STRUCT(DllStorage) \ static DllStorage const FShaderParametersMetadata* GetStructMetadata(); #define INTERNAL_UNIFORM_BUFFER_STRUCT_GET_STRUCT_METADATA(StructTypeName) \ { return StructTypeName::GetStructMetadata(); } #define INTERNAL_SHADER_PARAMETER_GET_STRUCT_METADATA(StructTypeName) \ { \ static FShaderParametersMetadata StaticStructMetadata(\ FShaderParametersMetadata::EUseCase::ShaderParameterStruct, \ EUniformBufferBindingFlags::Shader, \ TEXT(#StructTypeName), \ TEXT(#StructTypeName), \ nullptr, \ nullptr, \ FTypeInfo::FileName, \ FTypeInfo::FileLine, \ sizeof(StructTypeName), \ StructTypeName::zzGetMembers()); \ return &StaticStructMetadata; \ } #define INTERNAL_SHADER_PARAMETER_STRUCT_CREATE_UNIFORM_BUFFER return nullptr; #define INTERNAL_UNIFORM_BUFFER_STRUCT_CREATE_UNIFORM_BUFFER return RHICreateUniformBuffer(&InContents, FTypeInfo::GetStructMetadata()->GetLayoutPtr(), InUsage); /** Begins a uniform buffer struct declaration. */ #define INTERNAL_SHADER_PARAMETER_STRUCT_BEGIN(StructTypeName,DllStorage,ConstructorSuffix,GetStructMetadataScope,CreateUniformBufferImpl) \ MS_ALIGN(SHADER_PARAMETER_STRUCT_ALIGNMENT) class StructTypeName \ { \ public: \ DllStorage StructTypeName () ConstructorSuffix \ struct FTypeInfo { \ static constexpr int32 NumRows = 1; \ static constexpr int32 NumColumns = 1; \ static constexpr int32 NumElements = 0; \ static constexpr int32 Alignment = SHADER_PARAMETER_STRUCT_ALIGNMENT; \ static constexpr bool bIsStoredInConstantBuffer = true; \ static constexpr const ANSICHAR* const FileName = UE_LOG_SOURCE_FILE(__builtin_FILE()); \ static constexpr int32 FileLine = __builtin_LINE(); \ using TAlignedType = StructTypeName; \ static const FShaderParametersMetadata* GetStructMetadata() GetStructMetadataScope \ }; \ static FUniformBufferRHIRef CreateUniformBuffer(const StructTypeName& InContents, EUniformBufferUsage InUsage) \ { \ CreateUniformBufferImpl \ } \ private: \ typedef StructTypeName zzTThisStruct; \ struct zzFirstMemberId { enum { HasDeclaredResource = 0 }; }; \ typedef void* zzFuncPtr; \ typedef zzFuncPtr(*zzMemberFunc)(zzFirstMemberId, TArray*); \ static zzFuncPtr zzAppendMemberGetPrev(zzFirstMemberId, TArray*) \ { \ return nullptr; \ } \ typedef zzFirstMemberId /** Declares a member of a uniform buffer struct. */ #define INTERNAL_SHADER_PARAMETER_EXPLICIT(BaseType,TypeInfo,MemberType,MemberName,ArrayDecl,DefaultValue,Precision,OptionalShaderType,IsMemberStruct) \ zzMemberId##MemberName; \ public: \ alignas(TypeInfo::Alignment) TypeInfo::TAlignedType MemberName DefaultValue; \ static_assert(BaseType != UBMT_INVALID, "Invalid type " #MemberType " of member " #MemberName "."); \ private: \ struct zzNextMemberId##MemberName { enum { HasDeclaredResource = zzMemberId##MemberName::HasDeclaredResource || !TypeInfo::bIsStoredInConstantBuffer }; }; \ static zzFuncPtr zzAppendMemberGetPrev(zzNextMemberId##MemberName, TArray* Members) \ { \ static_assert(TypeInfo::bIsStoredInConstantBuffer || TIsArrayOrRefOfTypeByPredicate::Value, "No shader type for " #MemberName "."); \ static_assert(\ (STRUCT_OFFSET(zzTThisStruct, MemberName) & (TypeInfo::Alignment - 1)) == 0, \ "Misaligned uniform buffer struct member " #MemberName "."); \ Members->Add(FShaderParametersMetadata::FMember( \ TEXT(#MemberName), \ (const TCHAR*)OptionalShaderType, \ __LINE__, \ STRUCT_OFFSET(zzTThisStruct,MemberName), \ EUniformBufferBaseType(BaseType), \ Precision, \ TypeInfo::NumRows, \ TypeInfo::NumColumns, \ TypeInfo::NumElements, \ TypeInfo::GetStructMetadata() \ )); \ zzFuncPtr(*PrevFunc)(zzMemberId##MemberName, TArray*); \ PrevFunc = zzAppendMemberGetPrev; \ return (zzFuncPtr)PrevFunc; \ } \ typedef zzNextMemberId##MemberName /** Finds the FShaderParametersMetadata corresponding to the given name, or NULL if not found. */ extern RENDERCORE_API FShaderParametersMetadata* FindUniformBufferStructByName(const TCHAR* StructName); extern RENDERCORE_API FShaderParametersMetadata* FindUniformBufferStructByFName(FName StructName); /** Finds the FShaderParameterMetadata corresponding to the given uniform buffer layout hash, or null if not found. */ extern RENDERCORE_API FShaderParametersMetadata* FindUniformBufferStructByLayoutHash(uint32 Hash); extern RENDERCORE_API FShaderParametersMetadata* FindUniformBufferStructByShaderVariableName(const FHashedName& Name); /** Build the shader binding layout desc from array of used Uniform buffers which will be bound as static uniform buffers to the rhi */ extern RENDERCORE_API void BuildShaderBindingLayout(TConstArrayView UniformBuffers, EShaderBindingLayoutFlags BaseShaderBindingLayoutFlags, FShaderBindingLayoutContainer& OutShaderBindingLayoutContainer); /** Begins & ends a shader parameter structure. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FMyParameterStruct, RENDERER_API) * END_SHADER_PARAMETER_STRUCT() */ #define BEGIN_SHADER_PARAMETER_STRUCT(StructTypeName, DllStorage) \ INTERNAL_SHADER_PARAMETER_STRUCT_BEGIN(StructTypeName,, {}, INTERNAL_SHADER_PARAMETER_GET_STRUCT_METADATA(StructTypeName), INTERNAL_SHADER_PARAMETER_STRUCT_CREATE_UNIFORM_BUFFER) #define END_SHADER_PARAMETER_STRUCT() \ zzLastMemberId; \ public: \ static TArray zzGetMembers() { \ TArray Members; \ zzFuncPtr(*LastFunc)(zzLastMemberId, TArray*); \ LastFunc = zzAppendMemberGetPrev; \ zzFuncPtr Ptr = (zzFuncPtr)LastFunc; \ do \ { \ Ptr = reinterpret_cast(Ptr)(zzFirstMemberId(), &Members); \ } while (Ptr); \ Algo::Reverse(Members); \ return Members; \ } \ } GCC_ALIGN(SHADER_PARAMETER_STRUCT_ALIGNMENT); /** Begins & ends a shader global parameter structure. * * Example: * // header * BEGIN_UNIFORM_BUFFER_STRUCT(FMyParameterStruct, RENDERER_API) * END_UNIFORM_BUFFER_STRUCT() * * // C++ file * IMPLEMENT_UNIFORM_BUFFER_STRUCT(FMyParameterStruct, "MyShaderBindingName"); */ #define BEGIN_UNIFORM_BUFFER_STRUCT(StructTypeName, DllStorage) \ DECLARE_UNIFORM_BUFFER_STRUCT(StructTypeName, DllStorage) \ INTERNAL_SHADER_PARAMETER_STRUCT_BEGIN(StructTypeName,,{} INTERNAL_BEGIN_UNIFORM_BUFFER_STRUCT(DllStorage), INTERNAL_UNIFORM_BUFFER_STRUCT_GET_STRUCT_METADATA(StructTypeName), INTERNAL_UNIFORM_BUFFER_STRUCT_CREATE_UNIFORM_BUFFER) #define BEGIN_UNIFORM_BUFFER_STRUCT_WITH_CONSTRUCTOR(StructTypeName, DllStorage) \ DECLARE_UNIFORM_BUFFER_STRUCT(StructTypeName, DllStorage) \ INTERNAL_SHADER_PARAMETER_STRUCT_BEGIN(StructTypeName,DllStorage,; INTERNAL_BEGIN_UNIFORM_BUFFER_STRUCT(DllStorage), INTERNAL_UNIFORM_BUFFER_STRUCT_GET_STRUCT_METADATA(StructTypeName), INTERNAL_UNIFORM_BUFFER_STRUCT_CREATE_UNIFORM_BUFFER) #define END_UNIFORM_BUFFER_STRUCT() \ END_SHADER_PARAMETER_STRUCT() class FShaderParametersMetadataRegistration { public: FShaderParametersMetadataRegistration(TFunctionRef LazyShaderParametersMetadataAccessor) : LazyShaderParametersMetadataAccessor(LazyShaderParametersMetadataAccessor) { GetInstances().Add(this); } static RENDERCORE_API TArray& GetInstances(); // Actually register all the instances and clear the array static RENDERCORE_API void CommitAll(); static RENDERCORE_API bool IsReadyForRegistration(); private: TFunctionRef LazyShaderParametersMetadataAccessor; }; #define IMPLEMENT_UNIFORM_BUFFER_STRUCT_EX(StructTypeName,ShaderVariableName,UsageFlags) \ const FShaderParametersMetadata* GetForwardDeclaredShaderParametersStructMetadata(const StructTypeName* DummyPtr) { return StructTypeName::FTypeInfo::GetStructMetadata(); } \ const FShaderParametersMetadata* StructTypeName::GetStructMetadata() \ { \ ensureMsgf(FShaderParametersMetadataRegistration::IsReadyForRegistration(), TEXT("GetStructMetadata should not be called from a static initializer")); \ static const FShaderParametersMetadata StaticStructMetadata( \ FShaderParametersMetadata::EUseCase::UniformBuffer, \ EUniformBufferBindingFlags::Shader, \ TEXT(#StructTypeName), \ TEXT(#StructTypeName), \ TEXT(ShaderVariableName), \ nullptr, \ StructTypeName::FTypeInfo::FileName, \ StructTypeName::FTypeInfo::FileLine, \ sizeof(StructTypeName), \ StructTypeName::zzGetMembers(), \ false, \ nullptr, \ UsageFlags); \ return &StaticStructMetadata; \ } \ FShaderParametersMetadataRegistration StructTypeName##MetadataRegistration { TFunctionRef{StructTypeName::GetStructMetadata} }; #define IMPLEMENT_UNIFORM_BUFFER_STRUCT(StructTypeName,ShaderVariableName) \ IMPLEMENT_UNIFORM_BUFFER_STRUCT_EX(StructTypeName,ShaderVariableName,FShaderParametersMetadata::EUsageFlags::None) #define IMPLEMENT_UNIFORM_BUFFER_ALIAS_STRUCT(StructTypeName, UniformBufferAlias) \ static const FShaderParametersMetadata UniformBufferAlias( \ FShaderParametersMetadata::EUseCase::UniformBuffer, \ EUniformBufferBindingFlags::Shader, \ TEXT(#StructTypeName), \ TEXT(#StructTypeName), \ TEXT(#UniformBufferAlias), \ nullptr, \ StructTypeName::FTypeInfo::FileName, \ StructTypeName::FTypeInfo::FileLine, \ sizeof(StructTypeName), \ StructTypeName::zzGetMembers()) #define IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT_EX(StructTypeName,ShaderVariableName,StaticSlotName,BindingFlagsEnum) \ static_assert(EnumHasAnyFlags(EUniformBufferBindingFlags::BindingFlagsEnum, EUniformBufferBindingFlags::Static), "Shader bindings must include 'Static'."); \ const FShaderParametersMetadata* GetForwardDeclaredShaderParametersStructMetadata(const StructTypeName* DummyPtr) { return StructTypeName::FTypeInfo::GetStructMetadata(); } \ const FShaderParametersMetadata* StructTypeName::GetStructMetadata() \ { \ ensureMsgf(FShaderParametersMetadataRegistration::IsReadyForRegistration(), TEXT("GetStructMetadata should not be called from a static initializer")); \ static const FShaderParametersMetadata StaticStructMetadata( \ FShaderParametersMetadata::EUseCase::UniformBuffer, \ EUniformBufferBindingFlags::BindingFlagsEnum, \ TEXT(#StructTypeName), \ TEXT(#StructTypeName), \ TEXT(ShaderVariableName), \ TEXT(#StaticSlotName), \ StructTypeName::FTypeInfo::FileName, \ StructTypeName::FTypeInfo::FileLine, \ sizeof(StructTypeName), \ StructTypeName::zzGetMembers()); \ return &StaticStructMetadata; \ } \ FShaderParametersMetadataRegistration StructTypeName##MetadataRegistration { TFunctionRef{StructTypeName::GetStructMetadata} }; #define IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT_EX2(StructTypeName,ShaderVariableName,StaticSlotName,BindingFlagsEnum,UsageFlags) \ static_assert(EnumHasAnyFlags(EUniformBufferBindingFlags::BindingFlagsEnum, EUniformBufferBindingFlags::Static), "Shader bindings must include 'Static'."); \ const FShaderParametersMetadata* GetForwardDeclaredShaderParametersStructMetadata(const StructTypeName* DummyPtr) { return StructTypeName::FTypeInfo::GetStructMetadata(); } \ const FShaderParametersMetadata* StructTypeName::GetStructMetadata() \ { \ ensureMsgf(FShaderParametersMetadataRegistration::IsReadyForRegistration(), TEXT("GetStructMetadata should not be called from a static initializer")); \ static const FShaderParametersMetadata StaticStructMetadata( \ FShaderParametersMetadata::EUseCase::UniformBuffer, \ EUniformBufferBindingFlags::BindingFlagsEnum, \ TEXT(#StructTypeName), \ TEXT(#StructTypeName), \ TEXT(ShaderVariableName), \ TEXT(#StaticSlotName), \ StructTypeName::FTypeInfo::FileName, \ StructTypeName::FTypeInfo::FileLine, \ sizeof(StructTypeName), \ StructTypeName::zzGetMembers(), \ false, \ nullptr, \ UsageFlags); \ return &StaticStructMetadata; \ } \ FShaderParametersMetadataRegistration StructTypeName##MetadataRegistration { TFunctionRef{StructTypeName::GetStructMetadata} }; /** Implements the same contract as IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT, with the addition of the 'StaticAndShader' binding * flag. This means that the uniform buffer may be bound statically or through SetShaderParameters. The uniform buffer is NOT * removed from the parameter map, which means it is possible to end up with both global and shader bindings. The RHI validation * layer will catch and report these cases, as they are both inefficient and would produce confusing behavior if the two bindings * differ. Only one binding model should be used at a time. */ #define IMPLEMENT_STATIC_AND_SHADER_UNIFORM_BUFFER_STRUCT(StructTypeName,ShaderVariableName,StaticSlotName) \ IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT_EX(StructTypeName, ShaderVariableName, StaticSlotName, StaticAndShader) #define IMPLEMENT_STATIC_AND_SHADER_UNIFORM_BUFFER_STRUCT_EX(StructTypeName,ShaderVariableName,StaticSlotName,UsageFlags) \ IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT_EX2(StructTypeName, ShaderVariableName, StaticSlotName, StaticAndShader, UsageFlags) /** Implements a uniform buffer tied to a static binding slot. The third parameter is the name of the slot. * Multiple uniform buffers can be associated to a slot; only one uniform buffer can be bound to a slot * at one time. * * Example: * BEGIN_UNIFORM_BUFFER_STRUCT(FMyParameterStruct, RENDERER_API) * END_UNIFORM_BUFFER_STRUCT() * * // C++ file * * // Define uniform buffer slot. * IMPLEMENT_STATIC_UNIFORM_BUFFER_SLOT(MySlot) * * // Associate uniform buffer with slot. * IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(FMyParameterStruct, "MyShaderBindingName", MySlot); */ #define IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(StructTypeName,ShaderVariableName,StaticSlotName) \ IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT_EX(StructTypeName, ShaderVariableName, StaticSlotName, Static) /** Implements a uniform buffer static binding slot. */ #define IMPLEMENT_STATIC_UNIFORM_BUFFER_SLOT(SlotName) \ static FUniformBufferStaticSlotRegistrar UniformBufferStaticSlot_##SlotName(TEXT(#SlotName)); /** Legacy macro definitions. */ #define BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT \ BEGIN_UNIFORM_BUFFER_STRUCT #define BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT_WITH_CONSTRUCTOR \ BEGIN_UNIFORM_BUFFER_STRUCT_WITH_CONSTRUCTOR #define END_GLOBAL_SHADER_PARAMETER_STRUCT \ END_UNIFORM_BUFFER_STRUCT #define IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT \ IMPLEMENT_UNIFORM_BUFFER_STRUCT #define IMPLEMENT_GLOBAL_SHADER_PARAMETER_ALIAS_STRUCT \ IMPLEMENT_UNIFORM_BUFFER_ALIAS_STRUCT /** Adds a constant-buffer stored value. * * Example: * SHADER_PARAMETER(float, MyScalar) * SHADER_PARAMETER(FMatrix44f, MyMatrix) */ #define SHADER_PARAMETER(MemberType,MemberName) \ SHADER_PARAMETER_EX(MemberType,MemberName,EShaderPrecisionModifier::Float) #define SHADER_PARAMETER_EX(MemberType,MemberName,Precision) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(TShaderParameterTypeInfo::BaseType, TShaderParameterTypeInfo, MemberType,MemberName,,,Precision,TEXT(""),false) /** Adds a constant-buffer stored array of values. * MemberType size must be a multiple of 16byte (see SHADER_PARAMETER_SCALAR_ARRAY for scalar arrays). * * Example: * SHADER_PARAMETER_ARRAY(FMatrix44f, MyMatrixArray, [2]) */ #define SHADER_PARAMETER_ARRAY(MemberType,MemberName,ArrayDecl) \ SHADER_PARAMETER_ARRAY_EX(MemberType,MemberName,ArrayDecl,EShaderPrecisionModifier::Float) #define SHADER_PARAMETER_ARRAY_EX(MemberType,MemberName,ArrayDecl,Precision) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(TShaderParameterTypeInfo::BaseType, TShaderParameterTypeInfo, MemberType,MemberName,ArrayDecl,,Precision,TEXT(""),false) /** Adds a texture. * * Example: * SHADER_PARAMETER_TEXTURE(Texture2D, MyTexture) * SHADER_PARAMETER_TEXTURE_ARRAY(Texture2D, MyArrayOfTextures, [8]) */ #define SHADER_PARAMETER_TEXTURE(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_TEXTURE, TShaderResourceParameterTypeInfo, FRHITexture*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_TEXTURE_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_TEXTURE, TShaderResourceParameterTypeInfo, FRHITexture*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a shader resource view. * * Example: * SHADER_PARAMETER_SRV(Texture2D, MySRV) * SHADER_PARAMETER_SRV_ARRAY(Texture2D, MyArrayOfSRVs, [8]) */ #define SHADER_PARAMETER_SRV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_SRV, TShaderResourceParameterTypeInfo, FRHIShaderResourceView*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_SRV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_SRV, TShaderResourceParameterTypeInfo, FRHIShaderResourceView*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds an unordered access view. * * Example: * SHADER_PARAMETER_UAV(RWTexture2D, MyUAV) */ #define SHADER_PARAMETER_UAV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_UAV, TShaderResourceParameterTypeInfo, FRHIUnorderedAccessView*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a sampler. * * Example: * SHADER_PARAMETER_SAMPLER(SamplerState, MySampler) * SHADER_PARAMETER_SAMPLER_ARRAY(SamplerState, MyArrayOfSamplers, [8]) */ #define SHADER_PARAMETER_SAMPLER(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_SAMPLER, TShaderResourceParameterTypeInfo, FRHISamplerState*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_SAMPLER_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_SAMPLER, TShaderResourceParameterTypeInfo, FRHISamplerState*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a render graph tracked texture. * * Example: * SHADER_PARAMETER_RDG_TEXTURE(Texture2D, MyTexture) * SHADER_PARAMETER_RDG_TEXTURE_ARRAY(Texture2D, MyArrayOfTextures, [4]) */ #define SHADER_PARAMETER_RDG_TEXTURE(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE, TShaderResourceParameterTypeInfo, FRDGTexture*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_TEXTURE_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE, TShaderResourceParameterTypeInfo, FRDGTexture*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a shader resource view for a render graph tracked texture. * * Example: * SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, MySRV) * SHADER_PARAMETER_RDG_TEXTURE_SRV_ARRAY(Texture2D, MyArrayOfSRVs, [4]) */ #define SHADER_PARAMETER_RDG_TEXTURE_SRV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_SRV, TShaderResourceParameterTypeInfo, FRDGTextureSRV*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_TEXTURE_SRV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_SRV, TShaderResourceParameterTypeInfo, FRDGTextureSRV*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a non-pixel shader resource view for a render graph tracked texture. * * Example: * SHADER_PARAMETER_RDG_TEXTURE_NON_PIXEL_SRV(Texture2D, MySRV) * SHADER_PARAMETER_RDG_TEXTURE_NON_PIXEL_SRV_ARRAY(Texture2D, MyArrayOfSRVs, [4]) */ #define SHADER_PARAMETER_RDG_TEXTURE_NON_PIXEL_SRV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_NON_PIXEL_SRV, TShaderResourceParameterTypeInfo, FRDGTextureSRV*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_TEXTURE_NON_PIXEL_SRV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_NON_PIXEL_SRV, TShaderResourceParameterTypeInfo, FRDGTextureSRV*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a unordered access view for a render graph tracked texture. * * Example: * SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, MyUAV) * SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(Texture2D, MyArrayOfUAVs, [4]) */ #define SHADER_PARAMETER_RDG_TEXTURE_UAV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_UAV, TShaderResourceParameterTypeInfo, FRDGTextureUAV*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_UAV, TShaderResourceParameterTypeInfo, FRDGTextureUAV*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a shader resource view for a render graph tracked buffer. * * Example: * SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, MySRV) * SHADER_PARAMETER_RDG_BUFFER_SRV_ARRAY(Buffer, MyArrayOfSRVs, [4]) */ #define SHADER_PARAMETER_RDG_BUFFER_SRV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_SRV, TShaderResourceParameterTypeInfo, FRDGBufferSRV*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_BUFFER_SRV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_SRV, TShaderResourceParameterTypeInfo, FRDGBufferSRV*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a unordered access view for a render graph tracked buffer. * * Example: * SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, MyUAV) * SHADER_PARAMETER_RDG_BUFFER_UAV_ARRAY(RWBuffer, MyArrayOfUAVs, [4]) */ #define SHADER_PARAMETER_RDG_BUFFER_UAV(ShaderType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_UAV, TShaderResourceParameterTypeInfo, FRDGBufferUAV*,MemberName,, = nullptr,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) #define SHADER_PARAMETER_RDG_BUFFER_UAV_ARRAY(ShaderType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_UAV, TShaderResourceParameterTypeInfo, FRDGBufferUAV*,MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#ShaderType),false) /** Adds a render graph tracked uniform buffer. * * Example: * SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FMyStruct, MemberName) */ #define SHADER_PARAMETER_RDG_UNIFORM_BUFFER(StructType, MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_UNIFORM_BUFFER, TShaderParameterTypeInfo>, TRDGUniformBufferBinding,MemberName,,,EShaderPrecisionModifier::Float,TEXT(#StructType),false) /** Nests a shader parameter structure into another one, in C++ and shader code. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FMyNestedStruct,) * SHADER_PARAMETER(float, MyScalar) * // ... * END_SHADER_PARAMETER_STRUCT() * * BEGIN_SHADER_PARAMETER_STRUCT(FOtherStruct) * SHADER_PARAMETER_STRUCT(FMyNestedStruct, MyStruct) * * C++ use case: * FOtherStruct Parameters; * Parameters.MyStruct.MyScalar = 1.0f; * * Shader code for a globally named shader parameter struct: * float MyScalar = MyGlobalShaderBindingName.MyStruct.MyScalar; * * Shader code for a unnamed shader parameter struct: * float MyScalar = MyStruct_MyScalar; */ #define SHADER_PARAMETER_STRUCT(StructType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_NESTED_STRUCT, StructType::FTypeInfo, StructType, MemberName,,,EShaderPrecisionModifier::Float,TEXT(#StructType),true) /** Nests an array of shader parameter structure into another one, in C++ and shader code. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FMyNestedStruct,) * SHADER_PARAMETER(float, MyScalar) * // ... * END_SHADER_PARAMETER_STRUCT() * * BEGIN_SHADER_PARAMETER_STRUCT(FOtherStruct) * SHADER_PARAMETER_STRUCT_ARRAY(FMyNestedStruct, MyStructArray, [4]) * * C++ use case: * FOtherStruct Parameters; * Parameters.MyStructArray[0].MyScalar = 1.0f; * * Shader code for a globally named shader parameter struct (UNSUPPORTED): * float MyScalar = MyGlobalShaderBindingName.MyStructArray_0.MyScalar; * * Shader code for a unnamed shader parameter struct: * float MyScalar = MyStructArray_0_MyScalar; */ #define SHADER_PARAMETER_STRUCT_ARRAY(StructType,MemberName, ArrayDecl) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_NESTED_STRUCT, TShaderParameterStructTypeInfo, StructType, MemberName,ArrayDecl,,EShaderPrecisionModifier::Float,TEXT(#StructType),true) /** Include a shader parameter structure into another one in shader code. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FMyNestedStruct,) * SHADER_PARAMETER(float, MyScalar) * // ... * END_SHADER_PARAMETER_STRUCT() * * BEGIN_SHADER_PARAMETER_STRUCT(FOtherStruct) * SHADER_PARAMETER_STRUCT_INCLUDE(FMyNestedStruct, MyStruct) * * C++ use case: * FOtherStruct Parameters; * Parameters.MyStruct.MyScalar = 1.0f; * * Shader code for a globally named shader parameter struct: * float MyScalar = MyGlobalShaderBindingName.MyScalar; * * Shader code for a unnamed shader parameter struct: * float MyScalarValue = MyScalar; */ #define SHADER_PARAMETER_STRUCT_INCLUDE(StructType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_INCLUDED_STRUCT, StructType::FTypeInfo, StructType, MemberName,,,EShaderPrecisionModifier::Float,TEXT(#StructType),true) /** Include a binding slot for a globally named shader parameter structure * * Example: * BEGIN_UNIFORM_BUFFER_STRUCT(FGlobalViewParameters,) * SHADER_PARAMETER(FVector4f, ViewSizeAndInvSize) * // ... * END_UNIFORM_BUFFER_STRUCT() * * BEGIN_SHADER_PARAMETER_STRUCT(FOtherStruct) * SHADER_PARAMETER_STRUCT_REF(FMyNestedStruct, MyStruct) */ #define SHADER_PARAMETER_STRUCT_REF(StructType,MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_REFERENCED_STRUCT, TShaderParameterTypeInfo>, TUniformBufferBinding,MemberName,,,EShaderPrecisionModifier::Float,TEXT(#StructType),false) /** Informs the RDG pass to transition the buffer into the requested state. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FParameters,) * RDG_BUFFER_ACCESS(MyBuffer) * // ... * END_SHADER_PARAMETER_STRUCT() * * FParameters Parameters; * Parameters.MyBuffer = FRDGBufferAccess(Buffer, ERHIAccess::CopyDest); **/ #define RDG_BUFFER_ACCESS(MemberName, Access) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_ACCESS, TRDGResourceAccessTypeInfo>, TRDGBufferAccess,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) #define RDG_BUFFER_ACCESS_DYNAMIC(MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_ACCESS, TRDGResourceAccessTypeInfo, FRDGBufferAccess,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) #define RDG_BUFFER_ACCESS_ARRAY(MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_BUFFER_ACCESS_ARRAY, TRDGResourceAccessTypeInfo, FRDGBufferAccessArray,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) /** Informs the RDG pass to transition the texture into the requested state. */ #define RDG_TEXTURE_ACCESS(MemberName, Access) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_ACCESS, TRDGTextureAccessTypeInfo>, TRDGTextureAccess,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) #define RDG_TEXTURE_ACCESS_DYNAMIC(MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_ACCESS, TRDGTextureAccessTypeInfo, FRDGTextureAccess,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) #define RDG_TEXTURE_ACCESS_ARRAY(MemberName) \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RDG_TEXTURE_ACCESS_ARRAY, TRDGResourceAccessTypeInfo, FRDGTextureAccessArray,MemberName,,,EShaderPrecisionModifier::Float,TEXT(""),false) /** Adds bindings slots for render targets on the structure. This is important for rasterizer based pass bind the * render target at the RHI pass creation. The name of the struct member will forced to RenderTargets, and * its type is a FRenderTargetBindingSlots. * * Example: * BEGIN_SHADER_PARAMETER_STRUCT(FGlobalViewParameters,) * RENDER_TARGET_BINDING_SLOTS() * // ... * END_SHADER_PARAMETER_STRUCT() * * FGlobalViewParameters Parameters; * Parameters.RenderTargets.DepthStencil = FDepthStencilBinding( //... ); */ #define RENDER_TARGET_BINDING_SLOTS() \ INTERNAL_SHADER_PARAMETER_EXPLICIT(UBMT_RENDER_TARGET_BINDING_SLOTS, FRenderTargetBindingSlots::FTypeInfo, FRenderTargetBindingSlots,RenderTargets,,,EShaderPrecisionModifier::Float,TEXT(""),false) /** An empty shader parameter structure ready to be used anywhere. */ BEGIN_SHADER_PARAMETER_STRUCT(FEmptyShaderParameters, RENDERCORE_API) END_SHADER_PARAMETER_STRUCT() /** Useful parameter struct that only have render targets. * * FRenderTargetParameters PassParameters; * PassParameters.RenderTargets.DepthStencil = ... ; * PassParameters.RenderTargets[0] = ... ; */ BEGIN_SHADER_PARAMETER_STRUCT(FRenderTargetParameters, RENDERCORE_API) RENDER_TARGET_BINDING_SLOTS() END_SHADER_PARAMETER_STRUCT() /** Returns the name of the macro that should be used for a given shader parameter base type. */ const TCHAR* GetShaderParameterMacroName(EUniformBufferBaseType ShaderParameterBaseType); /** Deprecated buffer macros. */ #define SHADER_PARAMETER_RDG_BUFFER_UPLOAD(MemberName) \ UE_DEPRECATED_MACRO(5.0, "SHADER_PARAMETER_RDG_BUFFER_UPLOAD has been deprecated. Use RDG_BUFFER_ACCESS(Buffer, ERHIAccess::CopyDest) instead.") \ RDG_BUFFER_ACCESS(MemberName, ERHIAccess::CopyDest) #define SHADER_PARAMETER_RDG_BUFFER(ShaderType,MemberName) \ UE_DEPRECATED_MACRO(5.0, "SHADER_PARAMETER_RDG_BUFFER has been deprecated. Use RDG_BUFFER_ACCESS with an explicit RHI state instead.") \ RDG_BUFFER_ACCESS(MemberName, ERHIAccess::SRVMask | ERHIAccess::IndirectArgs) #define SHADER_PARAMETER_RDG_BUFFER_ARRAY(ShaderType,MemberName, ArrayDecl) \ UE_DEPRECATED_MACRO(5.0, "SHADER_PARAMETER_RDG_BUFFER_ARRAY has been deprecated. Use RDG_BUFFER_ACCESS_ARRAY instead.") /** Upgrade the scalar type to a vector for storage. */ template struct TShaderParameterScalarArrayTypeInfo { static_assert(sizeof(TypeParameter) == 0, "This type is not supported for automatic packing."); using PackedArrayType = void; }; template<> struct TShaderParameterScalarArrayTypeInfo { using PackedArrayType = FUintVector4; }; template<> struct TShaderParameterScalarArrayTypeInfo { using PackedArrayType = FIntVector4; }; template<> struct TShaderParameterScalarArrayTypeInfo { using PackedArrayType = FVector4f; }; constexpr uint32 CalcPackedArraySize(uint32 NumElements) { return (NumElements + 3) / 4; } constexpr uint32 CalcPackedArrayIndex(uint32 ElementIndex) { return (ElementIndex >> 2); } constexpr uint32 CalcPackedComponentIndex(uint32 ElementIndex) { return (ElementIndex & 3); } /** Adds a packed constant-buffer stored array of values. * * Example: * SHADER_PARAMETER_SCALAR_ARRAY(float, MyScalarArray, 8) */ #define SHADER_PARAMETER_SCALAR_ARRAY(MemberType,MemberName,ArrayDecl) \ SHADER_PARAMETER_ARRAY(TShaderParameterScalarArrayTypeInfo::PackedArrayType, MemberName, [CalcPackedArraySize(TShaderParameterTypeInfo::PackedArrayType ArrayDecl>::NumElements)]) #define GET_SCALAR_ARRAY_ELEMENT(PackedArray, ElementIndex) \ PackedArray[CalcPackedArrayIndex(ElementIndex)][CalcPackedComponentIndex(ElementIndex)] PRAGMA_ENABLE_BUFFER_OVERRUN_WARNING