Просмотр исходного кода

Properly dispose of custom shaders, closes #19300

Juan Linietsky 6 лет назад
Родитель
Сommit
973b68f396

+ 29 - 1
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<uint32_t>::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);
 }

+ 1 - 0
drivers/gles2/shader_gles2.h

@@ -104,6 +104,7 @@ private:
 		Vector<StringName> texture_uniforms;
 		Vector<StringName> custom_uniforms;
 		Vector<CharString> custom_defines;
+		Set<uint32_t> versions;
 	};
 
 	struct Version {

+ 27 - 1
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<uint32_t>::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);
 }

+ 1 - 0
drivers/gles3/shader_gles3.h

@@ -117,6 +117,7 @@ private:
 		uint32_t version;
 		Vector<StringName> texture_uniforms;
 		Vector<CharString> custom_defines;
+		Set<uint32_t> versions;
 	};
 
 	struct Version {