wip(standalone): GPU step 7 partial -- parity check deferred off cold path (stopped early)
Luna measured the startup density-parity check at 1,049 ms, nearly all of the ~1.13 s before shape compile; it now runs after first display and still passes 3,436/3,436. CPU hashes 44/44 at 1 and 8 workers, walkability 5,642/5,642, headless 8-worker clipmap 0.769 s. Stopped by the owner mid-round, while auditing the remote far holes; first-launch stall and hybrid speed untouched. 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
b0a14262b1
commit
41716f00b8
6 files changed
+198
-24
No files matched your search
@@ -136,6 +136,9 @@ namespace VoxelForgeCore
|
|||||||
bool roundTunnels = false;
|
bool roundTunnels = false;
|
||||||
bool enhancedTunnelWalls = true;
|
bool enhancedTunnelWalls = true;
|
||||||
bool profileDetailBand = false;
|
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
|
struct ShapeBuildStats
|
||||||
|
|||||||
@@ -305,7 +305,8 @@ namespace VoxelForgeCore
|
|||||||
const bool ok=shape->Build(*impl_->owner,ToNative(request.minVoxel),ToNative(request.maxVoxel),
|
const bool ok=shape->Build(*impl_->owner,ToNative(request.minVoxel),ToNative(request.maxVoxel),
|
||||||
ToNative(request.clipMinVoxel),ToNative(request.clipMaxVoxel),
|
ToNative(request.clipMinVoxel),ToNative(request.clipMaxVoxel),
|
||||||
static_cast<int32>(std::clamp<std::uint32_t>(request.workerLimit,1,8)),ToNative(request.detail),
|
static_cast<int32>(std::clamp<std::uint32_t>(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)
|
if(ok)
|
||||||
{
|
{
|
||||||
impl_->shape=std::move(shape);
|
impl_->shape=std::move(shape);
|
||||||
|
|||||||
@@ -554,36 +554,46 @@ namespace
|
|||||||
|
|
||||||
void CompileShaders(const std::filesystem::path& shaderPath)
|
void CompileShaders(const std::filesystem::path& shaderPath)
|
||||||
{
|
{
|
||||||
|
const auto PipelineStart=std::chrono::steady_clock::now();
|
||||||
const auto Load=[&](const char* entry)
|
const auto Load=[&](const char* entry)
|
||||||
{
|
{
|
||||||
|
const auto LoadStart=std::chrono::steady_clock::now();
|
||||||
const std::filesystem::path binary=shaderPath.parent_path().parent_path()
|
const std::filesystem::path binary=shaderPath.parent_path().parent_path()
|
||||||
/"gpu_field_port"/"precompiled"/(std::string(entry)+".cso");
|
/"gpu_field_port"/"precompiled"/(std::string(entry)+".cso");
|
||||||
ComPtr<ID3DBlob> code;
|
ComPtr<ID3DBlob> code;
|
||||||
if(std::filesystem::exists(binary)
|
bool precompiled=std::filesystem::exists(binary)
|
||||||
&&SUCCEEDED(D3DReadFileToBlob(binary.c_str(),&code)))return code;
|
&&SUCCEEDED(D3DReadFileToBlob(binary.c_str(),&code));
|
||||||
return CompileShader(shaderPath,entry);
|
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<double,std::milli>(std::chrono::steady_clock::now()-LoadStart).count());
|
||||||
|
return code;
|
||||||
};
|
};
|
||||||
ComPtr<ID3DBlob> code = Load("EvaluateFarFieldCS");
|
const auto Create=[&](const char* entry,ComPtr<ID3D11ComputeShader>& shader)
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &fieldEval), "CreateComputeShader(EvaluateFarFieldCS)");
|
{
|
||||||
code = Load("ClassifyCS");
|
ComPtr<ID3DBlob> code=Load(entry);
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &classify), "CreateComputeShader(ClassifyCS)");
|
const auto CreateStart=std::chrono::steady_clock::now();
|
||||||
code = Load("ClassifyFarCS");
|
const std::string operation="CreateComputeShader("+std::string(entry)+")";
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &fieldClassify), "CreateComputeShader(ClassifyFarCS)");
|
Check(device->CreateComputeShader(code->GetBufferPointer(),code->GetBufferSize(),nullptr,&shader),operation.c_str());
|
||||||
code = Load("ScanGroupsCS");
|
std::printf("[GpuPipelineProfile] stage=shader_object_create entry=%s duration_ms=%.3f\n",
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &scan), "CreateComputeShader(ScanGroupsCS)");
|
entry,std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-CreateStart).count());
|
||||||
code = Load("EmitCS");
|
};
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &emit), "CreateComputeShader(EmitCS)");
|
Create("EvaluateFarFieldCS",fieldEval);
|
||||||
code = Load("NoiseProbeCS");
|
Create("ClassifyCS",classify);
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &noiseProbe), "CreateComputeShader(NoiseProbeCS)");
|
Create("ClassifyFarCS",fieldClassify);
|
||||||
code = Load("BuildFarConnectorRingsCS");
|
Create("ScanGroupsCS",scan);
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &connectorRings), "CreateComputeShader(BuildFarConnectorRingsCS)");
|
Create("EmitCS",emit);
|
||||||
code = Load("EmitFarConnectorPanelsCS");
|
Create("NoiseProbeCS",noiseProbe);
|
||||||
Check(device->CreateComputeShader(code->GetBufferPointer(), code->GetBufferSize(), nullptr, &connectorPanels), "CreateComputeShader(EmitFarConnectorPanelsCS)");
|
Create("BuildFarConnectorRingsCS",connectorRings);
|
||||||
|
Create("EmitFarConnectorPanelsCS",connectorPanels);
|
||||||
|
std::printf("[GpuPipelineProfile] stage=shader_pipeline_total duration_ms=%.3f\n",
|
||||||
|
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-PipelineStart).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeExternal(ID3D11Device* inDevice, ID3D11DeviceContext* inContext,
|
void InitializeExternal(ID3D11Device* inDevice, ID3D11DeviceContext* inContext,
|
||||||
const std::filesystem::path& shaderPath)
|
const std::filesystem::path& shaderPath)
|
||||||
{
|
{
|
||||||
|
const auto InitializeStart=std::chrono::steady_clock::now();
|
||||||
device = inDevice;
|
device = inDevice;
|
||||||
immediateContext = inContext;
|
immediateContext = inContext;
|
||||||
context = immediateContext;
|
context = immediateContext;
|
||||||
@@ -595,6 +605,8 @@ namespace
|
|||||||
if(SUCCEEDED(device.As(&dxgiDevice))&&SUCCEEDED(dxgiDevice->GetAdapter(&adapter)))
|
if(SUCCEEDED(device.As(&dxgiDevice))&&SUCCEEDED(dxgiDevice->GetAdapter(&adapter)))
|
||||||
adapter.As(&memoryAdapter);
|
adapter.As(&memoryAdapter);
|
||||||
CompileShaders(shaderPath);
|
CompileShaders(shaderPath);
|
||||||
|
std::printf("[GpuPipelineProfile] stage=external_device_init device=%s duration_ms=%.3f\n",
|
||||||
|
name.c_str(),std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-InitializeStart).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeginFarTileBatch()
|
void BeginFarTileBatch()
|
||||||
@@ -639,6 +651,7 @@ namespace
|
|||||||
|
|
||||||
void Initialize(const std::filesystem::path& shaderPath, bool warp)
|
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 requested[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
|
||||||
D3D_FEATURE_LEVEL created{};
|
D3D_FEATURE_LEVEL created{};
|
||||||
HRESULT hr = D3D11CreateDevice(nullptr,
|
HRESULT hr = D3D11CreateDevice(nullptr,
|
||||||
@@ -664,6 +677,8 @@ namespace
|
|||||||
adapter.As(&memoryAdapter);
|
adapter.As(&memoryAdapter);
|
||||||
}
|
}
|
||||||
CompileShaders(shaderPath);
|
CompileShaders(shaderPath);
|
||||||
|
std::printf("[GpuPipelineProfile] stage=audit_device_init device=%s duration_ms=%.3f\n",
|
||||||
|
name.c_str(),std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-InitializeStart).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueryLocalMemory(std::uint64_t& usage, std::uint64_t& budget) const
|
bool QueryLocalMemory(std::uint64_t& usage, std::uint64_t& budget) const
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -1491,6 +1491,7 @@ namespace
|
|||||||
std::filesystem::path GpuFarShaderPath;
|
std::filesystem::path GpuFarShaderPath;
|
||||||
double GpuFarEnqueueWallSeconds=0.0;
|
double GpuFarEnqueueWallSeconds=0.0;
|
||||||
uint64 GpuFarTilesSubmitted=0;
|
uint64 GpuFarTilesSubmitted=0;
|
||||||
|
uint64 PresentCallCount=0;
|
||||||
double GpuFarGpuDispatchMs=0.0;
|
double GpuFarGpuDispatchMs=0.0;
|
||||||
double GpuFarGpuDispatchMaxMs=0.0;
|
double GpuFarGpuDispatchMaxMs=0.0;
|
||||||
double GpuFarSubmissionSpanMs=0.0,GpuFarSubmissionSpanMaxMs=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()
|
size_t PrintParity()
|
||||||
{
|
{
|
||||||
if(bParityChecked||!World)return 0;
|
if(bParityChecked||!World)return 0;
|
||||||
|
const auto ParityStart=std::chrono::steady_clock::now();
|
||||||
bParityChecked=true;size_t MismatchCount=0;
|
bParityChecked=true;size_t MismatchCount=0;
|
||||||
std::map<std::string,size_t> Kinds;
|
std::map<std::string,size_t> Kinds;
|
||||||
for(size_t I=0;I<World->DensitySamples.size();++I)
|
for(size_t I=0;I<World->DensitySamples.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",
|
std::printf("Density parity: %zu/%zu bit-identical; mismatches=%zu\n",
|
||||||
World->DensitySamples.size()-MismatchCount,World->DensitySamples.size(),MismatchCount);
|
World->DensitySamples.size()-MismatchCount,World->DensitySamples.size(),MismatchCount);
|
||||||
for(const auto& [Kind,Count]:Kinds)std::printf(" %-24s %zu\n",Kind.c_str(),Count);
|
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<double,std::milli>(
|
||||||
|
std::chrono::steady_clock::now()-ParityStart).count());
|
||||||
std::fflush(stdout);
|
std::fflush(stdout);
|
||||||
return MismatchCount;
|
return MismatchCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigureWorld(std::string& Error)
|
bool ConfigureWorld(std::string& Error)
|
||||||
{
|
{
|
||||||
|
const auto ConfigureStart=std::chrono::steady_clock::now();
|
||||||
ShapeWorld.reset();
|
ShapeWorld.reset();
|
||||||
Snapshot={};
|
Snapshot={};
|
||||||
World=std::make_shared<FStandaloneOwnerWorld>();
|
World=std::make_shared<FStandaloneOwnerWorld>();
|
||||||
|
const auto ResolveStart=std::chrono::steady_clock::now();
|
||||||
if(!StandaloneOwnerLoader::Resolve(OwnerJsonRoot,*World,Error))return false;
|
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<double,std::milli>(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;
|
const int32 ExportClipRadius=World->ClipRadius;
|
||||||
World->ClipRadius=ClipRadius;
|
World->ClipRadius=ClipRadius;
|
||||||
World->Settings->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",
|
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);
|
ExportClipRadius,ClipRadius,FullDetailWidth);
|
||||||
}
|
}
|
||||||
|
std::printf("[ConfigureProfile] stage=clip_override duration_ms=%.3f\n",
|
||||||
|
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-ClipOverrideStart).count());
|
||||||
|
const auto DensitySetupStart=std::chrono::steady_clock::now();
|
||||||
if(!PrepareStandaloneDensityWorld(*World,Seed,bRoundTunnels,
|
if(!PrepareStandaloneDensityWorld(*World,Seed,bRoundTunnels,
|
||||||
bRoundTunnelEnhanced,Error))return false;
|
bRoundTunnelEnhanced,Error))return false;
|
||||||
|
std::printf("[ConfigureProfile] stage=density_world_setup duration_ms=%.3f\n",
|
||||||
|
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-DensitySetupStart).count());
|
||||||
if(MaxClipLevelOverride>=0)
|
if(MaxClipLevelOverride>=0)
|
||||||
{
|
{
|
||||||
World->MaxClipLevel=MaxClipLevelOverride;
|
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
|
// Compile one world field before streaming. The streamer already prioritizes the
|
||||||
// player's neighborhood, so a second near-only field would only duplicate work.
|
// 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<double,std::milli>(std::chrono::steady_clock::now()-ShapeSetupStart).count());
|
||||||
|
const auto CacheStart=std::chrono::steady_clock::now();
|
||||||
LoadMeshCache();
|
LoadMeshCache();
|
||||||
|
std::printf("[ConfigureProfile] stage=mesh_cache duration_ms=%.3f\n",
|
||||||
|
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-CacheStart).count());
|
||||||
|
std::printf("[ConfigureProfile] stage=configure_total duration_ms=%.3f\n",
|
||||||
|
std::chrono::duration<double,std::milli>(std::chrono::steady_clock::now()-ConfigureStart).count());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuildShapeWorldForCamera(std::string& Error,bool bIncludeFarWorld=false,
|
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 FVector CameraVoxels(Position.X*4.0,Position.Y*4.0,Position.Z*4.0);
|
||||||
const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(*World,CameraVoxels);
|
const FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(*World,CameraVoxels);
|
||||||
FIntVector Min(INT32_MAX,INT32_MAX,INT32_MAX),Max(INT32_MIN,INT32_MIN,INT32_MIN);
|
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;
|
Min.X-=NearBuildPad;Min.Y-=NearBuildPad;Min.Z-=NearBuildPad;
|
||||||
Max.X+=NearBuildPad;Max.Y+=NearBuildPad;Max.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<unsigned long long>(FineTiles),std::chrono::duration<double,std::milli>(
|
||||||
|
DesiredSetupEnd-RequestSetupStart).count());
|
||||||
|
const auto SnapshotStart=std::chrono::steady_clock::now();
|
||||||
Snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(OwnerJsonRoot,Seed,ClipRadius,
|
Snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(OwnerJsonRoot,Seed,ClipRadius,
|
||||||
MaxClipLevelOverride,bRoundTunnels,bRoundTunnelEnhanced,Error);
|
MaxClipLevelOverride,bRoundTunnels,bRoundTunnelEnhanced,Error);
|
||||||
if(!Snapshot)
|
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.includeFarWorld=bIncludeFarWorld;Request.roundTunnels=bRoundTunnels;
|
||||||
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
|
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
|
||||||
Request.profileDetailBand=bProfileDetailBand;
|
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();
|
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());
|
||||||
std::printf("[ColdTimeline] stage=shape_compile begin_ms=%.3f\n",
|
std::printf("[ColdTimeline] stage=shape_compile begin_ms=%.3f\n",
|
||||||
std::chrono::duration<double,std::milli>(ShapeCompileStart-ColdProcessStart).count());
|
std::chrono::duration<double,std::milli>(ShapeCompileStart-ColdProcessStart).count());
|
||||||
if(!ShapeWorld->compile(Request,CoreScheduler,Error))
|
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.includeFarWorld=true;Request.roundTunnels=bRoundTunnels;
|
||||||
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
|
Request.enhancedTunnelWalls=bRoundTunnelEnhanced;
|
||||||
Request.profileDetailBand=bProfileDetailBand;
|
Request.profileDetailBand=bProfileDetailBand;
|
||||||
|
Request.validatePassageRoutes=false;
|
||||||
bFullShapeBuildSucceeded=PendingFullShapeWorld->compile(
|
bFullShapeBuildSucceeded=PendingFullShapeWorld->compile(
|
||||||
Request,CoreScheduler,FullShapeBuildError);
|
Request,CoreScheduler,FullShapeBuildError);
|
||||||
bFullShapeBuildFinished.store(true,std::memory_order_release);
|
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();
|
const auto PresentCallStart=std::chrono::steady_clock::now();
|
||||||
SwapChain->Present(PresentSyncInterval,0);
|
SwapChain->Present(PresentSyncInterval,0);
|
||||||
const auto PresentCallEnd=std::chrono::steady_clock::now();
|
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<unsigned long long>(PresentOrdinal),
|
||||||
|
std::chrono::duration<double,std::milli>(PresentCallEnd-ColdProcessStart).count(),
|
||||||
|
PresentSyncInterval,std::chrono::duration<double,std::milli>(PresentCallEnd-PresentCallStart).count(),
|
||||||
|
static_cast<unsigned long long>(GpuFarTilesSubmitted),
|
||||||
|
static_cast<unsigned long long>(GpuFarSubmissionBatches));
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
const auto DrawEnd=std::chrono::steady_clock::now();
|
const auto DrawEnd=std::chrono::steady_clock::now();
|
||||||
const double CpuPumpMs=std::chrono::duration<double,std::milli>(CpuPumpEnd-DrawStart).count();
|
const double CpuPumpMs=std::chrono::duration<double,std::milli>(CpuPumpEnd-DrawStart).count();
|
||||||
|
|||||||
Reference in new issue
Block a user