Skip to content

Commit

Permalink
Fix RHI bug with position buffer SRV types.
Browse files Browse the repository at this point in the history
  • Loading branch information
Koderz committed Jun 15, 2023
1 parent bc1b5a5 commit 993aeb0
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 15 deletions.
133 changes: 129 additions & 4 deletions Source/RealtimeMeshComponent/Private/RealtimeMeshDataTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ namespace RealtimeMesh
const TMap<FRealtimeMeshElementType, FRealtimeMeshElementTypeDefinition> FRealtimeMeshBufferLayoutUtilities::SupportedTypeDefinitions =
{
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 1, false, true), FRealtimeMeshElementTypeDefinition(VET_Float1, IET_None, PF_R32_FLOAT, sizeof(float), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 2, false, true), FRealtimeMeshElementTypeDefinition(VET_Float2, IET_None, PF_G32R32F, sizeof(FVector2f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 3, false, true), FRealtimeMeshElementTypeDefinition(VET_Float3, IET_None, PF_R32G32B32F, sizeof(FVector3f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 4, false, true), FRealtimeMeshElementTypeDefinition(VET_Float4, IET_None, PF_A32B32G32R32F, sizeof(FVector4f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 2, false, true), FRealtimeMeshElementTypeDefinition(VET_Float2, IET_None, PF_R32_FLOAT, sizeof(FVector2f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 3, false, true), FRealtimeMeshElementTypeDefinition(VET_Float3, IET_None, PF_R32_FLOAT, sizeof(FVector3f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Float, 4, false, true), FRealtimeMeshElementTypeDefinition(VET_Float4, IET_None, PF_R32_FLOAT, sizeof(FVector4f), alignof(float)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Int8, 4, true, true), FRealtimeMeshElementTypeDefinition(VET_PackedNormal, IET_None, PF_R8G8B8A8_SNORM, sizeof(FPackedNormal), alignof(FPackedNormal)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::UInt8, 4, false, false), FRealtimeMeshElementTypeDefinition(VET_UByte4, IET_None, PF_R8G8B8A8_UINT, sizeof(uint8)*4, alignof(uint8)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::UInt8, 4, true, true), FRealtimeMeshElementTypeDefinition(VET_UByte4N, IET_None, PF_R8G8B8A8_UINT, sizeof(uint8)*4, alignof(uint8)) },
Expand All @@ -41,7 +41,8 @@ namespace RealtimeMesh
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::Int32, 1, false, false), FRealtimeMeshElementTypeDefinition(VET_None, IET_Int32, PF_R32_SINT, sizeof(int32), alignof(int32)) },
{ FRealtimeMeshElementType(ERealtimeMeshDatumType::UInt32, 1, false, false), FRealtimeMeshElementTypeDefinition(VET_UInt, IET_UInt32, PF_R32_UINT, sizeof(uint32), alignof(uint32)) },
};


TMap<FRealtimeMeshElementConversionKey, FRealtimeMeshElementConverters> FRealtimeMeshBufferLayoutUtilities::TypeConversionMap;


FName FRealtimeMeshBufferLayoutUtilities::GetRealtimeMeshDatumTypeName(ERealtimeMeshDatumType Datum)
Expand Down Expand Up @@ -165,4 +166,128 @@ namespace RealtimeMesh
{
return FRealtimeMeshBufferLayoutDefinition(BufferLayout, GetTypeDefinition(BufferLayout.GetElementType()));
}

const FRealtimeMeshElementConverters& FRealtimeMeshBufferLayoutUtilities::GetTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType)
{
return TypeConversionMap.FindChecked(FRealtimeMeshElementConversionKey(FromType, ToType));
}

void FRealtimeMeshBufferLayoutUtilities::RegisterTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType,
FRealtimeMeshElementConverters Converters)
{
TypeConversionMap.Add(FRealtimeMeshElementConversionKey(FromType, ToType), Converters);
}

void FRealtimeMeshBufferLayoutUtilities::UnregisterTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType)
{
TypeConversionMap.Remove(FRealtimeMeshElementConversionKey(FromType, ToType));
}










// UInt16
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, uint16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, int16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, uint32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, int32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint16, FFloat16);


// Int16
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, uint16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, int16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, uint32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, int32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int16, FFloat16);

// UInt32
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, uint16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, int16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, uint32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, int32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(uint32, FFloat16);

// Int32
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, uint16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, int16);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, uint32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, int32);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(int32, FFloat16);

// float
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(float, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(float, FFloat16);

// FFloat16
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FFloat16, float);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FFloat16, FFloat16);

// FVector2DHalf
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2DHalf, FVector2DHalf);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2DHalf, FVector2f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2DHalf, FVector2d);

// FVector2f
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2f, FVector2DHalf);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2f, FVector2f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2f, FVector2d);

// FVector2d
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2d, FVector2DHalf);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2d, FVector2f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector2d, FVector2d);

// FVector3f
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector3f, FVector3f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector3f, FVector3d);

// FVector3d
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector3d, FVector3f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector3d, FVector3d);

// FVector4f
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4f, FVector4f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4f, FVector4d);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4f, FPackedNormal);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4f, FPackedRGBA16N);

// FVector4d
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4d, FVector4f);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4d, FVector4d);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4d, FPackedNormal);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FVector4d, FPackedRGBA16N);


// FPackedNormal
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedNormal, FVector4f, { *static_cast<FVector4f*>(Destination) = (*static_cast<FPackedNormal*>(Source)).ToFVector4f(); });
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedNormal, FVector4d, { *static_cast<FVector4d*>(Destination) = (*static_cast<FPackedNormal*>(Source)).ToFVector4(); });
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FPackedNormal, FPackedNormal);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedNormal, FPackedRGBA16N, { *static_cast<FPackedRGBA16N*>(Destination) = (*static_cast<FPackedNormal*>(Source)).ToFVector4f(); });

// FPackedRGBA16N
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FVector4f, { *static_cast<FVector4f*>(Destination) = (*static_cast<FPackedRGBA16N*>(Source)).ToFVector4f(); });
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FVector4d, { *static_cast<FVector4d*>(Destination) = (*static_cast<FPackedRGBA16N*>(Source)).ToFVector4(); });
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FPackedNormal, { *static_cast<FPackedNormal*>(Destination) = (*static_cast<FPackedRGBA16N*>(Source)).ToFVector4f(); });
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FPackedRGBA16N, FPackedRGBA16N);

// FColor
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FColor, FColor);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FColor, FLinearColor, { *static_cast<FLinearColor*>(Destination) = FLinearColor::FromSRGBColor(*static_cast<FColor*>(Source)); })

// FLinearColor
RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FLinearColor, FLinearColor);
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FLinearColor, FColor, { *static_cast<FColor*>(Destination) = static_cast<FLinearColor*>(Source)->ToFColorSRGB(); })


}
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ namespace RealtimeMesh
{
SCOPE_CYCLE_COUNTER(STAT_RealtimeMeshComponentSceneProxy_GetDynamicRayTracingInstances);

// Make sure all pending changes have been processed
/*// Make sure all pending changes have been processed
RealtimeMeshProxy->HandleUpdates(false);
// TODO: Should this use any LOD determination logic? Or always use a specific LOD?
Expand Down Expand Up @@ -302,10 +302,10 @@ namespace RealtimeMesh
IsShadowCast(Context.ReferenceView)
};
RealtimeMeshProxy->CreateMeshBatches(LODIndex, Params, Materials, nullptr, ERealtimeMeshSectionDrawType::Dynamic, true /* bForceDynamicPath */);
RealtimeMeshProxy->CreateMeshBatches(LODIndex, Params, Materials, nullptr, ERealtimeMeshSectionDrawType::Dynamic, true /* bForceDynamicPath #1#);
}
}
}
}*/

check(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ namespace RealtimeMesh
StreamData->InitializeIfRequired();

TSharedPtr<FRealtimeMeshGPUBuffer, ESPMode::ThreadSafe> GPUBuffer;


// If we have the stream already, just update it
if (const TSharedPtr<FRealtimeMeshGPUBuffer, ESPMode::ThreadSafe>* FoundBuffer = Streams.Find(StreamData->GetStreamKey()))
Expand All @@ -303,6 +304,8 @@ namespace RealtimeMesh
Streams.Add(StreamData->GetStreamKey(), GPUBuffer);
}

check(GPUBuffer);
check(GPUBuffer->IsResourceInitialized());
GPUBuffer->ApplyBufferUpdate(Batcher, StreamData);

MarkStateDirty();
Expand Down
121 changes: 119 additions & 2 deletions Source/RealtimeMeshComponent/Public/Data/RealtimeMeshDataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,43 @@ namespace RealtimeMesh
static const FRealtimeMeshBufferLayoutDefinition Invalid;
};

struct REALTIMEMESHCOMPONENT_API FRealtimeMeshElementConversionKey
{
const FRealtimeMeshElementType FromType;
const FRealtimeMeshElementType ToType;

FRealtimeMeshElementConversionKey(const FRealtimeMeshElementType& InFromType, const FRealtimeMeshElementType& InToType)
: FromType(InFromType), ToType(InToType)
{
}

bool operator==(const FRealtimeMeshElementConversionKey& OtherKey) const
{
return FromType == OtherKey.FromType && ToType == OtherKey.ToType;
}

friend uint32 GetTypeHash(const FRealtimeMeshElementConversionKey& Key)
{
return HashCombine(GetTypeHash(Key.FromType), GetTypeHash(Key.ToType));
}
};

struct REALTIMEMESHCOMPONENT_API FRealtimeMeshElementConverters
{
const TFunction<void(void*, void*)> SingleElementConverter;
const TFunction<void(void*, void*, uint32 Num, uint32 Stride)> ArrayElementConverter;

FRealtimeMeshElementConverters(const TFunction<void(void*, void*)> InSingleElementConverter, const TFunction<void(void*, void*, uint32 Num, uint32 Stride)> InArrayElementConverter)
: SingleElementConverter(InSingleElementConverter), ArrayElementConverter(InArrayElementConverter)
{
}
};

struct REALTIMEMESHCOMPONENT_API FRealtimeMeshBufferLayoutUtilities
{
private:
static const TMap<FRealtimeMeshElementType, FRealtimeMeshElementTypeDefinition> SupportedTypeDefinitions;
static TMap<FRealtimeMeshElementConversionKey, FRealtimeMeshElementConverters> TypeConversionMap;
public:
static FName GetRealtimeMeshDatumTypeName(ERealtimeMeshDatumType Datum);
static int32 GetRealtimeMeshDatumTypeSize(ERealtimeMeshDatumType Datum);
Expand All @@ -278,7 +311,10 @@ namespace RealtimeMesh

static const FRealtimeMeshElementTypeDefinition& GetTypeDefinition(const FRealtimeMeshElementType& VertexType);
static FRealtimeMeshBufferLayoutDefinition GetBufferLayoutDefinition(const FRealtimeMeshBufferLayout& BufferLayout);


static const FRealtimeMeshElementConverters& GetTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType);
static void RegisterTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType, FRealtimeMeshElementConverters Converters);
static void UnregisterTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType);
};


Expand All @@ -305,6 +341,15 @@ namespace RealtimeMesh
return FRealtimeMeshElementTypeTraits<ElementType>::ElementTypeDefinition;
}

inline TFunctionRef<void(void*, void*)> GetRealtimeMeshElementTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType)
{
return FRealtimeMeshBufferLayoutUtilities::GetTypeConverter(FromType, ToType).SingleElementConverter;
}

inline TFunctionRef<void(void*, void*, uint32 Num, uint32 Stride)> GetRealtimeMeshArrayTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType)
{
return FRealtimeMeshBufferLayoutUtilities::GetTypeConverter(FromType, ToType).ArrayElementConverter;
}

#define RMC_DEFINE_ELEMENT_TYPE(ElementType, DatumType, NumDatums, bNormalized, bShouldConvertToFloat) \
template<> struct FRealtimeMeshElementTypeTraits<ElementType> \
Expand All @@ -330,10 +375,17 @@ namespace RealtimeMesh
RMC_DEFINE_ELEMENT_TYPE(FVector2DHalf, ERealtimeMeshDatumType::Half, 2, false, true);

RMC_DEFINE_ELEMENT_TYPE(FColor, ERealtimeMeshDatumType::UInt8, 4, true, true);
RMC_DEFINE_ELEMENT_TYPE(FLinearColor, ERealtimeMeshDatumType::Float, 4, true, true);

RMC_DEFINE_ELEMENT_TYPE(FPackedNormal, ERealtimeMeshDatumType::Int8, 4, true, true);
RMC_DEFINE_ELEMENT_TYPE(FPackedRGBA16N, ERealtimeMeshDatumType::Int16, 4, true, true);

// These are mostly just used for external data conversion with BP for example. Not actual mesh rendering
RMC_DEFINE_ELEMENT_TYPE(double, ERealtimeMeshDatumType::Double, 1, false, true);
RMC_DEFINE_ELEMENT_TYPE(FVector2d, ERealtimeMeshDatumType::Double, 2, false, true);
RMC_DEFINE_ELEMENT_TYPE(FVector3d, ERealtimeMeshDatumType::Double, 3, false, true);
RMC_DEFINE_ELEMENT_TYPE(FVector4d, ERealtimeMeshDatumType::Double, 4, false, true);

template <typename Type>
struct TIsRealtimeMeshBaseElementType
{
Expand All @@ -345,10 +397,48 @@ namespace RealtimeMesh
static_assert(FRealtimeMeshElementTypeTraits<FPackedRGBA16N>::IsValid);
static_assert(FRealtimeMeshElementTypeTraits<FVector2f>::IsValid);
static_assert(FRealtimeMeshElementTypeTraits<FColor>::IsValid);
static_assert(FRealtimeMeshElementTypeTraits<FLinearColor>::IsValid);
static_assert(!FRealtimeMeshElementTypeTraits<void>::IsValid);
static_assert(!FRealtimeMeshElementTypeTraits<double>::IsValid);



template<typename FromType, typename ToType>
class FRealtimeMeshTypeConverterRegistration : FNoncopyable
{
static_assert(FRealtimeMeshElementTypeTraits<FromType>::IsValid);
static_assert(FRealtimeMeshElementTypeTraits<ToType>::IsValid);
public:
FRealtimeMeshTypeConverterRegistration(FRealtimeMeshElementConverters Converters)
{
FRealtimeMeshBufferLayoutUtilities::RegisterTypeConverter(GetRealtimeMeshDataElementType<FromType>(), GetRealtimeMeshDataElementType<ToType>(), Converters);
}

~FRealtimeMeshTypeConverterRegistration()
{
FRealtimeMeshBufferLayoutUtilities::UnregisterTypeConverter(GetRealtimeMeshDataElementType<FromType>(), GetRealtimeMeshDataElementType<ToType>());
}
};


#define RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FromElementType, ToElementType, ElementConverter) \
FRealtimeMeshTypeConverterRegistration<FromElementType, ToElementType> GRegister##FromElementType##To##ToElementType(FRealtimeMeshElementConverters( \
[](void* Source, void* Destination) ElementConverter, \
[](void* SourceArr, void* DestinationArr, uint32 Count, uint32 Stride) { \
for (uint32 Index = 0; Index < Count; Index++) \
{ \
void* Source = static_cast<FromElementType*>(SourceArr) + Index * Stride; \
void* Destination = static_cast<ToElementType*>(DestinationArr) + Index * Stride; \
ElementConverter; \
} \
} \
) \
);

#define RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FromElementType, ToElementType) \
RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FromElementType, ToElementType, { *static_cast<ToElementType*>(Destination) = ToElementType(*static_cast<FromElementType*>(Source)); });




template<typename TangentType>
struct FRealtimeMeshTangents
Expand Down Expand Up @@ -433,6 +523,33 @@ namespace RealtimeMesh

using FRealtimeMeshTangentsHighPrecision = FRealtimeMeshTangents<FPackedRGBA16N>;
using FRealtimeMeshTangentsNormalPrecision = FRealtimeMeshTangents<FPackedNormal>;


template<typename ChannelType>
FRealtimeMeshBufferLayout GetRealtimeMeshTexCoordFormatHelper(int32 NumChannels)
{
return
NumChannels >= 8? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 8>>() :
NumChannels >= 7? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 7>>() :
NumChannels >= 6? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 6>>() :
NumChannels >= 5? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 5>>() :
NumChannels >= 4? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 4>>() :
NumChannels >= 3? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 3>>() :
NumChannels >= 2? GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 2>>() :
GetRealtimeMeshBufferLayout<FRealtimeMeshTexCoord<ChannelType, 1>>();
}


inline FRealtimeMeshBufferLayout GetRealtimeMeshTexCoordFormatHelper(bool bUseHighPrecision, int32 NumChannels)
{
return bUseHighPrecision? GetRealtimeMeshTexCoordFormatHelper<FVector2f>(NumChannels) : GetRealtimeMeshTexCoordFormatHelper<FVector2DHalf>(NumChannels);
}


inline FRealtimeMeshBufferLayout GetRealtimeMeshTangentFormatHelper(bool bUseHighPrecision)
{
return bUseHighPrecision? GetRealtimeMeshBufferLayout<FRealtimeMeshTangentsHighPrecision>() : GetRealtimeMeshBufferLayout<FRealtimeMeshTangentsNormalPrecision>();
}



Expand Down

0 comments on commit 993aeb0

Please sign in to comment.