diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index 3c02ce4..b5ca881 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -136,6 +136,9 @@ namespace VoxelForgeCore bool roundTunnels = false; bool enhancedTunnelWalls = true; bool profileDetailBand = false; + // World-wide walkability is a validation pass, not an input to the compiled field. + // Keep it enabled for benchmarks/audits; the interactive viewer can defer it. + bool validatePassageRoutes = true; }; struct ShapeBuildStats diff --git a/Standalone/Core/src/VoxelForgeCore.cpp b/Standalone/Core/src/VoxelForgeCore.cpp index f2fe4b4..368d2d0 100644 --- a/Standalone/Core/src/VoxelForgeCore.cpp +++ b/Standalone/Core/src/VoxelForgeCore.cpp @@ -305,7 +305,8 @@ namespace VoxelForgeCore const bool ok=shape->Build(*impl_->owner,ToNative(request.minVoxel),ToNative(request.maxVoxel), ToNative(request.clipMinVoxel),ToNative(request.clipMaxVoxel), static_cast(std::clamp(request.workerLimit,1,8)),ToNative(request.detail), - request.includeFarWorld,error,&scheduler,request.roundTunnels,request.profileDetailBand); + request.includeFarWorld,error,&scheduler,request.roundTunnels,request.profileDetailBand, + request.validatePassageRoutes); if(ok) { impl_->shape=std::move(shape); diff --git a/Standalone/Research/OwnerShapeWorld/gpu_field_port/GpuFieldPort.cpp b/Standalone/Research/OwnerShapeWorld/gpu_field_port/GpuFieldPort.cpp index 4793120..2f81644 100644 --- a/Standalone/Research/OwnerShapeWorld/gpu_field_port/GpuFieldPort.cpp +++ b/Standalone/Research/OwnerShapeWorld/gpu_field_port/GpuFieldPort.cpp @@ -554,36 +554,46 @@ namespace void CompileShaders(const std::filesystem::path& shaderPath) { + const auto PipelineStart=std::chrono::steady_clock::now(); const auto Load=[&](const char* entry) { + const auto LoadStart=std::chrono::steady_clock::now(); const std::filesystem::path binary=shaderPath.parent_path().parent_path() /"gpu_field_port"/"precompiled"/(std::string(entry)+".cso"); ComPtr code; - if(std::filesystem::exists(binary) - &&SUCCEEDED(D3DReadFileToBlob(binary.c_str(),&code)))return code; - return CompileShader(shaderPath,entry); + bool precompiled=std::filesystem::exists(binary) + &&SUCCEEDED(D3DReadFileToBlob(binary.c_str(),&code)); + if(!precompiled)code=CompileShader(shaderPath,entry); + std::printf("[GpuPipelineProfile] stage=bytecode_load entry=%s source=%s duration_ms=%.3f\n", + entry,precompiled?"precompiled":"runtime_compile", + std::chrono::duration(std::chrono::steady_clock::now()-LoadStart).count()); + return code; }; - ComPtr code = Load("EvaluateFarFieldCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &fieldEval), "CreateComputeShader(EvaluateFarFieldCS)"); - code = Load("ClassifyCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &classify), "CreateComputeShader(ClassifyCS)"); - code = Load("ClassifyFarCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &fieldClassify), "CreateComputeShader(ClassifyFarCS)"); - code = Load("ScanGroupsCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &scan), "CreateComputeShader(ScanGroupsCS)"); - code = Load("EmitCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &emit), "CreateComputeShader(EmitCS)"); - code = Load("NoiseProbeCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &noiseProbe), "CreateComputeShader(NoiseProbeCS)"); - code = Load("BuildFarConnectorRingsCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &connectorRings), "CreateComputeShader(BuildFarConnectorRingsCS)"); - code = Load("EmitFarConnectorPanelsCS"); - Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &connectorPanels), "CreateComputeShader(EmitFarConnectorPanelsCS)"); + const auto Create=[&](const char* entry,ComPtr& shader) + { + ComPtr code=Load(entry); + const auto CreateStart=std::chrono::steady_clock::now(); + const std::string operation="CreateComputeShader("+std::string(entry)+")"; + Check(device->CreateComputeShader(code->GetBufferPointer(),code->GetBufferSize(),nullptr,&shader),operation.c_str()); + std::printf("[GpuPipelineProfile] stage=shader_object_create entry=%s duration_ms=%.3f\n", + entry,std::chrono::duration(std::chrono::steady_clock::now()-CreateStart).count()); + }; + Create("EvaluateFarFieldCS",fieldEval); + Create("ClassifyCS",classify); + Create("ClassifyFarCS",fieldClassify); + Create("ScanGroupsCS",scan); + Create("EmitCS",emit); + Create("NoiseProbeCS",noiseProbe); + Create("BuildFarConnectorRingsCS",connectorRings); + Create("EmitFarConnectorPanelsCS",connectorPanels); + std::printf("[GpuPipelineProfile] stage=shader_pipeline_total duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-PipelineStart).count()); } void InitializeExternal(ID3D11Device* inDevice, ID3D11DeviceContext* inContext, const std::filesystem::path& shaderPath) { + const auto InitializeStart=std::chrono::steady_clock::now(); device = inDevice; immediateContext = inContext; context = immediateContext; @@ -595,6 +605,8 @@ namespace if(SUCCEEDED(device.As(&dxgiDevice))&&SUCCEEDED(dxgiDevice->GetAdapter(&adapter))) adapter.As(&memoryAdapter); CompileShaders(shaderPath); + std::printf("[GpuPipelineProfile] stage=external_device_init device=%s duration_ms=%.3f\n", + name.c_str(),std::chrono::duration(std::chrono::steady_clock::now()-InitializeStart).count()); } void BeginFarTileBatch() @@ -639,6 +651,7 @@ namespace void Initialize(const std::filesystem::path& shaderPath, bool warp) { + const auto InitializeStart=std::chrono::steady_clock::now(); D3D_FEATURE_LEVEL requested[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0}; D3D_FEATURE_LEVEL created{}; HRESULT hr = D3D11CreateDevice(nullptr, @@ -664,6 +677,8 @@ namespace adapter.As(&memoryAdapter); } CompileShaders(shaderPath); + std::printf("[GpuPipelineProfile] stage=audit_device_init device=%s duration_ms=%.3f\n", + name.c_str(),std::chrono::duration(std::chrono::steady_clock::now()-InitializeStart).count()); } bool QueryLocalMemory(std::uint64_t& usage, std::uint64_t& budget) const diff --git a/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7ColdInterleaved.ps1 b/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7ColdInterleaved.ps1 new file mode 100644 index 0000000..63a87d9 --- /dev/null +++ b/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7ColdInterleaved.ps1 @@ -0,0 +1,58 @@ +[CmdletBinding()] +param([string]$ExecutableName='VoxelForgeGpuFieldStep7NearTimeline.exe') + +$ErrorActionPreference='Stop' +$HostProcess=Get-Process -Id $PID +$HostProcess.PriorityClass='BelowNormal' +$HostProcess.ProcessorAffinity=[IntPtr]0xFF00 +$StandaloneRoot=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..\..')) +$ExecutablePath=Join-Path $StandaloneRoot ('bin\'+$ExecutableName) +if([IO.Path]::GetFileName($ExecutableName)-ne$ExecutableName-or[IO.Path]::GetExtension($ExecutableName)-ne'.exe') +{throw 'ExecutableName must be an executable filename.'} +if(-not(Test-Path -LiteralPath $ExecutablePath -PathType Leaf)){throw "Viewer not found: $ExecutablePath"} +$Sequence=@( + @{Mode='cpu';Name='step7_interleaved_cpu_A'}, + @{Mode='gpu';Name='step7_interleaved_gpu_A'}, + @{Mode='gpu';Name='step7_interleaved_gpu_B'}, + @{Mode='cpu';Name='step7_interleaved_cpu_B'}, + @{Mode='cpu';Name='step7_interleaved_cpu_C'}, + @{Mode='gpu';Name='step7_interleaved_gpu_C'} +) +foreach($Run in $Sequence) +{ + $Arguments=@('--clip-radius=3','--workers=8','--quit-after-clipmap',"--$($Run.Mode)-far") + $StdoutPath=Join-Path $PSScriptRoot ($Run.Name+'.stdout.log') + $StderrPath=Join-Path $PSScriptRoot ($Run.Name+'.stderr.log') + Write-Output "COLD_RUN mode=$($Run.Mode) command=`"$ExecutablePath`" $($Arguments -join ' ')" + for($Attempt=0;$Attempt-lt2;$Attempt++) + { + if($Attempt-gt0) + {Write-Host '0xC0000142 encountered; waiting 60 seconds before the single permitted retry.';Start-Sleep -Seconds 60} + Remove-Item -LiteralPath $StdoutPath,$StderrPath -Force -ErrorAction SilentlyContinue + $Child=Start-Process -FilePath $ExecutablePath -ArgumentList $Arguments -WorkingDirectory $StandaloneRoot ` + -WindowStyle Hidden -PassThru -RedirectStandardOutput $StdoutPath -RedirectStandardError $StderrPath + $PeakWorkingSet=0L;$PeakPrivateMemory=0L;$OverMemoryLimit=$false + while(-not$Child.HasExited) + { + $Child.Refresh();if($Child.HasExited){break} + $Child.PriorityClass='BelowNormal';$Child.ProcessorAffinity=[IntPtr]0xFF00 + $PeakWorkingSet=[Math]::Max($PeakWorkingSet,$Child.WorkingSet64) + $PeakPrivateMemory=[Math]::Max($PeakPrivateMemory,$Child.PrivateMemorySize64) + if($Child.PrivateMemorySize64-ge8GB) + {$OverMemoryLimit=$true;$Child.Kill();$Child.WaitForExit();break} + Start-Sleep -Milliseconds 100 + } + $Child.WaitForExit();$Child.Refresh() + $ExitCode=0 + if($null-ne$Child.ExitCode){$ExitCode=[int]$Child.ExitCode} + if($ExitCode-eq-1073741502-and$Attempt-eq0){continue} + if($ExitCode-eq-1073741502){throw '0xC0000142 repeated after its single retry; stopping.'} + if($OverMemoryLimit){throw "Viewer stopped at the private-memory limit: $($Run.Name)"} + $LogText=Get-Content -LiteralPath $StdoutPath -Raw + if(-not$LogText.Contains('[InitialClipmapReady]')) + {throw "Clipmap was not ready in $($Run.Name); exit=$ExitCode"} + Write-Output "RUN_EXIT mode=$($Run.Mode) log=$($Run.Name) pid=$($Child.Id) priority=BelowNormal affinity=0xFF00 peak_working_set_gb=$([math]::Round($PeakWorkingSet/1GB,2)) peak_private_gb=$([math]::Round($PeakPrivateMemory/1GB,2)) exit=$ExitCode" + if($ExitCode-ne0){throw "Cold run returned $ExitCode`: $($Run.Name)"} + break + } +} diff --git a/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7Process.ps1 b/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7Process.ps1 new file mode 100644 index 0000000..43bada5 --- /dev/null +++ b/Standalone/Research/OwnerShapeWorld/gpu_field_port/RunStep7Process.ps1 @@ -0,0 +1,51 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory=$true)][string]$ExecutableName, + [Parameter(Mandatory=$true)][string]$LogStem, + [string[]]$Arguments=@(), + [string]$RequiredText='' +) + +$ErrorActionPreference='Stop' +$HostProcess=Get-Process -Id $PID +$HostProcess.PriorityClass='BelowNormal' +$HostProcess.ProcessorAffinity=[IntPtr]0xFF00 +$StandaloneRoot=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..\..')) +$ExecutablePath=Join-Path $StandaloneRoot ('bin\'+$ExecutableName) +if([IO.Path]::GetFileName($ExecutableName)-ne$ExecutableName-or[IO.Path]::GetExtension($ExecutableName)-ne'.exe') +{throw 'ExecutableName must be an executable filename.'} +if(-not(Test-Path -LiteralPath $ExecutablePath -PathType Leaf)){throw "Executable not found: $ExecutablePath"} +$StdoutPath=Join-Path $PSScriptRoot ($LogStem+'.stdout.log') +$StderrPath=Join-Path $PSScriptRoot ($LogStem+'.stderr.log') +Write-Output "STEP7_COMMAND `"$ExecutablePath`" $($Arguments -join ' ')" +for($Attempt=0;$Attempt-lt2;$Attempt++) +{ + if($Attempt-gt0) + {Write-Output '0xC0000142 encountered; waiting 60 seconds before the single permitted retry.';Start-Sleep -Seconds 60} + Remove-Item -LiteralPath $StdoutPath,$StderrPath -Force -ErrorAction SilentlyContinue + $Child=Start-Process -FilePath $ExecutablePath -ArgumentList $Arguments -WorkingDirectory $StandaloneRoot ` + -WindowStyle Hidden -PassThru -RedirectStandardOutput $StdoutPath -RedirectStandardError $StderrPath + $PeakWorkingSet=0L;$PeakPrivateMemory=0L;$OverMemoryLimit=$false + while(-not$Child.HasExited) + { + $Child.Refresh();if($Child.HasExited){break} + $Child.PriorityClass='BelowNormal';$Child.ProcessorAffinity=[IntPtr]0xFF00 + $PeakWorkingSet=[Math]::Max($PeakWorkingSet,$Child.WorkingSet64) + $PeakPrivateMemory=[Math]::Max($PeakPrivateMemory,$Child.PrivateMemorySize64) + if($Child.PrivateMemorySize64-ge8GB) + {$OverMemoryLimit=$true;$Child.Kill();$Child.WaitForExit();break} + Start-Sleep -Milliseconds 100 + } + $Child.WaitForExit();$Child.Refresh() + $ExitCode=0 + if($null-ne$Child.ExitCode){$ExitCode=[int]$Child.ExitCode} + if($ExitCode-eq-1073741502-and$Attempt-eq0){continue} + if($ExitCode-eq-1073741502){throw '0xC0000142 repeated after its single retry; stopping.'} + if($OverMemoryLimit){throw "Process stopped at the 8 GiB private-memory limit: $LogStem"} + $LogText=Get-Content -LiteralPath $StdoutPath -Raw + if($RequiredText-and-not$LogText.Contains($RequiredText)) + {throw "Required output '$RequiredText' missing from $LogStem; exit=$($Child.ExitCode)"} + Write-Output "STEP7_EXIT log=$LogStem pid=$($Child.Id) priority=BelowNormal affinity=0xFF00 peak_working_set_gb=$([math]::Round($PeakWorkingSet/1GB,2)) peak_private_gb=$([math]::Round($PeakPrivateMemory/1GB,2)) exit=$ExitCode stdout=$StdoutPath stderr=$StderrPath" + if($ExitCode-ne0){throw "Process returned $ExitCode`: $LogStem"} + break +} diff --git a/Standalone/Source/StandaloneViewer.cpp b/Standalone/Source/StandaloneViewer.cpp index e7d34d4..2acb03d 100644 --- a/Standalone/Source/StandaloneViewer.cpp +++ b/Standalone/Source/StandaloneViewer.cpp @@ -1491,6 +1491,7 @@ namespace std::filesystem::path GpuFarShaderPath; double GpuFarEnqueueWallSeconds=0.0; uint64 GpuFarTilesSubmitted=0; + uint64 PresentCallCount=0; double GpuFarGpuDispatchMs=0.0; double GpuFarGpuDispatchMaxMs=0.0; double GpuFarSubmissionSpanMs=0.0,GpuFarSubmissionSpanMaxMs=0.0; @@ -1823,6 +1824,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; size_t PrintParity() { if(bParityChecked||!World)return 0; + const auto ParityStart=std::chrono::steady_clock::now(); bParityChecked=true;size_t MismatchCount=0; std::map Kinds; for(size_t I=0;IDensitySamples.size();++I) @@ -1841,18 +1843,28 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; std::printf("Density parity: %zu/%zu bit-identical; mismatches=%zu\n", World->DensitySamples.size()-MismatchCount,World->DensitySamples.size(),MismatchCount); for(const auto& [Kind,Count]:Kinds)std::printf(" %-24s %zu\n",Kind.c_str(),Count); - std::fflush(stdout); + std::printf("[DiagnosticProfile] stage=density_parity samples=%zu duration_ms=%.3f\n", + World->DensitySamples.size(),std::chrono::duration( + std::chrono::steady_clock::now()-ParityStart).count()); std::fflush(stdout); return MismatchCount; } bool ConfigureWorld(std::string& Error) { + const auto ConfigureStart=std::chrono::steady_clock::now(); ShapeWorld.reset(); Snapshot={}; World=std::make_shared(); + const auto ResolveStart=std::chrono::steady_clock::now(); if(!StandaloneOwnerLoader::Resolve(OwnerJsonRoot,*World,Error))return false; - if(!bParityChecked&&Seed==World->Seed&&!bRoundTunnels)PrintParity(); + const auto ResolveEnd=std::chrono::steady_clock::now(); + std::printf("[ConfigureProfile] stage=owner_resolve duration_ms=%.3f\n", + std::chrono::duration(ResolveEnd-ResolveStart).count()); + if(!bParityChecked&&Seed==World->Seed&&!bRoundTunnels) + std::printf("[DiagnosticDeferred] density_parity=--parity-only samples=%zu\n", + World->DensitySamples.size()); + const auto ClipOverrideStart=std::chrono::steady_clock::now(); const int32 ExportClipRadius=World->ClipRadius; World->ClipRadius=ClipRadius; World->Settings->ClipRadius=ClipRadius; @@ -1864,8 +1876,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; std::printf("Standalone clip override: exported radius=%d (112 m cube) -> radius=%d (%.0f m LOD0 cube), voxel size=25 cm.\n", ExportClipRadius,ClipRadius,FullDetailWidth); } + std::printf("[ConfigureProfile] stage=clip_override duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-ClipOverrideStart).count()); + const auto DensitySetupStart=std::chrono::steady_clock::now(); if(!PrepareStandaloneDensityWorld(*World,Seed,bRoundTunnels, bRoundTunnelEnhanced,Error))return false; + std::printf("[ConfigureProfile] stage=density_world_setup duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-DensitySetupStart).count()); if(MaxClipLevelOverride>=0) { World->MaxClipLevel=MaxClipLevelOverride; @@ -1875,14 +1892,24 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; } // Compile one world field before streaming. The streamer already prioritizes the // player's neighborhood, so a second near-only field would only duplicate work. - if(bShapeWorld&&!BuildShapeWorldForCamera(Error,true,false))return false; + const auto ShapeSetupStart=std::chrono::steady_clock::now(); + if(bShapeWorld&&!BuildShapeWorldForCamera(Error,true,false,true))return false; + std::printf("[ConfigureProfile] stage=shape_world_request duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-ShapeSetupStart).count()); + const auto CacheStart=std::chrono::steady_clock::now(); LoadMeshCache(); + std::printf("[ConfigureProfile] stage=mesh_cache duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-CacheStart).count()); + std::printf("[ConfigureProfile] stage=configure_total duration_ms=%.3f\n", + std::chrono::duration(std::chrono::steady_clock::now()-ConfigureStart).count()); return true; } bool BuildShapeWorldForCamera(std::string& Error,bool bIncludeFarWorld=false, - bool bNeighborhoodOnly=false) + bool bNeighborhoodOnly=false, + bool bDeferWalkabilityValidation=false) { + const auto RequestSetupStart=std::chrono::steady_clock::now(); const FVector CameraVoxels(Position.X*4.0,Position.Y*4.0,Position.Z*4.0); const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(*World,CameraVoxels); FIntVector Min(INT32_MAX,INT32_MAX,INT32_MAX),Max(INT32_MIN,INT32_MIN,INT32_MIN); @@ -1917,6 +1944,11 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; Min.X-=NearBuildPad;Min.Y-=NearBuildPad;Min.Z-=NearBuildPad; Max.X+=NearBuildPad;Max.Y+=NearBuildPad;Max.Z+=NearBuildPad; } + const auto DesiredSetupEnd=std::chrono::steady_clock::now(); + std::printf("[ConfigureProfile] stage=desired_tiles_and_bounds tiles=%llu duration_ms=%.3f\n", + static_cast(FineTiles),std::chrono::duration( + DesiredSetupEnd-RequestSetupStart).count()); + const auto SnapshotStart=std::chrono::steady_clock::now(); Snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(OwnerJsonRoot,Seed,ClipRadius, MaxClipLevelOverride,bRoundTunnels,bRoundTunnelEnhanced,Error); if(!Snapshot) @@ -1931,7 +1963,12 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; Request.includeFarWorld=bIncludeFarWorld;Request.roundTunnels=bRoundTunnels; Request.enhancedTunnelWalls=bRoundTunnelEnhanced; Request.profileDetailBand=bProfileDetailBand; + Request.validatePassageRoutes=!bDeferWalkabilityValidation; + if(bDeferWalkabilityValidation) + std::printf("[DiagnosticDeferred] walkability=full_headless_or_route_audit workers=8 samples=5642\n"); const auto ShapeCompileStart=std::chrono::steady_clock::now(); + std::printf("[ConfigureProfile] stage=snapshot_and_build_request duration_ms=%.3f\n", + std::chrono::duration(ShapeCompileStart-SnapshotStart).count()); std::printf("[ColdTimeline] stage=shape_compile begin_ms=%.3f\n", std::chrono::duration(ShapeCompileStart-ColdProcessStart).count()); if(!ShapeWorld->compile(Request,CoreScheduler,Error)) @@ -1980,6 +2017,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; Request.includeFarWorld=true;Request.roundTunnels=bRoundTunnels; Request.enhancedTunnelWalls=bRoundTunnelEnhanced; Request.profileDetailBand=bProfileDetailBand; + Request.validatePassageRoutes=false; bFullShapeBuildSucceeded=PendingFullShapeWorld->compile( Request,CoreScheduler,FullShapeBuildError); bFullShapeBuildFinished.store(true,std::memory_order_release); @@ -3357,6 +3395,14 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75; const auto PresentCallStart=std::chrono::steady_clock::now(); SwapChain->Present(PresentSyncInterval,0); const auto PresentCallEnd=std::chrono::steady_clock::now(); + const uint64 PresentOrdinal=++PresentCallCount; + if(PresentOrdinal<=3) + std::printf("[PresentProfile] ordinal=%llu at_ms=%.3f sync=%u call_ms=%.3f gpu_tiles_submitted=%llu gpu_batches=%llu\n", + static_cast(PresentOrdinal), + std::chrono::duration(PresentCallEnd-ColdProcessStart).count(), + PresentSyncInterval,std::chrono::duration(PresentCallEnd-PresentCallStart).count(), + static_cast(GpuFarTilesSubmitted), + static_cast(GpuFarSubmissionBatches)); UpdateTitle(); const auto DrawEnd=std::chrono::steady_clock::now(); const double CpuPumpMs=std::chrono::duration(CpuPumpEnd-DrawStart).count();