欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > unreal gpuscene

unreal gpuscene

2024/10/25 2:26:51 来源:https://blog.csdn.net/kuangben2000/article/details/142299225  浏览:    关键词:unreal gpuscene

(1)

TypeOffsetTable 是 Primitive Type 相同 Primitive 的结束偏移,不是开始偏移,第一个类型开始偏移是 0,第一个类型结束偏移,是第一个类型的个数

Source\Runtime\Renderer\Private\RendererScene.cpp

FTypeOffsetTableEntry& NextEntry = TypeOffsetTable[TypeIndex];

(1)

Primitives SOA 数据,不会修改这个数据结构,PersistentPrimitiveIdToIndexMap 是进行二次映射,映射到 Primitives,PersistentPrimitiveIdToIndexMap 下标索引和 Primitives 一致,PersistentPrimitiveIdToIndexMap 下标索引内容,对应 Primitives 索引

Primitives[SourceIndex]->PackedIndex 表示应该放置的数组下标

Source\Runtime\Renderer\Private\RendererScene.cpp

FPersistentPrimitiveIndex MovedPersisitentIndex = Primitives[DestIndex]->PersistentIndex;

PersistentPrimitiveIdToIndexMap[MovedPersisitentIndex.Index] = SourceIndex;

Primitives[SourceIndex]->PackedIndex = DestIndex;

(1)

需要更新 instance 条件,UpdatedInstances 和 AddedLocalPrimitiveSceneInfos

PendingAllocateInstanceIds.Reserve(UpdatedInstances.Num() + AddedLocalPrimitiveSceneInfos.Num());

(1)

primitive 更新条件 AddedPrimitiveSceneInfos 和 UpdatedTransforms 和 UpdatedInstances,不太明白为什么 UpdatedInstances 更新需要修改 primitive

const int32 SceneInfosContainerReservedSize = AddedPrimitiveSceneInfos.Num() + UpdatedTransforms.Num() + UpdatedInstances.Num();

(1)

GPUSceneInstanceSceneDataRW 是 float4 的 soa

Saved\ShaderDebugInfo\PCD3D_SM6\Global\FGPUSceneSetInstancePrimitiveIdCS\0\GPUSceneDataManagement.usf

RWStructuredBuffer<float4> GPUSceneInstanceSceneDataRW;
float4 LoadInstanceSceneDataElement(uint Index)
{
    return GPUSceneInstanceSceneDataRW[Index];
}

(1)

Source\Runtime\Engine\Public\InstanceUniformShaderParameters.h

ENGINE_API void Build

    (

        uint32 PrimitiveId,

        uint32 RelativeId,

        uint32 InstanceFlags,

        uint32 LastUpdateFrame,

        uint32 CustomDataCount,

        float RandomID,

        bool bIsVisible = true

    );

(1)

Source\Runtime\Renderer\Private\GPUScene.cpp

InstanceUploadInfo.InstanceSceneDataBuffers = PrimitiveSceneInfo->GetInstanceSceneDataBuffers();

        if (InstanceUploadInfo.InstanceSceneDataBuffers)

        {

            const FInstanceSceneDataBuffers::FReadView InstanceSceneDataBuffers = InstanceUploadInfo.InstanceSceneDataBuffers->GetReadView();

            InstanceUploadInfo.NumInstances = InstanceUploadInfo.InstanceSceneDataBuffers->GetNumInstances();

            InstanceUploadInfo.InstanceFlags = PackFlags(InstanceSceneDataBuffers.Flags);

            InstanceUploadInfo.InstanceLightShadowUVBias = InstanceSceneDataBuffers.InstanceLightShadowUVBias;

            InstanceUploadInfo.InstanceCustomData = InstanceSceneDataBuffers.InstanceCustomData;

            InstanceUploadInfo.InstanceRandomID = InstanceSceneDataBuffers.InstanceRandomIDs;

            InstanceUploadInfo.InstanceHierarchyOffset = InstanceSceneDataBuffers.InstanceHierarchyOffset;

            InstanceUploadInfo.InstancePayloadExtension = InstanceSceneDataBuffers.InstancePayloadExtension;

            InstanceUploadInfo.InstanceLocalBounds = InstanceSceneDataBuffers.InstanceLocalBounds;

#if WITH_EDITOR

            InstanceUploadInfo.InstanceEditorData = InstanceSceneDataBuffers.InstanceEditorData;

#endif

(1)

UploadDataSourceAdapter  cpu 信息获取读写封装

PrimitiveUploader gpu 数据读写封装

GetPrimitiveShaderData 获取内存 primitive 数据

Source\Runtime\Renderer\Private\GPUScene.cpp

            ParallelForTemplate(TEXT("GPUScene Upload Primitives Task"), TaskContext.NumPrimitiveDataUploads, 1, [&TaskContext, &UploadDataSourceAdapter](int32 ItemIndex)

            {

                FOptionalTaskTagScope TaskTagScope(ETaskTag::EParallelRenderingThread);

                FVector4f* DstData = static_cast<FVector4f*>(TaskContext.PrimitiveUploader->GetRef(ItemIndex));

                UploadDataSourceAdapter.GetPrimitiveShaderData(ItemIndex, DstData);

            }, bExecuteInParallel ? EParallelForFlags::None : EParallelForFlags::ForceSingleThread);

        }

(1)

Instance Data 内存数据打包流程

Source\Runtime\Engine\Public\InstanceUniformShaderParameters.h

FORCEINLINE void BuildInternal

    (

        uint32 PrimitiveId,

        uint32 RelativeId,

        uint32 InstanceFlags,

        uint32 LastUpdateFrame,

        uint32 CustomDataCount,

        float RandomID,

        const FRenderTransform& LocalToWorld,

        bool bIsVisible,

        bool bSupportsCompressedTransforms

    )

    {

        // Note: layout must match GetInstanceData in SceneData.ush and InitializeInstanceSceneData in GPUSceneWriter.ush

        const float RotDeterminant = LocalToWorld.RotDeterminant();

        if (RotDeterminant < 0.0f)

        {

            InstanceFlags |= INSTANCE_SCENE_DATA_FLAG_DETERMINANT_SIGN;

        }

        else

        {

            InstanceFlags &= ~INSTANCE_SCENE_DATA_FLAG_DETERMINANT_SIGN;

        }

        // Mark zero scaled instances as hidden.

        if (!bIsVisible || RotDeterminant == 0.0f)

        {

            InstanceFlags |= INSTANCE_SCENE_DATA_FLAG_HIDDEN;

        }

        checkSlow((PrimitiveId      & 0x000FFFFF) == PrimitiveId);

        checkSlow((InstanceFlags    & 0x00000FFF) == InstanceFlags);

        checkSlow((RelativeId       & 0x00FFFFFF) == RelativeId);

        checkSlow((CustomDataCount  & 0x000000FF) == CustomDataCount);

        const uint32 Packed0 = (InstanceFlags   << 20u) | PrimitiveId;

        const uint32 Packed1 = (CustomDataCount << 24u) | RelativeId;

        Data[0].X  = *(const float*)&Packed0;

        Data[0].Y  = *(const float*)&Packed1;

        Data[0].Z  = *(const float*)&LastUpdateFrame;

        Data[0].W  = *(const float*)&RandomID;

        if (bSupportsCompressedTransforms)

        {

            FCompressedTransform CompressedLocalToWorld(LocalToWorld);

            Data[1] = *(const FVector4f*)&CompressedLocalToWorld.Rotation[0];

            Data[2] = *(const FVector3f*)&CompressedLocalToWorld.Translation;

        }

        else

        {

            // Note: writes 3x float4s

            LocalToWorld.To3x4MatrixTranspose((float*)&Data[1]);

        }

    }

(1)

instance data 内存数据编码,上传显存数据

Source\Runtime\Renderer\Private\GPUScene.cpp

if (UploadInfo.InstanceSceneDataBuffers != nullptr)

                        {

                            InstanceSceneData.BuildInternal(

                                UploadInfo.PrimitiveID,

                                InstanceIndex,

                                UploadInfo.InstanceFlags,

                                UploadInfo.LastUpdateSceneFrameNumber,

                                UploadInfo.InstanceCustomDataCount,

                                RandomID,

                                UploadInfo.InstanceSceneDataBuffers->GetInstanceToPrimitiveRelative(InstanceIndex),

                                !UploadInfo.bIsPrimitiveForceHidden && UploadInfo.InstanceSceneDataBuffers->GetInstanceVisible(InstanceIndex),

                                bSupportsCompressedTransforms

                            );

                        }

(1)

instance data 保存在 Primitive data 中的  InstanceSceneDataBuffers 或者 PrimitiveInstances 字段, ism static mesh 或者多个 instance 使用的是 InstanceSceneDataBuffers ,dynamic mesh 使用的是 PrimitiveInstances 字段传递 instance 数据

Source\Runtime\Renderer\Private\GPUScene.cpp

FInstanceSceneShaderData InstanceSceneData;

                        if (UploadInfo.InstanceSceneDataBuffers != nullptr)

                        {

                            InstanceSceneData.BuildInternal(

                                UploadInfo.PrimitiveID,

                                InstanceIndex,

                                UploadInfo.InstanceFlags,

                                UploadInfo.LastUpdateSceneFrameNumber,

                                UploadInfo.InstanceCustomDataCount,

                                RandomID,

                                UploadInfo.InstanceSceneDataBuffers->GetInstanceToPrimitiveRelative(InstanceIndex),

                                !UploadInfo.bIsPrimitiveForceHidden && UploadInfo.InstanceSceneDataBuffers->GetInstanceVisible(InstanceIndex),

                                bSupportsCompressedTransforms

                            );

                        }

                        else if (UploadInfo.PrimitiveInstances.IsEmpty())

                        {

                            // This path should only be taken for uninstanced primitives

                            check(UploadInfo.NumInstances == 1 && InstanceIndex == 0);

                            InstanceSceneData.BuildInternal(

                                UploadInfo.PrimitiveID,

                                InstanceIndex,

                                UploadInfo.InstanceFlags,

                                UploadInfo.LastUpdateSceneFrameNumber,

                                UploadInfo.InstanceCustomDataCount,

                                RandomID,

                                UploadInfo.PrimitiveToWorld,

                                !UploadInfo.bIsPrimitiveForceHidden,

                                bSupportsCompressedTransforms

                            );

                        }

                        else

                        {

                            const FInstanceSceneData& SceneData = UploadInfo.PrimitiveInstances[InstanceIndex];

                            InstanceSceneData.Build(

                                UploadInfo.PrimitiveID,

                                InstanceIndex,

                                UploadInfo.InstanceFlags,

                                UploadInfo.LastUpdateSceneFrameNumber,

                                UploadInfo.InstanceCustomDataCount,

                                RandomID,

                                SceneData.LocalToPrimitive,

                                UploadInfo.PrimitiveToWorld,

                                !UploadInfo.bIsPrimitiveForceHidden

                            );

                        }

(1)

gpu scene 收集 dynamic instance 数据 MeshBatchData

E:\e\UE4\UnrealEngine\Engine\Source\Runtime\Renderer\Private\GPUScene.cpp

void FGPUScenePrimitiveCollector::Add(

    const FMeshBatchDynamicPrimitiveData* MeshBatchData,

    const FPrimitiveUniformShaderParameters& PrimitiveShaderParams,

    uint32 NumInstances,

    uint32& OutPrimitiveIndex,

    uint32& OutInstanceSceneDataOffset)

{

    check(GPUSceneDynamicContext != nullptr);

    check(!bCommitted);

   

    // Lazy allocation of the upload data to not waste space and processing if none was needed.

    if (UploadData == nullptr)

    {

        UploadData = AllocateUploadData();

    }

    const int32 PrimitiveIndex = UploadData->PrimitiveData.Num();

    FPrimitiveData& PrimitiveData = UploadData->PrimitiveData.AddDefaulted_GetRef();        

    if (MeshBatchData != nullptr)

    {

        // make sure the source data is appropriately structured

        MeshBatchData->Validate(NumInstances);

        PrimitiveData.SourceData = *MeshBatchData;

    }

   

    const int32 PayloadFloat4Stride = PrimitiveData.SourceData.GetPayloadFloat4Stride();

   

    PrimitiveData.ShaderParams = &PrimitiveShaderParams;

    PrimitiveData.NumInstances = NumInstances;

    PrimitiveData.LocalInstanceSceneDataOffset = UploadData->TotalInstanceCount;

    PrimitiveData.LocalPayloadDataOffset = PayloadFloat4Stride > 0 ? UploadData->InstancePayloadDataFloat4Count : INDEX_NONE;

    UploadData->TotalInstanceCount += NumInstances;

    UploadData->InstancePayloadDataFloat4Count += PayloadFloat4Stride * NumInstances;

    if (PrimitiveData.SourceData.DataWriterGPU.IsBound())

    {

        // Enqueue this primitive data to be executed (either upon upload or deferred to a later GPU write pass)

        UploadData->GPUWritePrimitives.Add(PrimitiveIndex);

    }

    // Set the output data offsets

    OutPrimitiveIndex = PrimitiveIndex;

    OutInstanceSceneDataOffset = PrimitiveData.LocalInstanceSceneDataOffset;

}

(1)

gpu 数据更新

Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp

FInitViewTaskDatas InitViewTaskDatas = OnRenderBegin(GraphBuilder);

(1)

Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp

{

        RDG_GPU_STAT_SCOPE(GraphBuilder, VisibilityCommands);

        BeginInitViews(GraphBuilder, SceneTexturesConfig, InstanceCullingManager, ExternalAccessQueue, InitViewTaskDatas);

    }

(1)

Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp

InitViewTaskDatas.VisibilityTaskData->FinishGatherDynamicMeshElements(BasePassDepthStencilAccess, InstanceCullingManager, VirtualTextureUpdater.Get());

(1)

Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp

Scene->GPUScene.UploadDynamicPrimitiveShaderDataForView(GraphBuilder, View);

(1)

Source\Runtime\Engine\Private\SceneManagement.cpp

void FMeshElementCollector::Commit()

{

    TRACE_CPUPROFILER_EVENT_SCOPE(FMeshElementCollector::Commit);

    check(RHICmdList);

    for (TPair<FGPUScenePrimitiveCollector*, FMeshBatch*> Pair : MeshBatchesForGPUScene)

    {

        GetRendererModule().AddMeshBatchToGPUScene(Pair.Key, *Pair.Value);

    }

(1)

bGPUWrite 或者 InstanceDynamicData.Num()) == NumInstances 都可以

Source\Runtime\Engine\Public\MeshBatch.h

/**

 * Dynamic primitive/instance data for a mesh batch element.

 *

 * NOTES:

 * - When applied to a FMeshBatchElement, data provided to the TConstArrayView members are expected to live until the end of the frame on the render thread

 * - If `DataWriterGPU` is bound and the TConstArrayView members are left empty, the delegate is expected to write any missing data, as it will not be uploaded

 */

struct FMeshBatchDynamicPrimitiveData

{

    FORCEINLINE void Validate(uint32 NumInstances) const

    {

#if DO_CHECK

        // Ensure array views are sized exactly for all instances, or are empty and there is a GPU writer

        const bool bGPUWrite = DataWriterGPU.IsBound();

        checkf(uint32(InstanceSceneData.Num()) == NumInstances || (bGPUWrite && InstanceSceneData.Num() == 0),

            TEXT("DynamicPrimitiveData provided should have %u instances in InstanceSceneData. Found %d"),

            NumInstances, InstanceSceneData.Num());

        if (PayloadDataFlags & INSTANCE_SCENE_DATA_FLAG_HAS_DYNAMIC_DATA)

        {

            checkf(uint32(InstanceDynamicData.Num()) == NumInstances || (bGPUWrite && InstanceDynamicData.Num() == 0),

                TEXT("DynamicPrimitiveData provided should have %u elements in InstanceDynamicData. Found %d"),

                NumInstances, InstanceDynamicData.Num());

        }

        if (PayloadDataFlags & INSTANCE_SCENE_DATA_FLAG_HAS_CUSTOM_DATA)

        {

            checkf(NumInstanceCustomDataFloats > 0,

                TEXT("DynamicPrimitiveData provided has the custom data flag set, but NumInstanceCustomDataFloats == 0"));

            checkf(uint32(InstanceCustomData.Num()) == NumInstances * NumInstanceCustomDataFloats || (bGPUWrite && InstanceCustomData.Num() == 0),

                TEXT("DynamicPrimitiveData provided should have %u elements in InstanceCustomData. Found %d"),

                NumInstances * NumInstanceCustomDataFloats, InstanceCustomData.Num());

        }

#endif

    }

};

(1)

dynamic primitive instance 数据上传,取决于 DataWriterGPU

Source\Runtime\Renderer\Private\GPUScene.cpp

void FGPUScene::UploadDynamicPrimitiveShaderDataForViewInternal(FRDGBuilder& GraphBuilder, FViewInfo& View, UE::Renderer::Private::IShadowInvalidatingInstances *ShadowInvalidatingInstances)

                // Defer this write to a later GPU write pass

                FDeferredGPUWrite DeferredWrite;

                DeferredWrite.DataWriterGPU = PrimData.SourceData.DataWriterGPU;

                DeferredWrite.ViewId = View.GPUSceneViewId;

                DeferredWrite.PrimitiveId = PrimitiveIdStart + PrimitiveIndex;

                DeferredWrite.InstanceSceneDataOffset = InstanceIdStart + PrimData.LocalInstanceSceneDataOffset;

                uint32 PassIndex = uint32(PrimData.SourceData.DataWriterGPUPass);

                DeferredGPUWritePassDelegates[PassIndex].Add(DeferredWrite);

            }

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com