diff --git a/src/CRE/mdl/draw_object.cpp b/src/CRE/mdl/draw_object.cpp index 349908a4..6ee24818 100644 --- a/src/CRE/mdl/draw_object.cpp +++ b/src/CRE/mdl/draw_object.cpp @@ -181,17 +181,34 @@ 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 (sv_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, !!GLAD_GL_VERSION_4_3)) + if (GLAD_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; - rctx->data.buffer_skinning.WriteMemory(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 (GLAD_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/CRE/render_context.cpp b/src/CRE/render_context.cpp index 0d28bdb6..9a290191 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -412,7 +412,10 @@ void render_data::init() { buffer_shader.Create(sizeof(obj_shader_data)); buffer_scene.Create(sizeof(obj_scene_data)); buffer_batch.Create(sizeof(obj_batch_data)); - buffer_skinning.Create(sizeof(obj_skinning_data)); + if (GLAD_GL_VERSION_4_3) + buffer_skinning.Create(sizeof(obj_skinning_data)); + else + buffer_skinning_ubo.Create(sizeof(obj_skinning_data)); buffer_shader_data.reset(); enum_or(flags, RENDER_DATA_SHADER_UPDATE); @@ -423,7 +426,10 @@ void render_data::init() { } void render_data::free() { - buffer_skinning.Destroy(); + if (GLAD_GL_VERSION_4_3) + buffer_skinning.Destroy(); + else + buffer_skinning_ubo.Destroy(); buffer_batch.Destroy(); buffer_scene.Destroy(); buffer_shader.Destroy(); @@ -493,8 +499,11 @@ void render_data::set(render_context* rctx) { buffer_scene.Bind(1); buffer_batch.Bind(2); - if (uniform_value[U_SKINNING]) - buffer_skinning.Bind(0); + if (uniform_value[U_SKINNING] && !sv_shared_storage_uniform_buffer) + if (GLAD_GL_VERSION_4_3) + buffer_skinning.Bind(0); + else + buffer_skinning_ubo.Bind(6); } void render_data::set_shader(uint32_t index) { @@ -504,6 +513,68 @@ void render_data::set_shader(uint32_t index) { enum_or(flags, RENDER_DATA_SHADER_UPDATE); } +bool render_context::shared_storage_buffer::can_fill_data(size_t size) { + return (size + align_val(offset, sv_min_storage_buffer_alignment)) <= this->size; +} + +void render_context::shared_storage_buffer::create(size_t size) { + if (buffer) + return; + + size = size / sv_min_storage_buffer_alignment * sv_min_storage_buffer_alignment; + + buffer.Create(size); + data = force_malloc(size); + memset(data, 0, size); + offset = 0; + this->size = size; +} + +void render_context::shared_storage_buffer::destroy() { + buffer.Destroy(); + free_def(data); +} + +size_t render_context::shared_storage_buffer::fill_data(const void* data, size_t size) { + size_t offset = align_val(this->offset, sv_min_storage_buffer_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(size_t size) { + return (size + align_val(offset, sv_min_uniform_buffer_alignment)) <= this->size; +} + +void render_context::shared_uniform_buffer::create(size_t size) { + if (buffer) + return; + + size = size / sv_min_uniform_buffer_alignment * sv_min_uniform_buffer_alignment; + + buffer.Create(size); + data = force_malloc(size); + memset(data, 0, size); + offset = 0; + this->size = size; +} + +void render_context::shared_uniform_buffer::destroy() { + buffer.Destroy(); + free_def(data); +} + +size_t render_context::shared_uniform_buffer::fill_data(const void* data, size_t size) { + size_t offset = align_val(this->offset, sv_min_uniform_buffer_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() : litproj(), chara_reflect(), chara_refract(), box_vao(), lens_ghost_vao(), common_vao(), empty_texture_2d(), empty_texture_cube_map(), samplers(), render_samplers(), sprite_samplers(), sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_width(), screen_height() { @@ -689,9 +760,30 @@ sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_wi 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); + + max_uniform_block_size = min_def((uint32_t)sv_max_uniform_buffer_size, 64u * 1024); + + if (GLAD_GL_VERSION_4_3) + max_storage_block_size = min_def((uint32_t)sv_max_storage_buffer_size, 1024u * 1024); } render_context::~render_context() { + if (sv_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 (GLAD_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); @@ -883,6 +975,44 @@ void render_context::resize(int32_t render_width, int32_t render_height, } } +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(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(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(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(data, size); + shared_uniform_buffer_entries.insert({ index, { buffer->buffer, offset, buffer_size } }); + } +} + 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; @@ -912,6 +1042,140 @@ 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::pre_proc() { + if (sv_shared_storage_uniform_buffer) { + auto add_obj_list = [](render_context* rctx, const mdl::ObjSubMeshArgs* args) { + if (!args->mat_count || !args->mats) + return; + + if (GLAD_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, !!GLAD_GL_VERSION_4_3); + }; + + for (int32_t type = 0; type < mdl::OBJ_TYPE_MAX; type++) + for (mdl::ObjData*& i : disp_manager->obj[type]) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(this, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(this, 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->obj_local[type]) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(this, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(this, 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->obj_reflect[type]) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: + add_obj_list(this, &i->args.sub_mesh); + break; + case mdl::OBJ_KIND_TRANSLUCENT: + for (int32_t j = 0; j < i->args.translucent.count; j++) + add_obj_list(this, i->args.translucent.sub_mesh[j]); + break; + } + + if (GLAD_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, sv_min_storage_buffer_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, sv_min_uniform_buffer_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 (sv_shared_storage_uniform_buffer) { + if (GLAD_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::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/CRE/render_context.hpp b/src/CRE/render_context.hpp index 9f4b1373..74d3ce14 100644 --- a/src/CRE/render_context.hpp +++ b/src/CRE/render_context.hpp @@ -20,6 +20,7 @@ #include "render.hpp" #include "render_manager.hpp" #include "render_texture.hpp" +#include #define MATRIX_BUFFER_COUNT 320 @@ -403,6 +404,7 @@ struct render_data { GL::UniformBuffer buffer_shader; GL::UniformBuffer buffer_scene; GL::UniformBuffer buffer_batch; + GL::UniformBuffer buffer_skinning_ubo; GL::ShaderStorageBuffer buffer_skinning; void init(); @@ -422,6 +424,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(size_t size); + void create(size_t size); + void destroy(); + size_t fill_data(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(size_t size); + void create(size_t size); + void destroy(); + size_t fill_data(const void* data, size_t size); + }; + + struct shared_buffer_entry { + GLuint buffer; + size_t offset; + size_t size; + }; + ::camera* camera; draw_state* draw_state; mdl::DispManager* disp_manager; @@ -490,6 +522,14 @@ struct render_context { int32_t screen_width; int32_t screen_height; + uint32_t max_uniform_block_size = 0; + uint32_t max_storage_block_size = 0; + + std::vector shared_storage_buffers; + std::unordered_map shared_storage_buffer_entries; + std::vector shared_uniform_buffers; + std::unordered_map shared_uniform_buffer_entries; + render_context(); ~render_context(); @@ -501,10 +541,16 @@ struct render_context { int32_t sprite_width, int32_t sprite_height, int32_t screen_width, int32_t screen_height); + void add_shared_storage_uniform_buffer_data(size_t index, + const void* data, size_t size, size_t max_size, bool storage = false); 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 post_proc(); + void pre_proc(); void set_batch_alpha_threshold(const float_t value); void set_batch_blend_color_offset_color(const vec4& blend_color, const vec4& offset_color); void set_batch_joint(const mat4& mat); diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 23def1fd..cd7c9afe 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -328,6 +328,7 @@ namespace rndr { void RenderManager::rndpass_post_proc() { gl_state_begin_event("rndpass_post_proc"); + rctx_ptr->post_proc(); render->post_proc(); field_31C = false; gl_state_end_event(); @@ -337,6 +338,7 @@ namespace rndr { gl_state_begin_event("rndpass_pre_proc"); render->pre_proc(cam); Glitter::glt_particle_manager->CalcDisp(); + rctx_ptr->pre_proc(); gl_state_end_event(); } diff --git a/src/CRE/shader.cpp b/src/CRE/shader.cpp index d205e283..d31f76aa 100644 --- a/src/CRE/shader.cpp +++ b/src/CRE/shader.cpp @@ -86,6 +86,197 @@ int32_t shader::bind(shader_set_data* set, uint32_t sub_index) { return 0; } +static char* get_uniform_location(char* data, prj::vector_pair& samplers, + prj::vector_pair& uniforms, bool apple_fix) { + std::string temp; + temp.assign(data); + free_def(data); + + size_t version_pos = temp.find("#version 430 core"); + if (version_pos != -1) + if (GLAD_GL_VERSION_4_2) + temp.replace(version_pos, 17, "#version 420 core", 17); + else if (GLAD_GL_VERSION_4_1) + temp.replace(version_pos, 17, "#version 410 core", 17); + + if (apple_fix) { + size_t result_pos = temp.size() - 1; + while ((result_pos = temp.rfind("result_", result_pos)) != -1) + temp.replace(result_pos, 7, "frg_", 4); + } + + size_t binding_pos = 0; + size_t binding_end_pos = 0; + while ((binding_pos = temp.find("layout(set = 0, binding = ", binding_pos)) != -1 + && (binding_end_pos = temp.find(") uniform sampler", binding_pos)) != -1) { + std::string binding_str = temp.substr(binding_pos + 26, binding_end_pos - (binding_pos + 26)); + int32_t binding = atoi(binding_str.c_str()); + + bool sampler_2d = !temp.compare(binding_end_pos + 10, 9, "sampler2D"); + bool sampler_cube = !temp.compare(binding_end_pos + 10, 11, "samplerCube"); + if (GLAD_GL_VERSION_4_2) { + if (sampler_2d) { + char buf[0x40]; + sprintf_s(buf, sizeof(buf), "layout(binding = %d) uniform sampler2D", binding); + temp.replace(binding_pos, binding_end_pos + 19 - binding_pos, buf); + } + else if (sampler_cube) { + char buf[0x40]; + sprintf_s(buf, sizeof(buf), "layout(binding = %d) uniform samplerCube", binding); + temp.replace(binding_pos, binding_end_pos + 21 - binding_pos, buf); + } + } + else { + if (sampler_2d) { + size_t name_pos = binding_end_pos + 19; + while (isspace(temp.data()[name_pos])) + name_pos++; + + size_t name_end_pos = temp.find(';', name_pos); + if (name_end_pos != -1) { + while (isspace(temp.data()[name_end_pos - 1])) + name_end_pos--; + + std::string name_str = temp.substr(name_pos, name_end_pos - name_pos); + + bool found = false; + for (auto& i : samplers) + if (i.first == binding && i.second == name_str) { + found = true; + break; + } + + if (!found) + samplers.push_back(binding, name_str); + } + } + else if (sampler_cube) { + size_t name_pos = binding_end_pos + 21; + while (isspace(temp.data()[name_pos])) + name_pos++; + + size_t name_end_pos = temp.find(';', name_pos); + if (name_end_pos != -1) { + while (isspace(temp.data()[name_end_pos - 1])) + name_end_pos--; + + std::string name_str = temp.substr(name_pos, name_end_pos - name_pos); + + bool found = false; + for (auto& i : samplers) + if (i.first == binding && i.second == name_str) { + found = true; + break; + } + + if (!found) + samplers.push_back(binding, name_str); + } + } + + temp.erase(binding_pos, binding_end_pos + 2 - binding_pos); + } + } + + binding_pos = 0; + binding_end_pos = 0; + while ((binding_pos = temp.find("layout(set = 1, binding = ", binding_pos)) != -1 + && (binding_end_pos = temp.find(") uniform", binding_pos)) != -1) { + std::string binding_str = temp.substr(binding_pos + 26, binding_end_pos - (binding_pos + 26)); + int32_t binding = atoi(binding_str.c_str()); + + if (GLAD_GL_VERSION_4_2) { + char buf[0x40]; + sprintf_s(buf, sizeof(buf), "layout(binding = %d) uniform", binding); + temp.replace(binding_pos, binding_end_pos + 9 - binding_pos, buf); + } + else { + size_t name_pos = binding_end_pos + 9; + while (isspace(temp.data()[name_pos])) + name_pos++; + + size_t name_end_pos = temp.find('{', name_pos); + if (name_end_pos != -1) { + while (isspace(temp.data()[name_end_pos - 1])) + name_end_pos--; + + std::string name_str = temp.substr(name_pos, name_end_pos - name_pos); + + bool found = false; + for (auto& i : uniforms) + if (i.first == binding && i.second == name_str) { + found = true; + break; + } + + if (!found) + uniforms.push_back(binding, name_str); + } + + temp.erase(binding_pos, binding_end_pos + 2 - binding_pos); + } + } + + binding_pos = 0; + binding_end_pos = 0; + while ((binding_pos = temp.find("layout(std430, set = 2, binding = ", binding_pos)) != -1 + && (binding_end_pos = temp.find(") readonly buffer", binding_pos)) != -1) { + std::string binding_str = temp.substr(binding_pos + 34, binding_end_pos - (binding_pos + 34)); + int32_t binding = atoi(binding_str.c_str()) + 6; + + if (GLAD_GL_VERSION_4_2) { + char buf[0x40]; + sprintf_s(buf, sizeof(buf), "layout(binding = %d) uniform", binding); + temp.replace(binding_pos, binding_end_pos + 17 - binding_pos, buf); + } + else { + size_t name_pos = binding_end_pos + 17; + while (isspace(temp.data()[name_pos])) + name_pos++; + + size_t name_end_pos = temp.find('{', name_pos); + if (name_end_pos != -1) { + while (isspace(temp.data()[name_end_pos - 1])) + name_end_pos--; + + std::string name_str = temp.substr(name_pos, name_end_pos - name_pos); + + bool found = false; + for (auto& i : uniforms) + if (i.first == binding && i.second == name_str) { + found = true; + break; + } + + if (!found) + uniforms.push_back(binding, name_str); + } + + temp.replace(binding_pos, binding_end_pos + 17 - binding_pos, "uniform", 7); + } + } + + size_t in_pos = temp.size() - 1; + while ((in_pos = temp.rfind("in const", in_pos)) != -1) + temp.replace(in_pos, 8, "const", 5); + + size_t const_pos = temp.size() - 1; + size_t offsets_pos = temp.size() - 1; + while ((const_pos = temp.rfind("const ", const_pos)) != -1) { + offsets_pos = temp.find("offsets", const_pos); + if (offsets_pos == -1 || offsets_pos - const_pos > 20) + temp.erase(const_pos, 6); + else + const_pos--; + } + + size_t use_vertex_attrib_pos = temp.size() - 1; + while ((use_vertex_attrib_pos = temp.rfind("USE_VERTEX_ATTRIB", use_vertex_attrib_pos)) != -1) + temp.replace(use_vertex_attrib_pos, 17, "(1)", 3); + + return str_utils_copy(temp.c_str()); +} + static void parse_define_inner(std::string& temp, bool vulkan) { if (!vulkan) { size_t off = 0; @@ -716,6 +907,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*)glGetString(GL_VENDOR), "Apple"); + + if (strstr((const char*)glGetString(GL_VERSION), "Mesa")) + ignore_cache = true; + wcscat_s(temp_buf, sizeof(temp_buf) / sizeof(wchar_t), L"\\ReDIVA"); path_create_directory(temp_buf); @@ -844,6 +1040,14 @@ void shader_set_data::load(farc* f, bool ignore_cache, vert_data = shader::parse_include(vert_data, f); frag_data = shader::parse_include(frag_data, f); + + prj::vector_pair samplers; + prj::vector_pair uniforms; + if (!GLAD_GL_VERSION_4_3) { + vert_data = get_uniform_location(vert_data, samplers, uniforms, apple); + frag_data = get_uniform_location(frag_data, samplers, uniforms, apple); + } + uint64_t vert_data_hash = hash_utf8_xxh3_64bits(vert_data); uint64_t frag_data_hash = hash_utf8_xxh3_64bits(frag_data); @@ -939,6 +1143,30 @@ void shader_set_data::load(farc* f, bool ignore_cache, memcpy((void*)b->binary, (void*)((size_t)bin + bin->binary), bin->length); } + if (!GLAD_GL_VERSION_4_3) { + if (programs[k] && samplers.size()) { + GLuint program = programs[k]; + + gl_state_use_program(program); + for (auto& i : samplers) { + GLint loc = glGetUniformLocation(program, i.second.c_str()); + if (loc != -1) + glUniform1i(loc, i.first); + } + gl_state_use_program(0); + } + + if (programs[k] && uniforms.size()) { + GLuint program = programs[k]; + + for (auto& i : uniforms) { + GLuint loc = glGetUniformBlockIndex(program, i.second.c_str()); + if (loc != -1) + glUniformBlockBinding(program, loc, i.first); + } + } + } + if (!ignore_cache && bin) bin++; } @@ -980,6 +1208,30 @@ void shader_set_data::load(farc* f, bool ignore_cache, memcpy((void*)b->binary, (void*)((size_t)bin + bin->binary), bin->length); } + if (!GLAD_GL_VERSION_4_3) { + if (programs[0] && samplers.size()) { + GLuint program = programs[0]; + + gl_state_use_program(program); + for (auto& i : samplers) { + GLint loc = glGetUniformLocation(program, i.second.c_str()); + if (loc != -1) + glUniform1i(loc, i.first); + } + gl_state_use_program(0); + } + + if (programs[0] && uniforms.size()) { + GLuint program = programs[0]; + + for (auto& i : uniforms) { + GLint loc = glGetUniformBlockIndex(program, i.second.c_str()); + if (loc != -1) + glUniformBlockBinding(program, loc, i.first); + } + } + } + if (!ignore_cache && bin) bin++; } diff --git a/src/CRE/static_var.cpp b/src/CRE/static_var.cpp index ecde4626..bb96903a 100644 --- a/src/CRE/static_var.cpp +++ b/src/CRE/static_var.cpp @@ -8,8 +8,9 @@ int32_t sv_max_texture_size = 2048; int32_t sv_max_texture_max_anisotropy = 1; int32_t sv_max_uniform_buffer_size = 0x10000; -int32_t sv_min_uniform_buffer_alignment = 0x40; -int32_t sv_min_storage_buffer_alignment = 0x40; +int32_t sv_max_storage_buffer_size = 0x8000000; +int32_t sv_min_uniform_buffer_alignment = 0x100; +int32_t sv_min_storage_buffer_alignment = 0x100; bool sv_anisotropy_changed = false; int32_t sv_old_anisotropy = 1; @@ -17,6 +18,8 @@ int32_t sv_anisotropy = 1; bool sv_better_reflect = false; +bool sv_shared_storage_uniform_buffer = true; + int32_t uniform_value[U_MAX]; const vec3 sv_rgb_to_luma = { diff --git a/src/CRE/static_var.hpp b/src/CRE/static_var.hpp index f74f0a9b..ce5a9f95 100644 --- a/src/CRE/static_var.hpp +++ b/src/CRE/static_var.hpp @@ -100,6 +100,7 @@ enum uniform_name { extern int32_t sv_max_texture_size; extern int32_t sv_max_texture_max_anisotropy; extern int32_t sv_max_uniform_buffer_size; +extern int32_t sv_max_storage_buffer_size; extern int32_t sv_min_uniform_buffer_alignment; extern int32_t sv_min_storage_buffer_alignment; @@ -108,6 +109,8 @@ extern int32_t sv_anisotropy; extern bool sv_better_reflect; +extern bool sv_shared_storage_uniform_buffer; + extern int32_t uniform_value[U_MAX]; extern const vec3 sv_rgb_to_luma; diff --git a/src/ReDIVA/app.cpp b/src/ReDIVA/app.cpp index 479d27d3..4df22993 100644 --- a/src/ReDIVA/app.cpp +++ b/src/ReDIVA/app.cpp @@ -415,6 +415,7 @@ int32_t app_main(const app_init_struct& ais) { sv_max_texture_size = supported_limits.maxImageDimension2D; sv_max_texture_max_anisotropy = (int32_t)supported_limits.maxSamplerAnisotropy; sv_max_uniform_buffer_size = (int32_t)supported_limits.maxUniformBufferRange; + sv_max_storage_buffer_size = (int32_t)supported_limits.maxStorageBufferRange; sv_min_uniform_buffer_alignment = (int32_t)supported_limits.minUniformBufferOffsetAlignment; sv_min_storage_buffer_alignment = (int32_t)supported_limits.minStorageBufferOffsetAlignment; } @@ -429,8 +430,11 @@ int32_t app_main(const app_init_struct& ais) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &sv_max_texture_size); glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &sv_max_texture_max_anisotropy); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &sv_max_uniform_buffer_size); + if (GLAD_GL_VERSION_4_3) + glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &sv_max_storage_buffer_size); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &sv_min_uniform_buffer_alignment); - glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &sv_min_storage_buffer_alignment); + if (GLAD_GL_VERSION_4_3) + glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &sv_min_storage_buffer_alignment); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); } @@ -2252,15 +2256,6 @@ static int32_t app_end_present_vulkan() { } static void app_recreate_swapchain() { - int32_t width = 0; - int32_t height = 0; - glfwGetFramebufferSize(window, &width, &height); - - while (width == 0 || height == 0) { - glfwWaitEvents(); - glfwGetFramebufferSize(window, &width, &height); - } - vkDeviceWaitIdle(vulkan_device); for (Vulkan::Framebuffer& i : vulkan_swapchain_framebuffers)