From 3e9f331c79557ed70ef883592d8e9e825a83d924 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Sun, 13 Apr 2025 19:19:21 +0300 Subject: [PATCH] Added support for OpenGL 4.1 and 4.2 --- res/ft_shaders.farc | Bin 98304 -> 98960 bytes src/DivaGL/GL/shader_storage_buffer.cpp | 10 +- src/DivaGL/effect.cpp | 317 ++++++++++++++++++------ src/DivaGL/gl_state.cpp | 21 +- src/DivaGL/hook.cpp | 36 +-- src/DivaGL/mdl/draw_object.cpp | 6 +- src/DivaGL/render_context.cpp | 15 +- src/DivaGL/render_context.hpp | 1 + src/DivaGL/renderer/dof.cpp | 11 +- src/DivaGL/renderer/transparency.cpp | 26 +- src/DivaGL/shader.cpp | 256 ++++++++++++++++++- src/DivaGL/wrap.cpp | 47 +++- src/DivaGL/wrap.hpp | 6 + 13 files changed, 634 insertions(+), 118 deletions(-) diff --git a/res/ft_shaders.farc b/res/ft_shaders.farc index b462eb8f80abaa5463c81b4bed6d6dd3456b3c04..2e74de223a00f35cffc28640fc4a298108f50043 100644 GIT binary patch delta 7075 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 fog_ring_ssbo; +struct EffectStorageAttrib { + uint32_t index; + uint32_t size; + size_t offset; +}; + +struct EffectStorage { + GLuint vao; + GL::ArrayBuffer vbo; + GL::ShaderStorageBuffer ssbo; + + EffectStorage() : vao() { + + } + + void Bind(int32_t index, bool force = false) { + if (GL_VERSION_4_3) + ssbo.Bind(index, force); + else + gl_state_bind_vertex_array(vao); + } + + void Create(size_t size, size_t count, const EffectStorageAttrib* attribs) { + if (GL_VERSION_4_3) { + ssbo.Create(size * count); + return; + } + else if (vao || !attribs) + return; + + glGenVertexArrays(1, &vao); + gl_state_bind_vertex_array(vao, true); + + vbo.Create(size * count); + vbo.Bind(true); + + const EffectStorageAttrib* attrib = attribs; + while (attrib->index != -1) { + glEnableVertexAttribArray(attrib->index); + glVertexAttribPointer((GLuint)attrib->index, (GLint)(attrib->size / sizeof(float_t)), + GL_FLOAT, GL_FALSE, (GLsizei)size, (void*)attrib->offset); + glVertexAttribDivisor(attrib->index, 1); + attrib++; + } + + gl_state_bind_array_buffer(0); + gl_state_bind_vertex_array(0); + } + + void Create(size_t size, size_t count, const EffectStorageAttrib* attribs, + const void* data, bool dynamic = false) { + if (GL_VERSION_4_3) { + ssbo.Create(size * count, data, dynamic); + return; + } + else if (vao || !attribs) + return; + + glGenVertexArrays(1, &vao); + gl_state_bind_vertex_array(vao, true); + + vbo.Create(size * count, data, true); + vbo.Bind(true); + + const EffectStorageAttrib* attrib = attribs; + while (attrib->index != -1) { + glEnableVertexAttribArray(attrib->index); + glVertexAttribPointer((GLuint)attrib->index, (GLint)(attrib->size / sizeof(float_t)), + GL_FLOAT, GL_FALSE, (GLsizei)size, (void*)attrib->offset); + glVertexAttribDivisor(attrib->index, 1); + attrib++; + } + + gl_state_bind_array_buffer(0); + gl_state_bind_vertex_array(0); + } + + void Destroy() { + if (GL_VERSION_4_3) { + ssbo.Destroy(); + return; + } + + if (vao) { + glDeleteVertexArrays(1, &vao); + vao = 0; + } + + vbo.Destroy(); + } + + void Draw(GLenum mode, GLint first, GLsizei count) { + if (GL_VERSION_4_3) + glDrawArraysDLL(mode, first, count); + else + glDrawArraysInstanced(mode, first, 6, count / 6); + } + + void* MapMemory() { + if (GL_VERSION_4_3) + return ssbo.MapMemory(); + else + return vbo.MapMemory(); + } + + void UnmapMemory() { + if (GL_VERSION_4_3) + ssbo.UnmapMemory(); + else + vbo.UnmapMemory(); + } + + void WriteMemory(size_t offset, size_t size, const void* data) { + if (GL_VERSION_4_3) + ssbo.WriteMemory(offset, size, data); + else + vbo.WriteMemory(offset, size, data); + } +}; + +static prj::vector_pair fog_ring_storage; static GLuint leaf_ptcl_vao; static GL::ArrayBuffer leaf_ptcl_vbo; @@ -432,7 +552,7 @@ static GL::ArrayBuffer ptcl_vbo; static GL::UniformBuffer particle_scene_ubo; static const size_t ptcl_count = 0x400; -static GL::ShaderStorageBuffer rain_ssbo; +static EffectStorage rain_storage; static GL::UniformBuffer rain_particle_scene_ubo; static GL::UniformBuffer rain_particle_batch_ubo; static const size_t rain_ptcl_count = 0x8000; @@ -440,26 +560,26 @@ static const size_t rain_ptcl_count = 0x8000; static GL::UniformBuffer ripple_batch_ubo; static GL::UniformBuffer ripple_scene_ubo; -static GL::ShaderStorageBuffer ripple_emit_ssbo; +static EffectStorage ripple_emit_storage; static GL::UniformBuffer ripple_emit_scene_ubo; static const size_t ripple_emit_count = 5000; -static GL::ShaderStorageBuffer snow_ssbo; -static GL::ShaderStorageBuffer snow_gpu_ssbo; -static GL::ShaderStorageBuffer snow_fallen_ssbo; +static EffectStorage snow_storage; +static EffectStorage snow_gpu_storage; +static EffectStorage snow_fallen_storage; static GL::UniformBuffer snow_particle_scene_ubo; static GL::UniformBuffer snow_particle_batch_ubo; static const size_t snow_ptcl_count = 0x8000; static const size_t snow_ptcl_fallen_count = 0x2000; -static GL::ShaderStorageBuffer stars_ssbo; +static EffectStorage stars_storage; static GL::UniformBuffer stars_scene_ubo; static GL::UniformBuffer stars_batch_ubo; static int32_t star_count; static int32_t star_b_count; static GLuint star_sampler; -static prj::vector_pair water_particle_ssbo; +static prj::vector_pair water_particle_storage; static GL::UniformBuffer water_particle_scene_ubo; static float_t& snow_particle_delta_frame = *(float_t*)0x0000000140C9A4E0; @@ -617,10 +737,10 @@ void rain_particle_draw() { vec4 color = rain->color; float_t color_a = color.w; + gl_state_bind_vertex_array(rctx->common_vao); rain_particle_scene_ubo.Bind(0); rain_particle_batch_ubo.Bind(1); - rain_ssbo.Bind(0); - gl_state_bind_vertex_array(rctx->common_vao); + rain_storage.Bind(0); for (int32_t i = 0; i < 8; i++, first += count) { particle_data& data = rain_ptcl_data[i]; vec3 pos_offset = *(vec3*)&data.position / range; @@ -632,7 +752,7 @@ void rain_particle_draw() { batch_shader_data.g_tangent = { tangent.x, tangent.y, tangent.z, tangent_sign }; batch_shader_data.g_color = color; rain_particle_batch_ubo.WriteMemory(batch_shader_data); - shaders_ft.draw_arrays(GL_TRIANGLES, first, count); + rain_storage.Draw(GL_TRIANGLES, first, count); } gl_state_bind_vertex_array(0); gl_state_active_bind_texture_2d(0, 0); @@ -732,11 +852,11 @@ void snow_particle_draw() { snow_particle_scene_ubo.Bind(0); snow_particle_batch_ubo.Bind(1); - snow_ssbo.Bind(0); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, snow->num_snow * 6); + snow_storage.Bind(0); + snow_storage.Draw(GL_TRIANGLES, 0, snow->num_snow * 6); - snow_fallen_ssbo.Bind(0); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, (GLsizei)(snow_ptcl_fallen_count * 6)); + snow_fallen_storage.Bind(0); + snow_fallen_storage.Draw(GL_TRIANGLES, 0, (GLsizei)(snow_ptcl_fallen_count * 6)); uniform->arr[U_SNOW_PARTICLE] = 1; shaders_ft.set(SHADER_FT_SNOW_PT); @@ -749,7 +869,7 @@ void snow_particle_draw() { snow_scene.g_state_point_attenuation = { 0.0f, 0.0f, point_attenuation, 0.0f }; snow_particle_scene_ubo.WriteMemory(snow_scene); - snow_gpu_ssbo.Bind(0); + snow_gpu_storage.Bind(0); int32_t count = snow->num_snow_gpu / 4; count = min_def(count, (int32_t)snow_ptcl_count / 4) * 6; @@ -767,7 +887,7 @@ void snow_particle_draw() { snow_batch.start_vertex_location.x = first; snow_particle_batch_ubo.WriteMemory(snow_batch); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, count); + snow_gpu_storage.Draw(GL_TRIANGLES, first, count); first += count; } @@ -797,11 +917,11 @@ HOOK(void, FASTCALL, TaskEffectAuth3D__SetEnable, 0x0000000140345B30, size_t Thi } HOOK(void, FASTCALL, EffectFogRing__dest, 0x0000000140348090, EffectFogRing* fog_ring) { - auto elem = fog_ring_ssbo.find(fog_ring); - if (elem != fog_ring_ssbo.end()) { + auto elem = fog_ring_storage.find(fog_ring); + if (elem != fog_ring_storage.end()) { elem->second.Destroy(); - fog_ring_ssbo.erase(elem); - fog_ring_ssbo.sort(); + fog_ring_storage.erase(elem); + fog_ring_storage.sort(); } originalEffectFogRing__dest(fog_ring); @@ -817,23 +937,30 @@ HOOK(void, FASTCALL, EffectFogRing__set_stage_indices, 0x0000000140348790, EffectFogRing* fog_ring, prj::vector* stage_indices) { originalEffectFogRing__set_stage_indices(fog_ring, stage_indices); - auto elem = fog_ring_ssbo.find(fog_ring); - if (elem == fog_ring_ssbo.end()) { - fog_ring_ssbo.push_back({ fog_ring, {} }); - fog_ring_ssbo.sort(); - elem = fog_ring_ssbo.find(fog_ring); + auto elem = fog_ring_storage.find(fog_ring); + if (elem == fog_ring_storage.end()) { + fog_ring_storage.push_back({ fog_ring, {} }); + fog_ring_storage.sort(); + elem = fog_ring_storage.find(fog_ring); } else elem->second.Destroy(); - elem->second.Create(sizeof(fog_ring_vertex_data) * fog_ring->max_ptcls); + + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(fog_ring_vertex_data::position), offsetof(fog_ring_vertex_data, position), }, + { 1, sizeof(fog_ring_vertex_data::color ), offsetof(fog_ring_vertex_data, color ), }, + { 2, sizeof(fog_ring_vertex_data::size ), offsetof(fog_ring_vertex_data, size ), }, + { (uint32_t)-1 }, + }; + elem->second.Create(sizeof(fog_ring_vertex_data), fog_ring->max_ptcls, attribs); } HOOK(void, FASTCALL, EffectFogRing__calc_vert, 0x000000001403495B0, EffectFogRing* fog_ring) { - auto elem = fog_ring_ssbo.find(fog_ring); - if (elem == fog_ring_ssbo.end()) + auto elem = fog_ring_storage.find(fog_ring); + if (elem == fog_ring_storage.end()) return; - GL::ShaderStorageBuffer& ssbo = elem->second; + EffectStorage& storage = elem->second; float_t density = fog_ring->density; fog_ring_data* ptcl_data = fog_ring->ptcl_data; @@ -857,7 +984,7 @@ HOOK(void, FASTCALL, EffectFogRing__calc_vert, 0x000000001403495B0, EffectFogRin ptcl_vtx_data->size = size; } - ssbo.UnmapMemory(); + storage.UnmapMemory(); fog_ring->num_vtx = (int32_t)(fog_ring->num_ptcls * 6LL); } @@ -1063,7 +1190,11 @@ HOOK(void, FASTCALL, rain_particle_init, 0x00000001403546A0, bool change_stage) vtx_data -= rain_ptcl_count; - rain_ssbo.Create(sizeof(vec3) * rain_ptcl_count, vtx_data); + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(vec3), 0, }, + { (uint32_t)-1 }, + }; + rain_storage.Create(sizeof(vec3), rain_ptcl_count, attribs, vtx_data); free_def(vtx_data); @@ -1193,7 +1324,7 @@ HOOK(void, FASTCALL, snow_particle_ctrl, 0x000000014035CA20) { snow_particle_data_kill_fallen(snow_ptcl_fallen, true); } - snow_particle_vertex_data* vtx_data = (snow_particle_vertex_data*)snow_ssbo.MapMemory(); + snow_particle_vertex_data* vtx_data = (snow_particle_vertex_data*)snow_storage.MapMemory(); if (vtx_data) { particle_data* snow_ptcl = snow_ptcl_data; for (int32_t i = snow->num_snow; i; i--, snow_ptcl++, vtx_data++) { @@ -1202,9 +1333,9 @@ HOOK(void, FASTCALL, snow_particle_ctrl, 0x000000014035CA20) { vtx_data->alpha = snow_ptcl->alpha; } } - snow_ssbo.UnmapMemory(); + snow_storage.UnmapMemory(); - snow_particle_vertex_data* fallen_vtx_data = (snow_particle_vertex_data*)snow_fallen_ssbo.MapMemory(); + snow_particle_vertex_data* fallen_vtx_data = (snow_particle_vertex_data*)snow_fallen_storage.MapMemory(); if (fallen_vtx_data) { particle_data* snow_ptcl_fallen = snow_ptcl_fallen_data; for (size_t i = snow_ptcl_fallen_count; i; i--, snow_ptcl_fallen++, fallen_vtx_data++) { @@ -1213,7 +1344,7 @@ HOOK(void, FASTCALL, snow_particle_ctrl, 0x000000014035CA20) { fallen_vtx_data->alpha = snow_ptcl_fallen->alpha; } } - snow_fallen_ssbo.UnmapMemory(); + snow_fallen_storage.UnmapMemory(); } HOOK(void, FASTCALL, snow_particle_init, 0x000000014035DD30, bool change_stage) { @@ -1292,15 +1423,28 @@ HOOK(void, FASTCALL, snow_particle_init, 0x000000014035DD30, bool change_stage) j.direction = 0.0f; } + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(snow_particle_vertex_data::position), offsetof(snow_particle_vertex_data, position), }, + { 1, sizeof(snow_particle_vertex_data::size ), offsetof(snow_particle_vertex_data, size ), }, + { 2, sizeof(snow_particle_vertex_data::alpha ), offsetof(snow_particle_vertex_data, alpha ), }, + { (uint32_t)-1 }, + }; + + static const EffectStorageAttrib gpu_attribs[] = { + { 0, sizeof(snow_particle_gpu_vertex_data::position), offsetof(snow_particle_gpu_vertex_data, position), }, + { 1, sizeof(snow_particle_gpu_vertex_data::size ), offsetof(snow_particle_gpu_vertex_data, size ), }, + { (uint32_t)-1 }, + }; + if (change_stage) { - snow_ssbo.Destroy(); - snow_ssbo.Create(sizeof(snow_particle_vertex_data) * snow->num_snow); + snow_storage.Destroy(); + snow_storage.Create(sizeof(snow_particle_vertex_data), snow->num_snow, attribs); return; } snow_particle_free(); - snow_ssbo.Create(sizeof(snow_particle_vertex_data) * snow->num_snow); + snow_storage.Create(sizeof(snow_particle_vertex_data), snow->num_snow, attribs); snow_particle_gpu_vertex_data* vtx_data = force_malloc(snow_ptcl_count); @@ -1313,22 +1457,22 @@ HOOK(void, FASTCALL, snow_particle_init, 0x000000014035DD30, bool change_stage) vtx_data -= snow_ptcl_count; - snow_gpu_ssbo.Create(sizeof(snow_particle_gpu_vertex_data) * snow_ptcl_count, vtx_data); + snow_gpu_storage.Create(sizeof(snow_particle_gpu_vertex_data), snow_ptcl_count, gpu_attribs, vtx_data); free_def(vtx_data); - snow_fallen_ssbo.Create(sizeof(snow_particle_vertex_data) * snow_ptcl_fallen_count); + snow_fallen_storage.Create(sizeof(snow_particle_vertex_data), snow_ptcl_fallen_count, attribs); snow_particle_scene_ubo.Create(sizeof(snow_particle_scene_shader_data)); snow_particle_batch_ubo.Create(sizeof(snow_particle_batch_shader_data)); } HOOK(void, FASTCALL, water_particle__free, 0x0000000140363F00, water_particle* water_ptcl) { - auto elem = water_particle_ssbo.find(water_ptcl); - if (elem != water_particle_ssbo.end()) { + auto elem = water_particle_storage.find(water_ptcl); + if (elem != water_particle_storage.end()) { elem->second.Destroy(); - water_particle_ssbo.erase(elem); - water_particle_ssbo.sort(); + water_particle_storage.erase(elem); + water_particle_storage.sort(); } originalwater_particle__free(water_ptcl); @@ -1359,15 +1503,22 @@ HOOK(void, FASTCALL, water_particle__set, 0x0000000140364F20, water_particle* water_ptcl, splash_particle* splash, int32_t splash_tex_id) { originalwater_particle__set(water_ptcl, splash, splash_tex_id); - auto elem = water_particle_ssbo.find(water_ptcl); - if (elem == water_particle_ssbo.end()) { - water_particle_ssbo.push_back({ water_ptcl, {} }); - water_particle_ssbo.sort(); - elem = water_particle_ssbo.find(water_ptcl); + auto elem = water_particle_storage.find(water_ptcl); + if (elem == water_particle_storage.end()) { + water_particle_storage.push_back({ water_ptcl, {} }); + water_particle_storage.sort(); + elem = water_particle_storage.find(water_ptcl); } else elem->second.Destroy(); - elem->second.Create(sizeof(water_particle_vertex_data) * water_ptcl->splash_count); + + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(water_particle_vertex_data::position), offsetof(water_particle_vertex_data, position), }, + { 1, sizeof(water_particle_vertex_data::size ), offsetof(water_particle_vertex_data, size ), }, + { 2, sizeof(water_particle_vertex_data::color ), offsetof(water_particle_vertex_data, color ), }, + { (uint32_t)-1 }, + }; + elem->second.Create(sizeof(water_particle_vertex_data), water_ptcl->splash_count, attribs); } HOOK(bool, FASTCALL, TaskEffectSplash__init, 0x00000001403655A0, size_t task_effect_splash) { @@ -1832,14 +1983,14 @@ void star_catalog::draw() { stars_scene_ubo.Bind(0); stars_batch_ubo.Bind(1); - stars_ssbo.Bind(0); + stars_storage.Bind(0); if (i) { gl_state_active_bind_texture_2d(0, star_b_tex->glid); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, star_b_count * 6); + stars_storage.Draw(GL_TRIANGLES, 0, star_b_count * 6); } else { gl_state_active_bind_texture_2d(0, star_tex->glid); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, star_count * 6); + stars_storage.Draw(GL_TRIANGLES, 0, star_count * 6); } } gl_state_active_bind_texture_2d(0, 0); @@ -1848,7 +1999,7 @@ void star_catalog::draw() { } void star_catalog::free() { - stars_ssbo.Destroy(); + stars_storage.Destroy(); stars_batch_ubo.Destroy(); stars_scene_ubo.Destroy(); @@ -1924,7 +2075,13 @@ bool star_catalog::init() { star_count = (int32_t)vec.size(); - stars_ssbo.Create(sizeof(stars_buffer_data) * vec.size(), vec.data()); + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(stars_buffer_data::position), offsetof(stars_buffer_data, position), }, + { 1, sizeof(stars_buffer_data::size ), offsetof(stars_buffer_data, size ), }, + { 2, sizeof(stars_buffer_data::color ), offsetof(stars_buffer_data, color ), }, + { (uint32_t)-1 }, + }; + stars_storage.Create(sizeof(stars_buffer_data), vec.size(), attribs, vec.data()); } milky_way.create_default_sphere(); @@ -1938,13 +2095,13 @@ void water_particle::draw(mat4* mat) { if (count <= 0) return; - auto elem = water_particle_ssbo.find(this); - if (elem == water_particle_ssbo.end()) + auto elem = water_particle_storage.find(this); + if (elem == water_particle_storage.end()) return; - GL::ShaderStorageBuffer& ssbo = elem->second; + EffectStorage& storage = elem->second; - water_particle_vertex_data* vtx_data = (water_particle_vertex_data*)ssbo.MapMemory(); + water_particle_vertex_data* vtx_data = (water_particle_vertex_data*)storage.MapMemory(); if (!vtx_data) return; @@ -1954,7 +2111,7 @@ void water_particle::draw(mat4* mat) { vtx_data->color = ptcl_data->color; vtx_data->size = ptcl_data->size; } - ssbo.UnmapMemory(); + storage.UnmapMemory(); water_particle_scene_shader_data scene_shader_data = {}; mat4 temp; @@ -1981,11 +2138,11 @@ void water_particle::draw(mat4* mat) { gl_state_bind_vertex_array(rctx->common_vao); water_particle_scene_ubo.Bind(0); - ssbo.Bind(0); + storage.Bind(0); texture* tex = texture_manager_get_texture(splash_tex_id); if (tex) gl_state_active_bind_texture_2d(0, tex->glid); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, count * 6); + storage.Draw(GL_TRIANGLES, 0, count * 6); gl_state_bind_vertex_array(0); shader::unbind(); @@ -2019,11 +2176,11 @@ static void draw_fog_particle(EffectFogRing* data, mat4* mat) { if (!data->num_vtx) return; - auto elem = fog_ring_ssbo.find(data); - if (elem == fog_ring_ssbo.end()) + auto elem = fog_ring_storage.find(data); + if (elem == fog_ring_storage.end()) return; - GL::ShaderStorageBuffer& ssbo = elem->second; + EffectStorage& storage = elem->second; shaders_ft.set(SHADER_FT_FOGPTCL); gl_state_enable_blend(); @@ -2031,8 +2188,8 @@ static void draw_fog_particle(EffectFogRing* data, mat4* mat) { if (tex) gl_state_active_bind_texture_2d(0, tex->glid); gl_state_bind_vertex_array(rctx->common_vao); - ssbo.Bind(0); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, data->num_vtx); + storage.Bind(0); + storage.Draw(GL_TRIANGLES, 0, data->num_vtx); gl_state_bind_vertex_array(0); gl_state_disable_blend(); shader::unbind(); @@ -2042,7 +2199,7 @@ static void draw_ripple_particles(ripple_struct* data, mat4* mat) { if (data->count > 5000) return; - vec3* vtx_data = (vec3*)ripple_emit_ssbo.MapMemory(); + vec3* vtx_data = (vec3*)ripple_emit_storage.MapMemory(); if (!vtx_data) return; @@ -2052,7 +2209,7 @@ static void draw_ripple_particles(ripple_struct* data, mat4* mat) { for (size_t i = data->count; i; i--, vtx_data++, position++, color++) *vtx_data = { position->x, -position->z, (float_t)color->a * (float_t)(1.0 / 255.0) }; - ripple_emit_ssbo.UnmapMemory(); + ripple_emit_storage.UnmapMemory(); int32_t size = (int32_t)(data->size + 0.5f); @@ -2086,8 +2243,8 @@ static void draw_ripple_particles(ripple_struct* data, mat4* mat) { shaders_ft.set(SHADER_FT_RIPEMIT); ripple_emit_scene_ubo.Bind(0); - ripple_emit_ssbo.Bind(0); - shaders_ft.draw_arrays(GL_TRIANGLES, 0, data->count * 6); + ripple_emit_storage.Bind(0); + ripple_emit_storage.Draw(GL_TRIANGLES, 0, data->count * 6); shader::unbind(); @@ -2267,7 +2424,7 @@ static int32_t particle_disp(particle_vertex_data* vtx_data, particle_rot_data* } static void rain_particle_free() { - rain_ssbo.Destroy(); + rain_storage.Destroy(); rain_particle_scene_ubo.Destroy(); rain_particle_batch_ubo.Destroy(); @@ -2277,7 +2434,11 @@ static void ripple_emit_init() { ripple_batch_ubo.Create(sizeof(ripple_batch_shader_data)); ripple_scene_ubo.Create(sizeof(ripple_scene_shader_data)); - ripple_emit_ssbo.Create(sizeof(vec3) * ripple_emit_count); + static const EffectStorageAttrib attribs[] = { + { 0, sizeof(vec3), 0, }, + { (uint32_t)-1 }, + }; + ripple_emit_storage.Create(sizeof(vec3), ripple_emit_count, attribs); ripple_emit_scene_ubo.Create(sizeof(ripple_emit_scene_shader_data)); } @@ -2286,7 +2447,7 @@ static void ripple_emit_free() { ripple_batch_ubo.Destroy(); ripple_scene_ubo.Destroy(); - ripple_emit_ssbo.Destroy(); + ripple_emit_storage.Destroy(); ripple_emit_scene_ubo.Destroy(); } @@ -2360,9 +2521,9 @@ static vec3 snow_particle_get_random_velocity() { } static void snow_particle_free() { - snow_ssbo.Destroy(); - snow_gpu_ssbo.Destroy(); - snow_fallen_ssbo.Destroy(); + snow_storage.Destroy(); + snow_gpu_storage.Destroy(); + snow_fallen_storage.Destroy(); snow_particle_scene_ubo.Destroy(); snow_particle_batch_ubo.Destroy(); diff --git a/src/DivaGL/gl_state.cpp b/src/DivaGL/gl_state.cpp index 7ec20c6..d5612d3 100644 --- a/src/DivaGL/gl_state.cpp +++ b/src/DivaGL/gl_state.cpp @@ -117,6 +117,9 @@ void gl_state_bind_uniform_buffer_range(GLuint index, } void gl_state_bind_shader_storage_buffer(GLuint buffer, bool force) { + if (!GL_VERSION_4_3) + return; + if (force || gl_state.shader_storage_buffer_binding != buffer) { glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); gl_state.shader_storage_buffer_binding = buffer; @@ -124,6 +127,9 @@ void gl_state_bind_shader_storage_buffer(GLuint buffer, bool force) { } void gl_state_bind_shader_storage_buffer_base(GLuint index, GLuint buffer, bool force) { + if (!GL_VERSION_4_3) + return; + if (force || gl_state.shader_storage_buffer_bindings[index] != buffer) { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer); shader_storage_buffer_binding = buffer; @@ -135,6 +141,9 @@ void gl_state_bind_shader_storage_buffer_base(GLuint index, GLuint buffer, bool void gl_state_bind_shader_storage_buffer_range(GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, bool force) { + if (!GL_VERSION_4_3) + return; + if (force || gl_state.shader_storage_buffer_bindings[index] != buffer || gl_state.shader_storage_buffer_offsets[index] != offset || gl_state.shader_storage_buffer_sizes[index] != size) { @@ -327,11 +336,13 @@ void gl_state_get() { glGetIntegeri_v(GL_UNIFORM_BUFFER_SIZE, i, (GLint*)&gl_state.uniform_buffer_sizes[i]); } - glGetIntegervDLL(GL_SHADER_STORAGE_BUFFER_BINDING, (GLint*)&gl_state.shader_storage_buffer_binding); - for (GLuint i = 0; i < 14; i++) { - glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, i, (GLint*)&gl_state.shader_storage_buffer_bindings[i]); - glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_START, i, (GLint*)&gl_state.shader_storage_buffer_offsets[i]); - glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_SIZE, i, (GLint*)&gl_state.shader_storage_buffer_sizes[i]); + if (GL_VERSION_4_3) { + glGetIntegervDLL(GL_SHADER_STORAGE_BUFFER_BINDING, (GLint*)&gl_state.shader_storage_buffer_binding); + for (GLuint i = 0; i < 14; i++) { + glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, i, (GLint*)&gl_state.shader_storage_buffer_bindings[i]); + glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_START, i, (GLint*)&gl_state.shader_storage_buffer_offsets[i]); + glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_SIZE, i, (GLint*)&gl_state.shader_storage_buffer_sizes[i]); + } } glGetBooleanvDLL(GL_COLOR_WRITEMASK, gl_state.color_mask); diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp index bd54d16..f9e08f9 100644 --- a/src/DivaGL/hook.cpp +++ b/src/DivaGL/hook.cpp @@ -34,21 +34,23 @@ static void APIENTRY gl_debug_output(GLenum source, GLenum type, uint32_t id, HOOK(int32_t, FASTCALL, data_init, 0x0000000140192FF0) { #ifdef DEBUG - typedef void (APIENTRY* GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, - GLenum severity, GLsizei length, const GLchar* message, const void* userParam); + if (GL_VERSION_4_3) { + typedef void (APIENTRY* GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, + GLenum severity, GLsizei length, const GLchar* message, const void* userParam); - typedef void (GLAPIENTRY* PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void* userParam); - PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback - = (PFNGLDEBUGMESSAGECALLBACKPROC)wglGetProcAddressDLL("glDebugMessageCallback"); - typedef void (GLAPIENTRY* PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, - GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); - PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl - = (PFNGLDEBUGMESSAGECONTROLPROC)wglGetProcAddressDLL("glDebugMessageControl"); + typedef void (GLAPIENTRY* PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void* userParam); + PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback + = (PFNGLDEBUGMESSAGECALLBACKPROC)wglGetProcAddressDLL("glDebugMessageCallback"); + typedef void (GLAPIENTRY* PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, + GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); + PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl + = (PFNGLDEBUGMESSAGECONTROLPROC)wglGetProcAddressDLL("glDebugMessageControl"); - glEnableDLL(GL_DEBUG_OUTPUT); - glEnableDLL(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallback(gl_debug_output, 0); - glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); + glEnableDLL(GL_DEBUG_OUTPUT); + glEnableDLL(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(gl_debug_output, 0); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); + } #endif #ifdef USE_STUB @@ -254,7 +256,7 @@ HOOK(void, FASTCALL, set_render_defaults, 0x00000001401948B0) { } HOOK(GLenum, FASTCALL, gl_check_framebuffer_status, 0x0000000140503240) { - GLenum ret = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + GLenum ret = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (ret != GL_FRAMEBUFFER_COMPLETE) return ret; @@ -334,13 +336,15 @@ static HGLRC FASTCALL glut_create_context(int64_t a1, int64_t a2, int64_t a3, in int32_t minor = 6; HGLRC ctx = 0; - while (!ctx || minor < 3) { + while (!ctx && minor >= 1) { const int32_t attrib_list[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, minor, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, #ifdef DEBUG - WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, +#else + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, #endif 0, }; diff --git a/src/DivaGL/mdl/draw_object.cpp b/src/DivaGL/mdl/draw_object.cpp index e846f6d..97a0809 100644 --- a/src/DivaGL/mdl/draw_object.cpp +++ b/src/DivaGL/mdl/draw_object.cpp @@ -193,7 +193,11 @@ namespace mdl { g_joint_transforms[2] = mat.row2; } - rctx->data.buffer_skinning.WriteMemory(rctx->data.buffer_skinning_data); + 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 d3193a1..9829189 100644 --- a/src/DivaGL/render_context.cpp +++ b/src/DivaGL/render_context.cpp @@ -258,7 +258,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 (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); @@ -269,7 +272,10 @@ void render_data::init() { } void render_data::free() { - buffer_skinning.Destroy(); + if (GL_VERSION_4_3) + buffer_skinning.Destroy(); + else + buffer_skinning_ubo.Destroy(); buffer_batch.Destroy(); buffer_scene.Destroy(); buffer_shader.Destroy(); @@ -340,7 +346,10 @@ void render_data::set(render_context* rctx) { buffer_batch.Bind(2); if (uniform->arr[U_SKINNING]) - buffer_skinning.Bind(0); + if (GL_VERSION_4_3) + buffer_skinning.Bind(0); + else + buffer_skinning_ubo.Bind(6); } void render_data::set_shader(uint32_t index) { diff --git a/src/DivaGL/render_context.hpp b/src/DivaGL/render_context.hpp index b78f25b..f125346 100644 --- a/src/DivaGL/render_context.hpp +++ b/src/DivaGL/render_context.hpp @@ -384,6 +384,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(); diff --git a/src/DivaGL/renderer/dof.cpp b/src/DivaGL/renderer/dof.cpp index 9a49648..940846c 100644 --- a/src/DivaGL/renderer/dof.cpp +++ b/src/DivaGL/renderer/dof.cpp @@ -283,9 +283,14 @@ namespace renderer { gl_state_bind_sampler(4, samplers[1]); glDrawArraysDLL(GL_TRIANGLE_STRIP, 0, 4); - glCopyImageSubData( - buf_rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, - rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1); + if (GL_VERSION_4_3) + glCopyImageSubData( + buf_rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, + rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1); + else + fbo_blit(buf_rt->fbos[0], rt->fbos[0], + 0, 0, width, height, + 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); gl_state_end_event(); } diff --git a/src/DivaGL/renderer/transparency.cpp b/src/DivaGL/renderer/transparency.cpp index b4e07d5..cc1a89c 100644 --- a/src/DivaGL/renderer/transparency.cpp +++ b/src/DivaGL/renderer/transparency.cpp @@ -55,15 +55,33 @@ namespace renderer { shaders_ft.draw_arrays(GL_TRIANGLE_STRIP, 0, 4); gl_state_enable_depth_test(); - glCopyImageSubData(rctx->render_buffer.GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, - rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, fbo.width, fbo.height, 1); + if (GL_VERSION_4_3) + glCopyImageSubData(rctx->render_buffer.GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, + rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, fbo.width, fbo.height, 1); + else + fbo_blit(rctx->render_buffer.fbos[0], rt->fbos[0], + 0, 0, fbo.width, fbo.height, + 0, 0, fbo.width, fbo.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } void Transparency::copy(GLuint texture) { - glCopyImageSubData(texture, GL_TEXTURE_2D, 0, 0, 0, 0, - fbo.textures[0], GL_TEXTURE_2D, 0, 0, 0, 0, fbo.width, fbo.height, 1); + if (GL_VERSION_4_3) + glCopyImageSubData(texture, GL_TEXTURE_2D, 0, 0, 0, 0, + fbo.textures[0], GL_TEXTURE_2D, 0, 0, 0, 0, fbo.width, fbo.height, 1); + fbo.bind_buffer(); gl_state_set_viewport(0, 0, fbo.width, fbo.height); + + if (!GL_VERSION_4_3) { + gl_state_disable_depth_test(); + uniform->arr[U_REDUCE] = 0; + shaders_ft.set(SHADER_FT_REDUCE); + gl_state_active_bind_texture_2d(0, texture); + gl_state_bind_sampler(0, rctx->render_samplers[1]); + render_get()->draw_quad(fbo.width, fbo.height, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + gl_state_enable_depth_test(); + } } void Transparency::resize(GLuint color_texture, GLuint depth_texture, int32_t width, int32_t height) { diff --git a/src/DivaGL/shader.cpp b/src/DivaGL/shader.cpp index 7a68e8f..a6232ce 100644 --- a/src/DivaGL/shader.cpp +++ b/src/DivaGL/shader.cpp @@ -6,6 +6,7 @@ #include "shader.hpp" #include "../KKdLib/io/file_stream.hpp" #include "../KKdLib/io/path.hpp" +#include "../KKdLib/prj/vector_pair.hpp" #include "../KKdLib/hash.hpp" #include "../KKdLib/str_utils.hpp" #include "gl_state.hpp" @@ -62,6 +63,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 (GL_VERSION_4_2) + temp.replace(version_pos, 17, "#version 420 core", 17); + else if (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 (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 (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 (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) { size_t off = 0; while (true) { @@ -99,7 +291,8 @@ bool shader::parse_define(const char* data, std::string& temp) { else temp.assign(data); - parse_define_inner(temp); + if (GL_VERSION_4_3) + parse_define_inner(temp); return true; } @@ -134,7 +327,8 @@ bool shader::parse_define(const char* data, int32_t num_uniform, else temp.assign(data); - parse_define_inner(temp); + if (GL_VERSION_4_3) + parse_define_inner(temp); return true; } @@ -384,6 +578,8 @@ 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]; @@ -499,6 +695,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 (!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); @@ -594,6 +798,30 @@ void shader_set_data::load(farc* f, bool ignore_cache, memcpy((void*)b->binary, (void*)((size_t)bin + bin->binary), bin->length); } + if (!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++; } @@ -635,6 +863,30 @@ void shader_set_data::load(farc* f, bool ignore_cache, memcpy((void*)b->binary, (void*)((size_t)bin + bin->binary), bin->length); } + if (!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/DivaGL/wrap.cpp b/src/DivaGL/wrap.cpp index 8d721f6..3c9d64f 100644 --- a/src/DivaGL/wrap.cpp +++ b/src/DivaGL/wrap.cpp @@ -531,7 +531,7 @@ gl_func_struct gl_addr[1057] = { { 0x00000001411A4268, 0, }, // glBindAttribLocation { 0x00000001411A4CE0, 0, }, // glBindAttribLocationARB { 0x00000001411A41E0, 0, }, // glBindBuffer - { 0x0000001411A4598, 0, }, // glBindBufferBase + { 0x00000001411A4598, 0, }, // glBindBufferBase { 0x00000001411A3570, 0, }, // glBindBufferOffsetNV { 0x00000001411A4590, 0, }, // glBindBufferRange { 0x00000001411A3568, 0, }, // glBindBufferRangeNV @@ -1582,6 +1582,8 @@ gl_func_struct gl_addr_glut[7] = { { 0x000000000002A430, 0, }, // wglMakeCurrent }; +bool GL_VERSION_4_1 = false; +bool GL_VERSION_4_2 = false; bool GL_VERSION_4_3 = false; bool GL_VERSION_4_4 = false; bool GL_VERSION_4_5 = false; @@ -1710,6 +1712,8 @@ void wrap_addresses() { int32_t minor; sscanf_s(version, "%d.%d", &major, &minor); + GL_VERSION_4_1 = (major == 4 && minor >= 1) || major > 4; + GL_VERSION_4_2 = (major == 4 && minor >= 2) || major > 4; GL_VERSION_4_3 = (major == 4 && minor >= 3) || major > 4; GL_VERSION_4_4 = (major == 4 && minor >= 4) || major > 4; GL_VERSION_4_5 = (major == 4 && minor >= 5) || major > 4; @@ -2491,7 +2495,11 @@ HGLRC GLAPIENTRY wglCreateContextGLUT(HDC hDc) { } typedef void (GLAPIENTRY* PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY* PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); typedef void (GLAPIENTRY* PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index); +typedef GLuint(GLAPIENTRY* PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar* uniformBlockName); +typedef void (GLAPIENTRY* PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GLAPIENTRY* PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor); typedef void (GLAPIENTRY* PFNGLCLEARDEPTHFPROC)(GLfloat d); typedef void (GLAPIENTRY* PFNGLGETPROGRAMBINARYPROC)(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary); typedef void (GLAPIENTRY* PFNGLPROGRAMBINARYPROC)(GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); @@ -2508,7 +2516,11 @@ typedef void (GLAPIENTRY* PFNGLPUSHDEBUGGROUPPROC)(GLenum source, GLuint id, GLs typedef void (GLAPIENTRY* PFNGLPOPDEBUGGROUPPROC)(); static PFNGLTEXPARAMETERIVPROC _glTexParameteriv = 0; +static PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced = 0; static PFNGLPRIMITIVERESTARTINDEXPROC _glPrimitiveRestartIndex = 0; +static PFNGLGETUNIFORMBLOCKINDEXPROC _glGetUniformBlockIndex = 0; +static PFNGLUNIFORMBLOCKBINDINGPROC _glUniformBlockBinding = 0; +static PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor = 0; static PFNGLCLEARDEPTHFPROC _glClearDepthf = 0; static PFNGLGETPROGRAMBINARYPROC _glGetProgramBinary = 0; static PFNGLPROGRAMBINARYPROC _glProgramBinary = 0; @@ -2530,13 +2542,40 @@ void GLAPIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* param _glTexParameteriv(target, pname, params); } +void GLAPIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { + if (!_glDrawArraysInstanced) + _glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)wglGetProcAddressDLL("glDrawArraysInstanced"); + _glDrawArraysInstanced(mode, first, count, instancecount); +} + void GLAPIENTRY glPrimitiveRestartIndex(GLuint index) { if (!_glPrimitiveRestartIndex) _glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)wglGetProcAddressDLL("glPrimitiveRestartIndex"); _glPrimitiveRestartIndex(index); } +GLuint GLAPIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { + if (!_glGetUniformBlockIndex) + _glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)wglGetProcAddressDLL("glGetUniformBlockIndex"); + return _glGetUniformBlockIndex(program, uniformBlockName); +} + +void GLAPIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { + if (!_glUniformBlockBinding) + _glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)wglGetProcAddressDLL("glUniformBlockBinding"); + _glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); +} + +void GLAPIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) { + if (!_glVertexAttribDivisor) + _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)wglGetProcAddressDLL("glVertexAttribDivisor"); + _glVertexAttribDivisor(index, divisor); +} + void GLAPIENTRY glClearDepthf(GLfloat d) { + if (!GL_VERSION_4_1) + return glClearDepthDLL(d); + if (!_glClearDepthf) _glClearDepthf = (PFNGLCLEARDEPTHFPROC)wglGetProcAddressDLL("glClearDepthf"); _glClearDepthf(d); @@ -2603,12 +2642,18 @@ void GLAPIENTRY glTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, } void constexpr GLAPIENTRY glPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar* message) { + if (!GL_VERSION_4_3) + return; + if (!_glPushDebugGroup) _glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)wglGetProcAddressDLL("glPushDebugGroup"); return _glPushDebugGroup(source, id, length, message); } void constexpr GLAPIENTRY glPopDebugGroup() { + if (!GL_VERSION_4_3) + return; + if (!_glPopDebugGroup) _glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)wglGetProcAddressDLL("glPopDebugGroup"); return _glPopDebugGroup(); diff --git a/src/DivaGL/wrap.hpp b/src/DivaGL/wrap.hpp index b7abbd9..2418ad4 100644 --- a/src/DivaGL/wrap.hpp +++ b/src/DivaGL/wrap.hpp @@ -3247,6 +3247,8 @@ extern gl_func_struct gl_addr_glut[7]; #define wglGetProcAddressGLUT ((PFNWGLGETPROCADDRESSGLUTPROC)gl_addr_glut[WGLGETPROCADDRESSGLUT].func) #define wglMakeCurrentGLUT ((PFNWGLMAKECURRENTGLUTPROC)gl_addr_glut[WGLMAKECURRENTGLUT].func) +extern bool GL_VERSION_4_1; +extern bool GL_VERSION_4_2; extern bool GL_VERSION_4_3; extern bool GL_VERSION_4_4; extern bool GL_VERSION_4_5; @@ -3418,7 +3420,11 @@ extern void GLAPIENTRY glVertex3fvGLUT(GLfloat const * v); extern HGLRC GLAPIENTRY wglCreateContextGLUT(HDC hDc); extern void GLAPIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params); +extern void GLAPIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); extern void GLAPIENTRY glPrimitiveRestartIndex(GLuint index); +extern GLuint GLAPIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); +extern void GLAPIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +extern void GLAPIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor); extern void GLAPIENTRY glClearDepthf(GLfloat d); extern void GLAPIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary); extern void GLAPIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void* binary, GLsizei length);