Recorded draws without BDA page tables now take the device-local staging
of written and atomic buffer elements that dispatches use; their
copy-backs are already recorded through MarkGpuWrites. A draw that ends
up synchronous with staged regions is rebuilt unstaged.
APS5_NO_DRAW_STAGING=1 keeps draws' elements in place.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The controller sound card path already scales its samples by ANYPS5_RUMBLE, but
the Bluetooth haptics stream took the vibration port samples before that, so
ANYPS5_RUMBLE=0 still left a Bluetooth DualSense vibrating.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolve the two conflicts in Texture.cpp: keep main's creationHandOvers
counter next to linearImportRetiles, and address the retile's tiled
side through main's new SurfaceGeometry::GuestOffset(layer, mip) in both
the direct-import and the scratch dispatch. A level-major surface does
not keep each layer contiguous, so the whole-layer check that picks the
direct import now skips it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An invalid-descriptor fault check of a GPU-descriptor buffer access, and the
swizzle-selector check of a formatted load, is not emitted when an identical
check on the same descriptor under the same execution guard sits earlier in
the same IR block or in a dominating block. The fault record, the invocation
stop and the host error stay the same; only the pc stored for a fault that two
invocations race to record can differ. APS5_NO_FAULT_CHECK_DEDUP restores every
check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A build grew its binding and allocation vectors one element at a time and
tracked occupied binding numbers in a std::set; about 3.7% of the queue-0
worker on one title's hub was allocator time inside builds. The counts are
known before the plan is walked, so the vectors are reserved once and the
binding numbers go in a reserved vector.
A build that binds BDA tables, or a fault buffer while APS5_LOOP_GUARD is
set, can never be reused (noteReusable and NeverReusable refuse it), so it
no longer copies its data words for a template refresh nor records the proof
of its sampled textures for a Revalidate (the lookup log is still cleared).
A fault-only build is reusable and keeps both. APS5_KEEP_TEMPLATE_RECORDS=1
keeps both for every build.
ShaderResources::ReadsOverlap built the whole InPlaceReads vector on every
call. recordDraw calls it once per queued store for every draw that is not
address-based (the touches predicate of AnyQueuedStore), and the queue-0
worker of one title spent about 3% of its time there (InPlaceReads, vector
growth, malloc and free under AnyQueuedStore).
GuestBufferMemory::InPlaceReadsOverlap walks the same regions (the address
space's base regions, then the build's own, each when bound in place) and
stops at the first overlap. The answer is the same as the listed ranges'.
APS5_NO_READS_OVERLAP_WALK=1 builds the list as before.
The descriptor web entry and APS5_STRICT_DESCRIPTOR_WEBS said "texels";
the fold takes image loads and samples only. A path through an image
gather or an image atomic's returned value still throws.
AI-assisted.
MoltenVK has no VK_EXT_image_view_min_lod, so since #130 the first T#
with a MIN_LOD clamp above its base level threw. ASTRO BOT (PPSA21564
01.007.000) hits it on the title screen, about four minutes after boot.
MoltenVK does offer shaderResourceMinLod, which maps the SPIR-V MinLod
operand to Metal's min_lod_clamp.
On a device with shaderResourceMinLod, without the extension and
without graphics pipeline libraries, the new target flag
shaderImageMinLod moves the clamp into the shader:
- DescriptorBindingBuilder writes each direct image's clamp, relative
to the view's base level and bounded by its last level and MAX_MIP,
as a float specialization constant at MinLodBase + image.
- Samples of direct images take it as the MinLod operand, or as an FMax
on an explicit LOD when the clamp is above 0, combined with an
instruction's _cl clamp.
- The image view no longer chains the clamp there; image table entries
with a clamp are still rejected, and devices with the extension are
unaffected. APS5_NO_IMAGE_VIEW_MIN_LOD forces the shader lane.
- It throws when the clamp sits above a paired S#'s MAX_LOD or has no
mip filter, follows an explicit LOD or gradient with a nonzero S# LOD
bias, pairs with a run-time S# or different min and mag filters, or
meets image_get_lod, gathers at a clamp of a level or more, or the
emulated depth-compare or 11:11:10 sample.
- ValidateShaders accepts CapabilityMinLod when the device enables
shaderResourceMinLod.
- The flag is written after hostInterpolationFirst as request
serialization version 53; older versions read it as false.
The gaps, including llvmpipe applying the S# bias after the clamp, are
recorded in docs/dev/debt/shader.md.
Tested on an M-series Mac (MoltenVK 1.4.2, x86_64 under Rosetta):
image_sample_lod_clamp samples a T# with fractional and level clamps
over BASE_LEVEL 0 and 1 in both lanes, and fails without the shader
clamp or with an absolute one; graphics, shader disk cache, shader
memory and request serializer tests pass. PPSA21564 renders the title
and reaches the warp sequence after it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since #8697 every device with shaderDenormPreserveFloat32 and an independent
f32 denormal behaviour gets DenormPreserve 32. RADV on Vega (GCN 5, Mesa
26.0.8) miscompiles the preserving forms of the transcendental ops: its
v_log_f32 lowering picks the denormal scale with a v_cndmask_b32 that reads
two SGPRs, which GFX9 cannot do, so log2(2.0) is 25.0 in some lanes and
agc_driver_log_near_one, vop1_float_unary, fp16_overflow and
float16_result_modifiers fail.
ProbeFloat32DenormPreserve runs v_log_f32, v_sqrt_f32, v_rsq_f32, v_rcp_f32
and v_exp_f32 on normal values with and without the mode, after the flush
probe. The mode only changes denormal handling, but Vulkan does not require
these ops to be correctly rounded, so Float32ResultsAgree accepts each of
the 256 result pairs when they are no further apart than the width of the
interval the Vulkan precision bound allows around the exact result (sqrt's
bound inherited from 1.0 / inversesqrt(), an absolute 2^-21 for log2 inputs
in [0.5, 2.0]). When one falls outside, float32DenormPreserve
stays off and the device keeps its default f32 denormal handling.