Browse Source

Fix Compatibility Rendering (GLES3) on old and low budget devices.

Co-Authored-By: joined72 <[email protected]>
Alexander Hartmann 1 year ago
parent
commit
e17cecf54a

+ 16 - 1
drivers/gles3/rasterizer_gles3.cpp

@@ -194,6 +194,11 @@ typedef void(GLAPIENTRY *DebugMessageCallbackARB)(DEBUGPROCARB callback, const v
 
 void RasterizerGLES3::initialize() {
 	Engine::get_singleton()->print_header(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
+
+	// FLIP XY Bug: Are more devices affected?
+	// Confirmed so far: all Adreno 3xx
+	// ok on some tested Adreno devices: 4xx, 5xx and 6xx
+	flip_xy_bugfix = GLES3::Config::get_singleton()->adreno_3xx_compatibility;
 }
 
 void RasterizerGLES3::finalize() {
@@ -398,8 +403,18 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
 	}
 
 	Vector2i screen_rect_end = p_screen_rect.get_end();
+
+	// Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
+	// Reversing both the X and Y axis is equivalent to rotating 180 degrees
+	bool flip_x = false;
+	if (flip_xy_bugfix && screen_rect_end.x > screen_rect_end.y) {
+		flip_y = !flip_y;
+		flip_x = !flip_x;
+	}
+
 	glBlitFramebuffer(0, 0, rt->size.x, rt->size.y,
-			p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y, screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y,
+			flip_x ? screen_rect_end.x : p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y,
+			flip_x ? p_screen_rect.position.x : screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y,
 			GL_COLOR_BUFFER_BIT, GL_NEAREST);
 
 	if (read_fbo != 0) {

+ 1 - 0
drivers/gles3/rasterizer_gles3.h

@@ -55,6 +55,7 @@ private:
 	float delta = 0;
 
 	double time_total = 0.0;
+	bool flip_xy_bugfix = false;
 
 	static bool gles_over_gl;
 

+ 31 - 12
drivers/gles3/shaders/canvas.glsl

@@ -187,8 +187,31 @@ void main() {
 #endif // !USE_INSTANCING
 
 #else // !USE_ATTRIBUTES
-	vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
-	vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
+
+	// crash on Adreno 320/330
+	//vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
+	//vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
+	//-----------------------------------------
+	// ID |  0  |  1  |  2  |  3  |  4  |  5  |
+	//-----------------------------------------
+	// X  | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 |
+	// Y  | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 1.0 |
+	//-----------------------------------------
+	// no crash or freeze on all Adreno 3xx	with 'if / else if' and slightly faster!
+	int vertex_id = gl_VertexID % 6;
+	vec2 vertex_base;
+	if (vertex_id == 0)
+		vertex_base = vec2(0.0, 0.0);
+	else if (vertex_id == 1)
+		vertex_base = vec2(0.0, 1.0);
+	else if (vertex_id == 2)
+		vertex_base = vec2(1.0, 1.0);
+	else if (vertex_id == 3)
+		vertex_base = vec2(1.0, 0.0);
+	else if (vertex_id == 4)
+		vertex_base = vec2(0.0, 0.0);
+	else if (vertex_id == 5)
+		vertex_base = vec2(1.0, 1.0);
 
 	vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
 	vec4 color = read_draw_data_modulation;
@@ -475,16 +498,12 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
 void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
 	uint blend_mode = light_array[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
 
-	switch (blend_mode) {
-		case LIGHT_FLAGS_BLEND_MODE_ADD: {
-			color.rgb += light_color.rgb * light_color.a;
-		} break;
-		case LIGHT_FLAGS_BLEND_MODE_SUB: {
-			color.rgb -= light_color.rgb * light_color.a;
-		} break;
-		case LIGHT_FLAGS_BLEND_MODE_MIX: {
-			color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
-		} break;
+	if (blend_mode == LIGHT_FLAGS_BLEND_MODE_ADD) {
+		color.rgb += light_color.rgb * light_color.a;
+	} else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_SUB) {
+		color.rgb -= light_color.rgb * light_color.a;
+	} else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_MIX) {
+		color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
 	}
 }
 

+ 4 - 1
drivers/gles3/shaders/scene.glsl

@@ -1200,7 +1200,10 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
 	vec3 spot_dir = spot_lights[idx].direction;
 	float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle);
 	float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle));
-	spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation);
+
+	mediump float cone_attenuation = spot_lights[idx].cone_attenuation;
+	spot_attenuation *= 1.0 - pow(spot_rim, cone_attenuation);
+
 	vec3 color = spot_lights[idx].color;
 
 	float size_A = 0.0;

+ 5 - 0
drivers/gles3/storage/config.cpp

@@ -166,6 +166,11 @@ Config::Config() {
 	max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements");
 	max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights");
 	max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object");
+
+	//Adreno 3xx Compatibility
+	const String rendering_device_name = String::utf8((const char *)glGetString(GL_RENDERER));
+	//TODO: Check the number between 300 and 399(?)
+	adreno_3xx_compatibility = (rendering_device_name.left(13) == "Adreno (TM) 3");
 }
 
 Config::~Config() {

+ 2 - 0
drivers/gles3/storage/config.h

@@ -91,6 +91,8 @@ public:
 	bool rt_msaa_multiview_supported = false;
 	bool multiview_supported = false;
 
+	bool adreno_3xx_compatibility = false;
+
 #ifdef ANDROID_ENABLED
 	PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
 	PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;

+ 18 - 1
platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java

@@ -1673,7 +1673,24 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
 				mWantRenderNotification = true;
 				mRequestRender = true;
 				mRenderComplete = false;
-				mFinishDrawingRunnable = finishDrawing;
+
+				// fix lost old callback when continuous call requestRenderAndNotify
+				//
+				// If continuous call requestRenderAndNotify before trigger old
+				// callback, old callback will lose, cause VRI will wait for SV's
+				// draw to finish forever not calling finishDraw.
+				// https://android.googlesource.com/platform/frameworks/base/+/044fce0b826f2da3a192aac56785b5089143e693%5E%21/
+				//+++++++++++++++++++++++++++++++++++++++++++++++++++
+				final Runnable oldCallback = mFinishDrawingRunnable;
+				mFinishDrawingRunnable = () -> {
+					if (oldCallback != null) {
+						oldCallback.run();
+					}
+					if (finishDrawing != null) {
+						finishDrawing.run();
+					}
+				};
+				//----------------------------------------------------
 
 				sGLThreadManager.notifyAll();
 			}

+ 7 - 3
platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java

@@ -66,11 +66,15 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
 
 		GLUtils.checkEglError(TAG, "Before eglCreateContext", egl);
 		EGLContext context;
+		int[] debug_attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
+		int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
 		if (mUseDebugOpengl) {
-			int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
-			context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+			context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, debug_attrib_list);
+			if (context == null || context == EGL10.EGL_NO_CONTEXT) {
+				Log.w(TAG, "creating 'OpenGL Debug' context failed");
+				context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+			}
 		} else {
-			int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
 			context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
 		}
 		GLUtils.checkEglError(TAG, "After eglCreateContext", egl);