WIP: fix(vk): a slow movie shows its pictures, and a fault in Intel's Windows compiler leaves that shader out #252
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!252
Loading…
Reference in a new issue
No description provided.
Delete branch "Yeetbot90/Longshot:fix/windows-movie-and-intel-compiler"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
This fix is for Unity's laptop. Every change below comes from his two logs and the hardware they report, so that Longshot runs on that laptop:
What the logs show on it:
igvk64.dll+0x14d102, read at 0x170. It happened in 5 of his 7 v3.0.0-rc.3 runs, all in Kokiri Forest, with the same backtrace:igvk64.dll+0x14d102 +0x134aaf +0x7f23a +0x322ef, thenlongshot_vk.dll+0x20ccbc, then+0x22375d, then the thread's start.longshot_vk.dll(dd02c6cc, whosegpu/vkis identical to v3.0.0-rc.3's0c74253d):+0x22375dis thestd::threadstarted bypipeline_cache_save, and+0x20ccbcreturns frompipeline_cache_save(bool)::$_0aftercallq *(%rdi), which isvkGetPipelineCacheData(dev.device, pcache, &n, data), right afterPipelineCacheFile::writable(pcache_path, n).play_cacheneedspipelineCreationCacheControl), so every pipeline built in play goes into that same cache.the shaders' preparation was skipped at the build. The builder writes that marker only when its preparation run stopped with "the GPU driver stopped responding", most likely the same driver problem during the build's own compiles. Every start since then compiles each shader when it is first drawn: 15 pipelines took 8.5 s, and 312 took 203 s in the older log.The Intel compiler and movie fixes are ported from https://github.com/NotRexed/Hookshot/pull/2849, without its updater change. Updated for HumanBean's review: see the reply below the review.
What changed
Intel's driver, problem 1.
IntelDriverGateingpu/vk/vk_internal.hlets one thread at a time into Intel's compiler on Windows. That covers the game's shaders, every compute pipeline of the renderer's own, and nowvkGetPipelineCacheDatatoo (pcache_datainvk_draw.cpp: all six reads). Other vendors, and Intel on Linux, are not held.FAIL_ON_PIPELINE_COMPILE_REQUIRED: a draw's or a dispatch's ask) only tries the lock. While a worker compiles, it answersVK_PIPELINE_COMPILE_REQUIRED(cold), so the replay thread never waits behind a compile. On Intel a dispatch's module, for a program read from the cache without its code, is made on the worker, not on the replay thread.__try/__except) leaves that shader out. A fault making a shader module is now written tolongshot_driver_faults.txt, as pipeline faults already were, so later starts on the same driver leave that program out (make_module,driver_faulted_module).A row for a low-core Intel CPU. The Debug tab's Intel shader compiles row (Developer section, Intel graphics on Windows only):
It applies after a restart and is saved as
intel_shader_compiles=.RX_VK_NO_INTEL_SERIAL=1is Side by side for one run.The movie, problem 3.
host/nn_video.c:decode_pending()has already decoded what was submitted, so the wait never showed the first picture (the review's item 2).recent_ns, about the last 8) instead of the movie's mean, which a slow first decode held high.The movie decoder's threads, problem 4.
host/dav1d_av1.c: with 4 logical processors or fewer, dav1d decodes on 2 threads; above 4, it keeps its own count.HOS_DAV1D_THREADS=<n>still sets it.Tests.
test_intel_compiler_gate.py: the gate, the try-lock for asks, the dispatch's module on the worker, the fault record,pcache_data, the row, and the 8 compute sources.test_video_catchup.py: a slow first decode no longer turns the catch-up off.test_dav1d_av1.py: the thread rule.test_vcore_video_acquire.py,test_program_cache_one_variant.py,test_damage_debug_menu.py, and the program-cache and pipeline-cache C++ stubs.Docs. The README covers this fix in every section it touches:
website/src/content/docs/requirements.mdx).longshot_prepare_skippeddoes.docs/development.mdhas the switches.How this relates to other Intel work
vkGetPipelineCacheData. On Windows Intel this pull request now takes Intel's gate around that fetch too, which covers the same crash for every build that holds the gate. If both land, the lock order must be IntelDriverGate outside, #190's shared lock inside, in every function. That way a builder never waits for the gate while it holds the shared side. Glad to rebase on #190, or to droppcache_dataif #190 lands first.RX_VK_COMPUTE_SERIALon main sends the dispatch's compute pipeline jobs to one serial queue on Intel (issue 496). The gate is lower down: it orders every entry into Intel's compiler, from any thread, compute or graphics. The serial queue still keeps compute jobs from piling up behind each other. The two do not wait on each other.Flags and settings
RX_VK_NO_INTEL_SERIAL=1HOS_DAV1D_THREADS=<n>HOS_VIDEO_NO_CATCHUP=1HOS_VIDEO_ACQUIRE_TRIES=1Measurements
No measurement of main against this pull request yet: it needs Unity's laptop.
igvk64.dll(5 of 7 rc.3 runs, all in the background pipeline-cache save), the preparation skipped, about 35 fps on the title (30–50 fps in the rc.3 runs), and 14–24 ms memory-sync waits. None of these logs is a run of this branch.Testing
Tested:
python -I -B tests/run_all.pyon Windows 11 at2bc07a1d, with maind906c8f4merged in, using llvm-mingw 20261104: 464 passed, 4 failed, 67 skipped. The game was not built.nx2/test_nup_paths,test_check_third_party,test_releaseandtest_menu_i18n. They fail on main too, and #255 fixes them.test_dav1d_av1was skipped: there is no dav1d build on this PC.Not tested:
Needs other testers:
longshot_prepare_skippedfirst.vk: Intel's compiler is entered by one threadandvideo: AV1 on dav1d ... (2 threads; 4 logical processors).longshot_log.txtwithHOS_VIDEO_LOG=1(it reports how far the picture is behind the sound at the movie's end), and the fps on the title and the movie.Screenshots
None taken. Screenshots from Unity's laptop would be the useful ones.
Risk and rollback
RX_VK_NO_INTEL_SERIAL=1, turns it off.longshot_driver_faults.txtto try again).HOS_DAV1D_THREADSchanges it.Reviewer notes
Start with
IntelDriverGateingpu/vk/vk_internal.h,cached_graphics,cached_computeandpcache_datainvk_draw.cpp,make_moduleinvk_shader.cpp,dec_acquire()inhost/nn_video.canddav1d_av1_threads()inhost/dav1d_av1.c. Frame generation was not changed: it did not run in either of Unity's logs.Issues
See https://github.com/NotRexed/Hookshot/pull/2849 and #190.
Checklist
For everyone
type(scope): description).main. (maind906c8f4merged in.)python -I -B tests/run_all.pyrun and passing. (Run; the 4 failures fail on main too, and #255 fixes them.)third_party/untouched.If applicable
Co-Authored-By:trailers.tests/that read changed source updated in this PR, not weakened.Updated after main
fbd42024was merged in (83c18ab3):make_pipeline(), which already takes Intel's gate and the guarded calls.host/nn_video.cis unchanged on main. No code change was needed.7734d426).Still WIP: this branch has not been built or played, and nobody has run it on an Intel GPU.
Thanks for bringing https://github.com/NotRexed/Hookshot/pull/2849 over and leaving the updater out. The description says plainly what was not run, and the switches are documented. Some parts are good: the guarded module create follows the existing
guarded_graphics/guarded_computepattern, a faulted module is not saved to the program cache (vk_shader.cppthrows beforeprogram_cache_save), and in this run the program is markedfailedrather than asked for again.IntelDriverGatehas external linkage, so itsstatic std::mutexis one lock acrossvk_draw.cpp,vk_shader.cppandvk_temporal.cpp. Pipeline-cache and program-cache keys are unchanged: no create info, flag or stamp changes.The PR is WIP and has no run of this branch on any PC, so this is request-changes. Below is what to fix before the Intel UHD run.
Must change
On Windows Intel the gate makes the replay thread wait behind a background compile.
cached_graphicsandcached_computetake the lock around all ofcreate_cached, including the ask-only calls (VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT). Those calls exist so that a draw or dispatch never waits for a compile. The dispatch path callscompute_pipeline_cached(p, true)(vk_draw.cpp:9479, "it comes back at once"), andprogram_cache_complete→make_moduleon the same path. Both now block on the mutex while a worker sits in a full Intel compile, which can take seconds. The cold first scene would hitch on every Intel Windows PC, not just the faulting UHD. Ask-only calls compile nothing: either leave them out of the gate, ortry_lockthe gate and treat a busy one as cold.The black first frame. The 500 ms first wait does not fit the code it is meant to fix:
decode_pending()runs synchronously before the wait loop (nn_video.c:751). A 426 ms first decode has already finished when the 100 ms wait starts, so the old wait never cut a slow decode short.dav1d_av1.cpictures(..., 1)is non-blocking), a picture still in flight in dav1d's frame threads is collected only at the next decode call. A loop with no new submission never picks it up, and #110 notes that OoT submits from the thread that takes the pictures.As written, the change lengthens the first acquire's stall from 100 to 500 ms on every PC whose first acquire finds nothing decoded, and does not show the picture. That includes fast PCs. Either find the real cause (an
HOS_VIDEO_LOG=1run shows the submits before acquire 1), or drop this half. Also,d->acquiresis never reset by Flush or Stop, so a decoder reused for a second movie gets 100 ms, not 500.A new default with no measurement. Serialising every shader-module and pipeline create on Windows Intel (UHD and Arc) is a new default. It has not run on any Intel PC, and nothing says what it costs on Arc, where the
--prepare-shadersrun and play compiles now use one thread. Keep the PR WIP until there are the Intel UHD run and an Arc before/after, with several interleaved runs each. The Measured box is honestly unticked. This item is that box.Should change
each > spacing, the catch-up stops decoding ahead. The stream then moves by at most one picture per acquire, so a frame that is late for any other reason (the late frames of #73) is never made up, and the lag only grows.eachis the movie's cumulative mean and includes the first decode (426 ms in the report), so early in a movie it also turns the catch-up off on mid-range PCs until enough pictures have been decoded to bring the mean down. At the report's 19.5 ms against 16.7 ms, the picture ends roughly 15 % behind: several seconds on the first movie and over 20 s on the 154 s second one, if acquires are frame-paced. Consider a bound instead of an off switch: decode ahead only within a time budget per acquire, or allow a maximum lag. Use a recent-window decode time, not the whole-movie mean. Either way, report the end-of-movie lag (HOS_VIDEO_LOGprints it) on the slow PC.driver_faults.h, issue 996). If Intel's compiler is left holding an internal lock after the SEH unwind, the next create blocks inside the driver while holdingIntelDriverGate. Every compile thread, and (through item 1) the replay thread, then freezes with no crash report. Consider latching: after one caught fault on Intel, log it and stop handing the driver new work, or at least say in the PR that the recovery is untested. The module fault is also not written tolongshot_driver_faults.txt, so a deterministic fault is hit again on every start.vk_texture.cpp(ASTC, unswizzle),vk_memory.cpp(write-back diff),vk_framegen.cpp,vk_reactive.cpp,vk_fsr3*.cppandvk_coopmat.cppstill callvkCreateShaderModule/vkCreateComputePipelinesdirectly. Some may run lazily, during play, beside the translation workers. "One thread enters vkCreateShaderModule and vkCreate*Pipelines" is not yet true. Gate them, or narrow the claim.cached_graphics,cached_compute,graphics_with, the warm pass) in a shared lock againstvkGetPipelineCacheData. Whichever lands second has to merge the two lock orders deliberately. With an exclusive gate inside a shared lock, a forced save waiting for the exclusive side can deadlock against a builder that holds the gate and asks for the shared side. Coordinate with that PR, or say which one goes first.RX_VK_COMPUTE_SERIAL, vk_draw.cpp:9474). Say how the two relate.fault_quarantine().begin,kBusy/kFaulted) sits outsidegraphics_with, so its lock order is fine. Its "a cold probe does not wait" is undone on Intel by item 1.I could not check the in-game behaviour, the llvm-mingw build of this branch, or whether OoT creates a new decoder for each movie. I ran nothing.
@ -1235,0 +1236,4 @@// igvk64 is short: an access violation there is not the pipeline guards' "driver faulted compiling" line, and it ends// the process. The same answer as those guards: that program is left out.#ifdef _WIN32__declspec(noinline) VkResult guarded_shader_module(const VkShaderModuleCreateInfo* ci, VkShaderModule* m) {If igvk64 faults while holding an internal lock, the SEH unwind leaves it held. The next create then blocks inside the driver with
IntelDriverGateheld, and every compile thread and the replay thread freeze: a hang instead of a crash. On AMD a caught fault did exactly that (driver_faults.h, issue 996). Consider a latch on Intel after the first caught fault, and recording the program inlongshot_driver_faults.txtso it isn't faulted again on every start.@ -1237,3 +1267,4 @@thread_local VkPipelineCache driver_ask_cache = VK_NULL_HANDLE;/// (with the pipeline cache: from it, or in play into the play generation's, create_cached)VkResult cached_graphics(const VkGraphicsPipelineCreateInfo* ci, VkPipeline* pl) {IntelDriverGate gate;On Windows Intel this holds the gate for the ask-only calls too (
FAIL_ON_PIPELINE_COMPILE_REQUIRED). They compile nothing, and they are what the dispatch path uses not to wait (compute_pipeline_cached, line 9479). Now the replay thread waits here behind a worker's whole compile. Leave the ask-only calls out of the gate, ortry_lockit and answer 'cold' when it is busy. The same applies tocached_computebelow.@ -122,0 +135,4 @@std::call_once(once, [] {logf("vk: Intel's compiler is entered by one thread (RX_VK_NO_INTEL_SERIAL: side by side)");});hold = std::unique_lock<std::mutex>(mu);Not every create goes through this lock: vk_texture.cpp (ASTC, unswizzle), vk_memory.cpp, vk_framegen.cpp, vk_reactive.cpp, vk_fsr3*.cpp and vk_coopmat.cpp still call
vkCreateShaderModule/vkCreateComputePipelinesdirectly. #190 also takes a shared lock in the same functions, so the two lock orders need settling before both land.@ -723,3 +723,3 @@ci.pCode = spirv.data();VkShaderModule m = VK_NULL_HANDLE;vkCreateShaderModule(dev.device, &ci, nullptr, &m);IntelDriverGate gate;make_moduleis also reached from the dispatch path (program_cache_complete, vk_draw.cpp:9470). On Intel Windows the draw thread now waits for this lock while a worker compiles.@ -755,3 +757,3 @@static int by_tries = -1;if (by_tries < 0) by_tries = env_on("HOS_VIDEO_ACQUIRE_TRIES");const int64_t wait_until = hos_now_ns() + 100000000;const int64_t wait_until = hos_now_ns() + (d->acquires ? 100000000 : 500000000);decode_pending()(line 751) decodes synchronously before this loop starts, so a 426 ms first decode was never cut short by the 100 ms wait. The loop only helps if another thread submits. With dav1d, a picture still in its frame threads is collected only at the next decode call. Issue #73 (fast Linux) and this PR's AMD run both still show the black first frame. As it stands, this adds up to 400 ms to the first acquire on every PC that reaches it with nothing decoded.d->acquiresis also never reset by Flush or Stop.@ -804,1 +809,4 @@if (!d->phead) break;const int64_t spacing = d->decoded > 1 ? (d->end_pts - d->first_pts) / (d->decoded - 1) : 0;const int64_t each = d->decoded > 0 ? d->decode_ns / d->decoded : 0;if (spacing > 0 && each > spacing) break;This turns the catch-up off rather than bounding it. From here on the stream moves at most one picture per acquire, so a frame that is late for any other reason is never made up, and the lag behind the sound only grows.
eachis the movie's cumulative mean and includes the slow first decode, so on mid-range PCs it also turns the catch-up off for a movie's first pictures. Consider a per-acquire time budget for decoding ahead, or a maximum lag, and a recent-window decode time. Please report the end-of-movie lag (HOS_VIDEO_LOG) from the slow PC.Thanks for the review. At
2bc07a1d, with maind906c8f4merged in:FAIL_ON_PIPELINE_COMPILE_REQUIREDonly tries the gate (IntelDriverGate(ask),std::try_to_lock). While a worker compiles, it answersVK_PIPELINE_COMPILE_REQUIRED, so the draw is left out as cold. That coverscached_graphics,cached_computeandgraphics_with. On Intel a dispatch's first module, for a program read without its code, is now made on the worker (program_cache_complete(q)in the job), not on the replay thread.test_intel_compiler_gate.pyandtest_program_cache_one_variant.pycheck both.decode_pending()decodes synchronously before the wait, so the wait never helped. Without it,acquiresnot being reset on Flush/Stop no longer matters. The README now says the first picture can still be black and that why is not known.recent_ns, about the last 8), not the movie's mean, so a slow first decode no longer turns it off. It decodes ahead at most one picture's time per acquire.test_video_catchup.pyhas the case of a 426 ms first decode followed by fast ones. With a decoder slower than the movie, the picture still falls behind; the README says so.longshot_driver_faults.txt, as pipeline faults were, so later starts on that driver leave the program out instead of faulting again.vkGetPipelineCacheDatais now too, throughpcache_data(all 6 reads), for #190's crash.RX_VK_COMPUTE_SERIAL. See the description's "How this relates to other Intel work". In short: the gate goes outside #190's shared lock in every function, or I droppcache_dataif #190 lands first.RX_VK_COMPUTE_SERIALstill orders the compute jobs, while the gate orders every entry into the compiler; they don't wait on each other.nn_video.c,dav1d_av1.cand their tests) as its own PR now. Unity's test needs both halves, so I'd rather keep them together until he has run it, unless you want the split first.Game-free suite at
2bc07a1d: 464 passed, 4 failed, 67 skipped. The 4 failures fail on main too, and #255 fixes them.Please test
Re-review at
9523024e. Code only: I didn't build it, run the tests or run the game.I diffed against
d906c8f4, the main this branch merged. No shader or*_spv.hheader changed, andvk_api.his untouched. The main commit since then (d9648863) changes other parts ofvk_menu.cpp, so it shouldn't conflict.Earlier points
cached_graphics,cached_computeandgraphics_withonly try the gate for aFAIL_ON_PIPELINE_COMPILE_REQUIREDcreate, and answer cold while it's busy. On Intel the dispatch's module is now made on the worker. I found no path that holds the gate and then takes it again.clear_pipelineandvk_fsr3.cpplet go of it beforecached_*, andplay_cache_savewaits forusersbeforepcache_datatakes the gate. That fix has two costs; see new points 1 and 2.dec_acquire's wait is the same as main's, and the README says the black first picture is still unexplained.recent_ns(about the last 8 pictures) replaces the movie's mean, and decoding ahead is capped at one picture's spacing per acquire. A decoder slower than the movie still falls behind without limit, and the README says so. The end-of-movie lag from Unity'sHOS_VIDEO_LOG=1run is part of point 3.longshot_driver_faults.txt(driver_faulted_module), andmake_moduleandtranslate_intocheck it first.vkGetPipelineCacheDatagoes throughpcache_data. The only raw creates left are inside the guards, plusvk_fsr4.cpp's hooks, which never run on Intel.RX_VK_COMPUTE_SERIAL. Addressed. The description sets the lock order (the gate outside, #190's shared lock inside) and explains how the gate relates to the serial queue.New
compute_pipeline_cached(p, true)on the replay thread got a prepared pipeline at once. Now, on Intel, every program read without its code goes to the serial worker queue. Its first dispatch waits up to 50 ms and is then left out until the worker gets to it, even on a fully prepared cache. Suggestion: make the module on the replay thread under a try-lock, like the asks do, and send it to the worker only when the gate is busy. Otherwise, add this to Risk and countst_pending_skipsin the Intel runs.pcache_data. A worker then rebuilds it behind the same gate. Risk says draws are left out "as on a cold cache". On Intel it also hits a prepared cache during any compile or save. Please say so in Risk, and count these answers in the log (for examplevk: … asked cold: Intel's gate busy) so the Intel runs can show how often it happens.movie_upscale). These aremovie_upscale,typed_upscale,mask_stabilize,astc_ready/bc_ready/unswizzle_ready,wbd_pipe_ready, the first masked clear, andgpl_link(behindRX_VK_GPL). Each now waits behind a worker's whole compile. On Unity's laptop the preparation was skipped, so the first movie or the first ASTC texture can stall for as long as a play compile takes. The description says the replay thread "never waits behind a compile", which is true for asks only. Either narrow that sentence and name these in Risk, or make them before play.on_workerreadsp.code_wordsbefore the CAS. A worker may be clearing that field at the same moment incomplete_from. Only the thread that wins the CAS uses the value, so work it out after the CAS.dav1d_av1_threadsalso applies on Linux, throughsysconf. Please also leave Unity's name and his laptop's details out of the README and the website (inline). They fit the PR and the test request better than the user docs.Verdict
Request changes. Points 1, 2, 4, 5, 6 and 7 are addressed, and the gate's locking looks right to me. Before this is marked ready, it needs the split (point 8), Risk text and log counts for new points 1 to 3, and then the WIP gates:
@ -332,1 +343,4 @@#### Intel laptopsWhat [#252](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/252) changes was made from one laptop's logs (Unity's:I'd leave a tester's name and laptop details out of the README and the website copy. Describe the kind of PC instead (Intel UHD, a 4-thread CPU, Windows), and keep Unity's specifics in the PR and the test request.
@ -1257,1 +1294,4 @@bool compiles_nothing(VkPipelineCreateFlags flags) { return (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0; }VkResult cached_graphics(const VkGraphicsPipelineCreateInfo* ci, VkPipeline* pl) {IntelDriverGate gate(compiles_nothing(ci->flags));if (gate.busy) return VK_PIPELINE_COMPILE_REQUIRED;This fixes the wait. But a pipeline that pcache or the driver's cache does have also comes back cold while any worker compiles or a save is in
pcache_data. The draw is left out, and a worker then rebuilds it behind the same gate. Please say in Risk that this also happens on a prepared cache, and count these answers (a log line or a counter) so the Intel runs show how often it happens.@ -7774,3 +7846,3 @@mi.codeSize = sizeof MOVIE_UPSCALE_COMP_SPV, mi.pCode = MOVIE_UPSCALE_COMP_SPV;VkShaderModule m{};vkCreateShaderModule(dev.device, &mi, nullptr, &m);IntelDriverGate gate;A blocking gate on the thread that records the movie: the first
movie_upscalenow waits behind a worker's whole compile. The same goes fortyped_upscale,mask_stabilize, the texture*_readyfunctions,wbd_pipe_ready, the first masked clear andgpl_link. On a PC whose preparation was skipped, like Unity's, a play compile can take seconds. Either name these in Risk and narrow the description's "never waits behind a compile" to asks, or make them before play.@ -9610,1 +9685,3 @@// pipeline. One whose code does not read is failed, and left out below)// pipeline. One whose code does not read is failed, and left out below. On Windows Intel the module is made on the// worker instead: here it would wait for the compiler's gate behind a worker's whole compile, IntelDriverGate)const bool on_worker = p.code_words && intel_gate_on();On Windows Intel this sends every program read without its code to the serial worker queue, even when its pipeline is prepared. Main got that pipeline at once through
compute_pipeline_cached(p, true). Now the first dispatch waits up to 50 ms and is then left out until the worker gets to it. Could the module be made here under a try-lock (as the asks are), with the worker used only when the gate is busy? Also:p.code_wordsis read here before the CAS while a worker may be clearing it incomplete_from. Work outon_workerafter the CAS wins.Unity sent 7 logs and a bug report from v3.0.0-rc.3 (Intel UHD, driver 101.7088, i3-1115G4, 16 GB, Windows 11). The crash is located now:
0c74253d) and at nightly-70 (dd02c6cc), so I mapped the two longshot_vk.dll addresses with nightly-70's DLL and its symbols:On this branch, all six kGetPipelineCacheData calls go through pcache_data, which takes IntelDriverGate ( est_intel_compiler_gate.py checks that no other call is left). The save then waits for the build in progress, and builds wait for the save. The only read the draw thread can make is pcache_init's, once, when it creates the cache. The gate holds only the driver call, so nothing waits on another lock while holding it.
Every one of the 7 runs also logs he shaders' preparation was skipped at the build, so each built its shaders in play. Unity's test steps in the description start with deleting longshot_prepare_skipped. His report also has ASTC as RGBA8 on, the AMD workaround, which takes shared memory on integrated graphics; the README's Intel laptops section now says to leave it off.
Still untested on Intel: this branch has not been built or run on his laptop.
Code review only; not built or run.
Thanks for the quick turnaround on the first review. HumanBean's re-review covers the gate's lock order, the one-time creates and the split, so I'll stick to the movie half and how it meets #110's input limit. That pairing is what the Steam Deck is testing now: this branch's base has #110 (
ae7b1165), so a Deck run of it tests the limit and the new catch-up budget together. The dav1d thread rule doesn't apply on the Deck (8 logical processors), so it isn't part of that test.1. The budget assumes about one acquire per picture. The catch-up stops decoding ahead once one spacing (16.7 ms) has passed in an acquire. So an acquire decodes at most ceil(spacing / d) pictures ahead, plus
decode_pending's one when the queue starts empty. Take the T-BW29 Deck run in #110: the game took about 24 pictures a second of a 60-a-second movie, so each acquire had to advance 2.5.2. But the budget is also what can end the Deck's freeze. On main the catch-up decodes everything that came due, so the time between acquires is A = B + (A / spacing) × d, that is A = B / (1 − d / spacing), where B is the rest of the loop. That runs away as d nears the spacing.
The budget caps the decoding in one acquire at roughly a spacing plus two decodes, so the loop can't run away. A cap of two spacings (33 ms) would keep that bound (under ~55 ms at 9.6 ms). It would also keep the picture in time down to about 12 acquires a second.
How to tell which happened in the Deck runs (
HOS_VIDEO_LOG=1):video: N pictures skipped to catch up with the movie's clockwith a large N during the freeze means the catch-up's own decoding. That is the case this budget bounds.video: acquire N: nothing decodedmeans the 100 ms empty wait, which neither PR changes.HOS_VIDEO_INPUT_LIMIT=0beside one with the limit on would separate the budget from the limit.3. The fixture doesn't reach the budget. In
test_video_catchup.py,decode_nextnever advancesclock_ns, sohos_now_ns() - now >= spacingis never true, and each case has only one pending submission. A multi-acquire case would pin the budget and its interplay with #110:It could check that the lag after 10 s stays within a frame or two, and that an acquire's decoding stays bounded.
This applies to the movie half wherever it lands after the split.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.