diff --git a/Source/RealtimeMeshComponent/Private/RealtimeMeshDataTypes.cpp b/Source/RealtimeMeshComponent/Private/RealtimeMeshDataTypes.cpp index 1e0e53a..538da68 100644 --- a/Source/RealtimeMeshComponent/Private/RealtimeMeshDataTypes.cpp +++ b/Source/RealtimeMeshComponent/Private/RealtimeMeshDataTypes.cpp @@ -18,9 +18,9 @@ namespace RealtimeMesh const TMap 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)) }, @@ -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 FRealtimeMeshBufferLayoutUtilities::TypeConversionMap; FName FRealtimeMeshBufferLayoutUtilities::GetRealtimeMeshDatumTypeName(ERealtimeMeshDatumType Datum) @@ -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(Destination) = (*static_cast(Source)).ToFVector4f(); }); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedNormal, FVector4d, { *static_cast(Destination) = (*static_cast(Source)).ToFVector4(); }); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FPackedNormal, FPackedNormal); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedNormal, FPackedRGBA16N, { *static_cast(Destination) = (*static_cast(Source)).ToFVector4f(); }); + + // FPackedRGBA16N + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FVector4f, { *static_cast(Destination) = (*static_cast(Source)).ToFVector4f(); }); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FVector4d, { *static_cast(Destination) = (*static_cast(Source)).ToFVector4(); }); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FPackedRGBA16N, FPackedNormal, { *static_cast(Destination) = (*static_cast(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(Destination) = FLinearColor::FromSRGBColor(*static_cast(Source)); }) + + // FLinearColor + RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FLinearColor, FLinearColor); + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FLinearColor, FColor, { *static_cast(Destination) = static_cast(Source)->ToFColorSRGB(); }) + + } diff --git a/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshComponentProxy.cpp b/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshComponentProxy.cpp index a3257be..c753f27 100644 --- a/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshComponentProxy.cpp +++ b/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshComponentProxy.cpp @@ -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? @@ -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); } diff --git a/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshSectionGroupProxy.cpp b/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshSectionGroupProxy.cpp index 3091d45..448ca4e 100644 --- a/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshSectionGroupProxy.cpp +++ b/Source/RealtimeMeshComponent/Private/RenderProxy/RealtimeMeshSectionGroupProxy.cpp @@ -284,6 +284,7 @@ namespace RealtimeMesh StreamData->InitializeIfRequired(); TSharedPtr GPUBuffer; + // If we have the stream already, just update it if (const TSharedPtr* FoundBuffer = Streams.Find(StreamData->GetStreamKey())) @@ -303,6 +304,8 @@ namespace RealtimeMesh Streams.Add(StreamData->GetStreamKey(), GPUBuffer); } + check(GPUBuffer); + check(GPUBuffer->IsResourceInitialized()); GPUBuffer->ApplyBufferUpdate(Batcher, StreamData); MarkStateDirty(); diff --git a/Source/RealtimeMeshComponent/Public/Data/RealtimeMeshDataTypes.h b/Source/RealtimeMeshComponent/Public/Data/RealtimeMeshDataTypes.h index 5ad762f..43418e6 100644 --- a/Source/RealtimeMeshComponent/Public/Data/RealtimeMeshDataTypes.h +++ b/Source/RealtimeMeshComponent/Public/Data/RealtimeMeshDataTypes.h @@ -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 SingleElementConverter; + const TFunction ArrayElementConverter; + + FRealtimeMeshElementConverters(const TFunction InSingleElementConverter, const TFunction InArrayElementConverter) + : SingleElementConverter(InSingleElementConverter), ArrayElementConverter(InArrayElementConverter) + { + } + }; + struct REALTIMEMESHCOMPONENT_API FRealtimeMeshBufferLayoutUtilities { private: static const TMap SupportedTypeDefinitions; + static TMap TypeConversionMap; public: static FName GetRealtimeMeshDatumTypeName(ERealtimeMeshDatumType Datum); static int32 GetRealtimeMeshDatumTypeSize(ERealtimeMeshDatumType Datum); @@ -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); }; @@ -305,6 +341,15 @@ namespace RealtimeMesh return FRealtimeMeshElementTypeTraits::ElementTypeDefinition; } + inline TFunctionRef GetRealtimeMeshElementTypeConverter(const FRealtimeMeshElementType& FromType, const FRealtimeMeshElementType& ToType) + { + return FRealtimeMeshBufferLayoutUtilities::GetTypeConverter(FromType, ToType).SingleElementConverter; + } + + inline TFunctionRef 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 \ @@ -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 struct TIsRealtimeMeshBaseElementType { @@ -345,10 +397,48 @@ namespace RealtimeMesh static_assert(FRealtimeMeshElementTypeTraits::IsValid); static_assert(FRealtimeMeshElementTypeTraits::IsValid); static_assert(FRealtimeMeshElementTypeTraits::IsValid); + static_assert(FRealtimeMeshElementTypeTraits::IsValid); static_assert(!FRealtimeMeshElementTypeTraits::IsValid); - static_assert(!FRealtimeMeshElementTypeTraits::IsValid); + + + template + class FRealtimeMeshTypeConverterRegistration : FNoncopyable + { + static_assert(FRealtimeMeshElementTypeTraits::IsValid); + static_assert(FRealtimeMeshElementTypeTraits::IsValid); + public: + FRealtimeMeshTypeConverterRegistration(FRealtimeMeshElementConverters Converters) + { + FRealtimeMeshBufferLayoutUtilities::RegisterTypeConverter(GetRealtimeMeshDataElementType(), GetRealtimeMeshDataElementType(), Converters); + } + + ~FRealtimeMeshTypeConverterRegistration() + { + FRealtimeMeshBufferLayoutUtilities::UnregisterTypeConverter(GetRealtimeMeshDataElementType(), GetRealtimeMeshDataElementType()); + } + }; + + +#define RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FromElementType, ToElementType, ElementConverter) \ + FRealtimeMeshTypeConverterRegistration 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(SourceArr) + Index * Stride; \ + void* Destination = static_cast(DestinationArr) + Index * Stride; \ + ElementConverter; \ + } \ + } \ + ) \ + ); + +#define RMC_DEFINE_ELEMENT_TYPE_CONVERTER_TRIVIAL(FromElementType, ToElementType) \ + RMC_DEFINE_ELEMENT_TYPE_CONVERTER(FromElementType, ToElementType, { *static_cast(Destination) = ToElementType(*static_cast(Source)); }); + + template struct FRealtimeMeshTangents @@ -433,6 +523,33 @@ namespace RealtimeMesh using FRealtimeMeshTangentsHighPrecision = FRealtimeMeshTangents; using FRealtimeMeshTangentsNormalPrecision = FRealtimeMeshTangents; + + + template + FRealtimeMeshBufferLayout GetRealtimeMeshTexCoordFormatHelper(int32 NumChannels) + { + return + NumChannels >= 8? GetRealtimeMeshBufferLayout>() : + NumChannels >= 7? GetRealtimeMeshBufferLayout>() : + NumChannels >= 6? GetRealtimeMeshBufferLayout>() : + NumChannels >= 5? GetRealtimeMeshBufferLayout>() : + NumChannels >= 4? GetRealtimeMeshBufferLayout>() : + NumChannels >= 3? GetRealtimeMeshBufferLayout>() : + NumChannels >= 2? GetRealtimeMeshBufferLayout>() : + GetRealtimeMeshBufferLayout>(); + } + + + inline FRealtimeMeshBufferLayout GetRealtimeMeshTexCoordFormatHelper(bool bUseHighPrecision, int32 NumChannels) + { + return bUseHighPrecision? GetRealtimeMeshTexCoordFormatHelper(NumChannels) : GetRealtimeMeshTexCoordFormatHelper(NumChannels); + } + + + inline FRealtimeMeshBufferLayout GetRealtimeMeshTangentFormatHelper(bool bUseHighPrecision) + { + return bUseHighPrecision? GetRealtimeMeshBufferLayout() : GetRealtimeMeshBufferLayout(); + } diff --git a/Source/RealtimeMeshComponent/Public/RenderProxy/RealtimeMeshGPUBuffer.h b/Source/RealtimeMeshComponent/Public/RenderProxy/RealtimeMeshGPUBuffer.h index e003665..21259bf 100644 --- a/Source/RealtimeMeshComponent/Public/RenderProxy/RealtimeMeshGPUBuffer.h +++ b/Source/RealtimeMeshComponent/Public/RenderProxy/RealtimeMeshGPUBuffer.h @@ -88,7 +88,7 @@ namespace RealtimeMesh else { check(StreamKey.IsIndexStream()); - Buffer = RHICreateIndexBuffer(BufferLayout.GetStride(), Resource->GetResourceDataSize(), UsageFlags | BUF_IndexBuffer | BUF_ShaderResource, CreateInfo); + Buffer = RHICreateIndexBuffer(BufferLayout.GetStride(), Resource->GetResourceDataSize(), UsageFlags | BUF_IndexBuffer, CreateInfo); } } } @@ -132,6 +132,7 @@ namespace RealtimeMesh virtual ERealtimeMeshStreamType GetStreamType() const = 0; virtual void InitializeResources() = 0; virtual void ReleaseUnderlyingResource() = 0; + virtual bool IsResourceInitialized() const = 0; FORCEINLINE const FRealtimeMeshBufferLayoutDefinition& GetBufferLayout() const { return BufferLayout; } FORCEINLINE EPixelFormat GetElementFormat() const { return BufferLayout.GetElementTypeDefinition().GetPixelFormat(); } @@ -186,6 +187,8 @@ namespace RealtimeMesh virtual void ReleaseUnderlyingResource() override { ReleaseResource(); } + virtual bool IsResourceInitialized() const override { return IsInitialized(); } + /** Gets the format of the vertex */ FORCEINLINE EVertexElementType GetVertexType() const { return GetBufferLayout().GetElementTypeDefinition().GetVertexType(); } @@ -194,21 +197,30 @@ namespace RealtimeMesh FRHIResourceCreateInfo CreateInfo(TEXT("RealtimeMeshBuffer-Vertex-Init")); CreateInfo.bWithoutNativeResource = true; VertexBufferRHI = RHICreateVertexBuffer(0, BUF_VertexBuffer | BUF_Static, CreateInfo); - ShaderResourceViewRHI = RHISupportsManualVertexFetch(GMaxRHIShaderPlatform) - ? RHICreateShaderResourceView(FShaderResourceViewInitializer(nullptr, PF_R32_FLOAT)) - : nullptr; + if (VertexBufferRHI && RHISupportsManualVertexFetch(GMaxRHIShaderPlatform)) + { + ShaderResourceViewRHI = RHICreateShaderResourceView(FShaderResourceViewInitializer(nullptr, PF_R32G32B32F)); + } } virtual void ApplyBufferUpdate(TRHIResourceUpdateBatcher& Batcher, const FRealtimeMeshSectionGroupStreamUpdateDataRef& UpdateData) override { check(IsInitialized()); + FRealtimeMeshGPUBuffer::ApplyBufferUpdate(Batcher, UpdateData); { Batcher.QueueUpdateRequest(VertexBufferRHI, UpdateData->GetBuffer()); if (ShaderResourceViewRHI) { - Batcher.QueueUpdateRequest(ShaderResourceViewRHI, VertexBufferRHI, GetElementStride(), GetElementFormat()); + if (UpdateData->GetBuffer().IsValid()) + { + Batcher.QueueUpdateRequest(ShaderResourceViewRHI, VertexBufferRHI, GetElementStride(), GetElementFormat()); + } + else + { + Batcher.QueueUpdateRequest(ShaderResourceViewRHI, nullptr, 0, 0); + } } } } @@ -232,6 +244,8 @@ namespace RealtimeMesh virtual void ReleaseUnderlyingResource() override { ReleaseResource(); } + virtual bool IsResourceInitialized() const override { return IsInitialized(); } + /** Gets the format of the index buffer */ FORCEINLINE bool IsUsing32BitIndices() const { return FRealtimeMeshBufferLayoutUtilities::Is32BitIndex(GetBufferLayout().GetElementTypeDefinition()); } @@ -250,5 +264,5 @@ namespace RealtimeMesh Batcher.QueueUpdateRequest(IndexBufferRHI, UpdateData->GetBuffer()); } }; - + }