[Fix] (GL): Force depth clear when glClear is called with depth=1.0 on ANGLE.

This commit is contained in:
BZLZHH 2025-07-13 17:35:38 +08:00
parent 4bcd4d0dee
commit d16d87fd26
3 changed files with 112 additions and 4 deletions

View File

@ -1,4 +1,4 @@
// //
// Created by Swung0x48 on 2024/10/8. // Created by Swung0x48 on 2024/10/8.
// //
@ -7,16 +7,124 @@
#include "glcorearb.h" #include "glcorearb.h"
#include "log.h" #include "log.h"
#include "../gles/loader.h" #include "../gles/loader.h"
#include "../config/settings.h"
#include "mg.h" #include "mg.h"
#define DEBUG 0 #define DEBUG 0
static GLclampd currentDepthValue;
void glClearDepth(GLclampd depth) { void glClearDepth(GLclampd depth) {
LOG() LOG()
currentDepthValue = depth;
GLES.glClearDepthf((float)depth); GLES.glClearDepthf((float)depth);
CHECK_GL_ERROR 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 farplane 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) { void glHint(GLenum target, GLenum mode) {
LOG() LOG()
LOG_D("glHint, target = %s, mode = %s", glEnumToString(target), glEnumToString(mode)) LOG_D("glHint, target = %s, mode = %s", glEnumToString(target), glEnumToString(mode))

View File

@ -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, 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(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(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, 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, 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) NATIVE_FUNCTION_HEAD(void, glClearStencil, GLint s) NATIVE_FUNCTION_END_NO_RETURN(void, glClearStencil, s)

View File

@ -52,9 +52,9 @@ void internal_convert(GLenum* internal_format, GLenum* type, GLenum* format) {
break; break;
case GL_DEPTH_COMPONENT32: case GL_DEPTH_COMPONENT32:
*internal_format = GL_DEPTH_COMPONENT32F; *internal_format = GL_DEPTH_COMPONENT;
if(type) if(type)
*type = GL_FLOAT; *type = GL_UNSIGNED_INT;
break; break;
case GL_DEPTH_COMPONENT32F: case GL_DEPTH_COMPONENT32F: