From d16d87fd2640744a5de571a7c0ff633b38bc9f75 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 13 Jul 2025 17:35:38 +0800 Subject: [PATCH] [Fix] (GL): Force depth clear when glClear is called with depth=1.0 on ANGLE. --- src/main/cpp/gl/gl.cpp | 110 +++++++++++++++++++++++++++++++++- src/main/cpp/gl/gl_native.cpp | 2 +- src/main/cpp/gl/texture.cpp | 4 +- 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/main/cpp/gl/gl.cpp b/src/main/cpp/gl/gl.cpp index cb420cd..cd8d5b9 100644 --- a/src/main/cpp/gl/gl.cpp +++ b/src/main/cpp/gl/gl.cpp @@ -1,4 +1,4 @@ -// +// // Created by Swung0x48 on 2024/10/8. // @@ -7,16 +7,124 @@ #include "glcorearb.h" #include "log.h" #include "../gles/loader.h" +#include "../config/settings.h" #include "mg.h" #define DEBUG 0 +static GLclampd currentDepthValue; + void glClearDepth(GLclampd depth) { LOG() + currentDepthValue = depth; GLES.glClearDepthf((float)depth); CHECK_GL_ERROR } +static GLuint g_depthClearProgram = 0; +static GLuint g_depthClearVAO = 0; +static GLuint g_depthClearVBO = 0; + +static const GLfloat kFullScreenTri[3][2] = { + { -1.0f, -1.0f }, + { 3.0f, -1.0f }, + { -1.0f, 3.0f } +}; + +static const char* kDepthClearVS = R"glsl( + #version 300 es + layout(location = 0) in vec2 aPos; + void main() { + // Write far‐plane depth + gl_Position = vec4(aPos, 1.0, 1.0); + } +)glsl"; +static const char* kDepthClearFS = R"glsl( + #version 300 es + precision mediump float; + out vec4 fragColor; + void main() { + // Empty—color writes will be disabled + fragColor = vec4(0.0); + } +)glsl"; + +void InitDepthClearCoreProfile() { + if (g_depthClearProgram) return; + + auto compile = [&](GLenum type, const char* src) { + GLuint s = GLES.glCreateShader(type); + GLES.glShaderSource(s, 1, &src, nullptr); + GLES.glCompileShader(s); + return s; + }; + GLuint vs = compile(GL_VERTEX_SHADER, kDepthClearVS); + GLuint fs = compile(GL_FRAGMENT_SHADER, kDepthClearFS); + + g_depthClearProgram = GLES.glCreateProgram(); + GLES.glAttachShader(g_depthClearProgram, vs); + GLES.glAttachShader(g_depthClearProgram, fs); + GLES.glLinkProgram(g_depthClearProgram); + GLES.glDeleteShader(vs); + GLES.glDeleteShader(fs); + + GLES.glGenVertexArrays(1, &g_depthClearVAO); + GLES.glGenBuffers(1, &g_depthClearVBO); + + GLES.glBindVertexArray(g_depthClearVAO); + GLES.glBindBuffer(GL_ARRAY_BUFFER, g_depthClearVBO); + GLES.glBufferData(GL_ARRAY_BUFFER, sizeof(kFullScreenTri), kFullScreenTri, GL_STATIC_DRAW); + + GLES.glEnableVertexAttribArray(0); + GLES.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + + GLES.glBindBuffer(GL_ARRAY_BUFFER, 0); + GLES.glBindVertexArray(0); +} + +void DrawDepthClearTri() { + InitDepthClearCoreProfile(); + + GLboolean prevColorMask[4]; + GLES.glGetBooleanv(GL_COLOR_WRITEMASK, prevColorMask); + GLboolean prevDepthMask; + GLES.glGetBooleanv(GL_DEPTH_WRITEMASK, &prevDepthMask); + GLint prevDepthFunc; + GLES.glGetIntegerv(GL_DEPTH_FUNC, &prevDepthFunc); + + GLES.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + GLES.glDepthMask(GL_TRUE); + GLES.glDepthFunc(GL_ALWAYS); + + GLES.glUseProgram(g_depthClearProgram); + GLES.glBindVertexArray(g_depthClearVAO); + GLES.glDrawArrays(GL_TRIANGLES, 0, 3); + GLES.glBindVertexArray(0); + GLES.glUseProgram(0); + + GLES.glDepthFunc(prevDepthFunc); + GLES.glDepthMask(prevDepthMask); + GLES.glColorMask(prevColorMask[0], prevColorMask[1], prevColorMask[2], prevColorMask[3]); +} + +void glClear(GLbitfield mask) { + LOG(); + LOG_D("glClear, mask = 0x%x", mask); + + if (global_settings.angle == AngleMode::Enabled && mask == GL_DEPTH_BUFFER_BIT && fabs(currentDepthValue - 1.0f) <= 0.001f) { + // Workaround for ANGLE depth-clear bug: if depth≈1.0, draw a fullscreen triangle at z=1.0 to force actual depth buffer write. + DrawDepthClearTri(); + // Clear again + GLES.glClear(mask); + } else { + GLES.glClear(mask); + } + + CHECK_GL_ERROR; +} + + + void glHint(GLenum target, GLenum mode) { LOG() LOG_D("glHint, target = %s, mode = %s", glEnumToString(target), glEnumToString(mode)) diff --git a/src/main/cpp/gl/gl_native.cpp b/src/main/cpp/gl/gl_native.cpp index f2b64bc..d4ff350 100644 --- a/src/main/cpp/gl/gl_native.cpp +++ b/src/main/cpp/gl/gl_native.cpp @@ -27,7 +27,7 @@ NATIVE_FUNCTION_HEAD(void, glBlendFuncSeparate, GLenum sfactorRGB, GLenum dfacto //NATIVE_FUNCTION_HEAD(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) NATIVE_FUNCTION_END_NO_RETURN(void, glBufferData, target,size,data,usage) NATIVE_FUNCTION_HEAD(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) NATIVE_FUNCTION_END_NO_RETURN(void, glBufferSubData, target,offset,size,data) //NATIVE_FUNCTION_HEAD(GLenum, glCheckFramebufferStatus, GLenum target) NATIVE_FUNCTION_END(GLenum, glCheckFramebufferStatus, target) -NATIVE_FUNCTION_HEAD(void, glClear, GLbitfield mask) NATIVE_FUNCTION_END_NO_RETURN(void, glClear, mask) +//NATIVE_FUNCTION_HEAD(void, glClear, GLbitfield mask) NATIVE_FUNCTION_END_NO_RETURN(void, glClear, mask) NATIVE_FUNCTION_HEAD(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) NATIVE_FUNCTION_END_NO_RETURN(void, glClearColor, red,green,blue,alpha) NATIVE_FUNCTION_HEAD(void, glClearDepthf, GLfloat d) NATIVE_FUNCTION_END_NO_RETURN(void, glClearDepthf, d) NATIVE_FUNCTION_HEAD(void, glClearStencil, GLint s) NATIVE_FUNCTION_END_NO_RETURN(void, glClearStencil, s) diff --git a/src/main/cpp/gl/texture.cpp b/src/main/cpp/gl/texture.cpp index c4106e3..f1502c5 100644 --- a/src/main/cpp/gl/texture.cpp +++ b/src/main/cpp/gl/texture.cpp @@ -52,9 +52,9 @@ void internal_convert(GLenum* internal_format, GLenum* type, GLenum* format) { break; case GL_DEPTH_COMPONENT32: - *internal_format = GL_DEPTH_COMPONENT32F; + *internal_format = GL_DEPTH_COMPONENT; if(type) - *type = GL_FLOAT; + *type = GL_UNSIGNED_INT; break; case GL_DEPTH_COMPONENT32F: