From bd89a868cc383941b1ff69c19130d15db6838c9f Mon Sep 17 00:00:00 2001 From: artdeell Date: Thu, 25 Apr 2024 21:14:10 +0300 Subject: [PATCH] Feat[renderer]: changes - Better multidraw - Fixed memory leaks in shader_wrapper - Changed basevertex to use dumb rendering mode --- app/src/main/tinywrapper/Android.mk | 1 + app/src/main/tinywrapper/basevertex.c | 96 ++++++++++++++--------- app/src/main/tinywrapper/basevertex.h | 10 +++ app/src/main/tinywrapper/egl.c | 1 + app/src/main/tinywrapper/egl.h | 1 + app/src/main/tinywrapper/main.c | 20 +---- app/src/main/tinywrapper/multidraw.c | 43 ++++++++++ app/src/main/tinywrapper/shader_wrapper.c | 9 ++- 8 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 app/src/main/tinywrapper/basevertex.h create mode 100644 app/src/main/tinywrapper/multidraw.c diff --git a/app/src/main/tinywrapper/Android.mk b/app/src/main/tinywrapper/Android.mk index 87177f6..be63624 100644 --- a/app/src/main/tinywrapper/Android.mk +++ b/app/src/main/tinywrapper/Android.mk @@ -397,6 +397,7 @@ LOCAL_SRC_FILES := \ framebuffer.c \ of_buffer_copier.c \ stubs.c \ + multidraw.c \ vgpu_shaderconv/shaderconv.c \ unordered_map/unordered_map.c \ unordered_map/int_hash.c diff --git a/app/src/main/tinywrapper/basevertex.c b/app/src/main/tinywrapper/basevertex.c index 2756ac0..6ee5d08 100644 --- a/app/src/main/tinywrapper/basevertex.c +++ b/app/src/main/tinywrapper/basevertex.c @@ -119,6 +119,35 @@ static void restore_state(GLuint element_buffer) { es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, current_context->bound_buffers[get_buffer_index(GL_SHADER_STORAGE_BUFFER)]); } +void glDrawElementsBaseVertex_inner(basevertex_renderer_t *renderer, GLenum mode, + GLsizei count, + GLenum type, + void *indices, + GLint basevertex, + GLuint elementbuffer) { + es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeIndexBuffer); + es3_functions.glBufferData(GL_SHADER_STORAGE_BUFFER, count * (GLint)sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); + es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeMetaBuffer); + data_buffer_t buffer_info; + buffer_info.baseVertex = basevertex; + buffer_info.elementCount = count; + buffer_info.inputBitWidth = type_bits(type); + es3_functions.glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data_buffer_t), &buffer_info); + es3_functions.glUseProgram(renderer->computeProgram); + + uintptr_t offset = (uintptr_t)indices; + + es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, elementbuffer, (GLintptr)offset, count * + type_bytes(type)); + es3_functions.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, renderer->computeIndexBuffer); + es3_functions.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, renderer->computeMetaBuffer); + es3_functions.glDispatchCompute((count + (256-1))/256, 1, 1); + + es3_functions.glUseProgram(current_context->program); + es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->computeIndexBuffer); + es3_functions.glDrawElements(mode, count, GL_UNSIGNED_INT, NULL); +} + void glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, @@ -135,42 +164,44 @@ void glDrawElementsBaseVertex(GLenum mode, return; } - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeIndexBuffer); - es3_functions.glBufferData(GL_SHADER_STORAGE_BUFFER, count * (GLint)sizeof(GLuint), NULL, GL_DYNAMIC_DRAW); - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeMetaBuffer); - data_buffer_t buffer_info; - buffer_info.baseVertex = basevertex; - buffer_info.elementCount = count; - buffer_info.inputBitWidth = type_bits(type); - es3_functions.glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data_buffer_t), &buffer_info); - es3_functions.glUseProgram(renderer->computeProgram); - - uintptr_t offset = (uintptr_t)indices; - - es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, elementbuffer, (GLintptr)offset, count * - type_bytes(type)); - es3_functions.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, renderer->computeIndexBuffer); - es3_functions.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, renderer->computeMetaBuffer); - es3_functions.glDispatchCompute((count + (256-1))/256, 1, 1); - - es3_functions.glUseProgram(current_context->program); - es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->computeIndexBuffer); - es3_functions.glDrawElements(mode, count, GL_UNSIGNED_INT, NULL); + glDrawElementsBaseVertex_inner(renderer, mode, count, type, indices, basevertex, elementbuffer); restore_state(elementbuffer); } -/*void glMultiDrawElementsBaseVertex(GLenum mode, + +void glMultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const void * const *indices, GLsizei drawcount, const GLint *basevertex) { - for(GLsizei i = 0; i < drawcount; i++) { - glDrawElementsBaseVertex(mode, count[i], type, (void*)indices[i], basevertex[i]); + if(!current_context) return; + basevertex_renderer_t *renderer = ¤t_context->basevertex; + if(!renderer->ready) return; + GLint elementbuffer; + es3_functions.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementbuffer); + if(elementbuffer == 0) { + // I am not bothered enough to implement this. + printf("tinywrapper: Base vertex draws without element buffer are not supported\n"); + return; } -}*/ + + for(GLsizei i = 0; i < drawcount; i++) { + glDrawElementsBaseVertex_inner(renderer, mode, count[i], type, (void*)indices[i], basevertex[i], elementbuffer); + } + + restore_state(elementbuffer); + +} +// TODO: Figure out how to fix the proper way of doing it +/* +static void render_out( basevertex_renderer_t *renderer, GLenum mode, GLsizei inserted_count) { + es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->computeIndexBuffer); + es3_functions.glUseProgram(current_context->program); + es3_functions.glDrawElements(mode, inserted_count, GL_UNSIGNED_INT, NULL); +} void glMultiDrawElementsBaseVertex( GLenum mode, const GLsizei *count, @@ -191,14 +222,14 @@ void glMultiDrawElementsBaseVertex( GLenum mode, GLsizei total_count = 0; for (int i = 0; i < drawcount; i++) total_count += count[i]; es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeIndexBuffer); - es3_functions.glBufferData(GL_SHADER_STORAGE_BUFFER, total_count * 4, NULL, GL_DYNAMIC_DRAW); + es3_functions.glBufferData(GL_SHADER_STORAGE_BUFFER, total_count * 4, NULL, GL_STREAM_DRAW); es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeMetaBuffer); es3_functions.glUseProgram(renderer->computeProgram); + es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, renderer->computeMetaBuffer, 0, sizeof(data_buffer_t)); data_buffer_t buffer_info; buffer_info.inputBitWidth = type_bits(type); GLint current_type_bytes = type_bytes(type); GLsizei inserted_count = 0; - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); for (int i = 0; i < drawcount; i++) { GLsizei local_count = count[i]; uintptr_t local_indices = (uintptr_t)indices[i]; @@ -210,16 +241,9 @@ void glMultiDrawElementsBaseVertex( GLenum mode, es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, elementbuffer, (GLintptr)local_indices, local_count * current_type_bytes); es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, renderer->computeIndexBuffer, inserted_count * 4, local_count * 4); - es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, renderer->computeMetaBuffer, 0, sizeof(data_buffer_t)); - GLint temp; - es3_functions.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &temp); es3_functions.glDispatchCompute((local_count + (256-1))/256, 1, 1); - inserted_count += local_count; } - es3_functions.glFlush(); - es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->computeIndexBuffer); - es3_functions.glUseProgram(current_context->program); - es3_functions.glDrawElements(mode, inserted_count, GL_UNSIGNED_INT, NULL); + render_out(renderer, mode, inserted_count); restore_state(elementbuffer); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/app/src/main/tinywrapper/basevertex.h b/app/src/main/tinywrapper/basevertex.h new file mode 100644 index 0000000..4f4c02f --- /dev/null +++ b/app/src/main/tinywrapper/basevertex.h @@ -0,0 +1,10 @@ +// +// Created by maks on 25.04.2024. +// + +#ifndef GL4ES_WRAPPER_BASEVERTEX_H +#define GL4ES_WRAPPER_BASEVERTEX_H + +GLint type_bytes(GLenum type); + +#endif //GL4ES_WRAPPER_BASEVERTEX_H diff --git a/app/src/main/tinywrapper/egl.c b/app/src/main/tinywrapper/egl.c index 21a3d5b..6e998c9 100644 --- a/app/src/main/tinywrapper/egl.c +++ b/app/src/main/tinywrapper/egl.c @@ -64,6 +64,7 @@ static void init_incontext(context_t* tw_context) { } basevertex_init(tw_context); buffer_copier_init(tw_context); + es3_functions.glGenBuffers(1, &tw_context->multidraw_element_buffer); } EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { diff --git a/app/src/main/tinywrapper/egl.h b/app/src/main/tinywrapper/egl.h index 330a7b9..55f73ce 100644 --- a/app/src/main/tinywrapper/egl.h +++ b/app/src/main/tinywrapper/egl.h @@ -60,6 +60,7 @@ typedef struct { EGLContext phys_context; bool context_rdy; basevertex_renderer_t basevertex; + GLuint multidraw_element_buffer; framebuffer_copier_t framebuffer_copier; unordered_map* shader_map; unordered_map* program_map; diff --git a/app/src/main/tinywrapper/main.c b/app/src/main/tinywrapper/main.c index 45a8386..604db3c 100644 --- a/app/src/main/tinywrapper/main.c +++ b/app/src/main/tinywrapper/main.c @@ -132,28 +132,10 @@ const GLubyte* glGetString(GLenum name) { } void glEnable(GLenum cap) { - //if(!current_context || cap == GL_DEBUG_OUTPUT) return; + if(!current_context || cap == GL_DEBUG_OUTPUT) return; es3_functions.glEnable(cap); } -void glMultiDrawArrays( GLenum mode, GLint *first, GLsizei *count, GLsizei primcount ) -{ - if(!current_context) return; - for (int i = 0; i < primcount; i++) { - if (count[i] > 0) - es3_functions.glDrawArrays(mode, first[i], count[i]); - } -} - -void glMultiDrawElements( GLenum mode, GLsizei *count, GLenum type, const void * const *indices, GLsizei primcount ) -{ - if(!current_context) return; - for (int i = 0; i < primcount; i++) { - if (count[i] > 0) - es3_functions.glDrawElements(mode, count[i], type, indices[i]); - } -} - int get_buffer_index(GLenum buffer) { switch (buffer) { case GL_ARRAY_BUFFER: return 0; diff --git a/app/src/main/tinywrapper/multidraw.c b/app/src/main/tinywrapper/multidraw.c new file mode 100644 index 0000000..4a4ec3a --- /dev/null +++ b/app/src/main/tinywrapper/multidraw.c @@ -0,0 +1,43 @@ +// +// Created by maks on 25.04.2024. +// +#include +#include +#include "basevertex.h" +void glMultiDrawArrays( GLenum mode, GLint *first, GLsizei *count, GLsizei primcount ) +{ + // We'd need to merge each buffer attached to the VBO to properly achieve this. Nuh-uh. Aint no way im doin allat + if(!current_context) return; + for (int i = 0; i < primcount; i++) { + if (count[i] > 0) + es3_functions.glDrawArrays(mode, first[i], count[i]); + } +} + +void glMultiDrawElements( GLenum mode, GLsizei *count, GLenum type, const void * const *indices, GLsizei primcount ) +{ + if(!current_context) return; + GLint elementbuffer; + es3_functions.glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementbuffer); + es3_functions.glBindBuffer(GL_COPY_WRITE_BUFFER, current_context->multidraw_element_buffer); + GLsizei total = 0, offset = 0, typebytes = type_bytes(type); + for (GLsizei i = 0; i < primcount; i++) { + total += count[i]; + } + es3_functions.glBufferData(GL_COPY_WRITE_BUFFER, total*typebytes, NULL, GL_STREAM_DRAW); + for (GLsizei i = 0; i < primcount; i++) { + GLsizei icount = count[i]; + if(icount == 0) continue; + icount *= typebytes; + if(elementbuffer != 0) { + es3_functions.glCopyBufferSubData(GL_ELEMENT_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, (GLintptr)indices[i], offset, icount); + }else { + es3_functions.glBufferSubData(GL_COPY_WRITE_BUFFER, offset, icount, indices[i]); + } + offset += icount; + } + es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_context->multidraw_element_buffer); + es3_functions.glDrawElements(mode, total, type, 0); + if(elementbuffer != 0) es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); + +} \ No newline at end of file diff --git a/app/src/main/tinywrapper/shader_wrapper.c b/app/src/main/tinywrapper/shader_wrapper.c index d972b68..7fe33e7 100644 --- a/app/src/main/tinywrapper/shader_wrapper.c +++ b/app/src/main/tinywrapper/shader_wrapper.c @@ -95,15 +95,20 @@ void glLinkProgram(GLuint program) { insert_fragout_pos(new_source, colorbind, i); changesMade = true; } - if(!changesMade) goto fallthrough; + if(!changesMade) { + free(new_source); + goto fallthrough; + } const GLchar* const_source = (const GLchar*)new_source; GLuint patched_shader = es3_functions.glCreateShader(GL_FRAGMENT_SHADER); if(patched_shader == 0) { + free(new_source); printf("tinywrapper: failed to initialize patched shader\n"); goto fallthrough; } es3_functions.glShaderSource(patched_shader, 1, &const_source, NULL); es3_functions.glCompileShader(patched_shader); + free(new_source); GLint compileStatus; es3_functions.glGetShaderiv(patched_shader, GL_COMPILE_STATUS, &compileStatus); if(compileStatus != GL_TRUE) { @@ -167,7 +172,7 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, co #undef SRC_LEN GLchar* new_source = optimize_shader(target_string, shader_info->shader_type == GL_VERTEX_SHADER, 330, 300); - printf("\n\n\nShader Result\n%s\n\n\n", new_source); + //printf("\n\n\nShader Result\n%s\n\n\n", new_source); if(shader_info->source != NULL) free((void*)shader_info->source); shader_info->source = new_source; es3_functions.glShaderSource(shader, 1, &shader_info->source, 0);