flock, fstatfs, ftruncate, fsync, fdatasync, getdirentries, fchmod, futimes and mmap on an archived descriptor acted on its null device and succeeded or failed with an unrelated errno. They now throw NotImplemented, each covered by the kernel archive test; mmap is noexcept, so its refusal is checked through the terminate handler.
sceKernelOpen and open give an archived file a read-only null-device descriptor. Reads, positioned, vectored and AIO reads, seeks, fstat and FIONREAD are served from the archive; dup, dup2 and F_DUPFD share the position. sceKernelStat and sceKernelCheckReachability see archived paths.
Writing opens fail with EROFS, O_CREAT|O_EXCL with EEXIST and O_DIRECTORY on a file with ENOTDIR. Opening an archived directory or one merged with the disk throws until getdents can list it.
A ZArchive named app0.zar beside app0/ is a read-only layer under it. libc opens it at the first path resolution, looks paths missing from app0/ up case-insensitively, reads files across compressed blocks and keeps the archived descriptor table with shared positions.
Resolving an archive-only path through a call that does not read the archive throws instead of failing with ENOENT, as do opendir of a directory present in both places, fdopen of an archived descriptor and chdir into the archive. A path through .. in an archive-only directory resolves.
An import made at map time settles inside the guest's map call, so the mapping thread waits while the kernel maps the pages. A device that imports shared memory through host pointers settles nothing, so the test expects a settle only for a dma-buf import.
image_store with D16 data to a storage image of a SINT format threw
"stores 16-bit data to an image of a SINT format", both when the
descriptor is decoded and in the SPIR-V image emitter, and the runtime
image modes left out the SINT conversions for such images. God of War
Ragnarok (PPSA08330) stops on it in compute shader 0x1052a17900 right
after its MFSR setup.
Each 16-bit half is now converted like the D16 format buffer stores
(EmitD16StoreComponent): sign-extended, then saturated to the
component width as for 32-bit data. The buffer form was measured on
RDNA2 in #331; the image form is not measured (TechnicalDebt).
agc_driver_image_store_sint now stores D16 data with DMASK 0xf and 0x5
to all eight SINT formats and after an image_atomic_add on 32_SINT,
instead of expecting the refusal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A graphics pipeline the store builds or a compute pipeline a dispatch builds is
appended to pipelines.journal next to the shader cache entries, as the
materialized result of each stage (the specialized SPIR-V, bindings and push
constants) plus the recipe the pipeline was built from: the stages'
identities, vertex input layout, descriptor set layout keys and the state
fields the Pipeline constructor reads. When a VulkanDevice is created with a
window (a headless device waits for its first draw or dispatch, since the
window's device usually replaces it first) the journal is loaded and its
pipelines are built on a pool of threads while the title loads, so the first
draw or dispatch of a configuration seen on an earlier run finds its pipeline
resident instead of compiling it on the queue worker.
The pipeline stores key on RecompileResult::Identity, a hash of the module
words, specialization constants, subgroup width and bindings that is the same
on every run (SharedSpirv::ContentHash, computed once per shared module),
rather than on the process-lifetime variant ids; a generated stage is keyed
like any other. CachedPipeline builds outside the store's mutex and the
library parts and link are built outside the library store's mutex, so replay
threads and queue workers build in parallel; a concurrent build of the same
key keeps the first inserted. A replayed pipeline enters the store at its
least recently used end and a full store takes none, and its optimized relink
waits for the first draw that binds it, so the title's own pipelines come
first in both. The compute pipeline creation moves into
VulkanDevice::createComputePipeline, shared by dispatches and the replay. The
store key also covers the color component mapping, the depth target's sample
count and a depth bias clamp, which the constructor reads.
The file names the device it was written for (the properties the driver's
pipeline cache file is named by) and starts over for another; a torn tail is
cut at a record boundary; two runs sharing the directory take turns on a lock
file and keep each other's records; a read failure never starts the file
over. A device cancels its replay before it is replaced or destroyed, and a
replaced device destroys its pipelines then rather than at the driver's stop.
APS5_NO_PIPELINE_JOURNAL=1 disables it; APS5_PIPELINE_JOURNAL_THREADS,
APS5_PIPELINE_JOURNAL_ENTRIES (the first recorded), APS5_PIPELINE_STORE_ENTRIES
and APS5_PIPELINE_JOURNAL_MAX_MIB bound it; APS5_PROFILE_DRAW prints a
[pipeline-journal] summary. APS5_VERIFY_SET_LAYOUTS=1 now also checks a
dispatch's set layout against the one described from its shader. The lavapipe
test suite, which shares one cache directory, runs with the journal off except
for the journal's own tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6hw3kRAuQdfcU9YCZgaoK
A GPU hang or a crash in a title leaves no record of what the queues
were last given: APS5_TRACE_GPU prints every submission (too much to
leave on), and the WAIT_REG_MEM timeout message shows only the packet
before the wait on the waiting queue.
Each queue now keeps a ring of its last 16 submissions
(APS5_PM4_RING=<n>, 0 to 4096, 0 disables): the TraceMs time in tenths
of a millisecond, serial, size, guest address and a copy of the first
512 dwords after indirect buffers are inlined, recorded under the
driver lock next to the serial, REWIND tails included. The ring of a
queue and the failure report registration are set up at the top of
Submit, before any output is reserved, so recording under the lock
does not allocate. Disabled, Submit only tests a static flag; enabled,
it costs one bounded copy per submission.
DumpSubmissionRings decodes the kept dwords with Pm4::PacketWords and
the new Pm4::KnownName, which returns the decoder's names as views of
static strings (empty for an unknown opcode, printed as UNKNOWN_0x%02x);
Pm4::Name now builds its std::string from it. Every line is formatted
with integer and string conversions only into a 512-byte stack buffer
and written with one WriteFile / write(2) on the stderr handle, so the
dump does not allocate from the C runtime heap, lines from other
threads do not interleave and the CRT stream lock is not taken (the
rule of #3871). The header gives the number of queues and the ring
size, and each queue line the submissions recorded and kept.
libc gets a small registry of failure reports
(LibcRegisterFailureReport_nid_no_patch, Unregister, Run); Run runs
the registered reports the first time it is called and returns at once
after that. The Windows crash report runs it after the thread dump of
an unhandled exception, after SIGABRT (which also covers the
APS5_HANG_DUMP_SECS timed dump, since it aborts) and after an invalid
CRT parameter, so an abort after a reported exception does not print
the rings twice. The driver registers its dump at the first submission
and unregisters at static destruction; the dump there waits a bounded
time for each ring lock. What the crash-path dump cannot do (a ring
held by the crashed thread, rings corrupted by the crash, Linux) is
recorded in technical debt.
APS5_STALL_WATCHDOG_SECS=<n> (0 to 86400, 0 disables) makes a waiter
that has not progressed for n seconds dump the rings once per wait: a
WAIT_REG_MEM (progress as for APS5_GPU_WAIT_TIMEOUT_MS: another packet
runs or completes), a REWIND waiting for the title, and a compute
submission held behind queue 0. The last one prints under the driver
lock, so submissions and the other queues wait for it (USAGE.md says
so). Both variables are read at the top of Submit, so an invalid value
of either throws at the first submission and never later inside a GPU
worker. The order wait behind queue 0 releases its order hold on scope
exit, so a throwing dump cannot leave it counted.
No packet semantics change; packet sizes and names are those of the
existing decoder (PM4 type-3 header layout as in Mesa
src/amd/common/sid.h). The queue bound of Submit and of the rings is
one constant, SubmissionQueueEnd.
Tests: agc_driver_pm4_tests gets ten modes, each its own ctest:
agc_driver_pm4_ring (APS5_PM4_RING=4, six submissions on queue 0 and
two on 0x20: the dump holds #3..#6 and #1..#2 in order, nothing
older), agc_driver_pm4_ring_empty (one line), _ring_disabled (one
line), _ring_invalid and agc_driver_pm4_stall_watchdog_invalid
(APS5_STALL_WATCHDOG_SECS=1x: the submission throws and is not
executed), _ring_report (LibcRunFailureReports_nid_no_patch dumps the
rings), _ring_report_heap (Windows: with ucrtbase.dll's HeapAlloc and
HeapReAlloc imports counting calls from the reporting thread, the
failure report of a submission holding INDEX_BUFFER_SIZE names it and
allocates nothing, while Pm4::Name of the same header is seen
allocating), and with APS5_STALL_WATCHDOG_SECS=1 a WAIT_REG_MEM
(agc_driver_pm4_stall_watchdog), a REWIND (_stall_watchdog_rewind) and
a compute submission held behind a queue 0 rendering wait
(_stall_watchdog_order), each held for about 2.5 s, dump once and
complete when released. The PM4 catalog test checks KnownName against
every opcode and custom name. windows_backtrace_failure_report checks
that abort() runs the registered reports once and not an unregistered
one; windows_backtrace_failure_report_once that abort() does not run
them again after an earlier run. With the dump decoding through
Pm4::Name, agc_driver_pm4_ring_report_heap fails with "the failure
report allocated from the C runtime heap"; with Run resetting its
flag, windows_backtrace_failure_report_once prints the report twice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A multisampled rasterizer drawing into one-sample targets keeps
PERSP_SAMPLE, LINEAR_SAMPLE and ANCILLARY inputs, and with PS_ITER_SAMPLE
also centroid inputs, since only sample 0's coverage reaches the targets.
Coverage inputs, and the sample index with POS_X_FLOAT or POS_Y_FLOAT,
still throw. The input rule for the non-iterated case follows
fdfawef324's proposal on #5907 (PPSA07411).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A draw whose rasterizer has more samples than its color or depth targets
threw "a color target's sample count differs from the rasterizer's" or
"the depth target's sample count differs from the rasterizer's". When
every target has one sample, MSAA_ENABLE is set, and there is no
alpha-to-coverage, no PS_ITER_SAMPLE and no sample-dependent pixel input,
only sample 0's coverage reaches the targets, so draw it with one sample
at sample 0's location in each pixel of the grid. One-sample depth images
are created sample-location compatible when the device allows it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A geometry program with VGT_GS_OUT_PRIM_TYPE 1 was refused as an
unsupported output assembly. Each primitive export of an NGG line-strip
program is one line whose indices are packed like a triangle's, so the
mesh module now declares OutputLinesEXT with PrimitiveLineIndicesEXT for
it. A subgroup gets VGT_GS_MAX_VERT_OUT - 1 lines per input primitive and
at least GE_MAX_OUTPUT_PER_SUBGROUP line slots; fast launch keeps using
PRIM_AMP_FACTOR. The output size is part of the cache, draw, validation
and pipeline keys, and the request serialization version becomes 31.
Triangle-strip geometry is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>