diff --git a/res/ft_shaders.farc b/res/ft_shaders.farc index b462eb8..2e74de2 100644 Binary files a/res/ft_shaders.farc and b/res/ft_shaders.farc differ diff --git a/src/DivaGL/GL/shader_storage_buffer.cpp b/src/DivaGL/GL/shader_storage_buffer.cpp index 99abc20..de4713c 100644 --- a/src/DivaGL/GL/shader_storage_buffer.cpp +++ b/src/DivaGL/GL/shader_storage_buffer.cpp @@ -12,7 +12,7 @@ namespace GL { } void ShaderStorageBuffer::Create(size_t size) { - if (buffer) + if (!GL_VERSION_4_3 || buffer) return; if (GL_VERSION_4_5) { @@ -31,7 +31,7 @@ namespace GL { } void ShaderStorageBuffer::Create(size_t size, const void* data, bool dynamic) { - if (buffer) + if (!GL_VERSION_4_3 || buffer) return; if (GL_VERSION_4_5) { @@ -59,7 +59,7 @@ namespace GL { } void* ShaderStorageBuffer::MapMemory() { - if (!buffer) + if (!GL_VERSION_4_3 || !buffer) return 0; void* data; @@ -83,7 +83,7 @@ namespace GL { } void ShaderStorageBuffer::UnmapMemory() { - if (!buffer) + if (!GL_VERSION_4_3 || !buffer) return; if (GL_VERSION_4_5) @@ -95,7 +95,7 @@ namespace GL { } void ShaderStorageBuffer::WriteMemory(size_t offset, size_t size, const void* data) { - if (!buffer || !size) + if (!GL_VERSION_4_3 || !buffer || !size) return; if (GL_VERSION_4_5) diff --git a/src/DivaGL/effect.cpp b/src/DivaGL/effect.cpp index f1f253a..e5aa9f8 100644 --- a/src/DivaGL/effect.cpp +++ b/src/DivaGL/effect.cpp @@ -419,7 +419,127 @@ struct water_particle_scene_shader_data { vec4 g_state_point_attenuation; }; -static prj::vector_pair 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);