wip(standalone): GPU step 25 -- shape profile, roughness endpoint reuse, export before CPU frame; first launch REGRESSED
Luna: shape_compile profiled (8 workers, detail band ~323 ms of ~545 ms over 9.39M
candidates; roughness dominates). Exact vertical roughness endpoint reuse in
ShapeWorldInternal.h, hashes unchanged: ~548-577 -> ~535-548 ms. Overlapping
pipeline/pool with shape or streaming made things slower, so it stays serial (pool
precompile now 4-20 ms). Export starts before the first CPU frame. Marker-miss stall
reproduced and gated differently; the forced-cold survival audit now hits
DXGI 0x887A0005 (device removed) on a timestamp query and is NOT passing. Auto
survival passes (6.16 GB). The vertex count at InitialClipmapReady counts CPU
batches only (GPU-resident tiles excluded) -- confirmed counting, not missing geometry.
My runs outside the sandbox (Step25.exe, marker removed first, interleaved, -Timeline):
CPU 1.329 / 1.295 / 1.318 s
GPU cached 1.152 / 1.170 / 1.137 s, all 1,434 GPU tiles (timestamps 292 / 260 / 356 ms,
max dispatch 19.0 / 15.9 / 75.2 ms)
GPU marker miss 2.015 s -- REGRESSION vs step 24's 1.336 s. CPU had all 2,226 tiles by
~1.3 s, but near_all_tiles_ready waited for the post-view shader warmup
(queue 1,025 ms, finished 1,955 ms; handoff cpu_started=1434 takeover=0).
Audits: hashes w1/w8, walk 5,642/5,642, near 960 / far 1,114 0 diffs vs CPU and
WARP, thin 353, ten captures 2+2 edge pixels as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
94d50edb47
commit
20acf57678
9 files changed
+380
-20
No files matched your search
@@ -1469,6 +1469,7 @@ namespace
|
||||
std::once_flag StartOnce;
|
||||
std::chrono::steady_clock::time_point DispatchAt{};
|
||||
std::chrono::steady_clock::time_point PrepareStart{};
|
||||
std::chrono::steady_clock::time_point CpuReadyAt{};
|
||||
std::atomic<std::size_t> Remaining{0};
|
||||
std::atomic<std::size_t> Failed{0};
|
||||
std::atomic<uint64> WorkerNanoseconds{0};
|
||||
@@ -1542,6 +1543,10 @@ namespace
|
||||
bool bFarShapeStagePending=false;
|
||||
bool bGpuFarEnabled=false;
|
||||
bool bGpuFarPipelineInitialized=false;
|
||||
std::thread GpuPipelineStartupThread;
|
||||
bool bGpuPipelineStartupAttempted=false,bGpuPipelineStartupSucceeded=false;
|
||||
bool bGpuPipelineStartupWasDeferred=false;
|
||||
std::string GpuPipelineStartupError;
|
||||
bool bDisableGpuColdStartDrain=false;
|
||||
bool bGpuFarAuditEnabled=false;
|
||||
bool bGpuFarShaderPrewarm=false,bDisableGpuWarmupPresentHold=false;
|
||||
@@ -1577,6 +1582,8 @@ namespace
|
||||
std::atomic<bool> bGpuShaderWarmupQueueFinished{false};
|
||||
bool bGpuWarmupContextProtected=false;
|
||||
std::string GpuShaderWarmupQueueError;
|
||||
std::chrono::steady_clock::time_point GpuShaderWarmupQueueStartedAt{},GpuShaderWarmupQueueFinishedAt{};
|
||||
std::chrono::steady_clock::time_point CpuReadyFrameBeforeGpuAt{};
|
||||
bool bGpuFarAuditReported=false;
|
||||
bool bGpuSkirtEmitEnabled=true,bGpuConnectorRepairEnabled=true;
|
||||
bool bDisableVSync=false;
|
||||
@@ -1617,6 +1624,8 @@ namespace
|
||||
uint32 GpuFarMaxTilesPerSubmissionBatch=0;
|
||||
uint32 GpuFarOutputCapacitySlots=0,GpuFarNextOutputSlot=0;
|
||||
uint32 GpuFarOutputPoolReservedSlots=0;
|
||||
std::size_t GpuFarPreReservePoolSlots=0;
|
||||
int32 GpuFarPreReserveCoarseTileCells=0;
|
||||
std::vector<uint32> GpuFarFreeOutputSlots;
|
||||
std::unordered_map<FVoxelTileKey,VoxelForgeCore::FarFieldTileInput,FStandaloneTileKeyHash> GpuFarPreparedInputs;
|
||||
std::unordered_map<FVoxelTileKey,std::string,FStandaloneTileKeyHash> GpuFarPreparationErrors;
|
||||
@@ -1807,6 +1816,7 @@ namespace
|
||||
(void)bCancel;
|
||||
if(Streamer)Streamer->Stop();
|
||||
Streamer.reset();
|
||||
if(GpuPipelineStartupThread.joinable())GpuPipelineStartupThread.join();
|
||||
GpuFarPreparationState.reset();
|
||||
bGpuFarPreparationStarted=false;
|
||||
if(FullShapeBuildThread.joinable())FullShapeBuildThread.join();
|
||||
@@ -1995,7 +2005,18 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
|
||||
bool EnsureGpuFarPipeline(std::string& Error)
|
||||
{
|
||||
if(!bGpuFarEnabled||bGpuFarPipelineInitialized)return true;
|
||||
if(!bGpuFarEnabled)return true;
|
||||
if(GpuPipelineStartupThread.joinable())
|
||||
{
|
||||
GpuPipelineStartupThread.join();
|
||||
if(!bGpuPipelineStartupSucceeded&&!bGpuPipelineStartupWasDeferred)
|
||||
{
|
||||
Error=GpuPipelineStartupError.empty()
|
||||
?"overlapped GPU pipeline initialization failed":GpuPipelineStartupError;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(bGpuFarPipelineInitialized)return true;
|
||||
if(!Device||!Context)
|
||||
{Error="D3D device is unavailable for the GPU far pipeline";return false;}
|
||||
const auto GpuPipelineStart=std::chrono::steady_clock::now();
|
||||
@@ -2015,6 +2036,77 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartGpuPipelineStartup(std::size_t PreReservePoolSlots,int32 CoarseTileCells)
|
||||
{
|
||||
if(!bGpuFarEnabled||bGpuFarPipelineInitialized||GpuPipelineStartupThread.joinable()
|
||||
||bGpuPipelineStartupAttempted||bGpuFarWarmupBeforeWorkers)return;
|
||||
if(!Device||!Context)return;
|
||||
bGpuPipelineStartupAttempted=true;
|
||||
GpuPipelineStartupThread=std::thread([this,PreReservePoolSlots,CoarseTileCells]()
|
||||
{
|
||||
ResolveGpuWarmupLaunchPolicy(true);
|
||||
if(bGpuWarmupDeferredUntilFirstView)
|
||||
{
|
||||
bGpuPipelineStartupWasDeferred=true;
|
||||
std::printf("[GpuPipelineOverlap] status=deferred reason=launch_policy_after_first_CPU_view\n");
|
||||
return;
|
||||
}
|
||||
if(!SetGpuWarmupContextProtection(true))
|
||||
{
|
||||
bGpuPipelineStartupWasDeferred=true;
|
||||
std::printf("[GpuPipelineOverlap] status=deferred reason=immediate_context_protection_unavailable\n");
|
||||
return;
|
||||
}
|
||||
const auto PipelineStart=std::chrono::steady_clock::now();
|
||||
std::printf("[GpuPipelineStartup] status=started action=pipeline_init_and_output_pool phase=post_shape_compile_before_cpu_workers\n");
|
||||
std::printf("[ColdTimeline] stage=gpu_pipeline_init begin_ms=%.3f phase=post_shape_compile_before_cpu_workers\n",
|
||||
std::chrono::duration<double,std::milli>(PipelineStart-ColdProcessStart).count());
|
||||
if(!VoxelForgeGpuFarViewer::InitializeFarPipeline(Device,Context,GpuFarShaderPath,
|
||||
GpuPipelineStartupError))
|
||||
{
|
||||
bGpuPipelineStartupSucceeded=false;
|
||||
SetGpuWarmupContextProtection(false);
|
||||
std::fprintf(stderr,"[GpuPipelineInitError] overlapped: %s\n",
|
||||
GpuPipelineStartupError.c_str());
|
||||
return;
|
||||
}
|
||||
bGpuFarPipelineInitialized=true;
|
||||
bGpuPipelineStartupSucceeded=true;
|
||||
std::printf("[ColdTimeline] stage=gpu_pipeline_init end_ms=%.3f duration_ms=%.3f prewarm=%s phase=post_shape_compile_before_cpu_workers\n",
|
||||
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-ColdProcessStart).count(),
|
||||
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-PipelineStart).count(),
|
||||
bGpuFarShaderPrewarm?(bGpuFarWarmupResourcesOnly?"async_resources_only":"async_dispatch")
|
||||
:"disabled");
|
||||
if(PreReservePoolSlots>0)
|
||||
{
|
||||
const auto PoolStart=std::chrono::steady_clock::now();
|
||||
std::printf("[ColdTimeline] stage=gpu_output_pool_precompile begin_ms=%.3f slots=%zu phase=post_shape_compile_before_cpu_workers\n",
|
||||
ColdTimelineMilliseconds(PoolStart),PreReservePoolSlots);
|
||||
std::string PoolError;
|
||||
if(VoxelForgeGpuFarViewer::ReserveFarOutputPool(Device,Context,GpuFarShaderPath,
|
||||
static_cast<uint32>(PreReservePoolSlots),static_cast<uint32>(CoarseTileCells),PoolError))
|
||||
{
|
||||
GpuFarOutputCapacitySlots=static_cast<uint32>(PreReservePoolSlots);
|
||||
GpuFarOutputPoolReservedSlots=GpuFarOutputCapacitySlots;
|
||||
const double PoolMs=std::chrono::duration<double,std::milli>(
|
||||
std::chrono::steady_clock::now()-PoolStart).count();
|
||||
GpuFarPoolReserveMs+=PoolMs;
|
||||
std::printf("[ColdTimeline] stage=gpu_output_pool_precompile end_ms=%.3f duration_ms=%.3f reserved_slots=%u phase=post_shape_compile_before_cpu_workers\n",
|
||||
ColdTimelineMilliseconds(std::chrono::steady_clock::now()),PoolMs,
|
||||
GpuFarOutputPoolReservedSlots);
|
||||
}
|
||||
else
|
||||
std::fprintf(stderr,"[GpuFarPoolError] precompile reservation deferred: %s\n",
|
||||
PoolError.c_str());
|
||||
}
|
||||
// Shader warmup issues a long queue of GPU work and can throttle the
|
||||
// CPU-heavy detail pass and initial meshing. Pipeline and pool setup
|
||||
// start after shape compilation, before the CPU stream workers.
|
||||
if(!bGpuFarShaderPrewarm||bGpuWarmupCompleted)
|
||||
SetGpuWarmupContextProtection(false);
|
||||
});
|
||||
}
|
||||
|
||||
bool BuildGpuWarmupCacheKey()
|
||||
{
|
||||
GpuWarmupCacheKey.clear();
|
||||
@@ -2183,6 +2275,15 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
bGpuWarmupCacheKeyAvailable?GpuWarmupCacheIdentity.c_str():"unavailable",
|
||||
GpuWarmupPolicyResolutionMs);
|
||||
bGpuWarmupLaunchPolicyResolved=true;
|
||||
if(!bGpuWarmupDeferredUntilFirstView&&bGpuWarmupCacheMarkerMatches)
|
||||
{
|
||||
// This exact adapter/driver/shader key was recorded only after a
|
||||
// successful warmup. Replaying tiny dispatches every process start
|
||||
// competes with shape and tile workers without changing the pipeline.
|
||||
bGpuWarmupCompleted=true;
|
||||
std::printf("[GpuWarmupCacheHit] action=skip_redundant_dispatches identity=%s\n",
|
||||
GpuWarmupCacheIdentity.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2237,11 +2338,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartGpuShaderWarmupAsync()
|
||||
void StartGpuShaderWarmupAsync(bool bShapeCompileOverlap=false)
|
||||
{
|
||||
if(!bGpuFarShaderPrewarm||bGpuWarmupCompleted||GpuShaderWarmupThread.joinable())return;
|
||||
bGpuShaderWarmupQueueSucceeded=false;GpuShaderWarmupQueueError.clear();
|
||||
bGpuShaderWarmupQueueFinished.store(false,std::memory_order_relaxed);
|
||||
GpuShaderWarmupQueueStartedAt=std::chrono::steady_clock::now();
|
||||
GpuShaderWarmupQueueFinishedAt={};
|
||||
const bool bContextProtected=SetGpuWarmupContextProtection(true);
|
||||
if(!bContextProtected)
|
||||
std::fprintf(stderr,"[GpuWarmupContextProtection] enable_failed; async immediate-context protection is unavailable\n");
|
||||
@@ -2262,11 +2365,19 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
Device,Context,GpuFarShaderPath,!bGpuFarWarmupResourcesOnly,GpuWarmupEntryFilter,
|
||||
bGpuFarWarmupKernelFences,
|
||||
GpuShaderWarmupQueueError);
|
||||
GpuShaderWarmupQueueFinishedAt=std::chrono::steady_clock::now();
|
||||
if(bGpuFarTimelineEnabled)
|
||||
std::printf("[ColdTimeline] event=gpu_warmup_queue_finished at_ms=%.3f queue_ms=%.3f success=%s\n",
|
||||
ColdTimelineMilliseconds(GpuShaderWarmupQueueFinishedAt),
|
||||
std::chrono::duration<double,std::milli>(
|
||||
GpuShaderWarmupQueueFinishedAt-GpuShaderWarmupQueueStartedAt).count(),
|
||||
bGpuShaderWarmupQueueSucceeded?"yes":"no");
|
||||
bGpuShaderWarmupQueueFinished.store(true,std::memory_order_release);
|
||||
});
|
||||
std::printf("[GpuShaderWarmup] queue_thread=started overlap=%s\n",
|
||||
bGpuWarmupDeferredUntilFirstView?"after_first_CPU_view":
|
||||
(bGpuFarWarmupBeforeWorkers?"none_before_generation_workers":"CPU_world_configuration"));
|
||||
(bGpuFarWarmupBeforeWorkers?"none_before_generation_workers":
|
||||
(bShapeCompileOverlap?"shape_compile":"CPU_world_configuration")));
|
||||
std::fflush(stdout);
|
||||
}
|
||||
|
||||
@@ -2413,6 +2524,45 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
Request.validatePassageRoutes=!bDeferWalkabilityValidation;
|
||||
if(bDeferWalkabilityValidation)
|
||||
std::printf("[DiagnosticDeferred] walkability=full_headless_or_route_audit workers=8 samples=5642\n");
|
||||
GpuFarPreReservePoolSlots=0;
|
||||
GpuFarPreReserveCoarseTileCells=World->CoarseTileCells;
|
||||
const bool bCanPreReservePool=bGpuFarEnabled&&bIncludeFarWorld&&!bNeighborhoodOnly
|
||||
&&!bCaptureOnlyTile&&!(CaptureTileLimit>0&&!CapturePath.empty());
|
||||
if(bCanPreReservePool)
|
||||
{
|
||||
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> PoolDesiredSet;
|
||||
PoolDesiredSet.reserve(Desired.Tiles.size()*2+1);
|
||||
for(const FVoxelTileKey& Key:Desired.Tiles)PoolDesiredSet.insert(Key);
|
||||
const int32 ShapeMin[3]={Min.X-2,Min.Y-2,Min.Z-2};
|
||||
const int32 ShapeMax[3]={Max.X+2,Max.Y+2,Max.Z+2};
|
||||
for(const FVoxelTileKey& Key:Desired.Tiles)
|
||||
{
|
||||
if(Key.Level<0)continue;
|
||||
if(Key.Level<World->FullResClipLevels)
|
||||
{
|
||||
if(!World->bGenerateSkirts||ComputeVisibleSkirtFaceMask(Key,PoolDesiredSet)==0)
|
||||
++GpuFarPreReservePoolSlots;
|
||||
continue;
|
||||
}
|
||||
if(Key.Level>8)continue;
|
||||
const int32 Cells=std::max(1,World->CoarseTileCells);
|
||||
if(Cells>32)continue;
|
||||
const int32 Extent=CHUNK_SIZE<<Key.Level;
|
||||
const int32 Step=std::max(1,Extent/Cells);
|
||||
const FIntVector Origin=Key.OriginVoxels();
|
||||
const int32 Origins[3]={Origin.X,Origin.Y,Origin.Z};
|
||||
bool bOutsideNearRegion=false;
|
||||
for(int32 Axis=0;Axis<3;++Axis)
|
||||
{
|
||||
const double First=std::ceil((static_cast<double>(ShapeMin[Axis])-Origins[Axis])/Step);
|
||||
const double Last=std::floor((static_cast<double>(ShapeMax[Axis])-Origins[Axis])/Step);
|
||||
if(First>Cells+1||Last< -1){bOutsideNearRegion=true;break;}
|
||||
}
|
||||
if(bOutsideNearRegion)++GpuFarPreReservePoolSlots;
|
||||
}
|
||||
std::printf("[GpuOutputPoolPreReservePlan] desired=%zu candidate_slots=%zu status=geometry_match\n",
|
||||
Desired.Tiles.size(),GpuFarPreReservePoolSlots);
|
||||
}
|
||||
const auto ShapeCompileStart=std::chrono::steady_clock::now();
|
||||
std::printf("[ConfigureProfile] stage=snapshot_and_build_request duration_ms=%.3f\n",
|
||||
std::chrono::duration<double,std::milli>(ShapeCompileStart-SnapshotStart).count());
|
||||
@@ -2424,6 +2574,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::printf("[ColdTimeline] stage=shape_compile end_ms=%.3f duration_ms=%.3f\n",
|
||||
std::chrono::duration<double,std::milli>(ShapeCompileEnd-ColdProcessStart).count(),
|
||||
std::chrono::duration<double,std::milli>(ShapeCompileEnd-ShapeCompileStart).count());
|
||||
if(bIncludeFarWorld&&!bNeighborhoodOnly)
|
||||
StartGpuPipelineStartup(GpuFarPreReservePoolSlots,
|
||||
GpuFarPreReserveCoarseTileCells);
|
||||
bShapePipelineActive=bNeighborhoodOnly;
|
||||
bNeighborhoodReadyReported=false;
|
||||
bFarShapeStagePending=bShapeWorld&&!bNeighborhoodOnly&&!ShapeWorld->hasFarWorld();
|
||||
@@ -2526,7 +2679,12 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::chrono::duration<double,std::milli>(GenerationStart-ColdProcessStart).count());
|
||||
std::string Error;
|
||||
if(!ConfigureWorld(Error))
|
||||
{std::fprintf(stderr,"World load failed: %s\n",Error.c_str());MessageBoxA(Window,Error.c_str(),"VoxelForge viewer",MB_ICONERROR);return;}
|
||||
{
|
||||
if(GpuPipelineStartupThread.joinable())GpuPipelineStartupThread.join();
|
||||
std::fprintf(stderr,"World load failed: %s\n",Error.c_str());
|
||||
MessageBoxA(Window,Error.c_str(),"VoxelForge viewer",MB_ICONERROR);return;
|
||||
}
|
||||
if(GpuPipelineStartupThread.joinable())GpuPipelineStartupThread.join();
|
||||
std::printf("[ColdTimeline] stage=generation_setup configured_ms=%.3f\n",
|
||||
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-ColdProcessStart).count());
|
||||
ResolveGpuWarmupLaunchPolicy(false);
|
||||
@@ -2535,7 +2693,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
if(bGpuFarEnabled&&bPipelineCanStartNow&&!EnsureGpuFarPipeline(Error))
|
||||
{MessageBoxA(Window,Error.c_str(),"VoxelForge GPU pipeline",MB_ICONERROR);return;}
|
||||
if(bGpuFarShaderPrewarm&&!bGpuFarWarmupBeforeWorkers
|
||||
&&!bGpuWarmupDeferredUntilFirstView)
|
||||
&&!bGpuWarmupDeferredUntilFirstView&&!bGpuWarmupCompleted)
|
||||
StartGpuShaderWarmupAsync();
|
||||
const FVector CameraVoxels(Position.X*4.0,Position.Y*4.0,Position.Z*4.0);
|
||||
BuildTargetChunk=StandaloneWorldMesher::CameraChunk(CameraVoxels);
|
||||
@@ -2959,10 +3117,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
{
|
||||
Batch->PrepareStart=std::chrono::steady_clock::now();
|
||||
if(bGpuFarTimelineEnabled)
|
||||
std::printf("[ColdTimeline] event=gpu_input_export_workers_started at_ms=%.3f dispatch_to_start_ms=%.3f frame=%llu shared_workers=%zu\n",
|
||||
std::printf("[ColdTimeline] event=gpu_input_export_workers_started at_ms=%.3f dispatch_to_start_ms=%.3f cpu_ready_to_start_ms=%.3f frame=%llu shared_workers=%zu\n",
|
||||
ColdTimelineMilliseconds(Batch->PrepareStart),
|
||||
std::chrono::duration<double,std::milli>(
|
||||
Batch->PrepareStart-Batch->DispatchAt).count(),
|
||||
Batch->CpuReadyAt.time_since_epoch().count()!=0
|
||||
?std::chrono::duration<double,std::milli>(
|
||||
Batch->PrepareStart-Batch->CpuReadyAt).count():-1.0,
|
||||
static_cast<unsigned long long>(ColdTimelineFrame()),
|
||||
Batch->SharedWorkerCount);
|
||||
std::printf("[ColdTimeline] stage=gpu_input_export begin_ms=%.3f tiles=%zu shared_workers=%zu\n",
|
||||
@@ -3260,15 +3421,18 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
const auto DispatchAt=std::chrono::steady_clock::now();
|
||||
auto Batch=std::make_shared<FGpuFarPreparationBatch>();
|
||||
Batch->DispatchAt=DispatchAt;Batch->TileCount=NeedPreparation.size();
|
||||
Batch->CpuReadyAt=CpuReadyFrameBeforeGpuAt;
|
||||
Batch->SharedWorkerCount=Streamer?static_cast<std::size_t>(Streamer->GetWorkerCount()):0;
|
||||
Batch->Generation=GpuFarPreparationGeneration.load(std::memory_order_acquire);
|
||||
Batch->Remaining.store(NeedPreparation.size(),std::memory_order_relaxed);
|
||||
GpuFarPreparationState=Batch;
|
||||
bGpuFarPreparationFinished.store(false,std::memory_order_relaxed);
|
||||
if(bGpuFarTimelineEnabled)
|
||||
std::printf("[ColdTimeline] event=gpu_input_export_priority_queue at_ms=%.3f after_pool_ms=%.3f memory_sample_ms=%.3f list_copy_sort_ms=%.3f tiles=%zu shared_workers=%zu\n",
|
||||
std::printf("[ColdTimeline] event=gpu_input_export_priority_queue at_ms=%.3f after_pool_ms=%.3f cpu_ready_to_queue_ms=%.3f memory_sample_ms=%.3f list_copy_sort_ms=%.3f tiles=%zu shared_workers=%zu\n",
|
||||
ColdTimelineMilliseconds(DispatchAt),
|
||||
std::chrono::duration<double,std::milli>(DispatchAt-PoolEnd).count(),
|
||||
CpuReadyFrameBeforeGpuAt.time_since_epoch().count()!=0
|
||||
?std::chrono::duration<double,std::milli>(DispatchAt-CpuReadyFrameBeforeGpuAt).count():-1.0,
|
||||
MemorySampleMs,PreparationListMs,NeedPreparation.size(),Batch->SharedWorkerCount);
|
||||
constexpr std::size_t GpuInputPriorityBurst=3;
|
||||
std::printf("[GpuFarSchedulingPolicy] workers=%zu gpu_input_priority_burst=%zu cpu_mesh_jobs_per_burst=1 mode=shared_worker_pool\n",
|
||||
@@ -3316,6 +3480,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
{
|
||||
if(!bGpuFarShaderPrewarm||bGpuWarmupCompleted)return bGpuFarEnabled;
|
||||
if(!bGpuShaderWarmupQueueFinished.load(std::memory_order_acquire))return false;
|
||||
if(bGpuFarTimelineEnabled)
|
||||
{
|
||||
const auto ObservedAt=std::chrono::steady_clock::now();
|
||||
const double CpuReadyToObservedMs=CpuReadyFrameBeforeGpuAt.time_since_epoch().count()!=0
|
||||
?std::chrono::duration<double,std::milli>(ObservedAt-CpuReadyFrameBeforeGpuAt).count():-1.0;
|
||||
std::printf("[ColdTimeline] event=gpu_warmup_completion_observed at_ms=%.3f queue_finished_at_ms=%.3f observe_delay_ms=%.3f cpu_ready_frame_presented=%s cpu_ready_to_observed_ms=%.3f frame=%llu\n",
|
||||
ColdTimelineMilliseconds(ObservedAt),ColdTimelineMilliseconds(GpuShaderWarmupQueueFinishedAt),
|
||||
std::chrono::duration<double,std::milli>(ObservedAt-GpuShaderWarmupQueueFinishedAt).count(),
|
||||
CpuReadyFrameBeforeGpuAt.time_since_epoch().count()!=0?"yes":"no",
|
||||
CpuReadyToObservedMs,static_cast<unsigned long long>(ColdTimelineFrame()));
|
||||
}
|
||||
const auto WarmupStart=std::chrono::steady_clock::now();
|
||||
if(GpuShaderWarmupThread.joinable())GpuShaderWarmupThread.join();
|
||||
if(!bGpuShaderWarmupQueueSucceeded)
|
||||
@@ -3480,7 +3655,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
ResolveGpuWarmupLaunchPolicy(false);
|
||||
if(bGpuWarmupDeferredUntilFirstView&&!bGpuWarmupDeferredStarted)
|
||||
{
|
||||
if(!bWholeViewPresented)return;
|
||||
if(!bCpuReadyFramePresentedBeforeGpu)return;
|
||||
std::string DeferredPipelineError;
|
||||
if(!EnsureGpuFarPipeline(DeferredPipelineError))
|
||||
{
|
||||
@@ -5307,6 +5482,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
if(bDidPresent&&bDeferGpuUntilCpuFrame&&!StreamingBatches.empty())
|
||||
{
|
||||
bCpuReadyFramePresentedBeforeGpu=true;
|
||||
CpuReadyFrameBeforeGpuAt=PresentCallEnd;
|
||||
std::printf("[CpuReadyFrameBeforeGpu] at_ms=%.3f uploaded_cpu_batches=%zu next_action=submit_gpu_far\n",
|
||||
std::chrono::duration<double,std::milli>(PresentCallEnd-ColdProcessStart).count(),
|
||||
StreamingBatches.size());
|
||||
|
||||
Reference in new issue
Block a user