A 16-bit depth target with stencil maps to VK_FORMAT_D16_UNORM_S8_UINT,
which NVIDIA devices do not support as an attachment, so creating it threw.
The surface, its views and the pipelines now use the first of D16_UNORM_S8_UINT,
D24_UNORM_S8_UINT and D32_SFLOAT_S8_UINT the device can attach and sample.
Guest-side choices (16-bit sampled views, bias units) still follow the guest
format. A constant depth bias is scaled by 256 for D24 storage; on D32 float
storage it throws, as its unit depends on the depth value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read the device-local heap's VK_EXT_memory_budget figures before a texture
or storage image allocation and pick a host memory type when the
allocation does not fit, rather than allocating again after the driver
refused the first attempt. The allocation itself is made once and still
throws when it fails.
#4152 dropped the device-wide module list that #3173 added, so Pipeline
destroys the shader modules right after the library parts are created, also
for the parts prebuilt at registration. AMD's Windows driver still reads
them during the background link-time-optimized link and faults inside
amdvlk64.dll. Hand the modules of each new part to the device's library
store again and destroy them in ClearPipelineLibraries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refreshImports and importAllocation drop an import whose registered run changed (a title growing a
heap) while the GpuMutex hold that drops it may still hold a HostImport pointer from before: a
build's in-place region (UploadFinish flushes pending images between regions, and a flush may
reconcile the imports), an indirect argument or a vertex import. The holder went to the batch open
at the drop, or was destroyed at once with the recorder idle, and the map node the pointer names
was erased. A Submit or Sync later in the hold put the command using the old buffer or address into
a later batch, so the import could be freed before that batch ran and the GPU read an unmapped
page (VK_ERROR_DEVICE_LOST; VK_EXT_device_fault reports READ_INVALID inside the dropped import).
The dropped import's map node now moves into its holder (std::map::extract), so those pointers stay
valid, and the holder is kept by every batch the same hold opens (Recorder::KeepThroughHold), so
whatever the hold records with them completes first. Drops for pages the guest releases (the lease
waiter) keep the old lifetime, and the waiter lets go of what an ended hold kept so it does not pin
the ranges.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Goat Simulator 3 draws a triangle list whose indices are all 0xffffffff
with primitive restart off. Each fetch past a descriptor's records reads
zeros (out-of-bounds select 0 or 1), but the zero-padded vertex copies
were sized to the highest index: 160 GiB, which vkAllocateMemory refused.
When the highest index is at least 64Ki vertices past the largest
per-vertex record count, the draw now uses a copy of its indices with
every index past that count moved to it. Each attribute reads zeros
there as at the original index; only the vertex index the shader sees
changes, so indices closer to the records are left as they are.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An image whose results stay on the GPU is never written back, so
APS5_DUMP_STORAGE saw nothing; APS5_STORE_AT_FLIP=1 stores every pending
image and ran a 4 GB device out of memory at 3840x2160. The selected
images alone are now stored at each flip.
An indexed draw that binds its index buffer in place from a host import
(#2253) scans the bound range for its highest index on every draw, where
the copied path reuses the value kept with its snapshot. A draw of many
indices pays for the scan each time, and an indirect draw, which binds
the whole declared index buffer, scans the whole buffer per draw.
The recorder now keeps the highest index of an in-place index range of
4096 indices or more with the write generation collected before the
scan, and a draw takes it while the range is unchanged since
(GuestMemory::UnchangedSince and the allocation registry generation, as
for a reused snapshot). A smaller range is scanned at every draw as
before: the scan costs 0.4 ns per index and the write collect and lookup
0.2 to 1.4 us per draw, so the scan is the cheaper of the two below
about 3,000 indices, as #2253 measured on small ranges.
A multisampled target's samples are only on the host, so its guest memory
never holds them: a CPU read through GuestMemory::Read/ReadCommitted, a
DMA_DATA copy from it and a texture or storage image lookup at its address
throw instead of returning bytes that were never written there. Asked by
oneandonlydean; the test reads a resolved-only target's memory each way.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The duplicate ColorTarget::cmaskAddress, decode and size helper are gone: multisampled targets
use main's cmaskAddress/cmaskBytes (whole metablocks). Single-sample targets keep main's rule
(CMASK under FAST_CLEAR); a multisampled one takes it under FAST_CLEAR or COMPRESSION. A zero
fill of the whole CMASK clears at the next use, 0xFFFFFFFF marks it expanded, any other or
partial fill refuses the next use; eliminate/DCC passes over a multisampled target and a CB
resolve into a fast-clear destination are refused. The draw key adds CMASK_BASE_EXT (0x398),
which main decodes but did not key.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Draws with PA_SC_AA_CONFIG multisampling (2, 4 or 8 samples, every target with as many
fragments, the standard sample locations, MSAA_ENABLE) render into host-only multisampled
color images and multisampled depth surfaces; the pipeline rasterizes with that sample
count. A CB_COLOR_CONTROL resolve over a multisampled CB0 runs as a render pass whose
resolve attachment is CB1's resident image. A zero fill over a target's CMASK fast-clears
it to the CB_COLOR_CLEAR_WORD values of its next use. EQAA, coverage conversion,
nonstandard sample locations, sampling a multisampled surface and multisampled mips stay
refused.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>