From 2e58bf5be4951a4fbcca4d39ac496ad003c170c5 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Sun, 23 Jun 2024 12:21:56 +0300 Subject: [PATCH] `Shader`: better cache handling --- src/CRE/shader.cpp | 57 ++++++++++++++++++++++++---------------- src/ReDIVA/main.cpp | 64 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 85 insertions(+), 36 deletions(-) diff --git a/src/CRE/shader.cpp b/src/CRE/shader.cpp index 0332f078..fc88e4a7 100644 --- a/src/CRE/shader.cpp +++ b/src/CRE/shader.cpp @@ -22,7 +22,7 @@ static GLuint shader_compile_shader(GLenum type, const char* data, const char* f static GLuint shader_compile(const char* vert, const char* frag, const char* vp, const char* fp); static GLuint shader_compile_binary(const char* vert, const char* frag, const char* vp, const char* fp, program_binary* bin, GLsizei* buffer_size, void** binary); -static bool shader_load_binary_shader(program_binary* bin, GLuint* program); +static bool shader_load_binary_shader(program_binary* bin, GLuint* program, const char* vp, const char* fp); static void shader_update_data(shader_set_data* set); int32_t shader::bind(shader_set_data* set, uint32_t sub_index) { @@ -427,6 +427,7 @@ void shader_set_data::load(farc* f, bool ignore_cache, char frag_buf[MAX_PATH]; char vert_file_buf[MAX_PATH]; char frag_file_buf[MAX_PATH]; + char shader_cache_file_name[MAX_PATH]; GLsizei buffer_size = 0x100000; void* binary = force_malloc(buffer_size); @@ -493,32 +494,44 @@ void shader_set_data::load(farc* f, bool ignore_cache, continue; } - uint32_t uniform_flags = 0; + uint32_t uniform_vert_flags = 0; + uint32_t uniform_frag_flags = 0; for (int32_t k = 0; k < shader->num_uniform; k++) - if (shader->use_uniform[k].second) - uniform_flags |= 1 << k; + if (shader->use_uniform[k].second) { + if (sub_table->vp_unival_max[k] > 0) + uniform_vert_flags |= 1 << k; + if (sub_table->fp_unival_max[k] > 0) + uniform_frag_flags |= 1 << k; + } - char uniform_flags_buf[9]; + char uniform_vert_flags_buf[9]; + char uniform_frag_flags_buf[9]; for (int32_t k = 0, l = 7; k < 32; k += 4, l--) { - int32_t digit = (uniform_flags >> k) & 0xF; - if (digit >= 0x00 && digit <= 0x09) - uniform_flags_buf[l] = (char)('0' + digit); + int32_t vert_flags_digit = (uniform_vert_flags >> k) & 0xF; + if (vert_flags_digit >= 0x00 && vert_flags_digit <= 0x09) + uniform_vert_flags_buf[l] = (char)('0' + vert_flags_digit); else - uniform_flags_buf[l] = (char)('A' + (digit - 0x0A)); + uniform_vert_flags_buf[l] = (char)('A' + (vert_flags_digit - 0x0A)); + + int32_t frag_flags_digit = (uniform_frag_flags >> k) & 0xF; + if (frag_flags_digit >= 0x00 && frag_flags_digit <= 0x09) + uniform_frag_flags_buf[l] = (char)('0' + frag_flags_digit); + else + uniform_frag_flags_buf[l] = (char)('A' + (frag_flags_digit - 0x0A)); } - uniform_flags_buf[8] = 0; + uniform_vert_flags_buf[8] = 0; + uniform_frag_flags_buf[8] = 0; strcpy_s(vert_buf, sizeof(vert_buf), vert_file_buf); strcpy_s(frag_buf, sizeof(frag_buf), frag_file_buf); strcat_s(vert_buf, sizeof(vert_buf), "."); strcat_s(frag_buf, sizeof(frag_buf), "."); - strcat_s(vert_buf, sizeof(vert_buf), uniform_flags_buf); - strcat_s(frag_buf, sizeof(frag_buf), uniform_flags_buf); + strcat_s(vert_buf, sizeof(vert_buf), uniform_vert_flags_buf); + strcat_s(frag_buf, sizeof(frag_buf), uniform_frag_flags_buf); uint64_t vert_file_name_hash = hash_utf8_xxh3_64bits(vert_buf); uint64_t frag_file_name_hash = hash_utf8_xxh3_64bits(frag_buf); - char shader_cache_file_name[MAX_PATH]; strcpy_s(shader_cache_file_name, sizeof(shader_cache_file_name), sub_table->vp); if (str_utils_compare(sub_table->vp, sub_table->fp)) { strcat_s(shader_cache_file_name, sizeof(shader_cache_file_name), "."); @@ -542,13 +555,8 @@ void shader_set_data::load(farc* f, bool ignore_cache, else if (vert_data_hash != ((uint64_t*)shader_cache_file->data)[2] || frag_data_hash != ((uint64_t*)shader_cache_file->data)[3]) printf_debug("Shader hash not equal: %s %s\n", vert_file_buf, frag_file_buf); - else { + else bin = (program_binary*)&((uint64_t*)shader_cache_file->data)[4]; - if (bin->hash != hash_xxh3_64bits((void*)((size_t)bin + bin->binary), bin->length)) { - printf_debug("Compiled binary hash could not be validated: %s %s\n", vert_file_buf, frag_file_buf); - bin = 0; - } - } } if (shader->num_uniform > 0 @@ -604,7 +612,7 @@ void shader_set_data::load(farc* f, bool ignore_cache, } if (!bin || !bin->binary_format || !bin->length - || !shader_load_binary_shader(bin, &shaders[k].program)) { + || !shader_load_binary_shader(bin, &shaders[k].program, vert_buf, frag_buf)) { bool vert_succ = shader::parse_define(vert_data, num_uniform, vec_vert_data, &temp_vert, &temp_vert_size); bool frag_succ = shader::parse_define(frag_data, num_uniform, @@ -650,7 +658,7 @@ void shader_set_data::load(farc* f, bool ignore_cache, strcat_s(frag_buf, sizeof(vert_buf), "..frag"); if (!bin || !bin->binary_format || !bin->length - || !shader_load_binary_shader(bin, &shaders[0].program)) { + || !shader_load_binary_shader(bin, &shaders[0].program, vert_buf, frag_buf)) { bool vert_succ = shader::parse_define(vert_data, &temp_vert, &temp_vert_size); bool frag_succ = shader::parse_define(frag_data, &temp_frag, &temp_frag_size); @@ -1019,7 +1027,12 @@ static GLuint shader_compile_binary(const char* vert, const char* frag, const ch } } -static bool shader_load_binary_shader(program_binary* bin, GLuint* program) { +static bool shader_load_binary_shader(program_binary* bin, GLuint* program, const char* vp, const char* fp) { + if (bin->hash != hash_xxh3_64bits((void*)((size_t)bin + bin->binary), bin->length)) { + printf_debug("Compiled binary hash could not be validated: %s %s\n", vp, fp); + return false; + } + *program = glCreateProgram(); glProgramBinary(*program, bin->binary_format, (void*)((size_t)bin + bin->binary), bin->length); GLint success = 0; diff --git a/src/ReDIVA/main.cpp b/src/ReDIVA/main.cpp index 6e91e83d..92f9e572 100644 --- a/src/ReDIVA/main.cpp +++ b/src/ReDIVA/main.cpp @@ -300,6 +300,18 @@ void compile_shaders(farc* f, farc* of, const shader_table* shaders_table, const else options = "-O"; + char vert_buf[MAX_PATH]; + char frag_buf[MAX_PATH]; + char vert_file_buf[MAX_PATH]; + char frag_file_buf[MAX_PATH]; + wchar_t cmd_temp[0x800]; + char vert_bin_buf[MAX_PATH]; + char frag_bin_buf[MAX_PATH]; + wchar_t glsl_vert_file_buf[MAX_PATH]; + wchar_t glsl_frag_file_buf[MAX_PATH]; + wchar_t spv_vert_file_buf[MAX_PATH]; + wchar_t spv_frag_file_buf[MAX_PATH]; + GLsizei buffer_size = 0x20000; void* spv = force_malloc(buffer_size); size_t temp_vert_size = 0x10000; @@ -320,7 +332,6 @@ void compile_shaders(farc* f, farc* of, const shader_table* shaders_table, const int32_t* vec_vert_data = vec_vert.data(); int32_t* vec_frag_data = vec_frag.data(); for (size_t j = 0; j < num_sub; j++, sub_table++) { - char vert_file_buf[MAX_PATH]; strcpy_s(vert_file_buf, sizeof(vert_file_buf), sub_table->vp); strcat_s(vert_file_buf, sizeof(vert_file_buf), ".vert"); farc_file* vert_ff = f->read_file(vert_file_buf); @@ -334,7 +345,6 @@ void compile_shaders(farc* f, farc* of, const shader_table* shaders_table, const } } - char frag_file_buf[MAX_PATH]; strcpy_s(frag_file_buf, sizeof(frag_file_buf), sub_table->fp); strcat_s(frag_file_buf, sizeof(frag_file_buf), ".frag"); farc_file* frag_ff = f->read_file(frag_file_buf); @@ -354,22 +364,47 @@ void compile_shaders(farc* f, farc* of, const shader_table* shaders_table, const continue; } - uint64_t vert_file_name_hash = hash_utf8_xxh3_64bits(vert_file_buf); - uint64_t frag_file_name_hash = hash_utf8_xxh3_64bits(frag_file_buf); + uint32_t uniform_vert_flags = 0; + uint32_t uniform_frag_flags = 0; + for (int32_t k = 0; k < shader_table->num_uniform; k++) + if (shader_table->use_uniform[k].second) { + if (sub_table->vp_unival_max[k] > 0) + uniform_vert_flags |= 1 << k; + if (sub_table->fp_unival_max[k] > 0) + uniform_frag_flags |= 1 << k; + } + + char uniform_vert_flags_buf[9]; + char uniform_frag_flags_buf[9]; + for (int32_t k = 0, l = 7; k < 32; k += 4, l--) { + int32_t vert_flags_digit = (uniform_vert_flags >> k) & 0xF; + if (vert_flags_digit >= 0x00 && vert_flags_digit <= 0x09) + uniform_vert_flags_buf[l] = (char)('0' + vert_flags_digit); + else + uniform_vert_flags_buf[l] = (char)('A' + (vert_flags_digit - 0x0A)); + + int32_t frag_flags_digit = (uniform_frag_flags >> k) & 0xF; + if (frag_flags_digit >= 0x00 && frag_flags_digit <= 0x09) + uniform_frag_flags_buf[l] = (char)('0' + frag_flags_digit); + else + uniform_frag_flags_buf[l] = (char)('A' + (frag_flags_digit - 0x0A)); + } + uniform_vert_flags_buf[8] = 0; + uniform_frag_flags_buf[8] = 0; + + strcpy_s(vert_buf, sizeof(vert_buf), vert_file_buf); + strcpy_s(frag_buf, sizeof(frag_buf), frag_file_buf); + strcat_s(vert_buf, sizeof(vert_buf), "."); + strcat_s(frag_buf, sizeof(frag_buf), "."); + strcat_s(vert_buf, sizeof(vert_buf), uniform_vert_flags_buf); + strcat_s(frag_buf, sizeof(frag_buf), uniform_frag_flags_buf); + + uint64_t vert_file_name_hash = hash_utf8_xxh3_64bits(vert_buf); + uint64_t frag_file_name_hash = hash_utf8_xxh3_64bits(frag_buf); vert_data = shader::parse_include(vert_data, f); frag_data = shader::parse_include(frag_data, f); - wchar_t cmd_temp[0x800]; - char vert_buf[MAX_PATH]; - char frag_buf[MAX_PATH]; - char vert_bin_buf[MAX_PATH]; - char frag_bin_buf[MAX_PATH]; - wchar_t glsl_vert_file_buf[MAX_PATH]; - wchar_t glsl_frag_file_buf[MAX_PATH]; - wchar_t spv_vert_file_buf[MAX_PATH]; - wchar_t spv_frag_file_buf[MAX_PATH]; - strcpy_s(vert_bin_buf, sizeof(vert_bin_buf), sub_table->vp); strcat_s(vert_bin_buf, sizeof(vert_bin_buf), ".vert.bin"); @@ -486,6 +521,7 @@ void compile_shaders(farc* f, farc* of, const shader_table* shaders_table, const m /= unival_max; frag_buf[frag_buf_pos + l] = (char)('0' + vec_frag_data[l]); } + shader::parse_define(frag_data, num_uniform, vec_frag_data, &temp_frag, &temp_frag_size);