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:
1 parent
7d92e148a9
commit
7d1808fdf2
16 files changed
+796
-37
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user