UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
RHIUniformBufferUtilities.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "Misc/App.h"
8#include "RHIDefinitions.h"
9#include "RHIResources.h"
10
12{
13
14template<typename TResourceType> struct TResourceTypeStr {};
15template<> struct TResourceTypeStr<FRHISamplerState> { static constexpr TCHAR String[] = TEXT("Sampler State"); };
16template<> struct TResourceTypeStr<FRHITexture> { static constexpr TCHAR String[] = TEXT("Texture"); };
17template<> struct TResourceTypeStr<FRHIShaderResourceView> { static constexpr TCHAR String[] = TEXT("Shader Resource View"); };
18template<> struct TResourceTypeStr<FRHIUnorderedAccessView> { static constexpr TCHAR String[] = TEXT("Unordered Access View"); };
19template<> struct TResourceTypeStr<FRHIResourceCollection> { static constexpr TCHAR String[] = TEXT("Resource Collection"); };
20
21template<typename TResourceType, typename TCallback>
22inline void EnumerateUniformBufferResources(const FRHIUniformBuffer* RESTRICT Buffer, int32 BufferIndex, const uint32* RESTRICT ResourceMap, TCallback && Callback)
23{
24 const TRefCountPtr<FRHIResource>* RESTRICT Resources = Buffer->GetResourceTable().GetData();
25
26 uint32 BufferOffset = ResourceMap[BufferIndex];
27 if (BufferOffset > 0)
28 {
29 const uint32* RESTRICT ResourceInfos = &ResourceMap[BufferOffset];
30 uint32 ResourceInfo = *ResourceInfos++;
31 do
32 {
33 checkSlow(FRHIResourceTableEntry::GetUniformBufferIndex(ResourceInfo) == BufferIndex);
34
35 const uint16 ResourceIndex = FRHIResourceTableEntry::GetResourceIndex(ResourceInfo);
37
38 TResourceType* Resource = static_cast<TResourceType*>(Resources[ResourceIndex].GetReference());
39 checkf(Resource
40 , TEXT("Null %s (resource %d bind %d) on UB Layout %s")
42 , ResourceIndex
43 , BindIndex
44 , *Buffer->GetLayout().GetDebugName()
45 );
46
47 Callback(Resource, BindIndex);
48
49 ResourceInfo = *ResourceInfos++;
50 } while (FRHIResourceTableEntry::GetUniformBufferIndex(ResourceInfo) == BufferIndex);
51 }
52}
53
54template<typename TBinder, typename TUniformBufferArrayType, typename TBitMaskType, bool bFullyBindless = false>
55void SetUniformBufferResourcesFromTables(TBinder && Binder, FRHIShader const& Shader, TBitMaskType& DirtyUniformBuffers, TUniformBufferArrayType const& BoundUniformBuffers
57 , RHIValidation::FTracker* Tracker
58 #endif
59 )
60{
62 FShaderResourceTable const& SRT = Shader.GetShaderResourceTable();
63
64 // Mask the dirty bits by those buffers from which the shader has bound resources.
65 uint32 DirtyBits = SRT.ResourceTableBits & DirtyUniformBuffers;
66
67 #if PLATFORM_SUPPORTS_BINDLESS_RENDERING && !ENABLE_RHI_VALIDATION
68 if constexpr (bFullyBindless)
69 {
70 while (DirtyBits)
71 {
72 // Scan for the lowest set bit, compute its index, clear it in the set of dirty bits.
74 const int32 BufferIndex = FMath::CountTrailingZeros(LowestBitMask); // todo: This has a branch on zero, we know it could never be zero...
76
77 EnumerateUniformBufferResources<FRHITexture>(BoundUniformBuffers[BufferIndex], BufferIndex, SRT.TextureMap.GetData(),
79 {
80 Texture->SetLastRenderTime(CurrentTimeForTextureTimes);
81 });
82 }
83
84 DirtyUniformBuffers = TBitMaskType(0);
85
86 return;
87 }
88 #endif
89
90 while (DirtyBits)
91 {
92 // Scan for the lowest set bit, compute its index, clear it in the set of dirty bits.
94 const int32 BufferIndex = FMath::CountTrailingZeros(LowestBitMask); // todo: This has a branch on zero, we know it could never be zero...
96
97 check(BufferIndex < SRT.ResourceTableLayoutHashes.Num());
98
99 FRHIUniformBuffer* Buffer = BoundUniformBuffers[BufferIndex];
100
101 #if DO_CHECK
102
103 if (!Buffer)
104 {
105 UE_LOG(LogRHI, Fatal, TEXT("Shader expected a uniform buffer at slot %u but got null instead (Shader='%s' UB='%s'). Rendering code needs to set a valid uniform buffer for this slot.")
106 , BufferIndex
107 , Shader.GetShaderName()
108 , *Shader.GetUniformBufferName(BufferIndex)
109 );
110 }
111 else if (Buffer->GetLayout().GetHash() != SRT.ResourceTableLayoutHashes[BufferIndex])
112 {
113 FRHIUniformBufferLayout const& BufferLayout = Buffer->GetLayout();
114
115 FString ResourcesString;
116 for (FRHIUniformBufferResource const& Resource : BufferLayout.Resources)
117 {
118 ResourcesString += FString::Printf(TEXT("%s%d")
119 , ResourcesString.Len() ? TEXT(" ") : TEXT("")
120 , Resource.MemberType
121 );
122 }
123
124 // This might mean you are accessing a data you haven't bound e.g. GBuffer
126 TEXT("Uniform buffer bound to slot %u is not what the shader expected:\n")
127 TEXT("\tBound : Uniform Buffer[%s] with Hash[0x%08x]\n")
128 TEXT("\tExpected : Uniform Buffer[%s] with Hash[0x%08x]\n")
129 TEXT("\tShader Name : %s\n")
130 TEXT("\tLayout CB Size : %d\n")
131 TEXT("\tLayout Num Resources : %d\n")
132 TEXT("\tResource Types : %s\n")
133 , BufferIndex
134 , *BufferLayout.GetDebugName(), BufferLayout.GetHash()
135 , *Shader.GetUniformBufferName(BufferIndex), SRT.ResourceTableLayoutHashes[BufferIndex]
136 , Shader.GetShaderName()
137 , BufferLayout.ConstantBufferSize
138 , BufferLayout.Resources.Num()
140 );
141 }
142
143 #endif // DO_CHECK
144
145 // Textures
146 EnumerateUniformBufferResources<FRHITexture>(Buffer, BufferIndex, SRT.TextureMap.GetData(),
148 {
149 #if ENABLE_RHI_VALIDATION
150 if (Tracker)
151 {
152 ERHIAccess Access = IsComputeShaderFrequency(Shader.GetFrequency())
153 ? ERHIAccess::SRVCompute
154 : Shader.GetFrequency() == SF_Pixel
155 ? ERHIAccess::SRVGraphicsPixel
156 : ERHIAccess::SRVGraphicsNonPixel;
157
158 // Textures bound here only have their "common" plane accessible. Stencil etc is ignored.
159 // (i.e. only access the color plane of a color texture, or depth plane of a depth texture)
160 Tracker->Assert(Texture->GetViewIdentity(0, 0, 0, 0, uint32(RHIValidation::EResourcePlane::Common), 1), Access);
161 }
162 #endif
163 Texture->SetLastRenderTime(CurrentTimeForTextureTimes);
164 Binder.SetTexture(Texture, Index);
165 });
166
167 // SRVs
168 EnumerateUniformBufferResources<FRHIShaderResourceView>(Buffer, BufferIndex, SRT.ShaderResourceViewMap.GetData(),
170 {
171 #if ENABLE_RHI_VALIDATION
172 if (Tracker)
173 {
174 ERHIAccess Access = IsComputeShaderFrequency(Shader.GetFrequency())
175 ? ERHIAccess::SRVCompute
176 : Shader.GetFrequency() == SF_Pixel
177 ? ERHIAccess::SRVGraphicsPixel
178 : ERHIAccess::SRVGraphicsNonPixel;
179
180 Tracker->Assert(SRV->GetViewIdentity(), Access);
181 }
183 {
184 RHIValidation::ValidateShaderResourceView(&Shader, Index, SRV);
185 }
186 #endif
187 Binder.SetSRV(SRV, Index);
188 });
189
190 #if PLATFORM_SUPPORTS_BINDLESS_RENDERING
191 EnumerateUniformBufferResources<FRHIResourceCollection>(Buffer, BufferIndex, SRT.ResourceCollectionMap.GetData(),
193 {
194 #if ENABLE_RHI_VALIDATION
195 // todo: christopher.waters - ResourceCollection validation
196 #endif
197 Binder.SetResourceCollection(ResourceCollection, Index);
198 });
199 #endif // PLATFORM_SUPPORTS_BINDLESS_RENDERING
200
201 // Samplers
202 EnumerateUniformBufferResources<FRHISamplerState>(Buffer, BufferIndex, SRT.SamplerMap.GetData(),
204 {
205 Binder.SetSampler(Sampler, Index);
206 });
207
208 // UAVs
209 EnumerateUniformBufferResources<FRHIUnorderedAccessView>(Buffer, BufferIndex, SRT.UnorderedAccessViewMap.GetData(),
211 {
212 #if ENABLE_RHI_VALIDATION
213 if (Tracker)
214 {
215 ERHIAccess Access = IsComputeShaderFrequency(Shader.GetFrequency())
216 ? ERHIAccess::UAVCompute
217 : ERHIAccess::UAVGraphics;
218
219 Tracker->AssertUAV(UAV, Access, Index);
220 }
221 #endif
222 Binder.SetUAV(UAV, Index);
223 });
224 }
225
226 DirtyUniformBuffers = TBitMaskType(0);
227}
228
229
230template<typename TBinder, typename TUniformBufferArrayType, typename TBitMaskType>
233 , RHIValidation::FTracker* Tracker
234 #endif
235 )
236{
239 , Shader
240 , DirtyUniformBuffers
241 , BoundUniformBuffers
243 , Tracker
244 #endif
245 );
246}
247
248}
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define ENABLE_RHI_VALIDATION
Definition Build.h:475
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define RESTRICT
Definition Platform.h:706
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
const bool GRHIValidationEnabled
Definition RHIValidationCommon.h:20
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
if(Failed) console_printf("Failed.\n")
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
static FORCEINLINE double GetCurrentTime()
Definition App.h:602
Definition RHIResourceCollection.h:46
Definition RHIResources.h:671
Definition RHIResources.h:3304
Definition RHIResources.h:854
Definition RHIResources.h:2153
Definition RHIResources.h:1232
Definition RHIResources.h:3294
Definition RefCounting.h:454
UE_FORCEINLINE_HINT ReferencedType * GetReference() const
Definition RefCounting.h:584
Definition RHIUniformBufferUtilities.h:12
void EnumerateUniformBufferResources(const FRHIUniformBuffer *RESTRICT Buffer, int32 BufferIndex, const uint32 *RESTRICT ResourceMap, TCallback &&Callback)
Definition RHIUniformBufferUtilities.h:22
void SetFullyBindlessUniformBufferResourcesFromTables(TBinder &&Binder, const FRHIShader &Shader, TBitMaskType &DirtyUniformBuffers, const TUniformBufferArrayType &BoundUniformBuffers)
Definition RHIUniformBufferUtilities.h:231
void SetUniformBufferResourcesFromTables(TBinder &&Binder, FRHIShader const &Shader, TBitMaskType &DirtyUniformBuffers, TUniformBufferArrayType const &BoundUniformBuffers)
Definition RHIUniformBufferUtilities.h:55
U16 Index
Definition radfft.cpp:71
static uint16 GetBindIndex(uint32 Data)
Definition RHIDefinitions.h:761
static uint16 GetUniformBufferIndex(uint32 Data)
Definition RHIDefinitions.h:751
static uint16 GetResourceIndex(uint32 Data)
Definition RHIDefinitions.h:756
Definition RHIResources.h:1150
Definition RHIResources.h:1129
Definition RHIResources.h:755
Definition RHIUniformBufferUtilities.h:14