From 600342d99abd9b646fbcf2ffacab7341f489c9b7 Mon Sep 17 00:00:00 2001 From: artdeell Date: Mon, 24 Jun 2024 13:02:40 +0300 Subject: [PATCH] Feat[basevertex,shader]: Reimnplement basevertex rendering on top of indirect rendering. Make Iris be able to run shaders. --- app/src/main/tinywrapper/basevertex.c | 223 ++++---------------- app/src/main/tinywrapper/egl.h | 6 +- app/src/main/tinywrapper/es3_extended.h | 2 +- app/src/main/tinywrapper/es3_overrides.h | 8 +- app/src/main/tinywrapper/main.c | 3 +- app/src/main/tinywrapper/of_buffer_copier.c | 11 +- app/src/main/tinywrapper/shader_wrapper.c | 3 +- 7 files changed, 66 insertions(+), 190 deletions(-) diff --git a/app/src/main/tinywrapper/basevertex.c b/app/src/main/tinywrapper/basevertex.c index 6ee5d08..381ca89 100644 --- a/app/src/main/tinywrapper/basevertex.c +++ b/app/src/main/tinywrapper/basevertex.c @@ -6,93 +6,25 @@ #include "egl.h" #include "main.h" -const GLchar*const basevertex_offset_shader = - "#version 310 es\n" - "layout(std430) buffer;\n" - "layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n" - "layout(binding = 0) readonly buffer sourceBuffer {\n" - " uint src_elements[];\n" - "};\n" - "layout(binding = 1) writeonly buffer destinationBuffer {\n" - " uint dst_elements[];\n" - "};\n" - "layout(binding = 2) readonly buffer dataBuffer {\n" - " uint baseVertex;\n" - " uint elementCount;\n" - " uint inputBitWidth;\n" - "};\n" - "\n" - "void main()\n" - "{\n" - " uint ident = gl_GlobalInvocationID.x;\n" - " uint inputByteWidth = (uint(32) / inputBitWidth);\n" - " uint ident_src = ident / inputByteWidth;\n" - " dst_elements[ident] = bitfieldExtract(src_elements[ident_src], int((ident % inputByteWidth) * inputBitWidth), int(inputBitWidth)) + baseVertex;\n" - "}\n"; - - - typedef struct { - GLuint baseVertex; - GLuint elementCount; - GLuint inputBitWidth; -} data_buffer_t; + GLuint count; + GLuint instanceCount; + GLuint firstIndex; + GLint baseVertex; + GLuint reservedMustBeZero; +} indirect_pass_t; void basevertex_init(context_t* context) { basevertex_renderer_t *renderer = &context->basevertex; - while(es3_functions.glGetError() != 0) {} - GLuint offset_shader = es3_functions.glCreateShader(GL_COMPUTE_SHADER); - es3_functions.glShaderSource(offset_shader, 1, &basevertex_offset_shader, NULL); - es3_functions.glCompileShader(offset_shader); - GLint comp_status; - es3_functions.glGetShaderiv(offset_shader, GL_COMPILE_STATUS, &comp_status); - if(comp_status != GL_TRUE) { - GLchar infolog[2049]; - es3_functions.glGetShaderInfoLog(offset_shader, 2048, NULL, infolog); - printf("tinywrapper: Failed to compile compute shader: %s\n", infolog); - es3_functions.glDeleteShader(offset_shader); - return; - } - renderer->computeProgram = es3_functions.glCreateProgram(); - es3_functions.glAttachShader(renderer->computeProgram, offset_shader); - es3_functions.glLinkProgram(renderer->computeProgram); - es3_functions.glDeleteShader(offset_shader); - es3_functions.glGetProgramiv(renderer->computeProgram, GL_LINK_STATUS, &comp_status); - if(comp_status != GL_TRUE) { - GLchar infolog[2049]; - es3_functions.glGetProgramInfoLog(renderer->computeProgram, 2048, NULL, infolog); - printf("tinywrapper: Failed to link compute program: %s\n", infolog); - es3_functions.glDeleteProgram(offset_shader); - return; - } + es3_functions.glGenBuffers(1, &renderer->indirectRenderBuffer); GLenum error = es3_functions.glGetError(); if(error != GL_NO_ERROR) { - printf("tinywrapper: Failed to initialize compute shader: %x\n", error); - return; - } - while(es3_functions.glGetError() != 0) {} - es3_functions.glGenBuffers(1, &renderer->computeIndexBuffer); - es3_functions.glGenBuffers(1, &renderer->computeMetaBuffer); - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeMetaBuffer); - es3_functions.glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data_buffer_t), NULL, GL_DYNAMIC_DRAW); - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - error = es3_functions.glGetError(); - if(error != GL_NO_ERROR) { - printf("tinywrapper: Failed to initialize compute buffers: %x\n", error); + printf("tinywrapper: Failed to initialize indirect buffers: %x\n", error); return; } renderer->ready = true; } -GLint type_bits(GLenum type) { - switch (type) { - case GL_UNSIGNED_BYTE: return 8; - case GL_UNSIGNED_SHORT: return 16; - case GL_UNSIGNED_INT: return 32; - default: return -1; - } -} - GLint type_bytes(GLenum type) { switch (type) { case GL_UNSIGNED_BYTE: return 1; @@ -102,50 +34,8 @@ GLint type_bytes(GLenum type) { } } - static void restore_state(GLuint element_buffer) { - unordered_map* ssbos = current_context->bound_basebuffers[get_base_buffer_index(GL_SHADER_STORAGE_BUFFER)]; - if(unordered_map_size(ssbos) != 0) { - unordered_map_iterator iterator; - unordered_map_iterator_alloc_local(ssbos, &iterator); - void *k; - basebuffer_binding_t *v; - while(unordered_map_iterator_next(&iterator, &k, (void*)&v)) { - if(v->ranged) es3_functions.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, (GLuint)k, v->buffer, v->offset, v->size); - else es3_functions.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, (GLuint)k, v->buffer); - } - } - es3_functions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 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); + es3_functions.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, current_context->bound_buffers[get_buffer_index(GL_DRAW_INDIRECT_BUFFER)]); } void glDrawElementsBaseVertex(GLenum mode, @@ -163,16 +53,27 @@ void glDrawElementsBaseVertex(GLenum mode, printf("tinywrapper: Base vertex draws without element buffer are not supported\n"); return; } - - glDrawElementsBaseVertex_inner(renderer, mode, count, type, indices, basevertex, elementbuffer); - + GLint typeBytes = type_bytes(type); + uintptr_t indicesPointer = (uintptr_t)indices; + if(indicesPointer % typeBytes != 0) { + printf("tinywrapper: misaligned base vertex draw not supported\n"); + } + indirect_pass_t indirect_pass; + indirect_pass.count = count; + indirect_pass.firstIndex = indicesPointer / typeBytes; + indirect_pass.baseVertex = basevertex; + indirect_pass.instanceCount = 1; + indirect_pass.reservedMustBeZero = 0; + es3_functions.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, renderer->indirectRenderBuffer); + es3_functions.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirect_pass_t), &indirect_pass, GL_STREAM_DRAW); + es3_functions.glDrawElementsIndirect(mode, type, 0); restore_state(elementbuffer); } void glMultiDrawElementsBaseVertex(GLenum mode, - const GLsizei *count, + const GLsizei *count, GLenum type, const void * const *indices, GLsizei drawcount, @@ -187,63 +88,25 @@ void glMultiDrawElementsBaseVertex(GLenum mode, printf("tinywrapper: Base vertex draws without element buffer are not supported\n"); return; } - + GLint typeBytes = type_bytes(type); + indirect_pass_t indirect_passes[drawcount]; for(GLsizei i = 0; i < drawcount; i++) { - glDrawElementsBaseVertex_inner(renderer, mode, count[i], type, (void*)indices[i], basevertex[i], elementbuffer); + uintptr_t indicesPointer = (uintptr_t)indices[i]; + if(indicesPointer % typeBytes != 0) { + printf("tinywrapper: misaligned base vertex draw not supported (draw %i)\n", i); + return; + } + indirect_pass_t* pass = &indirect_passes[i]; + pass->count = count[i]; + pass->firstIndex = indicesPointer / typeBytes; + pass->baseVertex = basevertex[i]; + pass->instanceCount = 1; + pass->reservedMustBeZero = 0; + } + es3_functions.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, renderer->indirectRenderBuffer); + es3_functions.glBufferData(GL_DRAW_INDIRECT_BUFFER, (long)sizeof(indirect_pass_t) * drawcount, indirect_passes, GL_STREAM_DRAW); + for(GLsizei i = 0; i < drawcount; i++) { + es3_functions.glDrawElementsIndirect(mode, type, (void*)(sizeof(indirect_pass_t) * i)); } - 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, - GLenum type, - const void * const *indices, - GLsizei drawcount, - const GLint *basevertex) { - 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; - } - 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_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; - for (int i = 0; i < drawcount; i++) { - GLsizei local_count = count[i]; - uintptr_t local_indices = (uintptr_t)indices[i]; - GLint local_basevertex = basevertex[i]; - es3_functions.glBindBuffer(GL_SHADER_STORAGE_BUFFER, renderer->computeMetaBuffer); - buffer_info.elementCount = local_count; - buffer_info.baseVertex = local_basevertex; - es3_functions.glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data_buffer_t), &buffer_info); - 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.glDispatchCompute((local_count + (256-1))/256, 1, 1); - inserted_count += local_count; - } - 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/egl.h b/app/src/main/tinywrapper/egl.h index 55f73ce..497a03e 100644 --- a/app/src/main/tinywrapper/egl.h +++ b/app/src/main/tinywrapper/egl.h @@ -10,16 +10,14 @@ #include "proc.h" #include "unordered_map/unordered_map.h" -#define MAX_BOUND_BUFFERS 8 +#define MAX_BOUND_BUFFERS 9 #define MAX_BOUND_BASEBUFFERS 4 #define MAX_DRAWBUFFERS 8 #define MAX_FBTARGETS 8 typedef struct { bool ready; - GLuint computeIndexBuffer; - GLuint computeMetaBuffer; - GLuint computeProgram; + GLuint indirectRenderBuffer; } basevertex_renderer_t; typedef struct { diff --git a/app/src/main/tinywrapper/es3_extended.h b/app/src/main/tinywrapper/es3_extended.h index ac8db0b..7a34185 100644 --- a/app/src/main/tinywrapper/es3_extended.h +++ b/app/src/main/tinywrapper/es3_extended.h @@ -1,4 +1,4 @@ // Added manually as needed -GLESFUNC(glDispatchCompute,PFNGLDISPATCHCOMPUTEPROC) +GLESFUNC(glDrawElementsIndirect,PFNGLDRAWELEMENTSINDIRECTPROC) GLESFUNC(glMultiDrawArraysEXT,PFNGLMULTIDRAWARRAYSEXTPROC) GLESFUNC(glMultiDrawElementsEXT,PFNGLMULTIDRAWELEMENTSEXTPROC) \ No newline at end of file diff --git a/app/src/main/tinywrapper/es3_overrides.h b/app/src/main/tinywrapper/es3_overrides.h index 686aa01..cb4e33c 100644 --- a/app/src/main/tinywrapper/es3_overrides.h +++ b/app/src/main/tinywrapper/es3_overrides.h @@ -21,6 +21,11 @@ void glMultiDrawElementsBaseVertex( GLenum mode, void glBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name); +void glGetTexImage( GLenum target, + GLint level, + GLenum format, + GLenum type, + void * pixels); GLESOVERRIDE(glClearDepth) GLESOVERRIDE(glMapBuffer) @@ -55,4 +60,5 @@ GLESOVERRIDE(glReadPixels) GLESOVERRIDE(glTexSubImage2D) GLESOVERRIDE(glCopyTexSubImage2D) GLESOVERRIDE(glTexParameteri) -GLESOVERRIDE(glBindFragDataLocation) \ No newline at end of file +GLESOVERRIDE(glBindFragDataLocation) +GLESOVERRIDE(glGetTexImage) \ No newline at end of file diff --git a/app/src/main/tinywrapper/main.c b/app/src/main/tinywrapper/main.c index 604db3c..875a645 100644 --- a/app/src/main/tinywrapper/main.c +++ b/app/src/main/tinywrapper/main.c @@ -125,7 +125,7 @@ const GLubyte* glGetString(GLenum name) { case GL_VERSION: return (const GLubyte*)"3.0 tinywrapper"; case GL_SHADING_LANGUAGE_VERSION: - return (const GLubyte*)"150 tinywrapper"; + return (const GLubyte*)"1.50 tinywrapper"; default: return es3_functions.glGetString(name); } @@ -146,6 +146,7 @@ int get_buffer_index(GLenum buffer) { case GL_TRANSFORM_FEEDBACK_BUFFER: return 5; case GL_UNIFORM_BUFFER: return 6; case GL_SHADER_STORAGE_BUFFER: return 7; + case GL_DRAW_INDIRECT_BUFFER: return 8; default: return -1; } } diff --git a/app/src/main/tinywrapper/of_buffer_copier.c b/app/src/main/tinywrapper/of_buffer_copier.c index 453848c..57f9a94 100644 --- a/app/src/main/tinywrapper/of_buffer_copier.c +++ b/app/src/main/tinywrapper/of_buffer_copier.c @@ -47,8 +47,9 @@ static GLenum get_target_query_param(GLenum target) { case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return GL_TEXTURE_BINDING_CUBE_MAP; + default: + return GL_NONE; } - return GL_NONE; } static void buffer_copier_release(GLenum target, GLint level, GLint x, GLint y, GLsizei w, GLsizei h) { @@ -66,6 +67,14 @@ static void buffer_copier_release(GLenum target, GLint level, GLint x, GLint y, es3_functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, current_context->read_framebuffer); } +void glGetTexImage( GLenum target, + GLint level, + GLenum format, + GLenum type, + void * pixels) { + printf("glGetTexImage(%x, %i, %x, %x, %p)\n", target, level, format, type, pixels); +} + void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * data) { if(!current_context) return; if(format == GL_DEPTH_COMPONENT) { diff --git a/app/src/main/tinywrapper/shader_wrapper.c b/app/src/main/tinywrapper/shader_wrapper.c index 7fe33e7..33c333c 100644 --- a/app/src/main/tinywrapper/shader_wrapper.c +++ b/app/src/main/tinywrapper/shader_wrapper.c @@ -125,7 +125,6 @@ void glLinkProgram(GLuint program) { return; fallthrough: es3_functions.glLinkProgram(program); - return; } GLuint glCreateShader(GLenum shaderType) { @@ -171,7 +170,7 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, co target_string[target_length] = 0; #undef SRC_LEN - GLchar* new_source = optimize_shader(target_string, shader_info->shader_type == GL_VERTEX_SHADER, 330, 300); + GLchar* new_source = optimize_shader(target_string, shader_info->shader_type == GL_VERTEX_SHADER, 410, 300); //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;