bSupportsManualVertexFetch
bSupportsManualVertexFetch
#Overview
name: bSupportsManualVertexFetch
The value of this variable can be defined or overridden in .ini config files. 13
.ini config files referencing this setting variable.
It is referenced in 39
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of bSupportsManualVertexFetch is to indicate whether a particular graphics hardware and API combination supports manual vertex fetch, which is a technique used in shader programming for more efficient vertex data handling.
Key points about bSupportsManualVertexFetch:
-
It is part of the Unreal Engine’s RHI (Rendering Hardware Interface) subsystem, specifically within the DataDrivenShaderPlatformInfo class.
-
This variable is used across various rendering-related modules, including the core Engine, Niagara, and HairStrands plugins.
-
The value is typically set based on the capabilities of the current graphics hardware and API. It’s determined during engine initialization and remains constant for a given platform.
-
When manual vertex fetch is supported (bSupportsManualVertexFetch is true), shaders can manually read vertex attributes from buffers, potentially allowing for more optimized vertex processing.
-
This flag affects how vertex factories are set up and how vertex data is passed to shaders. For example, in many places in the code, there are conditional blocks that change behavior based on whether manual vertex fetch is supported.
-
It’s particularly important for performance optimization on certain platforms, as it can reduce the overhead of fixed-function vertex attribute fetching.
-
Developers should be aware of this flag when working on custom vertex factories or shader code, as it may require different implementation strategies depending on whether manual vertex fetch is supported.
-
Best practices include:
- Always check this flag before implementing manual vertex fetch in shaders.
- Design vertex factories and shaders to work with both manual and automatic vertex fetch, using preprocessor directives if necessary.
- Be aware that manual vertex fetch support can vary between different graphics APIs and hardware generations.
-
This variable interacts with other rendering system variables, such as those related to vertex buffer layouts and shader resource views (SRVs).
-
When implementing new rendering features or optimizing existing ones, developers should consider how manual vertex fetch support (or lack thereof) might impact their designs.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/Android/DataDrivenPlatformInfo.ini:65, section: [ShaderPlatform OPENGL_ES3_1_ANDROID]
- INI Section:
ShaderPlatform OPENGL_ES3_1_ANDROID
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/Android/DataDrivenPlatformInfo.ini:85, section: [ShaderPlatform VULKAN_ES3_1_ANDROID]
- INI Section:
ShaderPlatform VULKAN_ES3_1_ANDROID
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/Android/DataDrivenPlatformInfo.ini:107, section: [ShaderPlatform VULKAN_SM5_ANDROID]
- INI Section:
ShaderPlatform VULKAN_SM5_ANDROID
- Raw value:
true
- Is Array:
False
Location: <Workspace>/Engine/Config/IOS/DataDrivenPlatformInfo.ini:56, section: [ShaderPlatform METAL]
- INI Section:
ShaderPlatform METAL
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/IOS/DataDrivenPlatformInfo.ini:69, section: [ShaderPlatform METAL_MRT]
- INI Section:
ShaderPlatform METAL_MRT
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/IOS/DataDrivenPlatformInfo.ini:81, section: [ShaderPlatform METAL_SIM]
- INI Section:
ShaderPlatform METAL_SIM
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/Mac/DataDrivenPlatformInfo.ini:120, section: [ShaderPlatform METAL_MRT_MAC]
- INI Section:
ShaderPlatform METAL_MRT_MAC
- Raw value:
true
- Is Array:
False
Location: <Workspace>/Engine/Config/Mac/DataDrivenPlatformInfo.ini:132, section: [ShaderPlatform METAL_MACES3_1]
- INI Section:
ShaderPlatform METAL_MACES3_1
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/TVOS/DataDrivenPlatformInfo.ini:27, section: [ShaderPlatform METAL_MRT_TVOS]
- INI Section:
ShaderPlatform METAL_MRT_TVOS
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/TVOS/DataDrivenPlatformInfo.ini:38, section: [ShaderPlatform METAL_TVOS]
- INI Section:
ShaderPlatform METAL_TVOS
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/VulkanPC/DataDrivenPlatformInfo.ini:269, section: [ShaderPlatform VULKAN_PCES3_1]
- INI Section:
ShaderPlatform VULKAN_PCES3_1
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/DataDrivenPlatformInfo.ini:157, section: [ShaderPlatform PCD3D_ES3_1]
- INI Section:
ShaderPlatform PCD3D_ES3_1
- Raw value:
false
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/DataDrivenPlatformInfo.ini:178, section: [ShaderPlatform OPENGL_PCES3_1]
- INI Section:
ShaderPlatform OPENGL_PCES3_1
- Raw value:
false
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraMeshRendererProperties.cpp:766
Scope (from outer to inner):
file
function void UNiagaraMeshRendererProperties::CollectPSOPrecacheData
Source code excerpt:
{
const FVertexFactoryType* VFType = GetVertexFactoryType();
bool bSupportsManualVertexFetch = VFType->SupportsManualVertexFetch(GMaxRHIFeatureLevel);
for (int32 MeshIndex = 0; MeshIndex < Meshes.Num(); ++MeshIndex)
{
INiagaraRenderableMeshInterface* RenderableMeshInterface = nullptr;
UStaticMesh* StaticMesh = nullptr;
NiagaraMeshRendererPropertiesInternal::ResolveRenderableMeshInternal(Meshes[MeshIndex], InEmitter, RenderableMeshInterface, StaticMesh);
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraMeshRendererProperties.cpp:786
Scope (from outer to inner):
file
function void UNiagaraMeshRendererProperties::CollectPSOPrecacheData
Source code excerpt:
FPSOPrecacheParams& PSOPrecacheParams = OutParams.AddDefaulted_GetRef();
PSOPrecacheParams.MaterialInterface = MeshMaterial;
if (!bSupportsManualVertexFetch)
{
// Assuming here that all LOD use same vertex decl
int32 MeshLODIdx = StaticMesh->GetMinLODIdx();
if (StaticMesh->GetRenderData()->LODResources.IsValidIndex(MeshLODIdx))
{
FStaticMeshDataType Data;
FVertexDeclarationElementList Elements;
FNiagaraRenderableStaticMesh::InitVertexFactoryComponents(StaticMesh->GetRenderData()->LODResources[MeshLODIdx].VertexBuffers, nullptr, Data);
FNiagaraMeshVertexFactory::GetVertexElements(GMaxRHIFeatureLevel, bSupportsManualVertexFetch, Data, Elements);
PSOPrecacheParams.VertexFactoryDataList.Add(FPSOPrecacheVertexFactoryData(VFType, Elements));
}
}
else
{
PSOPrecacheParams.VertexFactoryDataList.Add(FPSOPrecacheVertexFactoryData(VFType));
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/NiagaraVertexFactories/Private/NiagaraMeshVertexFactory.cpp:70
Scope (from outer to inner):
file
function void FNiagaraMeshVertexFactory::GetVertexElements
Source code excerpt:
IMPLEMENT_TYPE_LAYOUT(FNiagaraMeshVertexFactoryShaderParametersPS);
void FNiagaraMeshVertexFactory::GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, bool bSupportsManualVertexFetch, FStaticMeshDataType& Data, FVertexDeclarationElementList& Elements, FVertexStreamList& InOutStreams)
{
if (Data.PositionComponent.VertexBuffer != NULL)
{
Elements.Add(AccessStreamComponent(Data.PositionComponent, 0, InOutStreams));
}
if (!bSupportsManualVertexFetch)
{
// only tangent,normal are used by the stream. the binormal is derived in the shader
uint8 TangentBasisAttributes[2] = { 1, 2 };
for (int32 AxisIndex = 0; AxisIndex < 2; AxisIndex++)
{
if (Data.TangentBasisComponents[AxisIndex].VertexBuffer != NULL)
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/NiagaraVertexFactories/Private/NiagaraMeshVertexFactory.cpp:135
Scope (from outer to inner):
file
function void FNiagaraMeshVertexFactory::InitRHI
Source code excerpt:
{
check(HasValidFeatureLevel());
const bool bSupportsManualVertexFetch = SupportsManualVertexFetch(GetFeatureLevel());
FVertexDeclarationElementList Elements;
GetVertexElements(GetFeatureLevel(), bSupportsManualVertexFetch, Data, Elements, Streams);
#if NIAGARA_ENABLE_GPU_SCENE_MESHES
if (bAddPrimitiveIDElement)
{
// TODO: Support GPU Scene on mobile? Maybe only for CPU particles?
AddPrimitiveIdStreamElement(EVertexInputStreamType::Default, Elements, 13, 0xFF);
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/NiagaraVertexFactories/Private/NiagaraMeshVertexFactory.cpp:210
Scope (from outer to inner):
file
function void FNiagaraMeshVertexFactory::GetVertexElements
Source code excerpt:
}
void FNiagaraMeshVertexFactory::GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, bool bSupportsManualVertexFetch, FStaticMeshDataType& Data, FVertexDeclarationElementList& Elements)
{
FVertexStreamList InOutStreams;
GetVertexElements(FeatureLevel, bSupportsManualVertexFetch, Data, Elements, InOutStreams);
#if NIAGARA_ENABLE_GPU_SCENE_MESHES
if (UseGPUScene(GMaxRHIShaderPlatform, GMaxRHIFeatureLevel)
&& !PlatformGPUSceneUsesUniformBufferView(GMaxRHIShaderPlatform))
{
Elements.Add(FVertexElement(InOutStreams.Num(), 0, VET_UInt, 13, sizeof(uint32), true));
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/NiagaraVertexFactories/Public/NiagaraMeshVertexFactory.h:153
Scope (from outer to inner):
file
class class FNiagaraMeshVertexFactory : public FNiagaraVertexFactoryBase
Source code excerpt:
*/
static NIAGARAVERTEXFACTORIES_API void GetPSOPrecacheVertexFetchElements(EVertexInputStreamType VertexInputStreamType, FVertexDeclarationElementList& Elements);
static NIAGARAVERTEXFACTORIES_API void GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, bool bSupportsManualVertexFetch, FStaticMeshDataType& Data, FVertexDeclarationElementList& Elements);
/**
* An implementation of the interface used by TSynchronizedResource to update the resource with new data from the game thread.
*/
NIAGARAVERTEXFACTORIES_API void SetData(FRHICommandListBase& RHICmdList, const FStaticMeshDataType& InData);
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/NiagaraVertexFactories/Public/NiagaraMeshVertexFactory.h:212
Scope (from outer to inner):
file
class class FNiagaraMeshVertexFactory : public FNiagaraVertexFactoryBase
Source code excerpt:
}
protected:
static NIAGARAVERTEXFACTORIES_API void GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, bool bSupportsManualVertexFetch, FStaticMeshDataType& Data, FVertexDeclarationElementList& Elements, FVertexStreamList& InOutStreams);
protected:
FStaticMeshDataType Data;
bool bAddPrimitiveIDElement;
/** Uniform buffer with mesh particle parameters. */
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/HairCardsVertexFactory.cpp:95
Scope (from outer to inner):
file
function FHairCardsUniformBuffer CreateHairCardsVFUniformBuffer
Source code excerpt:
const uint32 LODIndex,
EHairGeometryType GeometryType,
bool bSupportsManualVertexFetch)
{
FHairCardsVertexFactoryUniformShaderParameters UniformParameters;
if (GeometryType == EHairGeometryType::Cards)
{
const FHairGroupInstance::FCards::FLOD& LOD = Instance->Cards.LODs[LODIndex];
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/HairCardsVertexFactory.cpp:163
Scope (from outer to inner):
file
function FHairCardsUniformBuffer CreateHairCardsVFUniformBuffer
Source code excerpt:
}
if (!bSupportsManualVertexFetch)
{
UniformParameters.PositionBuffer = GNullVertexBuffer.VertexBufferSRV;
UniformParameters.PreviousPositionBuffer = GNullVertexBuffer.VertexBufferSRV;
UniformParameters.NormalsBuffer = GNullVertexBuffer.VertexBufferSRV;
UniformParameters.UVsBuffer = GNullVertexBuffer.VertexBufferSRV;
UniformParameters.MaterialsBuffer = GNullVertexBuffer.VertexBufferSRV;
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/HairCardsVertexFactory.cpp:362
Scope (from outer to inner):
file
function void FHairCardsVertexFactory::InitResources
Source code excerpt:
AddPrimitiveIdStreamElement(EVertexInputStreamType::Default, Elements, HAIR_CARDS_VF_PRIMITIVEID_STREAM_INDEX /*AttributeIndex*/, HAIR_CARDS_VF_PRIMITIVEID_STREAM_INDEX /*AttributeIndex_Mobile*/);
// Note this is a local version of the VF's bSupportsManualVertexFetch, which take into account the feature level
// When manual fetch is not supported, buffers are bound through input assembly based on vertex declaration.
// A vertex declaraction only access FVertexBuffer buffers, so we create wrappers of pooled buffers
const bool bManualFetch = SupportsManualVertexFetch(CurrentFeatureLevel);
if (!bManualFetch)
{
if (Data.GeometryType == EHairGeometryType::Cards)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Components/StaticMeshComponent.h:728
Scope (from outer to inner):
file
class class UStaticMeshComponent : public UMeshComponent
Source code excerpt:
ENGINE_API virtual void CollectPSOPrecacheData(const FPSOPrecacheParams& BasePrecachePSOParams, FMaterialInterfacePSOPrecacheParamsList& OutParams) override;
/** Shared implementation for all StaticMesh derived components */
using GetPSOVertexElementsFn = TFunctionRef<void(const FStaticMeshLODResources& LODRenderData, int32 LODIndex, bool bSupportsManualVertexFetch, FVertexDeclarationElementList& Elements)>;
ENGINE_API void CollectPSOPrecacheDataImpl(const FVertexFactoryType* VFType, const FPSOPrecacheParams& BasePrecachePSOParams, GetPSOVertexElementsFn GetVertexElements, FMaterialInterfacePSOPrecacheParamsList& OutParams) const;
/** Whether the component type supports static lighting. */
virtual bool SupportsStaticLighting() const override
{
return true;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/InstancedStaticMesh.h:281
Scope: file
Source code excerpt:
*/
static ENGINE_API void GetPSOPrecacheVertexFetchElements(EVertexInputStreamType VertexInputStreamType, FVertexDeclarationElementList& Elements);
static ENGINE_API void GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, EVertexInputStreamType InputStreamType, bool bSupportsManualVertexFetch, FDataType& Data, FInstancedStaticMeshDataType& InstanceData, FVertexDeclarationElementList& Elements);
/**
* An implementation of the interface used by TSynchronizedResource to update the resource with new data from the game thread.
*/
void SetData(FRHICommandListBase& RHICmdList, const FDataType& InData, const FInstancedStaticMeshDataType* InInstanceData)
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/InstancedStaticMesh.h:336
Scope: file
Source code excerpt:
}
protected:
static ENGINE_API void GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, EVertexInputStreamType InputStreamType, bool bSupportsManualVertexFetch, FDataType& Data, FInstancedStaticMeshDataType& InstanceData, FVertexDeclarationElementList& Elements, FVertexStreamList& Streams);
private:
FInstancedStaticMeshDataType InstanceData;
TUniformBufferRef<FInstancedStaticMeshVertexFactoryUniformShaderParameters> UniformBuffer;
};
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SplineMeshComponent.cpp:843
Scope (from outer to inner):
file
function void USplineMeshComponent::CollectPSOPrecacheData
lambda-function
Source code excerpt:
int32 LightMapCoordinateIndex = GetStaticMesh()->GetLightMapCoordinateIndex();
auto SMC_GetElements = [LightMapCoordinateIndex](const FStaticMeshLODResources& LODRenderData, int32 LODIndex, bool bSupportsManualVertexFetch, FVertexDeclarationElementList& Elements)
{
// FIXME: This will miss when SM component overrides vertex colors and source StaticMesh does not have vertex colors
constexpr bool bOverrideColorVertexBuffer = false;
FLocalVertexFactory::FDataType Data;
InitSplineMeshVertexFactoryComponents(LODRenderData.VertexBuffers, nullptr /*VertexFactory*/, LightMapCoordinateIndex, bOverrideColorVertexBuffer, Data);
FLocalVertexFactory::GetVertexElements(GMaxRHIFeatureLevel, EVertexInputStreamType::Default, bSupportsManualVertexFetch, Data, Elements);
};
FPSOPrecacheParams SplineMeshPSOParams = BasePrecachePSOParams;
SplineMeshPSOParams.bReverseCulling ^= (SplineParams.StartScale.X < 0) ^ (SplineParams.StartScale.Y < 0);
if (ShouldCreateNaniteProxy())
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/StaticMeshComponent.cpp:1572
Scope (from outer to inner):
file
function void UStaticMeshComponent::CollectPSOPrecacheDataImpl
Source code excerpt:
ERHIFeatureLevel::Type FeatureLevel = World ? World->GetFeatureLevel() : GMaxRHIFeatureLevel;
bool bSupportsManualVertexFetch = VFType->SupportsManualVertexFetch(GMaxRHIFeatureLevel);
bool bAnySectionCastsShadows = false;
int32 MeshMinLOD = GetStaticMesh()->GetMinLODIdx();
FPSOPrecacheVertexFactoryDataPerMaterialIndexList VFTypesPerMaterialIndex;
FStaticMeshLODResourcesArray& LODResources = GetStaticMesh()->GetRenderData()->LODResources;
for (int32 LODIndex = MeshMinLOD; LODIndex < LODResources.Num(); ++LODIndex)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/StaticMeshComponent.cpp:1582
Scope (from outer to inner):
file
function void UStaticMeshComponent::CollectPSOPrecacheDataImpl
Source code excerpt:
FStaticMeshLODResources& LODRenderData = LODResources[LODIndex];
FVertexDeclarationElementList VertexElements;
if (!bSupportsManualVertexFetch)
{
GetVertexElements(LODRenderData, LODIndex, bSupportsManualVertexFetch, VertexElements);
}
for (FStaticMeshSection& RenderSection : LODRenderData.Sections)
{
bAnySectionCastsShadows |= RenderSection.bCastShadow;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/StaticMeshComponent.cpp:1600
Scope (from outer to inner):
file
function void UStaticMeshComponent::CollectPSOPrecacheDataImpl
Source code excerpt:
}
if (bSupportsManualVertexFetch)
{
VFsPerMaterial->VertexFactoryDataList.AddUnique(FPSOPrecacheVertexFactoryData(VFType));
}
else
{
VFsPerMaterial->VertexFactoryDataList.AddUnique(FPSOPrecacheVertexFactoryData(VFType, VertexElements));
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/StaticMeshComponent.cpp:1654
Scope (from outer to inner):
file
function void UStaticMeshComponent::CollectPSOPrecacheData
lambda-function
Source code excerpt:
int32 LightMapCoordinateIndex = StaticMesh->GetLightMapCoordinateIndex();
auto SMC_GetElements = [LightMapCoordinateIndex, &LODData = this->LODData](const FStaticMeshLODResources& LODRenderData, int32 LODIndex, bool bSupportsManualVertexFetch, FVertexDeclarationElementList& Elements)
{
int32 NumTexCoords = (int32)LODRenderData.VertexBuffers.StaticMeshVertexBuffer.GetNumTexCoords();
int32 LODLightMapCoordinateIndex = LightMapCoordinateIndex < NumTexCoords ? LightMapCoordinateIndex : NumTexCoords - 1;
bool bOverrideColorVertexBuffer = LODIndex < LODData.Num() && LODData[LODIndex].OverrideVertexColors != nullptr;
FLocalVertexFactory::FDataType Data;
InitStaticMeshVertexFactoryComponents(LODRenderData.VertexBuffers, nullptr /*VertexFactory*/, LODLightMapCoordinateIndex, bOverrideColorVertexBuffer, Data);
FLocalVertexFactory::GetVertexElements(GMaxRHIFeatureLevel, EVertexInputStreamType::Default, bSupportsManualVertexFetch, Data, Elements);
};
if (ShouldCreateNaniteProxy())
{
if (NaniteLegacyMaterialsSupported())
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:759
Scope (from outer to inner):
file
function void FInstancedStaticMeshVertexFactory::GetVertexElements
Source code excerpt:
ERHIFeatureLevel::Type FeatureLevel,
EVertexInputStreamType InputStreamType,
bool bSupportsManualVertexFetch,
FDataType& Data,
FInstancedStaticMeshDataType& InstanceData,
FVertexDeclarationElementList& Elements)
{
FVertexStreamList VertexStreams;
GetVertexElements(FeatureLevel, InputStreamType, bSupportsManualVertexFetch, Data, InstanceData, Elements, VertexStreams);
}
void FInstancedStaticMeshVertexFactory::GetVertexElements(
ERHIFeatureLevel::Type FeatureLevel,
EVertexInputStreamType InputStreamType,
bool bSupportsManualVertexFetch,
FDataType& Data,
FInstancedStaticMeshDataType& InstanceData,
FVertexDeclarationElementList& Elements,
FVertexStreamList& Streams)
{
if (Data.PositionComponent.VertexBuffer != NULL)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:782
Scope (from outer to inner):
file
function void FInstancedStaticMeshVertexFactory::GetVertexElements
Source code excerpt:
}
if (!bSupportsManualVertexFetch)
{
// only tangent,normal are used by the stream. the binormal is derived in the shader
uint8 TangentBasisAttributes[2] = { 1, 2 };
for (int32 AxisIndex = 0; AxisIndex < 2; AxisIndex++)
{
if (Data.TangentBasisComponents[AxisIndex].VertexBuffer != NULL)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:5019
Scope (from outer to inner):
file
function void UInstancedStaticMeshComponent::CollectPSOPrecacheData
lambda-function
Source code excerpt:
int32 LightMapCoordinateIndex = GetStaticMesh()->GetLightMapCoordinateIndex();
auto ISMC_GetElements = [LightMapCoordinateIndex, InstanceBuffer, this](const FStaticMeshLODResources& LODRenderData, int32 LODIndex, bool bSupportsManualVertexFetch, FVertexDeclarationElementList& Elements)
{
FInstancedStaticMeshDataType InstanceData;
FInstancedStaticMeshVertexFactory::FDataType Data;
const FColorVertexBuffer* ColorVertexBuffer = LODRenderData.bHasColorVertexData ? &(LODRenderData.VertexBuffers.ColorVertexBuffer) : nullptr;
if (LODData.IsValidIndex(LODIndex) && LODData[LODIndex].OverrideVertexColors)
{
ColorVertexBuffer = LODData[LODIndex].OverrideVertexColors;
}
InitInstancedStaticMeshVertexFactoryComponents(LODRenderData.VertexBuffers, ColorVertexBuffer, InstanceBuffer, nullptr /*VertexFactory*/, LightMapCoordinateIndex, bSupportsManualVertexFetch, Data, InstanceData);
FInstancedStaticMeshVertexFactory::GetVertexElements(GMaxRHIFeatureLevel, EVertexInputStreamType::Default, bSupportsManualVertexFetch, Data, InstanceData, Elements);
};
if (ShouldCreateNaniteProxy())
{
if (NaniteLegacyMaterialsSupported())
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LocalVertexFactory.cpp:359
Scope (from outer to inner):
file
function void FLocalVertexFactory::GetVertexElements
Source code excerpt:
}
void FLocalVertexFactory::GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, EVertexInputStreamType InputStreamType, bool bSupportsManualVertexFetch, FDataType& Data, FVertexDeclarationElementList& Elements)
{
FVertexStreamList VertexStreams;
int32 ColorStreamIndex;
GetVertexElements(FeatureLevel, InputStreamType, bSupportsManualVertexFetch, Data, Elements, VertexStreams, ColorStreamIndex);
if (UseGPUScene(GMaxRHIShaderPlatform, GMaxRHIFeatureLevel)
&& !PlatformGPUSceneUsesUniformBufferView(GMaxRHIShaderPlatform))
{
Elements.Add(FVertexElement(VertexStreams.Num(), 0, VET_UInt, 13, sizeof(uint32), true));
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LocalVertexFactory.cpp:469
Scope (from outer to inner):
file
function void FLocalVertexFactory::GetVertexElements
Source code excerpt:
ERHIFeatureLevel::Type FeatureLevel,
EVertexInputStreamType InputStreamType,
bool bSupportsManualVertexFetch,
FDataType& Data,
FVertexDeclarationElementList& Elements,
FVertexStreamList& InOutStreams,
int32& OutColorStreamIndex)
{
check(InputStreamType == EVertexInputStreamType::Default);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LocalVertexFactory.cpp:487
Scope (from outer to inner):
file
function void FLocalVertexFactory::GetVertexElements
Source code excerpt:
// The vertex factories are then used during mobile rendering and will cause PSO creation failure.
// First need to fix invalid usage of these vertex factories before this can be enabled again. (UE-165187)
if (!bSupportsManualVertexFetch)
#endif // WITH_EDITOR
{
// Only the tangent and normal are used by the stream; the bitangent is derived in the shader.
uint8 TangentBasisAttributes[2] = { 1, 2 };
for (int32 AxisIndex = 0; AxisIndex < 2; AxisIndex++)
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkinnedAsset.cpp:214
Scope (from outer to inner):
file
function FPSOPrecacheVertexFactoryDataPerMaterialIndexList USkinnedAsset::GetVertexFactoryTypesPerMaterialIndex
Source code excerpt:
// Force static from GPU point of view
const FVertexFactoryType* CPUSkinVFType = &FLocalVertexFactory::StaticType;
bool bSupportsManualVertexFetch = CPUSkinVFType->SupportsManualVertexFetch(GMaxRHIFeatureLevel);
if (!bSupportsManualVertexFetch)
{
FVertexDeclarationElementList VertexElements;
bool bOverrideColorVertexBuffer = false;
FLocalVertexFactory::FDataType Data;
InitStaticMeshVertexFactoryComponents(LODRenderData.StaticVertexBuffers, nullptr /*VertexFactory*/, 0, bOverrideColorVertexBuffer, Data);
FLocalVertexFactory::GetVertexElements(GMaxRHIFeatureLevel, EVertexInputStreamType::Default, bSupportsManualVertexFetch, Data, VertexElements);
VFsPerMaterial->VertexFactoryDataList.AddUnique(FPSOPrecacheVertexFactoryData(CPUSkinVFType, VertexElements));
}
else
{
VFsPerMaterial->VertexFactoryDataList.AddUnique(FPSOPrecacheVertexFactoryData(CPUSkinVFType));
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/LocalVertexFactory.h:75
Scope: file
Source code excerpt:
static ENGINE_API void GetPSOPrecacheVertexFetchElements(EVertexInputStreamType VertexInputStreamType, FVertexDeclarationElementList& Elements);
static ENGINE_API void GetVertexElements(ERHIFeatureLevel::Type FeatureLevel, EVertexInputStreamType InputStreamType, bool bSupportsManualVertexFetch, FDataType& Data, FVertexDeclarationElementList& Elements);
/**
* An implementation of the interface used by TSynchronizedResource to update the resource with new data from the game thread.
*/
ENGINE_API void SetData(FRHICommandListBase& RHICmdList, const FDataType& InData);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/LocalVertexFactory.h:175
Scope: file
Source code excerpt:
ERHIFeatureLevel::Type FeatureLevel,
EVertexInputStreamType InputStreamType,
bool bSupportsManualVertexFetch,
FDataType& Data,
FVertexDeclarationElementList& Elements,
FVertexStreamList& InOutStreams,
int32& OutColorStreamIndex);
FDataType Data;
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:119
Scope (from outer to inner):
file
function FGeometryCollectionSceneProxy::FGeometryCollectionSceneProxy
Source code excerpt:
, MeshDescription(Component->GetRestCollection()->RenderData->MeshDescription)
, VertexFactory(GetScene().GetFeatureLevel())
, bSupportsManualVertexFetch(VertexFactory.SupportsManualVertexFetch(GetScene().GetFeatureLevel()))
, bSupportsTripleBufferVertexUpload(GRHISupportsMapWriteNoOverwrite)
#if WITH_EDITOR
, bShowBoneColors(Component->GetShowBoneColors())
, bSuppressSelectionMaterial(Component->GetSuppressSelectionMaterial())
, VertexFactoryDebugColor(GetScene().GetFeatureLevel())
#endif
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:249
Scope (from outer to inner):
file
function void FGeometryCollectionSceneProxy::SetupVertexFactory
Source code excerpt:
FGeometryCollectionVertexFactory::FDataType Data;
FPositionVertexBuffer const& PositionVB = bSupportsManualVertexFetch ? MeshResource.PositionVertexBuffer : SkinnedPositionVertexBuffer;
PositionVB.BindPositionVertexBuffer(&GeometryCollectionVertexFactory, Data);
MeshResource.StaticMeshVertexBuffer.BindTangentVertexBuffer(&GeometryCollectionVertexFactory, Data);
MeshResource.StaticMeshVertexBuffer.BindPackedTexCoordVertexBuffer(&GeometryCollectionVertexFactory, Data);
MeshResource.StaticMeshVertexBuffer.BindLightMapVertexBuffer(&GeometryCollectionVertexFactory, Data, 0);
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:259
Scope (from outer to inner):
file
function void FGeometryCollectionSceneProxy::SetupVertexFactory
Source code excerpt:
ColorVB.BindColorVertexBuffer(&GeometryCollectionVertexFactory, Data);
if (bSupportsManualVertexFetch)
{
Data.BoneMapSRV = MeshResource.BoneMapVertexBuffer.GetSRV();
Data.BoneTransformSRV = TransformBuffers[CurrentTransformBufferIndex].VertexBufferSRV;
Data.BonePrevTransformSRV = PrevTransformBuffers[CurrentTransformBufferIndex].VertexBufferSRV;
}
else
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:287
Scope (from outer to inner):
file
function void FGeometryCollectionSceneProxy::CreateRenderThreadResources
Source code excerpt:
void FGeometryCollectionSceneProxy::CreateRenderThreadResources(FRHICommandListBase& RHICmdList)
{
if (bSupportsManualVertexFetch)
{
// Initialize transform buffers and upload rest transforms.
TransformBuffers.AddDefaulted(1);
PrevTransformBuffers.AddDefaulted(1);
TransformBuffers[0].NumTransforms = NumTransforms;
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:372
Scope (from outer to inner):
file
function void FGeometryCollectionSceneProxy::DestroyRenderThreadResources
Source code excerpt:
void FGeometryCollectionSceneProxy::DestroyRenderThreadResources()
{
if (bSupportsManualVertexFetch)
{
for (int32 i = 0; i < TransformBuffers.Num(); i++)
{
TransformBuffers[i].ReleaseResource();
PrevTransformBuffers[i].ReleaseResource();
}
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.cpp:429
Scope (from outer to inner):
file
function void FGeometryCollectionSceneProxy::SetDynamicData_RenderThread
Source code excerpt:
TransformVertexBuffersContainsRestTransforms = !DynamicData->IsDynamic;
if (bSupportsManualVertexFetch)
{
const bool bLocalGeometryCollectionTripleBufferUploads = (GGeometryCollectionTripleBufferUploads != 0) && bSupportsTripleBufferVertexUpload;
if (bLocalGeometryCollectionTripleBufferUploads && TransformBuffers.Num() == 1)
{
TransformBuffers.AddDefaulted(2);
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionSceneProxy.h:223
Scope (from outer to inner):
file
class class FGeometryCollectionSceneProxy final : public FPrimitiveSceneProxy
Source code excerpt:
FGeometryCollectionVertexFactory VertexFactory;
bool bSupportsManualVertexFetch;
FPositionVertexBuffer SkinnedPositionVertexBuffer;
int32 CurrentTransformBufferIndex = 0;
bool TransformVertexBuffersContainsRestTransforms = true;
bool bSupportsTripleBufferVertexUpload = false;
bool bRenderResourcesCreated = false;
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/DataDrivenShaderPlatformInfo.cpp:144
Scope (from outer to inner):
file
function void FGenericDataDrivenShaderPlatformInfo::SetDefaultValues
Source code excerpt:
bSupportsAsyncPipelineCompilation = true;
bSupportsVertexShaderSRVs = true; // Explicitly overriden to false for ES 3.1 platforms via DDPI ini
bSupportsManualVertexFetch = true;
bSupportsVolumeTextureAtomics = true;
bSupportsClipDistance = true;
bSupportsShaderPipelines = true;
MaxSamplers = 16;
}
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/DataDrivenShaderPlatformInfo.cpp:275
Scope (from outer to inner):
file
function void FGenericDataDrivenShaderPlatformInfo::ParseDataDrivenShaderInfo
Source code excerpt:
GET_SECTION_BOOL_HELPER(bSupportsAsyncPipelineCompilation);
GET_SECTION_BOOL_HELPER(bSupportsVertexShaderSRVs);
GET_SECTION_BOOL_HELPER(bSupportsManualVertexFetch);
GET_SECTION_BOOL_HELPER(bRequiresReverseCullingOnMobile);
GET_SECTION_BOOL_HELPER(bOverrideFMaterial_NeedsGBufferEnabled);
GET_SECTION_BOOL_HELPER(bSupportsFFTBloom);
GET_SECTION_BOOL_HELPER(bSupportsVertexShaderLayer);
GET_SECTION_BINDLESS_SUPPORT_HELPER(BindlessSupport);
GET_SECTION_BOOL_HELPER(bSupportsVolumeTextureAtomics);
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/DataDrivenShaderPlatformInfo.cpp:473
Scope (from outer to inner):
file
function void FGenericDataDrivenShaderPlatformInfo::UpdatePreviewPlatforms
Source code excerpt:
PREVIEW_USE_RUNTIME_VALUE(bSupportsSceneDataCompressedTransforms);
PREVIEW_USE_RUNTIME_VALUE(bSupportsVertexShaderSRVs);
PREVIEW_USE_RUNTIME_VALUE(bSupportsManualVertexFetch);
PREVIEW_USE_RUNTIME_VALUE(bSupportsRealTypes);
PREVIEW_USE_RUNTIME_VALUE(bSupportsUniformBufferObjects);
// Settings that will never be supported in preview
PREVIEW_FORCE_DISABLE(bSupportsShaderRootConstants);
PREVIEW_FORCE_DISABLE(bSupportsShaderBundleDispatch);
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Public/DataDrivenShaderPlatformInfo.h:98
Scope (from outer to inner):
file
class class FGenericDataDrivenShaderPlatformInfo
Source code excerpt:
uint32 bSupportsAsyncPipelineCompilation : 1;
uint32 bSupportsVertexShaderSRVs : 1; // Whether SRVs can be bound to vertex shaders (may be independent from ManualVertexFetch)
uint32 bSupportsManualVertexFetch : 1;
uint32 bRequiresReverseCullingOnMobile : 1;
uint32 bOverrideFMaterial_NeedsGBufferEnabled : 1;
uint32 bSupportsFFTBloom : 1;
uint32 bSupportsInlineRayTracing : 1;
uint32 bSupportsRayTracingShaders : 1;
uint32 bSupportsVertexShaderLayer : 1;
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Public/DataDrivenShaderPlatformInfo.h:671
Scope (from outer to inner):
file
class class FGenericDataDrivenShaderPlatformInfo
function static const bool GetSupportsManualVertexFetch
Source code excerpt:
{
check(IsValid(Platform));
return Infos[Platform].bSupportsManualVertexFetch;
}
static FORCEINLINE_DEBUGGABLE const bool GetRequiresReverseCullingOnMobile(const FStaticShaderPlatform Platform)
{
check(IsValid(Platform));
return Infos[Platform].bRequiresReverseCullingOnMobile;