From 973b68f396d1de99342d17901f33c76d2ce69059 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 25 Jan 2019 19:28:27 -0300 Subject: Properly dispose of custom shaders, closes #19300 --- drivers/gles2/shader_gles2.cpp | 30 +++++++++++++++++++++++++++++- drivers/gles2/shader_gles2.h | 1 + drivers/gles3/shader_gles3.cpp | 28 +++++++++++++++++++++++++++- drivers/gles3/shader_gles3.h | 1 + 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index b50da3e9fe..3bf5baec14 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -229,6 +229,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -328,6 +329,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { if (iloglen < 0) { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?"); @@ -349,6 +351,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { Memory::free_static(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -403,6 +406,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?"); @@ -425,6 +429,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -452,6 +457,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL program link log. What the frick?"); @@ -476,6 +482,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -519,6 +526,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } + return &v; } @@ -683,9 +694,26 @@ void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { } void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { + ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 5805432d09..d493880d0b 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -104,6 +104,7 @@ private: Vector texture_uniforms; Vector custom_uniforms; Vector custom_defines; + Set versions; }; struct Version { diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index edc2a6c054..64396cadd1 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -204,6 +204,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -324,6 +325,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Vertex shader compilation failed with empty log"); @@ -345,6 +347,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { memfree(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -418,6 +421,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Fragment shader compilation failed with empty log"); } else { @@ -440,6 +444,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -486,6 +491,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_COND_V(iloglen <= 0, NULL); } @@ -508,6 +514,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -559,6 +566,9 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } return &v; } @@ -742,7 +752,23 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; //bye + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 1f98f4883d..1ed30986bf 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -117,6 +117,7 @@ private: uint32_t version; Vector texture_uniforms; Vector custom_defines; + Set versions; }; struct Version { -- cgit v1.2.3