mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
cache_load measured pipeline-cache.bin with ftell into a long, which is 32 bits on Windows: a file past 2 GB measured as -1, so the run started with an empty cache and the log said nothing, not even that the file was over pipeline_cache_max_mb. The read now lives in runtime/vk_cache_file.h: the length comes from the 64-bit tell, the read runs in 64 MB pieces, and a refusal returns its reason and the file's size, which cache_load logs. The Windows atomic write no longer cuts a block of 4 GB or more to a 32-bit count. tests/pipeline_cache_file_check.py reads a sparse file just over 2 GB through the header. With --probe-prewarm and such a file carrying this GPU's header, the log reads "holds 2048 MB, over NX2NAVI_PIPELINE_CACHE_MAX_MB 512" under the default limit and "2048.0 MB read" with the limit off; the exe before this change logged nothing for the same file. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
67 lines
3.0 KiB
C
67 lines
3.0 KiB
C
// Reads pipeline-cache.bin into memory for cache_load (runtime/vk_pipeline.c), with 64-bit sizes on every platform.
|
|
// ftell returns a long, which is 32 bits on Windows: a file past 2 GB measured as -1 there, and the run started with an
|
|
// empty cache without a word in the log. The length comes from the 64-bit tell, the read runs in pieces no C library
|
|
// call has to take whole, and every refusal names its reason and the file's size, so cache_load can log it.
|
|
// tests/pipeline_cache_file_check.py reads a sparse file just over 2 GB through it.
|
|
#pragma once
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
enum {
|
|
CACHE_FILE_OK,
|
|
CACHE_FILE_NONE, // no such file: a first run
|
|
CACHE_FILE_UNSIZED, // the file's length could not be measured
|
|
CACHE_FILE_SHORT, // not longer than the header every cache starts with
|
|
CACHE_FILE_OVER_CAP, // longer than the limit; not read
|
|
CACHE_FILE_NO_MEMORY, // no block of the file's size
|
|
CACHE_FILE_READ_FAIL, // the read ended early
|
|
};
|
|
|
|
#define CACHE_FILE_PIECE ((size_t)64 << 20)
|
|
|
|
static inline const char *cache_file_why(int why) {
|
|
switch (why) {
|
|
case CACHE_FILE_UNSIZED: return "its size cannot be measured";
|
|
case CACHE_FILE_SHORT: return "it is shorter than a pipeline cache header";
|
|
case CACHE_FILE_OVER_CAP: return "it is over the size limit";
|
|
case CACHE_FILE_NO_MEMORY: return "there is no memory for a block of its size";
|
|
case CACHE_FILE_READ_FAIL: return "reading it ended early";
|
|
default: return "";
|
|
}
|
|
}
|
|
|
|
// The whole file in a malloc block, or NULL with *why set. *len is the file's length in bytes whenever it could be
|
|
// measured, read or not. min: a file of at most this many bytes is refused; cap: so is one longer than cap (0: no limit),
|
|
// before any of it is read.
|
|
static inline void *cache_file_read(const char *path, uint64_t min, uint64_t cap, uint64_t *len, int *why) {
|
|
*len = 0;
|
|
FILE *f = fopen(path, "rb");
|
|
if (!f) return *why = CACHE_FILE_NONE, NULL;
|
|
#ifdef _WIN32
|
|
int64_t n = _fseeki64(f, 0, SEEK_END) ? -1 : _ftelli64(f);
|
|
if (n >= 0 && _fseeki64(f, 0, SEEK_SET)) n = -1;
|
|
#else
|
|
int64_t n = fseeko(f, 0, SEEK_END) ? -1 : (int64_t)ftello(f);
|
|
if (n >= 0 && fseeko(f, 0, SEEK_SET)) n = -1;
|
|
#endif
|
|
void *data = NULL;
|
|
if (n < 0) *why = CACHE_FILE_UNSIZED;
|
|
else if (*len = (uint64_t)n, (uint64_t)n <= min) *why = CACHE_FILE_SHORT;
|
|
else if (cap && (uint64_t)n > cap) *why = CACHE_FILE_OVER_CAP;
|
|
else if ((uint64_t)n > SIZE_MAX || !(data = malloc((size_t)n))) *why = CACHE_FILE_NO_MEMORY;
|
|
else {
|
|
size_t got = 0, want = (size_t)n;
|
|
while (got < want) {
|
|
size_t piece = want - got < CACHE_FILE_PIECE ? want - got : CACHE_FILE_PIECE;
|
|
size_t r = fread((char *)data + got, 1, piece, f);
|
|
got += r;
|
|
if (r != piece) break;
|
|
}
|
|
if (got == want) *why = CACHE_FILE_OK;
|
|
else free(data), data = NULL, *why = CACHE_FILE_READ_FAIL;
|
|
}
|
|
fclose(f);
|
|
return data;
|
|
}
|