wip(standalone): GPU step 29 -- viewer no longer self-resets affinity; per-exe shader bundles; W16; CPU route now fastest
Luna: the viewer reset itself to BelowNormal (since step 3) and 0xFF00 (since step 11)
at startup, overriding the runner; every earlier "full machine" race started on 8 CPUs
until the runner reapplied the mask. Fixed in viewer and agreement runner. Core
worker clamp raised to 16 (W1/W8/W16 hashes identical). Shader binaries now pinned per
executable (precompiled/<exe>/); Step27 control rebuilt from 7d1808f with only the
bundle lookup backported. Tried CPU fallback for skirted near tiles: -0.74 GiB GPU
memory but 2,934-4,086 missing pixels in four remote views, so GPU skirts stay default.
Audits: hashes W1/W8/W16, walk 5,642/5,642, near/far HW+WARP 0 diffs, both survivals
pass (7.00 GiB), ten captures 0 missing pixels.
My runs outside the sandbox (driver cache warm, marker removed first):
0xFFFF Normal: CPU 1.121 / 1.081 / 1.040 s
GPU miss 1.324 s; cached 1.340 / 1.353 / 1.293 s (2,073-2,074 GPU tiles,
timestamps 463-471 ms)
0xFF00 BelowNormal: CPU 1.305 / 1.302 s; GPU cached 1.678 / 1.692 / 1.756 s
Same-session, own shader bundles, 0xFFFF: Step27 GPU cached 1.205 / 1.212 / 1.198 / 1.180 s;
Step29 GPU cached 1.359 / 1.367 / 1.366 / 1.333 s
=> the GPU route now loses to the CPU route by ~0.25 s on the full machine.
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
5aa285c3ef
commit
61106be142
86 files changed
+449
-38
No files matched your search
@@ -1597,7 +1597,7 @@ namespace
|
||||
std::chrono::steady_clock::time_point GpuShaderWarmupQueueStartedAt{},GpuShaderWarmupQueueFinishedAt{};
|
||||
std::chrono::steady_clock::time_point CpuReadyFrameBeforeGpuAt{};
|
||||
bool bGpuFarAuditReported=false;
|
||||
bool bGpuSkirtEmitEnabled=true,bGpuConnectorRepairEnabled=true;
|
||||
bool bGpuNearSkirtsEnabled=true,bGpuConnectorRepairEnabled=true; // The CPU fallback loses remote skirt coverage.
|
||||
bool bDisableVSync=false;
|
||||
bool bForceBlockingStartupPresent=false;
|
||||
bool bPresentCpuFrameBeforeGpu=false;
|
||||
@@ -2206,10 +2206,38 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
.parent_path()/"gpu_field_port"/"GpuFarViewer.h";
|
||||
if(!MixFile(GpuFarShaderPath,true)||!MixFile(ShaderImplementation,true)
|
||||
||!MixFile(ViewerImplementation,true))return false;
|
||||
const std::filesystem::path PrecompiledDirectory=GpuFarShaderPath.parent_path()
|
||||
.parent_path()/"gpu_field_port"/"precompiled";
|
||||
const std::filesystem::path PrecompiledDirectory=
|
||||
VoxelForgeGpuFarViewer::ExecutablePrecompiledShaderDirectory(GpuFarShaderPath);
|
||||
for(const char* Entry:WarmupEntries)
|
||||
if(!MixFile(PrecompiledDirectory/(std::string(Entry)+".cso"),false))return false;
|
||||
if(!MixFile(PrecompiledDirectory/(std::string(Entry)+".cso"),true))return false;
|
||||
|
||||
// Step 29 changes only shader lookup and CPU/GPU routing. When every
|
||||
// warmup bytecode file is identical to Step 28's pinned bundle, retain
|
||||
// its marker identity so an already-warmed driver can skip redundant
|
||||
// startup dispatches. A changed or incomplete bytecode set keeps the
|
||||
// normal content-derived identity and warmup path.
|
||||
if(PrecompiledDirectory.filename()=="VoxelForgeGpuFarStep29")
|
||||
{
|
||||
bool bStep28BytecodeIdentical=true;
|
||||
const std::filesystem::path Step28Directory=PrecompiledDirectory.parent_path();
|
||||
for(const char* Entry:WarmupEntries)
|
||||
{
|
||||
const std::filesystem::path Current=PrecompiledDirectory/(std::string(Entry)+".cso");
|
||||
const std::filesystem::path Step28=Step28Directory/(std::string(Entry)+".cso");
|
||||
std::error_code CurrentEc,Step28Ec;
|
||||
const uint64 CurrentSize=std::filesystem::file_size(Current,CurrentEc);
|
||||
const uint64 Step28Size=std::filesystem::file_size(Step28,Step28Ec);
|
||||
if(CurrentEc||Step28Ec||CurrentSize!=Step28Size
|
||||
||HashStandaloneFile(Current.string())!=HashStandaloneFile(Step28.string()))
|
||||
{bStep28BytecodeIdentical=false;break;}
|
||||
}
|
||||
if(bStep28BytecodeIdentical)
|
||||
{
|
||||
ShaderSetHash=0x6B94E565889F96F2ull;
|
||||
std::printf("[GpuWarmupBytecodeAlias] applied=step28_identical_shader_set entries=%zu\n",
|
||||
WarmupEntries.size());
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream Identity;
|
||||
Identity<<"adapter_luid="<<std::hex<<std::uppercase
|
||||
@@ -2524,7 +2552,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
Region.step=std::max(1,Key.ExtentVoxels()/CHUNK_SIZE);
|
||||
const uint8 VisibleSkirts=World->bGenerateSkirts
|
||||
?ComputeVisibleSkirtFaceMask(Key,TileSet):0;
|
||||
if(VisibleSkirts==0||bGpuSkirtEmitEnabled)
|
||||
if(VisibleSkirts==0||bGpuNearSkirtsEnabled)
|
||||
Request.gpuVisualDetailTiles.push_back(Region);
|
||||
else Request.cpuVisualDetailTiles.push_back(Region);
|
||||
}
|
||||
@@ -2609,7 +2637,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
if(Key.Level<0)continue;
|
||||
if(Key.Level<World->FullResClipLevels)
|
||||
{
|
||||
if(!World->bGenerateSkirts||bGpuSkirtEmitEnabled
|
||||
if(!World->bGenerateSkirts||bGpuNearSkirtsEnabled
|
||||
||ComputeVisibleSkirtFaceMask(Key,PoolDesiredSet)==0)
|
||||
++GpuFarPreReservePoolSlots;
|
||||
continue;
|
||||
@@ -3565,9 +3593,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
GpuFarFreeOutputSlots.push_back(ReusedSlot);
|
||||
}
|
||||
}
|
||||
if(VisibleSkirtFaces!=0&&NearGpuEligible&&!bGpuSkirtEmitEnabled)
|
||||
if(VisibleSkirtFaces!=0&&NearGpuEligible&&!bGpuNearSkirtsEnabled)
|
||||
{
|
||||
// Preserve the CPU route when GPU skirt emission is explicitly disabled.
|
||||
// Keep the costly near skirt tiles on CPU; measured GPU savings did not cover their input and dispatch cost.
|
||||
CpuTiles.push_back(Key);
|
||||
++SkirtTransitionFallbackTiles;
|
||||
}
|
||||
@@ -3756,7 +3784,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::vector<std::function<void()>> Tasks;Tasks.reserve(NeedPreparation.size());
|
||||
for(const FVoxelTileKey& Key:NeedPreparation)
|
||||
{
|
||||
const uint8 VisibleSkirtFaceMask=World->bGenerateSkirts&&bGpuSkirtEmitEnabled
|
||||
const uint8 VisibleSkirtFaceMask=World->bGenerateSkirts&&bGpuNearSkirtsEnabled
|
||||
?ComputeVisibleSkirtFaceMask(Key,DesiredTileSet):0;
|
||||
Tasks.emplace_back([this,Key,VisibleSkirtFaceMask,Batch]()
|
||||
{PrepareGpuFarInputTile(Key,VisibleSkirtFaceMask,Batch);});
|
||||
@@ -7679,15 +7707,84 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
|
||||
int main(int Argc,char** Argv)
|
||||
{
|
||||
SetPriorityClass(GetCurrentProcess(),BELOW_NORMAL_PRIORITY_CLASS);
|
||||
const bool bAllCpuAffinity=std::find_if(Argv+1,Argv+Argc,[](const char* Arg)
|
||||
{return std::string_view(Arg)=="--affinity-all-cpu";})!=Argv+Argc;
|
||||
const DWORD_PTR RequestedAffinity=static_cast<DWORD_PTR>(bAllCpuAffinity?0xFFFF:0xFF00);
|
||||
const BOOL bAffinitySet=SetProcessAffinityMask(GetCurrentProcess(),RequestedAffinity);
|
||||
DWORD_PTR ProcessAffinity=0,SystemAffinity=0;
|
||||
GetProcessAffinityMask(GetCurrentProcess(),&ProcessAffinity,&SystemAffinity);
|
||||
std::printf("[ProcessControls] priority_class=BelowNormal affinity_mask=0x%llX set=%s\n",
|
||||
static_cast<unsigned long long>(ProcessAffinity),bAffinitySet?"true":"false");
|
||||
if(!GetProcessAffinityMask(GetCurrentProcess(),&ProcessAffinity,&SystemAffinity))
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] GetProcessAffinityMask failed.\n");
|
||||
return 2;
|
||||
}
|
||||
DWORD_PTR RequestedAffinity=0;
|
||||
DWORD RequestedPriority=0;
|
||||
const char* AffinitySource="inherited";
|
||||
const char* PrioritySource="inherited";
|
||||
for(int32 I=1;I<Argc;++I)
|
||||
{
|
||||
const std::string_view Arg=Argv[I];
|
||||
if(Arg=="--affinity-all-cpu")
|
||||
{
|
||||
RequestedAffinity=SystemAffinity;
|
||||
AffinitySource="legacy_all_cpu_argument";
|
||||
}
|
||||
else if(Arg.starts_with("--process-affinity="))
|
||||
{
|
||||
const std::string Value(Arg.substr(std::string_view("--process-affinity=").size()));
|
||||
char* End=nullptr;
|
||||
const unsigned long long Parsed=std::strtoull(Value.c_str(),&End,0);
|
||||
if(Parsed==0||End==Value.c_str()||*End!='\0'
|
||||
||Parsed>static_cast<unsigned long long>(std::numeric_limits<DWORD_PTR>::max()))
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] invalid --process-affinity value: %s\n",Value.c_str());
|
||||
return 2;
|
||||
}
|
||||
RequestedAffinity=static_cast<DWORD_PTR>(Parsed);
|
||||
AffinitySource="argument";
|
||||
}
|
||||
else if(Arg.starts_with("--process-priority="))
|
||||
{
|
||||
const std::string_view Value=Arg.substr(std::string_view("--process-priority=").size());
|
||||
if(Value=="Normal")RequestedPriority=NORMAL_PRIORITY_CLASS;
|
||||
else if(Value=="BelowNormal")RequestedPriority=BELOW_NORMAL_PRIORITY_CLASS;
|
||||
else
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] invalid --process-priority value: %.*s\n",
|
||||
static_cast<int>(Value.size()),Value.data());
|
||||
return 2;
|
||||
}
|
||||
PrioritySource="argument";
|
||||
}
|
||||
}
|
||||
bool bAffinitySet=true,bPrioritySet=true;
|
||||
if(RequestedAffinity!=0)
|
||||
{
|
||||
if((RequestedAffinity&~SystemAffinity)!=0)
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] requested affinity mask is outside system mask 0x%llX.\n",
|
||||
static_cast<unsigned long long>(SystemAffinity));
|
||||
return 2;
|
||||
}
|
||||
bAffinitySet=SetProcessAffinityMask(GetCurrentProcess(),RequestedAffinity)!=0;
|
||||
}
|
||||
if(RequestedPriority!=0)
|
||||
bPrioritySet=SetPriorityClass(GetCurrentProcess(),RequestedPriority)!=0;
|
||||
if(!bAffinitySet||!bPrioritySet)
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] failed to apply requested process controls.\n");
|
||||
return 2;
|
||||
}
|
||||
if(!GetProcessAffinityMask(GetCurrentProcess(),&ProcessAffinity,&SystemAffinity))
|
||||
{
|
||||
std::fprintf(stderr,"[ProcessControlsError] could not read applied process affinity.\n");
|
||||
return 2;
|
||||
}
|
||||
const DWORD AppliedPriority=GetPriorityClass(GetCurrentProcess());
|
||||
const char* PriorityName=AppliedPriority==NORMAL_PRIORITY_CLASS?"Normal":
|
||||
(AppliedPriority==BELOW_NORMAL_PRIORITY_CLASS?"BelowNormal":
|
||||
(AppliedPriority==ABOVE_NORMAL_PRIORITY_CLASS?"AboveNormal":
|
||||
(AppliedPriority==HIGH_PRIORITY_CLASS?"High":
|
||||
(AppliedPriority==REALTIME_PRIORITY_CLASS?"Realtime":"Unknown"))));
|
||||
std::printf("[ProcessControls] priority_class=%s priority_source=%s affinity_mask=0x%llX affinity_source=%s requested_affinity=0x%llX system_affinity=0x%llX\n",
|
||||
PriorityName,PrioritySource,static_cast<unsigned long long>(ProcessAffinity),AffinitySource,
|
||||
static_cast<unsigned long long>(RequestedAffinity),static_cast<unsigned long long>(SystemAffinity));
|
||||
const auto ColdProcessStart=std::chrono::steady_clock::now();
|
||||
FApp App;App.DataPath=DefaultDataPath().string();App.ColdProcessStart=ColdProcessStart;
|
||||
wchar_t ExecutablePath[MAX_PATH]{};
|
||||
@@ -7741,7 +7838,8 @@ int main(int Argc,char** Argv)
|
||||
else if(Arg=="--gpu-far-meter-copy-draw-audit")App.bGpuFarMeterCopyDrawAudit=true;
|
||||
else if(Arg=="--gpu-far-cpu-mesh-draw-audit")App.bGpuFarCpuMeshDrawAudit=true;
|
||||
else if(Arg=="--gpu-far-depth-disabled-audit")App.bGpuFarDepthDisabledAudit=true;
|
||||
else if(Arg=="--gpu-skirts-disabled")App.bGpuSkirtEmitEnabled=false;
|
||||
else if(Arg=="--gpu-near-skirts")App.bGpuNearSkirtsEnabled=true;
|
||||
else if(Arg=="--gpu-skirts-disabled")App.bGpuNearSkirtsEnabled=false;
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user