mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Give back the ASTC decoder's grown scratch 5 s after its last large texture, not at the next upload.
A scratch grown past 32 MiB for a large texture went back to the usual size only when the next ASTC upload asked for one, so in the 2026-11-13 session the decoder held 224 MiB for the 70 s after the first area load and from a later load to the session's end. Each present now gives it back once no texture needed more for 5 s; nothing is made then, the next request makes the usual scratch, and the buffer is freed once the upload batches recorded so far completed, as before. The present only tries the decoder's lock, which can be held while VMA makes a block. astc_scratch_trim = 0 keeps the scratch until the next upload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -364,6 +364,9 @@
|
||||
# With astc = gpu: 1 keeps the decoder's scratch buffer from one upload batch to the next instead of making it again for
|
||||
# each, to shorten the hitches when an area loads (0 = one per batch).
|
||||
# astc_scratch_keep = 1
|
||||
# With astc_scratch_keep = 1: 1 gives back a scratch grown for a large texture 5 s after the last one needed it (up to
|
||||
# 192 MiB of video memory after an area load); 0 keeps it until the next ASTC upload, as in 0.10.1.
|
||||
# astc_scratch_trim = 1
|
||||
# With astc = gpu: 1 stages a texture's ASTC blocks in the shared staging ranges instead of a buffer of their own
|
||||
# (0 = a buffer each).
|
||||
# astc_arena = 1
|
||||
|
||||
@@ -61,7 +61,7 @@ static const char *const known[] = {
|
||||
"SKIN_MOTION", // vk_skin_motion.inc
|
||||
"MVOBJ_ALL", "MVOBJ_BANKS", "MVOBJ_EQUAL", "MVOBJ_EXACT", "MVOBJ_EXEC", "MVOBJ_NOC4", "MVOBJ_ONLY", "MVOBJ_TIMES", "MVPREV_CHECK", "MVPREV_GROW", "MVPREV_SKIP", "MVPREV_TRUST", "MV_CHECK",
|
||||
"MV_SURVEY",
|
||||
"PIPE_SEED_BOOT", "ONE_PER_CORE", "OPERATION_MODE", "OUTPUT_RES", "PAD_LAYOUT", "PACE_HZ", "PASS_CRUMBS", "PATCH_OUTPUT", "PATCH_RES_FIXED", "PATCH_SCENE", "PATCH_WIDE_ASPECT", "PATCH_WIDE_HUD", "PATCH_WIDE_MOVIE", "PATCH_WIDE_OUT", "PATCH_FREECAM", "PATCH_OCCLUSION_OFF", "PATCH_WIDE_SAVE", "PATCH_WIDE_SCENE", "PCSS", "PCSS_K", "PERF_OVERLAY", "PERF_SLOW_MS", "PIPELINE_CACHE", "PIPELINE_CACHE_MAX_MB", "PIPELINE_CACHE_PLAY", "PIPELINE_CACHE_PLAY_MB", "PIPE_BINARIES", "PIPE_BINARIES_MAX_MB", "PIPE_FEEDBACK", "PIPE_MEMO", "PIPE_PREBUILD", "PIPE_SEED", "PIPE_SKIP", "PIPE_SYNC", "PIPE_WAIT", "POWER_FULL", "TEX_SAME", "TEX_SAME_BIG", "TEX_FLAT3D", "TEX_KEEP_TAKEN", "TEX_HARD_ORDER", "TEX_STALE_KEPT", "PRESENT_HELD", "HELD_SYNC",
|
||||
"PIPE_SEED_BOOT", "ONE_PER_CORE", "OPERATION_MODE", "OUTPUT_RES", "PAD_LAYOUT", "PACE_HZ", "PASS_CRUMBS", "PATCH_OUTPUT", "PATCH_RES_FIXED", "PATCH_SCENE", "PATCH_WIDE_ASPECT", "PATCH_WIDE_HUD", "PATCH_WIDE_MOVIE", "PATCH_WIDE_OUT", "PATCH_FREECAM", "PATCH_OCCLUSION_OFF", "PATCH_WIDE_SAVE", "PATCH_WIDE_SCENE", "PCSS", "PCSS_K", "PERF_OVERLAY", "PERF_SLOW_MS", "PIPELINE_CACHE", "PIPELINE_CACHE_MAX_MB", "PIPELINE_CACHE_PLAY", "PIPELINE_CACHE_PLAY_MB", "PIPE_BINARIES", "PIPE_BINARIES_MAX_MB", "PIPE_FEEDBACK", "PIPE_MEMO", "PIPE_PREBUILD", "PIPE_SEED", "PIPE_SKIP", "PIPE_SYNC", "PIPE_WAIT", "POWER_FULL", "TEX_SAME", "TEX_SAME_BIG", "TEX_FLAT3D", "TEX_KEEP_TAKEN", "TEX_HARD_ORDER", "TEX_STALE_KEPT", "ASTC_SCRATCH_TRIM", "PRESENT_HELD", "HELD_SYNC",
|
||||
"PREPARE_PIPELINES", "PREWARM_FULL", "PREWARM_FULL_S", "PREWARM_WAIT_MS", "PREWARM_XLATE", "PROBE_MOVIE", "PROBE_MOVIE_SHOT", "PROFILE", "PROFILE_CHAINS", "PROFILE_DIR", "PROFILE_FRAMES", "PROFILE_REPLAY", "PROFILE_SLOW",
|
||||
"POOL_FAST", "POOL_GROUP", "POOL_GROUP_CHECK", "POOL_PRESNAP", "POOL_PRESNAP_RUNS",
|
||||
"SUBMIT_FINISH_GPU", "SVC_WAITS", "SNAP_WIDEN", "SUBMIT_FINISH_RESULTS", "SUBMIT_FINISH_KINDS", "FOLIAGE", "MIRROR_STAGE", "FLUSH_SKIP_CLEAN", "MIRROR_HOT", "MESH_EMULATION", "MESH_EMU_MB", "MESH_EMU_TASKS", "MESH_EMU_BATCH", "GUEST_OPT", "LOG_TEX_NEW", "DUMP_KEY", "VEC_INDEX_FIX", "PASS_TIMES",
|
||||
|
||||
@@ -598,6 +598,7 @@ void vk_texture_split_counts(uint64_t *copies, uint64_t *fills);
|
||||
VkDeviceSize vk_astc_region_bytes(const VkAstcRegion *r, uint32_t bw, uint32_t bh); // source bytes the region reads
|
||||
void vk_astc_stats(uint64_t *dispatches, uint64_t *texels); // since start
|
||||
uint64_t vk_astc_scratch_bytes(void); // the decoder's shared scratch now
|
||||
void vk_astc_scratch_trim(void); // each present: a grown scratch idle for 5 s goes
|
||||
// NX2NAVI_ASTC_TIME=1: GPU timestamps around each vk_astc_record's dispatches (logged per footprint and the largest one)
|
||||
void vk_astc_time_enable(int on);
|
||||
int vk_astc_time_get(uint32_t bw, uint32_t bh, uint64_t *texels, uint64_t *calls, double *us); // totals so far
|
||||
|
||||
@@ -487,7 +487,7 @@ static void mem_barrier(VkCommandBuffer cb, VkPipelineStageFlags2 src, VkAccessF
|
||||
// only after that batch completed (vk_memory.c: completed batches go to the spare list), so the same handle means the
|
||||
// open batch, ordered by a barrier, or a finished one. g_lock held.
|
||||
static struct { VkBuffer buf; VmaAllocation alloc; VkDeviceSize size; VkCommandBuffer cb; VkDevice dev; uint64_t big_ns; } S;
|
||||
static uint64_t n_scratch_new, n_scratch_reuse;
|
||||
static uint64_t n_scratch_new, n_scratch_reuse, n_scratch_trim;
|
||||
|
||||
// NX2NAVI_ASTC_SCRATCH_KEEP=1 (the default): the scratch outlives its upload batch. Every
|
||||
// batch goes to gfx_queue, so the reuse barrier at the start of the next batch's first chunk (vk_astc_record) orders it
|
||||
@@ -560,6 +560,27 @@ static VkBuffer scratch_get(VkCtx *c, VkCommandBuffer cb, VkDeviceSize need, int
|
||||
return out;
|
||||
}
|
||||
|
||||
// Every present (vk_texture.c vk_texstat_frame): a scratch grown past SCRATCH_MIN goes once no texture needed more for
|
||||
// SCRATCH_SHRINK_NS, without waiting for the next ASTC upload, which is when scratch_get makes it small again: in a
|
||||
// session of 2026-11-13 the decoder held 224 MiB for the 70 s after an area load and from a later load to the session's
|
||||
// end. Nothing is made here: the next request makes the usual scratch, as after scratch_get's own shrink. The buffer
|
||||
// is freed once the upload batches recorded so far completed (vk_defer_buffer), as there. Only tried: scratch_get holds
|
||||
// g_lock while VMA makes a buffer, up to 19 ms for a new block, and the present does not wait for that.
|
||||
// NX2NAVI_ASTC_SCRATCH_TRIM=0: the grown scratch stays until the next upload, as in 0.10.1.
|
||||
void vk_astc_scratch_trim(void) {
|
||||
static int on = -1;
|
||||
if (on < 0) on = rt_knob("ASTC_SCRATCH_TRIM", "1") == 1;
|
||||
if (!on || !scratch_keep()) return;
|
||||
if (__atomic_load_n(&S.size, __ATOMIC_RELAXED) <= SCRATCH_MIN || !plat_mutex_trylock(&g_lock)) return;
|
||||
VkCtx *c = vk_ctx();
|
||||
if (S.buf && c && S.dev == c->device && S.size > SCRATCH_MIN && kern_now_ns() - S.big_ns > SCRATCH_SHRINK_NS) {
|
||||
vk_defer_buffer(S.buf, S.alloc);
|
||||
S.buf = VK_NULL_HANDLE, S.alloc = NULL, S.size = 0, S.cb = VK_NULL_HANDLE;
|
||||
n_scratch_trim++;
|
||||
}
|
||||
plat_mutex_unlock(&g_lock);
|
||||
}
|
||||
|
||||
// The shared scratch's size, for the log's VRAM breakdown (scratches still owned by an upload batch not counted).
|
||||
uint64_t vk_astc_scratch_bytes(void) {
|
||||
plat_mutex_lock(&g_lock);
|
||||
@@ -762,9 +783,9 @@ int vk_astc_record(VkCommandBuffer cb, VkBuffer src, VkDeviceSize src_size, cons
|
||||
}
|
||||
if ((n_dispatch + (uint64_t)n) / 1024 != n_dispatch / 1024 || !n_dispatch) {
|
||||
rt_log("vk: ASTC: %llu regions, %.1f M texels decoded on the GPU so far; shared scratch %llu MiB, made %llu "
|
||||
"times, reused %llu", (unsigned long long)(n_dispatch + (uint64_t)n), (double)n_texels / 1e6,
|
||||
(unsigned long long)(S.size >> 20), (unsigned long long)n_scratch_new,
|
||||
(unsigned long long)n_scratch_reuse);
|
||||
"times, reused %llu, given back idle %llu", (unsigned long long)(n_dispatch + (uint64_t)n),
|
||||
(double)n_texels / 1e6, (unsigned long long)(S.size >> 20), (unsigned long long)n_scratch_new,
|
||||
(unsigned long long)n_scratch_reuse, (unsigned long long)n_scratch_trim);
|
||||
vk_astc_time_summary();
|
||||
}
|
||||
n_dispatch += (uint64_t)n;
|
||||
|
||||
@@ -3429,6 +3429,7 @@ static void compact_frame_time(uint64_t d);
|
||||
|
||||
void vk_texstat_frame(uint64_t frame, uint64_t d) {
|
||||
if (compact_on()) compact_frame_time(d);
|
||||
vk_astc_scratch_trim();
|
||||
if (ts_log_ms < 0) {
|
||||
ts_log_ms = cfg_int("NX2NAVI_TEXUP_LOG_MS");
|
||||
if (ts_log_ms < 0) ts_log_ms = 0;
|
||||
|
||||
Reference in New Issue
Block a user