fix(buffer, drawing): correctly unmap buffer, fixing drawing on Mali GPU

This commit is contained in:
Swung0x48 2025-01-30 09:53:49 +08:00
parent a3aec1c09b
commit 7d80368008
4 changed files with 53 additions and 40 deletions

View File

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.22.1)
project("mobileglues") project("mobileglues")
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -30,7 +32,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
gl/texture.c gl/texture.c
gl/drawing.c gl/drawing.c
gl/mg.c gl/mg.c
gl/buffer.c gl/buffer.cpp
gl/getter.c gl/getter.c
gl/glsl/glsl_for_es.cpp gl/glsl/glsl_for_es.cpp
glx/lookup.c glx/lookup.c

View File

@ -3,9 +3,12 @@
// //
#include "buffer.h" #include "buffer.h"
#include <unordered_map>
#define DEBUG 0 #define DEBUG 0
std::unordered_map<GLuint, BufferMapping> g_active_mappings;
static GLenum get_binding_query(GLenum target) { static GLenum get_binding_query(GLenum target) {
switch(target) { switch(target) {
case GL_ARRAY_BUFFER: return GL_ARRAY_BUFFER_BINDING; case GL_ARRAY_BUFFER: return GL_ARRAY_BUFFER_BINDING;
@ -44,58 +47,55 @@ void* glMapBuffer(GLenum target, GLenum access) {
} }
void* ptr = glMapBufferRange(target, 0, buffer_size, flags); void* ptr = glMapBufferRange(target, 0, buffer_size, flags);
if (!ptr) return NULL; if (!ptr) return NULL;
g_active_mapping.target = target; BufferMapping mapping;
g_active_mapping.buffer_id = (GLuint)current_buffer; mapping.target = target;
g_active_mapping.mapped_ptr = ptr; mapping.buffer_id = (GLuint)current_buffer;
g_active_mapping.size = buffer_size; mapping.mapped_ptr = ptr;
g_active_mapping.flags = flags; mapping.size = buffer_size;
g_active_mapping.is_dirty = (flags & GL_MAP_WRITE_BIT) ? GL_TRUE : GL_FALSE; mapping.flags = flags;
mapping.is_dirty = (flags & GL_MAP_WRITE_BIT) ? GL_TRUE : GL_FALSE;
g_active_mappings[current_buffer] = mapping;
CHECK_GL_ERROR CHECK_GL_ERROR
return ptr; return ptr;
} }
static void force_unmap(GLenum target, GLuint original_buffer) { GLboolean force_unmap() {
GLint prev_buffer; if (g_active_mappings.empty())
glGetIntegerv(get_binding_query(target), &prev_buffer); return GL_FALSE;
GLuint temp_buffer;
glGenBuffers(1, &temp_buffer); LOAD_GLES(glBindBuffer, void, GLenum target, GLuint buffer)
glBindBuffer(target, temp_buffer); LOAD_GLES(glUnmapBuffer, GLboolean, GLenum target);
glBindBuffer(target, 0);
glDeleteBuffers(1, &temp_buffer); for (auto& [buffer, binding]: g_active_mappings) {
if (target == GL_ARRAY_BUFFER) { GLint prev_buffer = 0;
GLint prev_element_array; GLenum binding_query = get_binding_query(binding.target);
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prev_element_array); glGetIntegerv(binding_query, &prev_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_element_array); gles_glBindBuffer(binding.target, binding.buffer_id);
} else { GLboolean result = gles_glUnmapBuffer(binding.target);
GLint prev_array; gles_glBindBuffer(binding.target, prev_buffer);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_array);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, prev_array);
} }
glBindBuffer(target, original_buffer);
g_active_mappings.clear();
return GL_TRUE;
} }
GLboolean glUnmapBuffer(GLenum target) { GLboolean glUnmapBuffer(GLenum target) {
LOG() LOG()
if (g_active_mapping.mapped_ptr == NULL ||
g_active_mapping.target != target ||
g_active_mapping.buffer_id == 0) {
return GL_FALSE;
}
GLint prev_buffer; GLint buffer;
GLenum binding_query = get_binding_query(target); GLenum binding_query = get_binding_query(target);
glGetIntegerv(binding_query, &prev_buffer); glGetIntegerv(binding_query, &buffer);
glBindBuffer(target, g_active_mapping.buffer_id); if (buffer == 0)
return GL_FALSE;
LOAD_GLES(glUnmapBuffer, GLboolean, GLenum target); LOAD_GLES(glUnmapBuffer, GLboolean, GLenum target);
GLboolean result = gles_glUnmapBuffer(target); GLboolean result = gles_glUnmapBuffer(target);
glBindBuffer(target, prev_buffer); g_active_mappings.erase(buffer);
memset(&g_active_mapping, 0, sizeof(BufferMapping));
CHECK_GL_ERROR CHECK_GL_ERROR
return result; return result;
} }

View File

@ -12,10 +12,14 @@
#include "../gles/loader.h" #include "../gles/loader.h"
#include "mg.h" #include "mg.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { typedef struct {
GLenum target; GLenum target;
GLuint buffer_id; GLuint buffer_id;
void* mapped_ptr; void *mapped_ptr;
GLsizeiptr size; GLsizeiptr size;
GLbitfield flags; GLbitfield flags;
GLboolean is_dirty; GLboolean is_dirty;
@ -24,11 +28,17 @@ typedef struct {
static BufferMapping g_active_mapping = {0}; static BufferMapping g_active_mapping = {0};
static GLenum get_binding_query(GLenum target); static GLenum get_binding_query(GLenum target);
static void force_unmap(GLenum target, GLuint original_buffer);
GLboolean force_unmap();
GLAPI GLAPIENTRY GLboolean glUnmapBuffer(GLenum target); GLAPI GLAPIENTRY GLboolean glUnmapBuffer(GLenum target);
GLAPI GLAPIENTRY void *glMapBuffer(GLenum target, GLenum access); GLAPI GLAPIENTRY void *glMapBuffer(GLenum target, GLenum access);
#ifdef __cplusplus
}
#endif
#define MOBILEGLUES_BUFFER_H #define MOBILEGLUES_BUFFER_H
#endif //MOBILEGLUES_BUFFER_H #endif //MOBILEGLUES_BUFFER_H

View File

@ -3,13 +3,14 @@
// //
#include "drawing.h" #include "drawing.h"
#include "buffer.h"
#define DEBUG 0 #define DEBUG 0
void glMultiDrawElementsBaseVertex( GLenum mode, GLsizei *counts, GLenum type, const void * const *indices, GLsizei primcount, const GLint * basevertex) { void glMultiDrawElementsBaseVertex( GLenum mode, GLsizei *counts, GLenum type, const void * const *indices, GLsizei primcount, const GLint * basevertex) {
LOG(); LOG();
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); force_unmap();
for (int i = 0; i < primcount; i++) { for (int i = 0; i < primcount; i++) {
if (counts[i] > 0) if (counts[i] > 0)