wip(standalone): GPU step 27 -- slot-overflow fallback, -SkipCpuDetailBand (slower), -AffinityMask; full machine cached 0.93 s

Luna: normal completion path reads the raw vertex count before residency; an
over-cap count or failed readback falls back to CPU meshing. Max seen 18,153 of
19,456 vertices at (2,-9,-4,lod1) -- 1,303 headroom for this seed only.
Consumer map: 320 GPU near, 640 CPU near (skirted), 1,114 GPU far, 152 CPU far.
Exceptions are exported separately from roughness. Opt-in -SkipCpuDetailBand skips
CPU roughness for GPU-owned near visuals (lazy exact reconstruction on query).
Runner gains -AffinityMask (default 0xFF00) and -NormalPriority.

My runs outside the sandbox (Step27.exe, marker removed first):
  half machine (0xFF00, BelowNormal), interleaved:
    CPU 1.374 / 1.285 / 1.296 s
    GPU miss 1.330 s; cached 1.151 / 1.143 / 1.129 s (1,434 GPU tiles)
    GPU cached + -SkipCpuDetailBand 1.316 / 1.303 / 1.307 s -- SLOWER: detail apply
      331 -> 297 ms, but intervals+signs 112 -> 286 ms (the plan), shape 557 -> 692 ms
  full machine (0xFFFF, Normal), interleaved:
    CPU 1.004 / 1.015 / 0.974 s
    GPU cached 0.931 / 0.930 / 0.925 s -- first sub-second launches
Audits (Luna): hashes w1/w8, walk 5,642/5,642, near (skip) / far 0 sign/topology
diffs vs CPU and WARP, auto + cold survival pass, ten captures pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-08 04:11:23 +02:00
1 parent 7d92e148a9
commit 7d1808fdf2
16 files changed
+796 -37

No files matched your search

+217 -12
View File
@@ -1371,6 +1371,7 @@ namespace
VoxelForgeGpuFarViewer::GpuTimingQueries TimingQueries{};
uint64 VertexCapacityBytes=0;
uint32 OutputSlot=0,IndirectArgsByteOffset=0,BatchIndex=UINT32_MAX;
uint32 RequiredSurfaceVertexCount=0;
int32 InputCells=0,InputStep=0;
uint64 ProtectedSamples=0,ProtectedThinSamples=0,ProtectedSolidSamples=0;
uint32 NearProxySamples=0,ConnectorRings=0,ConnectorVertices=0;
@@ -1612,6 +1613,12 @@ namespace
std::filesystem::path GpuFarShaderPath;
double GpuFarEnqueueWallSeconds=0.0;
uint64 GpuFarTilesSubmitted=0;
uint64 GpuFarNearTilesSubmitted=0,GpuFarFarTilesSubmitted=0;
uint64 GpuFarPreparedNearTileInputs=0,GpuFarPreparedFarTileInputs=0;
uint64 GpuFarNearLatticeSamples=0,GpuFarNearPackedCandidateSamples=0;
uint64 GpuFarNearPackedSkippedSamples=0,GpuFarProtectedRouteSamples=0;
uint64 GpuFarProtectedThinSamples=0,GpuFarProtectedSolidSamples=0;
uint64 GpuFarProtectedSealSamples=0,GpuFarProtectedOverlaySamples=0;
uint64 PresentCallCount=0;
uint64 StartupNonBlockingPresentCalls=0,StartupNonBlockingPresentSkips=0;
double GpuFarGpuDispatchMs=0.0;
@@ -1625,6 +1632,10 @@ namespace
uint32 GpuFarMaxTilesPerSubmissionBatch=0;
uint32 GpuFarOutputCapacitySlots=0,GpuFarNextOutputSlot=0;
uint32 GpuFarOutputPoolReservedSlots=0;
uint64 GpuFarOutputCountChecks=0,GpuFarOutputOverflowCount=0;
uint64 GpuFarOutputCountReadbackFailures=0;
uint32 GpuFarMaxRequiredVertices=0,GpuFarMaxRequiredOutputSlot=UINT32_MAX;
FVoxelTileKey GpuFarMaxRequiredVertexKey{};
std::size_t GpuFarPreReservePoolSlots=0;
int32 GpuFarPreReserveCoarseTileCells=0;
std::vector<uint32> GpuFarFreeOutputSlots;
@@ -1653,6 +1664,7 @@ namespace
bool bGpuFirstBackedPresentReported=false;
bool bProfileAttribution=false;
bool bProfileDetailBand=false;
bool bGpuFarSkipCpuDetailBand=false;
bool bCompareEvaluators=false;
bool bParityOnly=false;
bool bDensityHash=false;
@@ -1793,6 +1805,12 @@ namespace
LastDrawEndAt={};
GpuFarAudit.reset();bGpuFarAuditReported=false;
GpuFarTilesSubmitted=0;GpuFarEnqueueWallSeconds=0.0;GpuFarGpuDispatchMs=0.0;
GpuFarNearTilesSubmitted=GpuFarFarTilesSubmitted=0;
GpuFarPreparedNearTileInputs=GpuFarPreparedFarTileInputs=0;
GpuFarNearLatticeSamples=GpuFarNearPackedCandidateSamples=0;
GpuFarNearPackedSkippedSamples=GpuFarProtectedRouteSamples=0;
GpuFarProtectedThinSamples=GpuFarProtectedSolidSamples=0;
GpuFarProtectedSealSamples=GpuFarProtectedOverlaySamples=0;
GpuFarGpuDispatchMaxMs=0.0;GpuFarSubmissionSpanMs=0.0;GpuFarSubmissionSpanMaxMs=0.0;
GpuFarGpuDispatchMaxKey={};bGpuFarGpuDispatchMaxKeyValid=false;
GpuFarLocalMemoryPeakBytes=0;GpuFarLocalMemoryBudgetBytes=0;
@@ -2469,6 +2487,30 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
return true;
}
void PopulateGpuVisualDetailBandPlan(VoxelForgeCore::ShapeBuildRequest& Request,
const std::vector<FVoxelTileKey>& TileKeys) const
{
if(!bGpuFarEnabled||(!bProfileDetailBand&&!bGpuFarSkipCpuDetailBand))return;
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> TileSet;
TileSet.reserve(TileKeys.size()*2+1);
for(const FVoxelTileKey& Key:TileKeys)TileSet.insert(Key);
for(const FVoxelTileKey& Key:TileKeys)
{
if(Key.Level<0||Key.Level>=World->FullResClipLevels)continue;
const FIntVector Origin=Key.OriginVoxels();
VoxelForgeCore::DetailBandTileRegion Region;
Region.originVoxel={Origin.X,Origin.Y,Origin.Z};
Region.cells=CHUNK_SIZE;
Region.step=std::max(1,Key.ExtentVoxels()/CHUNK_SIZE);
const uint8 VisibleSkirts=World->bGenerateSkirts
?ComputeVisibleSkirtFaceMask(Key,TileSet):0;
if(VisibleSkirts==0)Request.gpuVisualDetailTiles.push_back(Region);
else Request.cpuVisualDetailTiles.push_back(Region);
}
Request.skipCpuDetailBandForGpuVisuals=bGpuFarSkipCpuDetailBand
&&!Request.gpuVisualDetailTiles.empty();
}
bool BuildShapeWorldForCamera(std::string& Error,bool bIncludeFarWorld=false,
bool bNeighborhoodOnly=false,
bool bDeferWalkabilityValidation=false)
@@ -2527,6 +2569,8 @@ 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;
PopulateGpuVisualDetailBandPlan(Request,
bNeighborhoodOnly?InitialNeighborhoodTiles:Desired.Tiles);
Request.validatePassageRoutes=!bDeferWalkabilityValidation;
if(bDeferWalkabilityValidation)
std::printf("[DiagnosticDeferred] walkability=full_headless_or_route_audit workers=8 samples=5642\n");
@@ -2612,7 +2656,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
bFullShapeBuildFinished.store(false,std::memory_order_relaxed);
const int32 FullWorkers=WorkerCount>=8?6:WorkerCount;
FullShapeBuildStart=std::chrono::steady_clock::now();
FullShapeBuildThread=std::thread([this,FineMin,FineMax,ClipMin,ClipMax,FullWorkers]()
FullShapeBuildThread=std::thread([this,FineMin,FineMax,ClipMin,ClipMax,FullWorkers,
FullDesiredCopy=FullDesired]()
{
VoxelForgeCore::ShapeBuildRequest Request;
Request.minVoxel={FineMin.X,FineMin.Y,FineMin.Z};
@@ -2623,6 +2668,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;
PopulateGpuVisualDetailBandPlan(Request,FullDesiredCopy);
Request.validatePassageRoutes=false;
bFullShapeBuildSucceeded=PendingFullShapeWorld->compile(
Request,CoreScheduler,FullShapeBuildError);
@@ -2932,7 +2978,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
ColdTimelineMilliseconds(Tile.SubmittedAt),ColdTimelineMilliseconds(Tile.CompletedAt));
if(Tile.BatchIndex!=UINT32_MAX&&Tile.BatchIndex<GpuFarBatches.size())
{
FGpuFarBatch& Batch=GpuFarBatches[Tile.BatchIndex];
FGpuFarBatch& Batch=GpuFarBatches[Tile.BatchIndex];
++Batch.ResidentCount;
if(bGpuFarTimelineEnabled&&Batch.ResidentCount==Batch.TileCount)
{
@@ -3011,10 +3057,82 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
FGpuFarTile& Tile=It->second;
if(Tile.BatchIndex!=UINT32_MAX&&Tile.BatchIndex<GpuFarBatches.size())
{
FGpuFarBatch& Batch=GpuFarBatches[Tile.BatchIndex];
FGpuFarBatch& Batch=GpuFarBatches[Tile.BatchIndex];
const uint32 CurrentBatchIndex=Tile.BatchIndex;
if(!Batch.bGpuComplete&&Batch.CompletionEvent&&Context
&&Context->GetData(Batch.CompletionEvent,nullptr,0,D3D11_ASYNC_GETDATA_DONOTFLUSH)==S_OK)
{
std::vector<uint32> OutputSlots;
std::vector<FVoxelTileKey> BatchOutputKeys;
OutputSlots.reserve(Batch.Keys.size());
BatchOutputKeys.reserve(Batch.Keys.size());
for(const FVoxelTileKey& BatchKey:Batch.Keys)
{
const auto BatchTileIt=GpuFarTiles.find(BatchKey);
if(BatchTileIt==GpuFarTiles.end())continue;
OutputSlots.push_back(BatchTileIt->second.OutputSlot);
BatchOutputKeys.push_back(BatchKey);
}
std::vector<uint32> RequiredVertexCounts;
std::string CountReadbackError;
const bool bOutputCountsRead=
VoxelForgeGpuFarViewer::ReadFarTileRequiredVertexCounts(Device,Context,
GpuFarShaderPath,OutputSlots,RequiredVertexCounts,CountReadbackError);
std::vector<FVoxelTileKey> OverflowFallbackKeys;
if(!bOutputCountsRead)
{
++GpuFarOutputCountReadbackFailures;
std::fprintf(stderr,"[GpuFarSlotCountReadback] status=FAIL batch=%u tiles=%zu error=%s action=cpu_fallback_batch\n",
CurrentBatchIndex,BatchOutputKeys.size(),CountReadbackError.c_str());
OverflowFallbackKeys=BatchOutputKeys;
}
else
{
GpuFarOutputCountChecks+=RequiredVertexCounts.size();
for(std::size_t OutputIndex=0;OutputIndex<RequiredVertexCounts.size();++OutputIndex)
{
const uint32 Required=RequiredVertexCounts[OutputIndex];
const FVoxelTileKey& BatchKey=BatchOutputKeys[OutputIndex];
auto BatchTileIt=GpuFarTiles.find(BatchKey);
if(BatchTileIt==GpuFarTiles.end())continue;
FGpuFarTile& CheckedTile=BatchTileIt->second;
CheckedTile.RequiredSurfaceVertexCount=Required;
if(Required>GpuFarMaxRequiredVertices)
{
GpuFarMaxRequiredVertices=Required;
GpuFarMaxRequiredVertexKey=BatchKey;
GpuFarMaxRequiredOutputSlot=CheckedTile.OutputSlot;
}
if(Required>VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile)
{
++GpuFarOutputOverflowCount;
OverflowFallbackKeys.push_back(BatchKey);
std::fprintf(stderr,"[GpuFarSlotOverflow] key=(%d,%d,%d,lod%d) output_slot=%u required_vertices=%u capacity_vertices=%u batch=%u action=cpu_fallback\n",
BatchKey.Coord.X,BatchKey.Coord.Y,BatchKey.Coord.Z,BatchKey.Level,
CheckedTile.OutputSlot,Required,
VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile,CurrentBatchIndex);
}
}
}
for(const FVoxelTileKey& FallbackKey:OverflowFallbackKeys)
{
GpuFarEligibleTiles.erase(FallbackKey);
GpuFarPreparedInputs.erase(FallbackKey);
GpuFarPreparationErrors.erase(FallbackKey);
GpuFarPreparedAt.erase(FallbackKey);
auto FallbackTileIt=GpuFarTiles.find(FallbackKey);
if(FallbackTileIt==GpuFarTiles.end())continue;
const uint32 ReusableSlot=FallbackTileIt->second.OutputSlot;
ReleaseGpuFarTile(FallbackTileIt->second);
GpuFarTiles.erase(FallbackTileIt);
GpuFarFreeOutputSlots.push_back(ReusableSlot);
}
if(!OverflowFallbackKeys.empty())
{
Batch.TileCount-=static_cast<uint32>(std::min<std::size_t>(
Batch.TileCount,OverflowFallbackKeys.size()));
AddGpuFarCpuFallbackTiles(OverflowFallbackKeys);
}
Batch.bGpuComplete=true;
const auto PollAt=std::chrono::steady_clock::now();
Batch.CompletedAt=PollAt;
@@ -3025,11 +3143,11 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(bGpuFarTimelineEnabled)
{
std::printf("[GpuBatchTimeline] event=completed batch=%u at_ms=%.3f frame=%llu tile_count=%u submitted_ms=%.3f\n",
Tile.BatchIndex,ColdTimelineMilliseconds(PollAt),
CurrentBatchIndex,ColdTimelineMilliseconds(PollAt),
static_cast<unsigned long long>(ColdTimelineFrame()),Batch.TileCount,
ColdTimelineMilliseconds(Batch.SubmittedAt));
std::printf("[GpuBatchTimeline] event=uploaded batch=%u at_ms=%.3f frame=%llu method=direct_gpu_compute_output copy_upload=none\n",
Tile.BatchIndex,ColdTimelineMilliseconds(PollAt),
CurrentBatchIndex,ColdTimelineMilliseconds(PollAt),
static_cast<unsigned long long>(ColdTimelineFrame()));
}
for(const FVoxelTileKey& BatchKey:Batch.Keys)
@@ -3038,11 +3156,12 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(BatchTileIt!=GpuFarTiles.end())
{
BatchTileIt->second.bGpuComplete=true;
ReportGpuTileCompletion(BatchKey,BatchTileIt->second,Tile.BatchIndex);
ReportGpuTileCompletion(BatchKey,BatchTileIt->second,CurrentBatchIndex);
RecordGpuCrossingTileReady(BatchKey);
ReportGpuTileResident(BatchKey,BatchTileIt->second);
}
}
if(!GpuFarEligibleTiles.contains(Key))return false;
}
if(Batch.bGpuComplete&&!Batch.bTimingResolved)
{
@@ -3082,6 +3201,47 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(!Tile.bGpuComplete&&Tile.CompletionEvent&&Context
&&Context->GetData(Tile.CompletionEvent,nullptr,0,D3D11_ASYNC_GETDATA_DONOTFLUSH)==S_OK)
{
std::vector<uint32> RequiredVertexCounts;
std::string CountReadbackError;
const bool bOutputCountRead=VoxelForgeGpuFarViewer::ReadFarTileRequiredVertexCounts(
Device,Context,GpuFarShaderPath,{Tile.OutputSlot},RequiredVertexCounts,
CountReadbackError);
const bool bOverflow=!bOutputCountRead||RequiredVertexCounts.empty()
||RequiredVertexCounts[0]>VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile;
if(!bOutputCountRead)
{
++GpuFarOutputCountReadbackFailures;
std::fprintf(stderr,"[GpuFarSlotCountReadback] status=FAIL key=(%d,%d,%d,lod%d) output_slot=%u error=%s action=cpu_fallback\n",
Key.Coord.X,Key.Coord.Y,Key.Coord.Z,Key.Level,Tile.OutputSlot,
CountReadbackError.c_str());
}
else if(!RequiredVertexCounts.empty())
{
const uint32 Required=RequiredVertexCounts[0];
++GpuFarOutputCountChecks;Tile.RequiredSurfaceVertexCount=Required;
if(Required>GpuFarMaxRequiredVertices)
{
GpuFarMaxRequiredVertices=Required;GpuFarMaxRequiredVertexKey=Key;
GpuFarMaxRequiredOutputSlot=Tile.OutputSlot;
}
if(Required>VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile)
{
++GpuFarOutputOverflowCount;
std::fprintf(stderr,"[GpuFarSlotOverflow] key=(%d,%d,%d,lod%d) output_slot=%u required_vertices=%u capacity_vertices=%u action=cpu_fallback\n",
Key.Coord.X,Key.Coord.Y,Key.Coord.Z,Key.Level,Tile.OutputSlot,Required,
VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile);
}
}
if(bOverflow)
{
const uint32 ReusableSlot=Tile.OutputSlot;
GpuFarEligibleTiles.erase(Key);GpuFarPreparedInputs.erase(Key);
GpuFarPreparationErrors.erase(Key);GpuFarPreparedAt.erase(Key);
ReleaseGpuFarTile(Tile);GpuFarTiles.erase(Key);
GpuFarFreeOutputSlots.push_back(ReusableSlot);
AddGpuFarCpuFallbackTiles({Key});
return false;
}
Tile.bGpuComplete=true;
Tile.CompletionEvent->Release();Tile.CompletionEvent=nullptr;
ReportGpuTileCompletion(Key,Tile);
@@ -3575,6 +3735,19 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const FVoxelTileKey& Key=Result.Key;
if(Result.Input)
{
if(Result.Input->nearDetailEnabled)
{
++GpuFarPreparedNearTileInputs;
GpuFarNearLatticeSamples+=Result.Input->nearPackedProxy.size();
GpuFarNearPackedCandidateSamples+=Result.Input->nearPackedCandidateSampleCount;
GpuFarNearPackedSkippedSamples+=Result.Input->nearPackedSkippedSampleCount;
}
else ++GpuFarPreparedFarTileInputs;
GpuFarProtectedRouteSamples+=Result.Input->protectedSampleCount;
GpuFarProtectedThinSamples+=Result.Input->protectedThinSampleCount;
GpuFarProtectedSolidSamples+=Result.Input->protectedSolidSampleCount;
GpuFarProtectedSealSamples+=Result.Input->protectedSealSampleCount;
GpuFarProtectedOverlaySamples+=Result.Input->protectedSolidOverlaySampleCount;
GpuFarPreparedInputs.emplace(Key,std::move(*Result.Input));
GpuFarPreparedAt.emplace(Key,Result.FinishedAt);
GpuFarEligibleTiles.insert(Key);
@@ -4228,7 +4401,10 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
Tile.bTimingResolved=true;
}
++GpuFarTilesSubmitted;++Built;
++GpuFarTilesSubmitted;
if(Key.Level<World->FullResClipLevels)++GpuFarNearTilesSubmitted;
else ++GpuFarFarTilesSubmitted;
++Built;
GpuFarTiles.emplace(Key,Tile);
BuiltKeys.push_back(Key);
if(!bDeferredBatch&&bGpuFarTimelineEnabled)
@@ -5018,11 +5194,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
{
SampleGpuFarMemory();
double CpuMeshWorkerSeconds=0.0;
uint64 CpuMeshTiles=0;
uint64 CpuMeshTiles=0,CpuNearMeshTiles=0,CpuFarMeshTiles=0;
for(int32 Level=0;Level<=MaxLevels;++Level)
{
CpuMeshWorkerSeconds+=WorkerSecondsByLevel[Level];
CpuMeshTiles+=GeneratedByLevel[Level];
if(Level<World->FullResClipLevels)CpuNearMeshTiles+=GeneratedByLevel[Level];
else CpuFarMeshTiles+=GeneratedByLevel[Level];
}
const double AverageGpuMs=GpuFarTilesSubmitted
?GpuFarGpuDispatchMs/static_cast<double>(GpuFarTilesSubmitted):0.0;
@@ -5038,6 +5216,21 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
static_cast<unsigned long long>(GpuFarTilesSubmitted),GpuFarGpuDispatchMs,
Elapsed,static_cast<unsigned long long>(GpuFarWarmupCpuClaimedTiles),
static_cast<unsigned long long>(GpuFarWarmupGpuTakeoverTiles));
std::printf("[GpuFarFieldConsumerSummary] gpu_near_tiles_submitted=%llu gpu_far_tiles_submitted=%llu gpu_near_inputs_prepared=%llu gpu_far_inputs_prepared=%llu cpu_near_mesh_tiles=%llu cpu_far_mesh_tiles=%llu near_gpu_lattice_samples=%llu near_packed_candidate_samples=%llu near_proxy_samples_omitted_for_gpu=%llu protected_route_samples=%llu protected_thin_sign_samples=%llu protected_solid_samples=%llu protected_stratum_seal_samples=%llu protected_solid_overlay_samples=%llu collision_source=cpu_reference hashes_source=cpu_reference\n",
static_cast<unsigned long long>(GpuFarNearTilesSubmitted),
static_cast<unsigned long long>(GpuFarFarTilesSubmitted),
static_cast<unsigned long long>(GpuFarPreparedNearTileInputs),
static_cast<unsigned long long>(GpuFarPreparedFarTileInputs),
static_cast<unsigned long long>(CpuNearMeshTiles),
static_cast<unsigned long long>(CpuFarMeshTiles),
static_cast<unsigned long long>(GpuFarNearLatticeSamples),
static_cast<unsigned long long>(GpuFarNearPackedCandidateSamples),
static_cast<unsigned long long>(GpuFarNearPackedSkippedSamples),
static_cast<unsigned long long>(GpuFarProtectedRouteSamples),
static_cast<unsigned long long>(GpuFarProtectedThinSamples),
static_cast<unsigned long long>(GpuFarProtectedSolidSamples),
static_cast<unsigned long long>(GpuFarProtectedSealSamples),
static_cast<unsigned long long>(GpuFarProtectedOverlaySamples));
std::printf("[GpuFarTiming] submitted_tiles=%llu submission_batches=%llu max_tiles_per_batch=%u pooled_output_reserve_wall_ms=%.3f cpu_input_prepare_wall_ms=%.3f cpu_input_worker_sum_ms=%.3f cpu_upload_enqueue_sum_ms=%.3f gpu_dispatch_timestamp_total_ms=%.3f gpu_dispatch_mean_per_tile_ms=%.6f gpu_dispatch_max_tile_ms=%.6f gpu_submission_span_total_ms=%.3f gpu_submission_span_max_batch_ms=%.3f frame_budget_90hz_ms=11.111\n",
static_cast<unsigned long long>(GpuFarTilesSubmitted),
static_cast<unsigned long long>(GpuFarSubmissionBatches),GpuFarMaxTilesPerSubmissionBatch,
@@ -5073,7 +5266,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
std::printf("[GpuFarModeTiming] mode=cpu cpu_mesh_tiles=%llu cpu_mesh_worker_sum_s=%.6f whole_view_wall_s=%.6f\n",
static_cast<unsigned long long>(CpuMeshTiles),CpuMeshWorkerSeconds,Elapsed);
}
ReportTileTimings();std::fflush(stdout);
ReportTileTimings();
if(GpuFarOutputCountChecks>0)
std::printf("[GpuFarSlotCapacitySummary] checked_tiles=%llu overflow_tiles=%llu count_readback_failures=%llu capacity_vertices=%u max_required_vertices=%u max_key=(%d,%d,%d,lod%d) max_slot=%u check_path=normal_after_completion_event\n",
static_cast<unsigned long long>(GpuFarOutputCountChecks),
static_cast<unsigned long long>(GpuFarOutputOverflowCount),
static_cast<unsigned long long>(GpuFarOutputCountReadbackFailures),
VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile,
GpuFarMaxRequiredVertices,GpuFarMaxRequiredVertexKey.Coord.X,
GpuFarMaxRequiredVertexKey.Coord.Y,GpuFarMaxRequiredVertexKey.Coord.Z,
GpuFarMaxRequiredVertexKey.Level,GpuFarMaxRequiredOutputSlot);
std::fflush(stdout);
if(bQuitAfterClipmap&&CapturePath.empty()
&&(!bGpuFarEnabled||!bGpuFarShaderPrewarm||bGpuWarmupCompleted))
{
@@ -5266,7 +5469,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(!GpuSkirtArgsStaging)
{
D3D11_BUFFER_DESC StagingDesc{};
StagingDesc.ByteWidth=11u*sizeof(uint32);
StagingDesc.ByteWidth=VoxelForgeGpuFarViewer::PooledOutputArgsDwordsPerTile*sizeof(uint32);
StagingDesc.Usage=D3D11_USAGE_STAGING;
StagingDesc.CPUAccessFlags=D3D11_CPU_ACCESS_READ;
const HRESULT CreateResult=Device->CreateBuffer(&StagingDesc,nullptr,
@@ -5278,7 +5481,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(GpuSkirtArgsStaging)
{
const D3D11_BOX ArgsSource{Tile.IndirectArgsByteOffset,0,0,
Tile.IndirectArgsByteOffset+11u*sizeof(uint32),1,1};
Tile.IndirectArgsByteOffset
+VoxelForgeGpuFarViewer::PooledOutputArgsDwordsPerTile*sizeof(uint32),1,1};
Context->CopySubresourceRegion(GpuSkirtArgsStaging,0,0,0,0,
Tile.IndirectArgs,0,&ArgsSource);
D3D11_MAPPED_SUBRESOURCE ArgsMapped{};
@@ -5289,7 +5493,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
const auto* Args=static_cast<const uint32*>(ArgsMapped.pData);
if(bForceDirectDraw)std::copy_n(Args,11,DirectDrawArgs);
const uint32 LocalOutputSlot=Tile.IndirectArgsByteOffset
/(11u*sizeof(uint32));
/(VoxelForgeGpuFarViewer::PooledOutputArgsDwordsPerTile*sizeof(uint32));
const uint32 ExpectedStartIndex=LocalOutputSlot*32768u;
const uint32 ExpectedSurfaceStartIndex=LocalOutputSlot
*VoxelForgeGpuFarViewer::PooledOutputVertexCapacityPerTile;
@@ -7366,6 +7570,7 @@ int main(int Argc,char** Argv)
else if(Arg=="--gpu-connectors-disabled")App.bGpuConnectorRepairEnabled=false;
else if(Arg=="--profile-attribution")App.bProfileAttribution=true;
else if(Arg=="--profile-detail-band")bProfileDetailBand=true;
else if(Arg=="--gpu-far-skip-cpu-detail-band")App.bGpuFarSkipCpuDetailBand=true;
else if(Arg=="--compare-evaluators")App.bCompareEvaluators=true;
else if(Arg=="--parity-only")App.bParityOnly=true;
else if(Arg=="--density-hash")App.bDensityHash=true;