diff --git a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md index 7a53d17..4ad0032 100644 --- a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md +++ b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md @@ -29,7 +29,7 @@ SWShaderToolBox::DrawMaterial DrawMaterial_CS_RT 调用路径: -- AShaderWorldActor::RetrieveHeightAt(好像没有引用):检索高度 +- AShaderWorldActor::[[#RetrieveHeightAt]](好像没有引用):检索高度 - AShaderWorldActor::ComputeHeight_Segmented_MapForClipMap - AShaderWorldActor::ProcessSegmentedComputation() <- AShaderWorldActor::TerrainAndSpawnablesManagement() <- AShaderWorldActor::Tick() - AShaderWorldActor::ComputeHeightMapForClipMap @@ -155,6 +155,244 @@ SWorldSubsystem->DrawMaterialToRenderTarget 1. AShaderWorldActor::ComputeHeight_Segmented_MapForClipMap 十多次 2. UpdateCollisionMeshData 3. AShaderWorldActor::ComputeHeight_Segmented_MapForClipMap 十多次 -4. RetrieveHeightAt +4. [[#RetrieveHeightAt]] 5. UpdateCollisionMeshData 3次 -6. AShaderWorldActor::ComputeHeight_Segmented_MapForClipMap 十多次 \ No newline at end of file +6. AShaderWorldActor::ComputeHeight_Segmented_MapForClipMap 十多次 + +# RetrieveHeightAt +可能存在bug待排查的: +- ShaderWorldSubsystem->LoadSampleLocationsInRT() +- ShaderWorldSubsystem->DrawMaterialToRenderTarget() + +## 相关变量 +- FThreadSafeBool + - bProcessingHeightRetrieval + - bProcessingHeightRetrievalRT +- MID + - GeneratorDynamicForReadBack +- UShaderWorldRT2D(`UTextureRenderTarget2D`) + - ReadRequestLocation:RTF_RG32f,初始化于`InitializeReadBackDependencies() <- InitiateWorld()` + - ReadRequestLocationHeightmap:RTF_RGBA8,初始化于`InitializeReadBackDependencies() <- InitiateWorld()` + + + +## 代码 +```c++ +bool AShaderWorldActor::RetrieveHeightAt(const TArray& Origin, const FSWHeightRetrievalDelegate& Callback) +{ + if (!GeneratorDynamicForReadBack || !SWorldSubsystem) + return false; + + if (!bProcessingHeightRetrieval.IsValid()) + { + bProcessingHeightRetrieval = MakeShared(); + bProcessingHeightRetrieval->AtomicSet(false); + } + if (!bProcessingHeightRetrievalRT.IsValid()) + { + bProcessingHeightRetrievalRT = MakeShared(); + bProcessingHeightRetrievalRT->AtomicSet(false); + } + + + if (!(*bProcessingHeightRetrieval.Get()) && ReadRequestLocation && ReadRequestLocationHeightmap && GeneratorDynamicForReadBack) + { + bProcessingHeightRetrieval->AtomicSet(true); + bProcessingHeightRetrievalRT->AtomicSet(false); + HeightRetrieveDelegate = Callback; + + //初始化采样点数组结构体FSWShareableSamplePoints + PointsPendingReadBacks = MakeShared(); + TSharedPtr& Samples = PointsPendingReadBacks; + + FBox BoundingBoxRead(Origin); + + Samples->PositionsXY.SetNum(25 * 2); + for (int i = 0; i < 25; i++) + { + if (i < Origin.Num()) + { + Samples->PositionsXY[i * 2] = Origin[i].X; + Samples->PositionsXY[i * 2 + 1] = Origin[i].Y; + } + else + { + Samples->PositionsXY[i * 2] = 0.f; + Samples->PositionsXY[i * 2 + 1] = 0.f; + } + } + + if (USWorldSubsystem* ShaderWorldSubsystem = SWorldSubsystem) + { + //从渲染线程 + ShaderWorldSubsystem->LoadSampleLocationsInRT(ReadRequestLocation, Samples); + +#if SW_COMPUTE_GENERATION + ShaderWorldSubsystem->DrawMaterialToRenderTarget( + { false, + false, + GetWorld()->Scene, + (float)GetWorld()->TimeSeconds, + false, + true, + ReadRequestLocationHeightmap->SizeX, + 10, + FVector(0.f), + true, + ReadRequestLocation, + GeneratorDynamicForReadBack, + ReadRequestLocationHeightmap + }); +#else + UKismetRenderingLibrary::DrawMaterialToRenderTarget(this, ReadRequestLocationHeightmap, GeneratorDynamicForReadBack); +#endif + + int32 Size_RT_Readback = ReadRequestLocationHeightmap.Get()->SizeX; + + FVector Barycentre = BoundingBoxRead.GetCenter(); + FVector Extent = BoundingBoxRead.GetExtent(); + float gridspacing = Extent.X * 2.0 / (Size_RT_Readback - 1); + + if (IsValid(BrushManager)) + BrushManager->ApplyBrushStackToHeightMap(this, 0, ReadRequestLocationHeightmap.Get(), Barycentre, gridspacing, Size_RT_Readback, true, true, ReadRequestLocation.Get()); + + + ReadBackHeightData = MakeShared(); + ReadBackHeightData->ReadData.SetNum(25); + + ENQUEUE_RENDER_COMMAND(ReadGeoClipMapRTCmd)( + [InRT = ReadRequestLocationHeightmap, HeightData = ReadBackHeightData, Completion = bProcessingHeightRetrievalRT](FRHICommandListImmediate& RHICmdList) + { + check(IsInRenderingThread()); + + if (HeightData.IsValid() && InRT->GetResource()) + { + FRDGBuilder GraphBuilder(RHICmdList); + + TSharedPtr ReadBackStaging = MakeShared(TEXT("SWGPUTextureReadback")); + + FRDGTextureRef RDGSourceTexture = RegisterExternalTexture(GraphBuilder, InRT->GetResource()->TextureRHI, TEXT("SWSourceTextureToReadbackTexture")); + + AddEnqueueCopyPass(GraphBuilder, ReadBackStaging.Get(), RDGSourceTexture); + + GraphBuilder.Execute(); + + ShaderWorld::GSWReadbackManager.AddPendingReadBack(RHICmdList, GPixelFormats[RDGSourceTexture->Desc.Format].BlockBytes, RDGSourceTexture->Desc.Extent.X, RDGSourceTexture->Desc.Extent.Y, ReadBackStaging, const_cast&>(HeightData), const_cast&>(Completion)); + + } + + }); + + HeightReadBackFence.BeginFence(true); + } + + return true; + } + + return false; +} +``` + + +### RequestReadBackLoad +```c++ +bool USWorldSubsystem::LoadSampleLocationsInRT(UShaderWorldRT2D* LocationsRequestedRT, + TSharedPtr& Samples) +{ + if (!RenderThreadResponded) + return false; + + const SWSampleRequestComputeData ReadBackData(LocationsRequestedRT, Samples); + SWToolBox->RequestReadBackLoad(ReadBackData); + return true; +} +``` +# SWShaderToolBox +## RequestReadBackLoad +```c++ +void SWShaderToolBox::RequestReadBackLoad(const SWSampleRequestComputeData& Data) const +{ + if (Data.CPU) + return CPUTools.RequestReadBackLoad(Data); + + ENQUEUE_RENDER_COMMAND(ShaderTools_copy_rt) + ([this, Data](FRHICommandListImmediate& RHICmdList) + { + if (Data.SamplesXY && Data.SamplesXY->GetResource()) + RequestReadBackLoad_RT(RHICmdList,Data); + } + ); + +} + +void SWShaderToolBox::RequestReadBackLoad_RT(FRHICommandListImmediate& RHICmdList, const SWSampleRequestComputeData& Data) const +{ + if (!(Data.SamplesXY && Data.SamplesXY->GetResource())) + return; + + FRDGBuilder GraphBuilder(RHICmdList); + + { + RDG_EVENT_SCOPE(GraphBuilder, "ShaderWorld PositionReadBack"); + RDG_GPU_STAT_SCOPE(GraphBuilder, ShaderWorldReadBack); + + FIntVector GroupCount; + GroupCount.X = FMath::DivideAndRoundUp((float)Data.SamplesXY->GetResource()->GetSizeX(), (float)SW_LoadReadBackLocations_GroupSizeX); + GroupCount.Y = FMath::DivideAndRoundUp((float)Data.SamplesXY->GetResource()->GetSizeY(), (float)SW_LoadReadBackLocations_GroupSizeY); + GroupCount.Z = 1; + + const FUnorderedAccessViewRHIRef RT_UAV = GraphBuilder.RHICmdList.CreateUnorderedAccessView(Data.SamplesXY->GetResource()->TextureRHI); + + const FRDGBufferRef LocationRequest = CreateUploadBuffer( + GraphBuilder, + TEXT("SWLoadSampleLocations"), + sizeof(float), + Data.SamplesSource->PositionsXY.Num(), + Data.SamplesSource->PositionsXY.GetData(), + Data.SamplesSource->PositionsXY.Num() * Data.SamplesSource->PositionsXY.GetTypeSize() + ); + + const FRDGBufferSRVRef LocationRequestSRV = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(LocationRequest, PF_R32_FLOAT));; + + FLoadReadBackLocations_CS::FPermutationDomain PermutationVector; + TShaderMapRef ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel), PermutationVector); + + FLoadReadBackLocations_CS::FParameters* PassParameters = GraphBuilder.AllocParameters(); + PassParameters->SampleDim = Data.SamplesXY->GetResource()->GetSizeX(); + PassParameters->DestLocationsTex = RT_UAV; + PassParameters->SourceLocationBuffer = LocationRequestSRV; + + + GraphBuilder.AddPass( + RDG_EVENT_NAME("ShaderWorld LoadReadBacklocations_CS"), + PassParameters, + ERDGPassFlags::Compute | + ERDGPassFlags::NeverCull, + [PassParameters, ComputeShader, GroupCount](FRHICommandList& RHICmdList) + { + FComputeShaderUtils::Dispatch(RHICmdList, ComputeShader, *PassParameters, GroupCount); + }); + + } + + GraphBuilder.Execute(); +} +``` + +FLoadReadBackLocations_CS +```c++ +uint SampleDim; +RWTexture2D DestLocationsTex; +Buffer SourceLocationBuffer; + +[numthreads(THREADGROUP_SIZEX, THREADGROUP_SIZEY, THREADGROUP_SIZEZ)] +void SampleLocationLoaderCS(uint3 ThreadId : SV_DispatchThreadID) +{ + if (any(ThreadId.xy >= SampleDim.xx)) + return; + + uint IndexPixel = (ThreadId.x + ThreadId.y * SampleDim) * 2; + + DestLocationsTex[ThreadId.xy] = float2(SourceLocationBuffer[IndexPixel],SourceLocationBuffer[IndexPixel + 1]); +} +``` \ No newline at end of file