feat(tools): summarize terrain shade profiles
This commit is contained in:
@@ -1750,6 +1750,18 @@ state, not a persistent cache identity or a WEAR row. The observation narrows
|
||||
the next terrain task to profiling the cache's generated entries and their
|
||||
consumer; it still does not establish a Land1 blend equation.
|
||||
|
||||
The probe now also reads the bounded eight-byte entry table and only hashes
|
||||
the fixed 212-byte profile banks it observes; raw process bytes never enter
|
||||
the repository. The same AutoDemo cache had 3,426 materialized record pointers
|
||||
among 3,462 entries and referenced banks `0..4`. Two consecutive captures
|
||||
kept that count, bank set, and all five FNV-1a-64 bank hashes stable:
|
||||
`9426539192111566946`, `2915543853261903601`, `13156371703608727216`,
|
||||
`11280405573172155968`, and `18234288329145104612`. Their result views changed
|
||||
from `0x008A565C` to `0x008A55A8`. Thus the generated cache/profile state is
|
||||
stable over these render samples while the shared result view is not. This
|
||||
still identifies neither the record-field semantics nor the final terrain
|
||||
blend/pass operation.
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File `
|
||||
tools\capture-terrain-shade-cache.ps1 -ProcessId <iron_3d-pid>
|
||||
|
||||
@@ -78,6 +78,17 @@ public static class FparkanTerrainShadeProbe {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static ulong Fnv1a64(byte[] bytes, int offset, int length) {
|
||||
ulong hash = 14695981039346656037UL;
|
||||
unchecked {
|
||||
for (int index = offset; index < offset + length; index++) {
|
||||
hash ^= bytes[index];
|
||||
hash *= 1099511628211UL;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
@@ -175,6 +186,45 @@ function Find-ShadeCache {
|
||||
return $null
|
||||
}
|
||||
|
||||
function Get-ShadeCacheSummary {
|
||||
param([IntPtr]$Process, [Int64]$Cache, [byte[]]$Header)
|
||||
$entryTable = [BitConverter]::ToUInt32($Header, 316)
|
||||
$entryCount = [BitConverter]::ToUInt32($Header, 320)
|
||||
$summary = [ordered]@{
|
||||
materialized_entries = $null
|
||||
profile_banks = @()
|
||||
}
|
||||
# The count field is runtime data. Keep a hard observer bound so a corrupt
|
||||
# or stale candidate cannot turn a passive sample into an excessive read.
|
||||
if ($entryTable -lt 0x1000 -or $entryCount -gt 100000) { return $summary }
|
||||
$entryBytes = Read-Bytes $Process $entryTable ([int]($entryCount * 8))
|
||||
if ($null -eq $entryBytes) { return $summary }
|
||||
$materialized = 0
|
||||
$banks = [System.Collections.Generic.SortedSet[int]]::new()
|
||||
for ($index = 0; $index -lt $entryCount; $index++) {
|
||||
$offset = $index * 8
|
||||
if ([BitConverter]::ToUInt32($entryBytes, $offset) -ge 0x1000) {
|
||||
$materialized++
|
||||
[void]$banks.Add([int]$entryBytes[$offset + 4])
|
||||
}
|
||||
}
|
||||
$summary.materialized_entries = $materialized
|
||||
if ($banks.Count -eq 0) { return $summary }
|
||||
$maxBank = $banks.Max
|
||||
if ($maxBank -ge 100) { return $summary }
|
||||
$bankBytes = Read-Bytes $Process ($Cache + 332) (($maxBank + 1) * 212)
|
||||
if ($null -eq $bankBytes) { return $summary }
|
||||
$profiles = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($bank in $banks) {
|
||||
$profiles.Add([ordered]@{
|
||||
bank = $bank
|
||||
fnv1a64 = [FparkanTerrainShadeProbe]::Fnv1a64($bankBytes, $bank * 212, 212).ToString()
|
||||
})
|
||||
}
|
||||
$summary.profile_banks = @($profiles)
|
||||
return $summary
|
||||
}
|
||||
|
||||
if ($SearchEnd -le $SearchStart) { throw 'SearchEnd must exceed SearchStart' }
|
||||
$terrainBase = Get-TerrainModuleBase $ProcessId
|
||||
$process = [FparkanTerrainShadeProbe]::OpenProcess(
|
||||
@@ -194,6 +244,7 @@ try {
|
||||
if ($null -ne $cache) {
|
||||
$header = Read-Bytes $process $cache 324
|
||||
if ($null -ne $header) {
|
||||
$summary = Get-ShadeCacheSummary $process $cache $header
|
||||
[ordered]@{
|
||||
schema = 'fparkan-terrain-shade-cache-v1'
|
||||
process_id = $ProcessId
|
||||
@@ -203,6 +254,8 @@ try {
|
||||
result_view = ('0x{0:X8}' -f [BitConverter]::ToUInt32($header, 24))
|
||||
entry_table = ('0x{0:X8}' -f [BitConverter]::ToUInt32($header, 316))
|
||||
entry_count = [BitConverter]::ToUInt32($header, 320)
|
||||
materialized_entries = $summary.materialized_entries
|
||||
profile_banks = $summary.profile_banks
|
||||
scan_attempt = $attempt
|
||||
} | ConvertTo-Json -Compress
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user