Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion drivers/gles3/rasterizer_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/rasterizer_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class RasterizerGLES3 : public RendererCompositor {
float delta = 0;

double time_total = 0.0;
bool flip_xy_bugfix = false;

static bool gles_over_gl;

Expand Down
43 changes: 31 additions & 12 deletions drivers/gles3/shaders/canvas.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Alex2782 marked this conversation as resolved.
Show resolved Hide resolved
//-----------------------------------------
// 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;
Expand Down Expand Up @@ -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);
}
}

Expand Down
5 changes: 4 additions & 1 deletion drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions drivers/gles3/storage/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/storage/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class Config {
bool rt_msaa_multiview_supported = false;
bool multiview_supported = false;

bool adreno_3xx_compatibility = false;

#ifdef ANDROID_ENABLED
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1673,7 +1673,24 @@ public void requestRenderAndNotify(Runnable finishDrawing) {
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConf

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);
Expand Down
Loading