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")
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -30,7 +32,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
gl/texture.c
gl/drawing.c
gl/mg.c
gl/buffer.c
gl/buffer.cpp
gl/getter.c
gl/glsl/glsl_for_es.cpp
glx/lookup.c

View File

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

View File

@ -12,6 +12,10 @@
#include "../gles/loader.h"
#include "mg.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
GLenum target;
GLuint buffer_id;
@ -24,11 +28,17 @@ typedef struct {
static BufferMapping g_active_mapping = {0};
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 void *glMapBuffer(GLenum target, GLenum access);
#ifdef __cplusplus
}
#endif
#define MOBILEGLUES_BUFFER_H
#endif //MOBILEGLUES_BUFFER_H

View File

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