From 8e3468f9a6daa45acb921f02bb218b2f53ee1c12 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Wed, 16 Apr 2025 00:55:54 +0300 Subject: [PATCH] Shared Storage/Uniform Buffer --- res/ft_shaders.farc | Bin 98960 -> 99024 bytes src/DivaGL/dllmain.cpp | 21 ++- src/DivaGL/hook.cpp | 2 + src/DivaGL/mdl/draw_object.cpp | 40 +++-- src/DivaGL/render_context.cpp | 272 ++++++++++++++++++++++++++++++++- src/DivaGL/render_context.hpp | 47 ++++++ src/DivaGL/shader.cpp | 7 +- 7 files changed, 370 insertions(+), 19 deletions(-) diff --git a/res/ft_shaders.farc b/res/ft_shaders.farc index 2e74de223a00f35cffc28640fc4a298108f50043..b2e3abfcf9743f057378479769aa13494a1578e9 100644 GIT binary patch delta 3755 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 0 ? true : false; config_reflect_res_scale = GetPrivateProfileIntW(L"general", L"reflect_res_scale", 1, CONFIG_FILE); config_reflect_res_scale = config_reflect_res_scale ? clamp_def(config_reflect_res_scale, 25, 100) : 100; + config_shared_storage_uniform_buffer = GetPrivateProfileIntW(L"experimentals", + L"shared_storage_uniform_buffer", 0, CONFIG_FILE) > 0 ? true : false; dll_handle = (size_t)handle; - printf_divagl("Current version - v0.7.3.0"); + printf_divagl("Current version - v0.7.3.0 (Build date: " __DATE__ ")"); printf_divagl("Attach"); divagl_main(); break; @@ -76,7 +79,7 @@ extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void) { } extern "C" __declspec(dllexport) LPCWSTR GetBuildDate(void) { - return L"v0.7.3.0"; + return L"v0.7.3.0 (Build date: " __DATE__ ")"; } static std::wstring GetDirPath() { @@ -115,12 +118,24 @@ PluginConfig::PluginConfigOption config[] = { L"general", CONFIG_FILE, L"Reflect Resolution Scale", - L"Sets resolution for Full Reflect as a percentage relative to the Internal Resolution values.\nImportant note! Scale doesn't apply can't go lower than 256x144 or Internal Resolution.", + L"Sets resolution for Full Reflect as a percentage relative to the Internal Resolution values.\nImportant note! Scale can't go lower than 256x144 or Internal Resolution.", 100, 25, 100, } }, + { + PluginConfig::CONFIG_BOOLEAN, + new PluginConfig::PluginConfigBooleanData { + L"shared_storage_uniform_buffer", + L"experimentals", + CONFIG_FILE, + L"Shared Storage/Uniform Buffer", + L"May be seful for running AFT via Mesa or on Apple devices\nor when driver doesn't support OpenGL 4.3.", + false, + false, + } + }, }; extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void) { diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp index f9e08f9..9b98e49 100644 --- a/src/DivaGL/hook.cpp +++ b/src/DivaGL/hook.cpp @@ -165,6 +165,7 @@ HOOK(void, FASTCALL, rndr__RenderManager__rndpass_pre_proc, 0x0000000140502C90) render_manager.render->pre_proc(); Glitter::glt_particle_manager->CalcDisp(); Glitter::glt_particle_manager_x->CalcDisp(); + rctx->pre_proc(); gl_state_end_event(); } @@ -174,6 +175,7 @@ HOOK(void, FASTCALL, rndr__RenderManager__render_all, 0x0000000140502CA0) { HOOK(void, FASTCALL, rndr__RenderManager__rndpass_post_proc, 0x0000000140502C70) { gl_state_begin_event("rndpass_post_proc"); + rctx->post_proc(); render_manager.render->post_proc(); render_manager.field_31C = false; gl_state_end_event(); diff --git a/src/DivaGL/mdl/draw_object.cpp b/src/DivaGL/mdl/draw_object.cpp index 97a0809..521751d 100644 --- a/src/DivaGL/mdl/draw_object.cpp +++ b/src/DivaGL/mdl/draw_object.cpp @@ -30,6 +30,8 @@ static void draw_object_vertex_attrib_set_reflect(const mdl::ObjSubMeshArgs* arg static bool(FASTCALL* use_shader_get)() = (bool(FASTCALL*)())0x0000000140440E30; +extern bool config_shared_storage_uniform_buffer; + namespace mdl { void draw(obj_primitive_type primitive_type, uint32_t count, uint16_t start, uint16_t end, obj_index_format index_format, size_t indices) { @@ -183,21 +185,33 @@ namespace mdl { if (args->mat_count == 2) rctx->set_batch_joint(mats[0]); - vec4* g_joint_transforms = rctx->data.buffer_skinning_data.g_joint_transforms; - - mat4 mat; - for (int32_t i = 0; i < args->mat_count; i++, mats++, g_joint_transforms += 3) { - mat4_transpose(mats, &mat); - g_joint_transforms[0] = mat.row0; - g_joint_transforms[1] = mat.row1; - g_joint_transforms[2] = mat.row2; + if (config_shared_storage_uniform_buffer) { + GLuint buffer = 0; + size_t offset = 0; + size_t size = 0; + if (rctx->get_shared_storage_uniform_buffer_data((size_t)args->mats, buffer, offset, size, !!GL_VERSION_4_3)) + if (GL_VERSION_4_3) + gl_state_bind_shader_storage_buffer_range(0, buffer, (GLintptr)offset, (GLsizeiptr)size); + else + gl_state_bind_uniform_buffer_range(6, buffer, (GLintptr)offset, (GLsizeiptr)size); } + else { + vec4* g_joint_transforms = rctx->data.buffer_skinning_data.g_joint_transforms; - if (GL_VERSION_4_3) - rctx->data.buffer_skinning.WriteMemory(rctx->data.buffer_skinning_data); - else - rctx->data.buffer_skinning_ubo.WriteMemory(0, - sizeof(vec4) * 3 * args->mat_count, &rctx->data.buffer_skinning_data); + mat4 mat; + for (int32_t i = 0; i < args->mat_count; i++, mats++, g_joint_transforms += 3) { + mat4_transpose(mats, &mat); + g_joint_transforms[0] = mat.row0; + g_joint_transforms[1] = mat.row1; + g_joint_transforms[2] = mat.row2; + } + + if (GL_VERSION_4_3) + rctx->data.buffer_skinning.WriteMemory(rctx->data.buffer_skinning_data); + else + rctx->data.buffer_skinning_ubo.WriteMemory(0, + sizeof(vec4) * 3 * args->mat_count, &rctx->data.buffer_skinning_data); + } rctx->set_batch_worlds(mat4_identity); diff --git a/src/DivaGL/render_context.cpp b/src/DivaGL/render_context.cpp index 9829189..e3007a8 100644 --- a/src/DivaGL/render_context.cpp +++ b/src/DivaGL/render_context.cpp @@ -14,6 +14,8 @@ sss_data& _sss_data = *(sss_data*)0x000000014CC924E0; render_context* rctx; +extern bool config_shared_storage_uniform_buffer; + void draw_state_stats::reset() { object_draw_count = 0; object_translucent_draw_count = 0; @@ -345,7 +347,7 @@ void render_data::set(render_context* rctx) { buffer_scene.Bind(1); buffer_batch.Bind(2); - if (uniform->arr[U_SKINNING]) + if (uniform->arr[U_SKINNING] && !config_shared_storage_uniform_buffer) if (GL_VERSION_4_3) buffer_skinning.Bind(0); else @@ -359,6 +361,76 @@ void render_data::set_shader(uint32_t index) { enum_or(flags, RENDER_DATA_SHADER_UPDATE); } +bool render_context::shared_storage_buffer::can_fill_data(render_context* rctx, size_t size) { + return (size + align_val(offset, rctx->storage_buffer_offset_alignment)) <= this->size; +} + +void render_context::shared_storage_buffer::create(size_t size) { + if (buffer) + return; + + size = size / rctx->storage_buffer_offset_alignment * rctx->storage_buffer_offset_alignment; + + buffer.Create(size); + data = _operator_new(size); + memset(data, 0, size); + offset = 0; + this->size = size; +} + +void render_context::shared_storage_buffer::destroy() { + buffer.Destroy(); + + if (data) { + _operator_delete(data); + data = 0; + } +} + +size_t render_context::shared_storage_buffer::fill_data(render_context* rctx, const void* data, size_t size) { + size_t offset = align_val(this->offset, rctx->storage_buffer_offset_alignment); + if (offset != this->offset) + memset((void*)((size_t)this->data + this->offset), 0, offset - this->offset); + memcpy((void*)((size_t)this->data + offset), data, size); + this->offset = offset + size; + return offset; +} + +bool render_context::shared_uniform_buffer::can_fill_data(render_context* rctx, size_t size) { + return (size + align_val(offset, rctx->uniform_buffer_offset_alignment)) <= this->size; +} + +void render_context::shared_uniform_buffer::create(size_t size) { + if (buffer) + return; + + size = size / rctx->uniform_buffer_offset_alignment * rctx->uniform_buffer_offset_alignment; + + buffer.Create(size); + data = _operator_new(size); + memset(data, 0, size); + offset = 0; + this->size = size; +} + +void render_context::shared_uniform_buffer::destroy() { + buffer.Destroy(); + + if (data) { + _operator_delete(data); + data = 0; + } +} + +size_t render_context::shared_uniform_buffer::fill_data(render_context* rctx, const void* data, size_t size) { + size_t offset = align_val(this->offset, rctx->uniform_buffer_offset_alignment); + if (offset != this->offset) + memset((void*)((size_t)this->data + this->offset), 0, offset - this->offset); + memcpy((void*)((size_t)this->data + offset), data, size); + this->offset = offset + size; + return offset; +} + render_context::render_context() : box_vao(), lens_ghost_vao(), common_vao(), reflect_buffer(), render_buffer(), screen_buffer(), shadow_buffer(), empty_texture_2d(), empty_texture_cube_map(), samplers(), render_samplers(), sprite_samplers(), screen_width(), screen_height() { @@ -538,9 +610,35 @@ samplers(), render_samplers(), sprite_samplers(), screen_width(), screen_height( glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); + + glGetIntegervDLL(GL_MAX_UNIFORM_BLOCK_SIZE, (GLint*)&max_uniform_block_size); + glGetIntegervDLL(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, (GLint*)&uniform_buffer_offset_alignment); + + if (GL_VERSION_4_3) { + glGetIntegervDLL(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, (GLint*)&max_storage_block_size); + glGetIntegervDLL(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&storage_buffer_offset_alignment); + + max_storage_block_size = min_def(max_storage_block_size, 16u * 1024 * 1024); + } } render_context::~render_context() { + if (config_shared_storage_uniform_buffer) { + shared_uniform_buffer_entries.clear(); + + for (render_context::shared_uniform_buffer& i : shared_uniform_buffers) + i.destroy(); + shared_uniform_buffers.clear(); + + if (GL_VERSION_4_3) { + shared_storage_buffer_entries.clear(); + + for (render_context::shared_storage_buffer& i : shared_storage_buffers) + i.destroy(); + shared_storage_buffers.clear(); + } + } + glDeleteSamplers(3, sprite_samplers); glDeleteSamplers(4, render_samplers); glDeleteSamplers(18, samplers); @@ -701,6 +799,154 @@ void render_context::init() { screen_buffer.Init(screen_width, screen_height, 0, GL_RGBA8, 0); } +void render_context::add_shared_storage_uniform_buffer_data(size_t index, + const void* data, size_t size, size_t buffer_size, bool storage) { + if (storage) { + render_context::shared_storage_buffer* buffer = 0; + for (render_context::shared_storage_buffer& i : shared_storage_buffers) + if (i.can_fill_data(this, buffer_size)) { + buffer = &i; + break; + } + + if (!buffer) { + shared_storage_buffers.push_back({}); + buffer = &shared_storage_buffers.back(); + buffer->create(max_storage_block_size); + } + + size_t offset = buffer->fill_data(this, data, size); + shared_storage_buffer_entries.insert({ index, { buffer->buffer, offset, buffer_size } }); + } + else { + render_context::shared_uniform_buffer* buffer = 0; + for (render_context::shared_uniform_buffer& i : shared_uniform_buffers) + if (i.can_fill_data(this, buffer_size)) { + buffer = &i; + break; + } + + if (!buffer) { + shared_uniform_buffers.push_back({}); + buffer = &shared_uniform_buffers.back(); + buffer->create(max_uniform_block_size); + } + + size_t offset = buffer->fill_data(this, data, size); + shared_uniform_buffer_entries.insert({ index, { buffer->buffer, offset, buffer_size } }); + } +} + +void render_context::pre_proc() { + if (config_shared_storage_uniform_buffer) { + auto add_obj_list = [](render_context* rctx, const mdl::ObjSubMeshArgs* args) { + if (!args->mat_count || !args->mats) + return; + + if (GL_VERSION_4_3) { + if (rctx->shared_storage_buffer_entries.find((size_t)args->mats) + != rctx->shared_storage_buffer_entries.end()) + return; + } + else { + if (rctx->shared_uniform_buffer_entries.find((size_t)args->mats) + != rctx->shared_uniform_buffer_entries.end()) + return; + } + + const int32_t mat_count = min_def(args->mat_count, 256); + const mat4* mats = args->mats; + vec4* g_joint_transforms = rctx->data.buffer_skinning_data.g_joint_transforms; + + mat4 mat; + for (int32_t i = 0; i < mat_count; i++, mats++, g_joint_transforms += 3) { + mat4_transpose(mats, &mat); + g_joint_transforms[0] = mat.row0; + g_joint_transforms[1] = mat.row1; + g_joint_transforms[2] = mat.row2; + } + + const size_t buffer_size = sizeof(vec4) * 3 * 256; + const size_t size = sizeof(vec4) * 3 * mat_count; + rctx->add_shared_storage_uniform_buffer_data((size_t)args->mats, + rctx->data.buffer_skinning_data.g_joint_transforms, size, buffer_size, !!GL_VERSION_4_3); + }; + + for (int32_t type = 0; type < mdl::OBJ_TYPE_MAX; type++) + for (mdl::ObjData*& i : disp_manager->get_obj_list((mdl::ObjType)type)) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(rctx, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(rctx, i->args.translucent.sub_mesh[j]); + break; + } + + for (int32_t type = 0; type < mdl::OBJ_TYPE_LOCAL_MAX; type++) + for (mdl::ObjData*& i : disp_manager->get_obj_list((mdl::ObjTypeLocal)type)) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(rctx, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(rctx, i->args.translucent.sub_mesh[j]); + break; + } + + for (int32_t type = 0; type < mdl::OBJ_TYPE_REFLECT_MAX; type++) + for (mdl::ObjData*& i : disp_manager->get_obj_list((mdl::ObjTypeReflect)type)) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(rctx, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(rctx, i->args.translucent.sub_mesh[j]); + break; + } + + if (GL_VERSION_4_3) + for (render_context::shared_storage_buffer& i : shared_storage_buffers) { + if (!i.offset) + continue; + + size_t align = align_val(i.offset, storage_buffer_offset_alignment) - i.offset; + if (align) + memset((void*)((size_t)i.data + i.offset), 0, align); + i.buffer.WriteMemory(0, i.size, i.data); + } + + for (render_context::shared_uniform_buffer& i : shared_uniform_buffers) { + if (!i.offset) + continue; + + size_t align = align_val(i.offset, uniform_buffer_offset_alignment) - i.offset; + if (align) + memset((void*)((size_t)i.data + i.offset), 0, align); + i.buffer.WriteMemory(0, i.size, i.data); + } + } +} + +void render_context::post_proc() { + if (config_shared_storage_uniform_buffer) { + if (GL_VERSION_4_3) { + for (render_context::shared_storage_buffer& i : shared_storage_buffers) + i.offset = 0; + + shared_storage_buffer_entries.clear(); + } + + for (render_context::shared_uniform_buffer& i : shared_uniform_buffers) + i.offset = 0; + + shared_uniform_buffer_entries.clear(); + } +} + void render_context::get_scene_fog_params(render_context::fog_params& value) { render_data* data = &this->data; value.depth_color = data->buffer_scene_data.g_fog_depth_color; @@ -730,6 +976,30 @@ void render_context::get_scene_light(vec4* light_env_stage_diffuse, *light_env_chara_specular = data->buffer_scene_data.g_light_env_chara_specular; } +bool render_context::get_shared_storage_uniform_buffer_data(size_t index, + GLuint& buffer, size_t& offset, size_t& size, bool storage) { + if (storage) { + auto elem = shared_storage_buffer_entries.find(index); + if (elem == shared_storage_buffer_entries.end()) + return false; + + buffer = elem->second.buffer; + offset = elem->second.offset; + size = elem->second.size; + return true; + } + else { + auto elem = shared_uniform_buffer_entries.find(index); + if (elem == shared_uniform_buffer_entries.end()) + return false; + + buffer = elem->second.buffer; + offset = elem->second.offset; + size = elem->second.size; + return true; + } +} + void render_context::set_batch_alpha_threshold(const float_t value) { render_data* data = &this->data; data->buffer_batch_data.g_max_alpha.z = value; diff --git a/src/DivaGL/render_context.hpp b/src/DivaGL/render_context.hpp index f125346..09b3713 100644 --- a/src/DivaGL/render_context.hpp +++ b/src/DivaGL/render_context.hpp @@ -404,6 +404,36 @@ struct render_context { float_t end; }; + struct shared_storage_buffer { + void* data; + size_t offset; + size_t size; + GL::ShaderStorageBuffer buffer; + + bool can_fill_data(render_context* rctx, size_t size); + void create(size_t size); + void destroy(); + size_t fill_data(render_context* rctx, const void* data, size_t size); + }; + + struct shared_uniform_buffer { + void* data; + size_t offset; + size_t size; + GL::UniformBuffer buffer; + + bool can_fill_data(render_context* rctx, size_t size); + void create(size_t size); + void destroy(); + size_t fill_data(render_context* rctx, const void* data, size_t size); + }; + + struct shared_buffer_entry { + GLuint buffer; + size_t offset; + size_t size; + }; + mat4 view_mat; mat4 proj_mat; mat4 vp_mat; @@ -454,6 +484,17 @@ struct render_context { mdl::ObjList obj_local[mdl::OBJ_TYPE_LOCAL_MAX]; mdl::ObjList obj_reflect[mdl::OBJ_TYPE_REFLECT_MAX]; + uint32_t max_uniform_block_size = 0; + uint32_t uniform_buffer_offset_alignment = 0; + + uint32_t max_storage_block_size = 0; + uint32_t storage_buffer_offset_alignment = 0; + + prj::vector shared_storage_buffers; + std::unordered_map shared_storage_buffer_entries; + prj::vector shared_uniform_buffers; + std::unordered_map shared_uniform_buffer_entries; + render_context(); ~render_context(); @@ -461,10 +502,16 @@ struct render_context { void free(); void init(); + void add_shared_storage_uniform_buffer_data(size_t index, + const void* data, size_t size, size_t max_size, bool storage = false); + void post_proc(); + void pre_proc(); void get_scene_fog_params(render_context::fog_params& value); void get_scene_light(vec4* light_env_stage_diffuse, vec4* light_env_stage_specular, vec4* light_chara_dir, vec4* light_chara_luce, vec4* light_env_chara_diffuse, vec4* light_env_chara_specular); + bool get_shared_storage_uniform_buffer_data(size_t index, + GLuint& buffer, size_t& offset, size_t& size, bool storage = false); void set_batch_alpha_threshold(const float_t value); void set_batch_blend_color(const vec4& blend_color); void set_batch_blend_color_offset_color(const vec4& blend_color, const vec4& offset_color); diff --git a/src/DivaGL/shader.cpp b/src/DivaGL/shader.cpp index a6232ce..035939a 100644 --- a/src/DivaGL/shader.cpp +++ b/src/DivaGL/shader.cpp @@ -565,6 +565,11 @@ void shader_set_data::load(farc* f, bool ignore_cache, if (FAILED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA, 0, 0, temp_buf))) return; + const bool apple = !!strstr((const char*)glGetStringGLUT(GL_VENDOR), "Apple"); + + if (strstr((const char*)glGetStringGLUT(GL_VERSION), "Mesa")) + ignore_cache = true; + wcscat_s(temp_buf, sizeof(temp_buf) / sizeof(wchar_t), L"\\PDAFT"); path_create_directory(temp_buf); @@ -578,8 +583,6 @@ void shader_set_data::load(farc* f, bool ignore_cache, if (!ignore_cache && path_check_file_exists(buf)) shader_cache_farc.read(buf, true, false); - const bool apple = !!strstr((const char*)glGetStringGLUT(GL_VENDOR), "Apple"); - char vert_buf[MAX_PATH]; char frag_buf[MAX_PATH]; char vert_file_buf[MAX_PATH];