Native crash analysis — user Blackpine launch, 14 September 2026
The immediate crash is a null Direct3D resource passed by Unity to ID3D11DeviceContext::Map on UnityGfxDeviceWorker. It follows an already removed graphics device. It does not establish why the GPU device was removed.
Evidence is recorded in native-stack-analysis.json; the chronological native messages are in player-native.log. The original minidump stays outside Git and was not uploaded. No Unity/game/GPU process or system change was used for this analysis.
Confirmed fault
- Engine: Unity 6000.3.24f1; D3D11 threaded; RTX 4060 Laptop; logged driver 32.0.15.7700. Associated source head reported by the build owner:
eef49c8. - Exception thread 55752, named UnityGfxDeviceWorker; exception
0xC0000005, read address 0xC9. - Exception instruction at
d3d11.dll + 0x172FEB:movsx rax, byte ptr [rdx+0xC9]. - Exception RDX = 0. In this function's x64 signature, RDX is the
ID3D11Resource*argument. R9 is 4 (D3D11_MAP_WRITE_DISCARD). - The original unsymbolicated
D3DKMTOpenResourcelabel was a nearest-export fallback. Matching Microsoft symbols resolve the actual function toCContext::TID3D11DeviceContext_Map_<1>.
CContext::TID3D11DeviceContext_Map_<1> d3d11 + 0x172FEB
D3D11DynamicConstantBuffer::D3D11BufferUpdate UnityPlayer + 0x9176B5
GfxDeviceD3D11Base::DrawBuffersBatchMode UnityPlayer + 0x918367
GfxDeviceWorker::RunCommand UnityPlayer + 0x13A3E24
GfxDeviceWorker::RunExt UnityPlayer + 0x13981FD
GfxDeviceWorker::RunGfxDeviceWorker UnityPlayer + 0x139814C
Thread::RunThreadWrapper UnityPlayer + 0x12BC204
Stack addresses from Unity's crash handler were independently symbolicated. Exception registers/RIP and the thread name were separately parsed from the dump. The 173 ThreadList contexts represent the later crash-handler/suspended state; scanning those stacks is not treated as an independent unwind of the original failure. Public symbols supply function names but no engine source lines.
Sequence and limits
After RAMPAGE_LOAD race ready, multiple buffer allocations and a 2048×2048 staging texture fail with 0x887A0005. The log then reports an attempt to lock a null buffer and two failed 608-byte constant-buffer allocations. The later Map call dereferences a null resource.
Microsoft defines 0x887A0005 as DXGI_ERROR_DEVICE_REMOVED; the actual removal reason requires separate evidence such as GetDeviceRemovedReason. The subsequent allocation failures are not proof of an out-of-memory condition. Microsoft DXGI error reference, Map resource contract.
The concrete engine failure signature is useful for a Unity report: device removed → failed constant-buffer creation → null-resource Map on rendering worker. Fixing or avoiding the later null dereference alone does not restore the lost device. This dump cannot assign the initial removal to hardware, NVIDIA, a project shader/mesh, or earlier D3D12 CBV errors. It contains no GPU command history identifying the first failing draw. nvspcap64.dll 3.27.0.120 was loaded; its presence is only a possible controlled-test variable, not proof of causation.
Matching symbols and reproduction
The built UnityPlayer.dll and the installed 6000.3.24f1 nondevelopment Mono player DLL have identical SHA-256:
e286bd7f01c45197d051325423b13df133d2ac315671eca2881e7936d251c6bd.
Unity dump CodeView and local PDB both identify GUID 5d6f44bb-5db4-4976-b609-582e62f93ac2, age 1. Microsoft D3D11 dump/local DLL/PDB GUID is 69dd4774-b442-adfc-c7ed-384d7c231d80; CodeView and PDB DBI age are 1. The public PDB's Info-stream age is 3; this is recorded explicitly rather than claiming those two PDB age fields are identical. LLVM accepted the matching symbols without a mismatch override.
The exact Microsoft PDB was obtained from the official public symbol server, 3,338,240 bytes. Its hash, both DLL hashes, PDB identities, and the minidump hash are in the JSON.
Installed tools suffice; no debugger installation was needed. The D3D11 directory below contains a copy of the matching local DLL beside the downloaded PDB. These commands read binary files and do not load the game:
$symbolizer = 'C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/llvm-symbolizer.exe'
$unitySymbols = 'C:/Program Files/Unity/Hub/Editor/6000.3.24f1/Editor/Data/PlaybackEngines/windowsstandalonesupport/Variations/win64_player_nondevelopment_mono'
& $symbolizer --relative-address --addresses "--obj=$unitySymbols/UnityPlayer.dll" 0x9176b5 0x918367 0x13a3e24 0x13981fd 0x139814c 0x12bc204
& $symbolizer --relative-address --addresses "--obj=$env:TEMP/RampageNativeSymbols/d3d11.dll" 0x172feb
& 'C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/dumpbin.exe' /disasm:nobytes /range:0x180172fe0,0x180173050 "$env:TEMP/RampageNativeSymbols/d3d11.dll"
Exception extraction is reproducible using Python's standard library. Set dump_path to the private retained dump; the program only reads it:
import struct
from pathlib import Path
b = Path(dump_path).read_bytes()
u32 = lambda o: struct.unpack_from('<I', b, o)[0]
u64 = lambda o: struct.unpack_from('<Q', b, o)[0]
streams = {u32(o): u32(o + 8) for o in range(u32(12), u32(12) + 12*u32(8), 12)}
e = streams[6] # MINIDUMP_EXCEPTION_STREAM
context = u32(e + 164) # RVA of the preserved AMD64 exception context
print('Thread', u32(e), 'Exception', hex(u32(e + 8)))
print('Instruction', hex(u64(e + 24)))
print('Read/write kind', u64(e + 40), 'Access address', hex(u64(e + 48)))
print('RDX', hex(u64(context + 136)), 'RIP', hex(u64(context + 248)))