Files
rocky-vulkan-llama/patches/mesa-panvk-0002-csf-wls-reuse-and-grid-independent-instances.patch
T
Claude (noether) 97629e935c Fully characterize the ub64 cliff: TLS-stack register spill is the dominant term
Live instrumentation on panthor: WLS reuse verified working (644 REUSE/46 ALLOC) but the
crash is dominated by the TLS *stack* alloc in emit_tls() at EndCommandBuffer — L-variant
matmul shader spills 10x more registers (tls_size 544->5328 B/thread => 38MB->304MB stack),
x~12 cmdbufs retained in the tls pool => ~3GB, over the 4GB priv heap. Remaining fix is
structural (free tls-pool BOs post-submit and/or fix the x19 sparse-core overallocation).
See docs/root-cause-final.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 14:35:03 +02:00

75 lines
3.1 KiB
Diff

--- a/src/panfrost/vulkan/csf/panvk_cmd_buffer.h
+++ src/panfrost/vulkan/csf/panvk_cmd_buffer.h
@@ -409,6 +409,11 @@
struct pan_ptr desc;
struct pan_tls_info info;
unsigned max_wg_count;
+
+ /* rocky-vulkan-llama: grow-only WLS buffer reused across dispatch
+ * commands (PANVK_WLS_REUSE) instead of one BO per dispatch. */
+ uint64_t wls_ptr;
+ unsigned wls_size;
};
struct panvk_cond_render_state {
--- a/src/panfrost/vulkan/csf/panvk_vX_cmd_dispatch.c
+++ src/panfrost/vulkan/csf/panvk_vX_cmd_dispatch.c
@@ -13,6 +13,7 @@
#include "genxml/gen_macros.h"
#include "panvk_buffer.h"
+#include <stdio.h>
#include "panvk_cmd_alloc.h"
#include "panvk_cmd_buffer.h"
#include "panvk_cmd_desc_state.h"
@@ -89,8 +90,14 @@
unsigned core_id_range;
pan_query_core_count(&phys_dev->kmod.dev->props, &core_id_range);
+ /* rocky-vulkan-llama: size WLS with the grid-INDEPENDENT upper bound
+ * on instances (max_instances_per_core), not the per-dispatch grid.
+ * Makes wls_total_size constant per pipeline so the grow-only reuse
+ * below collapses to ~1 BO per distinct shader wls_size for the whole
+ * command buffer instead of one-per-new-high-water. Mirrors the
+ * indirect path and the JM/gallium single-batch-WLS model. */
tlsinfo.wls.instances = pan_calc_wls_instances(
- &cs->cs.local_size, &phys_dev->kmod.dev->props, indirect ? NULL : dim);
+ &cs->cs.local_size, &phys_dev->kmod.dev->props, NULL);
unsigned wls_total_size = pan_calc_total_wls_size(
tlsinfo.wls.size, tlsinfo.wls.instances, core_id_range);
@@ -100,10 +107,29 @@
* instance count) might differ significantly between dispatch commands,
* rather than track a single maximum size, we might want to consider
* multiple allocations for different size buckets. */
- tlsinfo.wls.ptr =
- panvk_cmd_alloc_dev_mem(cmdbuf, tls, wls_total_size, 4096).gpu;
- if (!tlsinfo.wls.ptr)
- return 0;
+ /* rocky-vulkan-llama fix (addresses the TODO above): reuse a grow-only
+ * WLS buffer across dispatches. CSF allocated a fresh WLS BO per
+ * dispatch, exhausting the sub-4GB priv VA heap over a ~300-dispatch
+ * LLM prefill graph -> OOM at ub>64. Gated by PANVK_WLS_REUSE (A/B). */
+ const bool wls_reuse = getenv("PANVK_WLS_REUSE") != NULL;
+ bool wls_did_reuse = false;
+ if (wls_reuse && wls_total_size <= cmdbuf->state.tls.wls_size) {
+ tlsinfo.wls.ptr = cmdbuf->state.tls.wls_ptr;
+ wls_did_reuse = true;
+ } else {
+ tlsinfo.wls.ptr =
+ panvk_cmd_alloc_dev_mem(cmdbuf, tls, wls_total_size, 4096).gpu;
+ if (!tlsinfo.wls.ptr)
+ return 0;
+ if (wls_reuse) {
+ cmdbuf->state.tls.wls_ptr = tlsinfo.wls.ptr;
+ cmdbuf->state.tls.wls_size = wls_total_size;
+ }
+ }
+ if (getenv("PANVK_WLS_LOG"))
+ fprintf(stderr, "[panvk-wls] total_size=%u %s prev_max=%u\n",
+ wls_total_size, wls_did_reuse ? "REUSE" : "ALLOC",
+ cmdbuf->state.tls.wls_size);
}
cmdbuf->state.tls.info.tls.size =