From fd836c00dd3bc9000e3083060a76c885f137f9a0 Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Sun, 5 Feb 2023 21:03:16 +0100 Subject: [PATCH] canvas renderer: parallel tiling pass and sorting pass --- .gitignore | 22 +- build.bat | 2 +- examples/win_canvas/main.c | 10 + src/gles_canvas.c | 144 ++++++++- src/gles_canvas_shaders.h | 293 ------------------ .../gles_canvas_blit_fragment.glsl | 13 + ...rtex.glsl => gles_canvas_blit_vertex.glsl} | 3 + .../gles_canvas_clear_counters.glsl | 15 + ...as_fragment.glsl => gles_canvas_draw.glsl} | 84 +++-- src/gles_canvas_shaders/gles_canvas_sort.glsl | 83 +++++ src/gles_canvas_shaders/gles_canvas_tile.glsl | 62 ++-- src/win32_gles_surface.c | 1 + 12 files changed, 352 insertions(+), 380 deletions(-) delete mode 100644 src/gles_canvas_shaders.h create mode 100644 src/gles_canvas_shaders/gles_canvas_blit_fragment.glsl rename src/gles_canvas_shaders/{gles_canvas_vertex.glsl => gles_canvas_blit_vertex.glsl} (83%) create mode 100644 src/gles_canvas_shaders/gles_canvas_clear_counters.glsl rename src/gles_canvas_shaders/{gles_canvas_fragment.glsl => gles_canvas_draw.glsl} (70%) create mode 100644 src/gles_canvas_shaders/gles_canvas_sort.glsl diff --git a/.gitignore b/.gitignore index d0568ac..3b95f2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ -.DS_Store -*.dSYM -bin/* -*.metallib - -*.pdb -*.exe -*.ilk -*.vs -*.obj \ No newline at end of file +.DS_Store +*.dSYM +bin/* +*.metallib + +*.pdb +*.exe +*.ilk +*.vs +*.obj + +src/gles_canvas_shaders.h \ No newline at end of file diff --git a/build.bat b/build.bat index ed255b8..0d36a88 100644 --- a/build.bat +++ b/build.bat @@ -1,7 +1,7 @@ if not exist bin mkdir bin -set gles_shaders=src\gles_canvas_shaders\gles_canvas_fragment.glsl src\gles_canvas_shaders\gles_canvas_vertex.glsl src\gles_canvas_shaders\gles_canvas_tile.glsl +set gles_shaders=src\gles_canvas_shaders\gles_canvas_blit_vertex.glsl src\gles_canvas_shaders\gles_canvas_blit_fragment.glsl src\gles_canvas_shaders\gles_canvas_clear_counters.glsl src\gles_canvas_shaders\gles_canvas_tile.glsl src\gles_canvas_shaders\gles_canvas_sort.glsl src\gles_canvas_shaders\gles_canvas_draw.glsl call python scripts\embed_text.py %gles_shaders% --output src\gles_canvas_shaders.h set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers diff --git a/examples/win_canvas/main.c b/examples/win_canvas/main.c index 644abc9..b6af770 100644 --- a/examples/win_canvas/main.c +++ b/examples/win_canvas/main.c @@ -183,6 +183,7 @@ int main() mg_ellipse_fill(x+70, y+50, 30, 50); // text +//* mg_set_color_rgba(0, 0, 1, 1); mg_set_font(font); mg_set_font_size(12); @@ -193,12 +194,21 @@ int main() frameTime, 1./frameTime); mg_text_outlines(text); +//*/ mg_fill(); +//* + printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", + frameTime, + 1./frameTime); +//*/ + /* mg_set_color_rgba(1, 1, 0, 1); mg_rectangle_fill(8, 8, 100, 50); */ + + mg_flush(); mg_surface_present(surface); diff --git a/src/gles_canvas.c b/src/gles_canvas.c index 1865e14..fef4702 100644 --- a/src/gles_canvas.c +++ b/src/gles_canvas.c @@ -22,8 +22,13 @@ typedef struct mg_gles_canvas_backend GLint indexBuffer; GLint tileCounterBuffer; GLint tileArrayBuffer; + GLint clearCounterProgram; GLint tileProgram; + GLint sortProgram; GLint drawProgram; + GLint blitProgram; + + GLint outTexture; char* indexMapping; char* vertexMapping; @@ -170,8 +175,16 @@ void mg_gles_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u3 //TODO: ensure there's enough space in tile buffer + //NOTE: first clear counters +/* + glUseProgram(backend->clearCounterProgram); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->tileCounterBuffer); + glDispatchCompute(tileCountX*tileCountY, 1, 1); +*/ //NOTE: we first distribute triangles into tiles: +/* glUseProgram(backend->tileProgram); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileCounterBuffer); @@ -182,26 +195,55 @@ void mg_gles_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u3 glUniform1ui(2, tileSize); glUniform1ui(3, tileArraySize); - glDispatchCompute(tileCountX, tileCountY, 1); + glDispatchCompute(indexCount/3, 1, 1); +*/ + //NOTE: next we sort triangles in each tile +/* + glUseProgram(backend->sortProgram); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileCounterBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileArrayBuffer); + + glUniform1ui(0, indexCount); + glUniform2ui(1, tileCountX, tileCountY); + glUniform1ui(2, tileSize); + glUniform1ui(3, tileArraySize); + + glDispatchCompute(tileCountX * tileCountY, 1, 1); +*/ //TODO: then we fire the fragment shader that will select only triangles in its tile // glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glUseProgram(backend->drawProgram); - glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer); +/* glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileCounterBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileArrayBuffer); +*/ +/* + glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glUniform1ui(0, indexCount); glUniform2ui(1, tileCountX, tileCountY); glUniform1ui(2, tileSize); glUniform1ui(3, tileArraySize); +*/ + glDispatchCompute(tileCountX, tileCountY, 1); + + //NOTE: now blit out texture to surface +/* + glUseProgram(backend->blitProgram); + glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, backend->outTexture); + glUniform1i(0, 0); glDrawArrays(GL_TRIANGLES, 0, 6); - +*/ mg_gles_canvas_update_vertex_layout(backend); } @@ -217,7 +259,7 @@ void mg_gles_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8* //TODO } -void compile_shader(GLuint shader, const char* source) +static void mg_gles_compile_shader(GLuint shader, const char* source) { glShaderSource(shader, 1, &source, 0); glCompileShader(shader); @@ -284,12 +326,40 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface) glGenBuffers(1, &backend->dummyVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer); + mp_rect frame = mg_surface_get_frame(backend->surface); + glGenTextures(1, &backend->outTexture); + glBindTexture(GL_TEXTURE_2D, backend->outTexture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, frame.w, frame.h); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + //NOTE: create clear program + { + GLuint clearShader = glCreateShader(GL_COMPUTE_SHADER); + backend->clearCounterProgram = glCreateProgram(); + + mg_gles_compile_shader(clearShader, gles_canvas_clear_counters); + + glAttachShader(backend->clearCounterProgram, clearShader); + glLinkProgram(backend->clearCounterProgram); + + int status = 0; + glGetProgramiv(backend->clearCounterProgram, GL_LINK_STATUS, &status); + if(!status) + { + char buffer[256]; + int size = 0; + glGetProgramInfoLog(backend->clearCounterProgram, 256, &size, buffer); + printf("link error in gl_canvas_clear_counters: %.*s\n", size, buffer); + exit(-1); + } + } //NOTE: create tile program { GLuint tileShader = glCreateShader(GL_COMPUTE_SHADER); backend->tileProgram = glCreateProgram(); - compile_shader(tileShader, gles_canvas_tile); + mg_gles_compile_shader(tileShader, gles_canvas_tile); glAttachShader(backend->tileProgram, tileShader); glLinkProgram(backend->tileProgram); @@ -301,20 +371,40 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface) char buffer[256]; int size = 0; glGetProgramInfoLog(backend->tileProgram, 256, &size, buffer); - printf("link error: %.*s\n", size, buffer); + printf("link error in gl_canvas_tile: %.*s\n", size, buffer); + exit(-1); } } + //NOTE: create sort program + { + GLuint sortShader = glCreateShader(GL_COMPUTE_SHADER); + backend->sortProgram = glCreateProgram(); + + mg_gles_compile_shader(sortShader, gles_canvas_sort); + + glAttachShader(backend->sortProgram, sortShader); + glLinkProgram(backend->sortProgram); + + int status = 0; + glGetProgramiv(backend->sortProgram, GL_LINK_STATUS, &status); + if(!status) + { + char buffer[256]; + int size = 0; + glGetProgramInfoLog(backend->sortProgram, 256, &size, buffer); + printf("link error gl_canvas_sort: %.*s\n", size, buffer); + exit(-1); + } + } + //NOTE: create draw program { - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + GLuint shader = glCreateShader(GL_COMPUTE_SHADER); backend->drawProgram = glCreateProgram(); - compile_shader(vertexShader, gles_canvas_vertex); - compile_shader(fragmentShader, gles_canvas_fragment); + mg_gles_compile_shader(shader, gles_canvas_draw); - glAttachShader(backend->drawProgram, vertexShader); - glAttachShader(backend->drawProgram, fragmentShader); + glAttachShader(backend->drawProgram, shader); glLinkProgram(backend->drawProgram); int status = 0; @@ -324,7 +414,33 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface) char buffer[256]; int size = 0; glGetProgramInfoLog(backend->drawProgram, 256, &size, buffer); - printf("link error: %.*s\n", size, buffer); + printf("link error gl_canvas_draw: %.*s\n", size, buffer); + exit(-1); + } + } + + //NOTE: create blit program + { + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + backend->blitProgram = glCreateProgram(); + + mg_gles_compile_shader(vertexShader, gles_canvas_blit_vertex); + mg_gles_compile_shader(fragmentShader, gles_canvas_blit_fragment); + + glAttachShader(backend->blitProgram, vertexShader); + glAttachShader(backend->blitProgram, fragmentShader); + glLinkProgram(backend->blitProgram); + + int status = 0; + glGetProgramiv(backend->blitProgram, GL_LINK_STATUS, &status); + if(!status) + { + char buffer[256]; + int size = 0; + glGetProgramInfoLog(backend->blitProgram, 256, &size, buffer); + printf("link error gl_canvas_blit: %.*s\n", size, buffer); + exit(-1); } } diff --git a/src/gles_canvas_shaders.h b/src/gles_canvas_shaders.h deleted file mode 100644 index 9cce15f..0000000 --- a/src/gles_canvas_shaders.h +++ /dev/null @@ -1,293 +0,0 @@ -/********************************************************************* -* -* file: gles_canvas_shaders.h -* note: string literals auto-generated by embed_text.py -* date: 03/022023 -* -**********************************************************************/ -#ifndef __GLES_CANVAS_SHADERS_H__ -#define __GLES_CANVAS_SHADERS_H__ - - -//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_fragment.glsl -const char* gles_canvas_fragment = -"#version 310 es\n" -"\n" -"precision mediump float;\n" -"layout(std430) buffer;\n" -"\n" -"struct vertex {\n" -" vec2 pos;\n" -" vec4 cubic;\n" -" vec2 uv;\n" -" vec4 color;\n" -" vec4 clip;\n" -" int zIndex;\n" -"};\n" -"\n" -"layout(binding = 0) buffer vertexBufferSSBO {\n" -" vertex elements[];\n" -"} vertexBuffer ;\n" -"\n" -"layout(binding = 1) buffer indexBufferSSBO {\n" -" uint elements[];\n" -"} indexBuffer ;\n" -"\n" -"layout(binding = 2) coherent buffer tileCounterBufferSSBO {\n" -" uint elements[];\n" -"} tileCounterBuffer ;\n" -"\n" -"layout(binding = 3) coherent buffer tileArrayBufferSSBO {\n" -" uint elements[];\n" -"} tileArrayBuffer ;\n" -"\n" -"layout(location = 0) uniform uint indexCount;\n" -"layout(location = 1) uniform uvec2 tileCount;\n" -"layout(location = 2) uniform uint tileSize;\n" -"layout(location = 3) uniform uint tileArraySize;\n" -"\n" -"layout(location = 0) out vec4 fragColor;\n" -"\n" -"\n" -"bool is_top_left(ivec2 a, ivec2 b)\n" -"{\n" -" return( (a.y == b.y && b.x < a.x)\n" -" ||(b.y < a.y));\n" -"}\n" -"\n" -"int orient2d(ivec2 a, ivec2 b, ivec2 p)\n" -"{\n" -" return((b.x-a.x)*(p.y-a.y) - (b.y-a.y)*(p.x-a.x));\n" -"}\n" -"\n" -"void main()\n" -"{\n" -" uvec2 tileCoord = uvec2(gl_FragCoord.xy)/tileSize;\n" -" uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x;\n" -" uint tileCounter = tileCounterBuffer.elements[tileIndex];\n" -"\n" -" const float subPixelFactor = 16.;\n" -" const int sampleCount = 8;\n" -"\n" -" ivec2 centerPoint = ivec2(round(gl_FragCoord.xy * subPixelFactor));\n" -" ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3),\n" -" centerPoint + ivec2(-1, -3),\n" -" centerPoint + ivec2(5, -1),\n" -" centerPoint + ivec2(-3, 5),\n" -" centerPoint + ivec2(-5, -5),\n" -" centerPoint + ivec2(-7, 1),\n" -" centerPoint + ivec2(3, -7),\n" -" centerPoint + ivec2(7, 7));\n" -"\n" -"\n" -" //DEBUG\n" -"/*\n" -" if( int(gl_FragCoord.x - 0.5) % 16 == 0\n" -" ||int(gl_FragCoord.y - 0.5) % 16 == 0)\n" -" {\n" -" fragColor = vec4(0, 0, 0, 1);\n" -" }\n" -" else if(tileCounterBuffer.elements[tileIndex] == 2u)\n" -" {\n" -" fragColor = vec4(1, 1, 0, 1);\n" -" }\n" -" else if(tileCounter != 0u)\n" -" {\n" -" fragColor = vec4(0, 1, 0, 1);\n" -" }\n" -" else\n" -" {\n" -" fragColor = vec4(1, 0, 0, 1);\n" -" }\n" -" return;\n" -"//*/\n" -" //----\n" -"\n" -" vec4 sampleColor[sampleCount];\n" -" vec4 currentColor[sampleCount];\n" -" int currentZIndex[sampleCount];\n" -" int flipCount[sampleCount];\n" -"\n" -" for(int i=0; i= 0 && (w1+bias1) >= 0 && (w2+bias2) >= 0)\n" -" {\n" -" vec4 cubic = (cubic0*float(w0) + cubic1*float(w1) + cubic2*float(w2))/(float(w0)+float(w1)+float(w2));\n" -"\n" -" float eps = 0.0001;\n" -" if(cubic.w*(cubic.x*cubic.x*cubic.x - cubic.y*cubic.z) <= eps)\n" -" {\n" -" if(zIndex == currentZIndex[sampleIndex])\n" -" {\n" -" flipCount[sampleIndex]++;\n" -" }\n" -" else\n" -" {\n" -" if((flipCount[sampleIndex] & 0x01) != 0)\n" -" {\n" -" sampleColor[sampleIndex] = currentColor[sampleIndex];\n" -" }\n" -" currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-color.a) + color.a*color;\n" -" currentZIndex[sampleIndex] = zIndex;\n" -" flipCount[sampleIndex] = 1;\n" -" }\n" -" }\n" -" }\n" -" }\n" -" }\n" -" vec4 pixelColor = vec4(0);\n" -" for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)\n" -" {\n" -" if((flipCount[sampleIndex] & 0x01) != 0)\n" -" {\n" -" sampleColor[sampleIndex] = currentColor[sampleIndex];\n" -" }\n" -" pixelColor += sampleColor[sampleIndex];\n" -" }\n" -" fragColor = pixelColor/float(sampleCount);\n" -"}\n"; - -//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_vertex.glsl -const char* gles_canvas_vertex = -"#version 310 es\n" -"\n" -"precision mediump float;\n" -"\n" -"void main()\n" -"{\n" -" float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);\n" -" float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);\n" -"\n" -" gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n" -"}\n"; - -//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_tile.glsl -const char* gles_canvas_tile = -"#version 310 es\n" -"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" -"\n" -"precision mediump float;\n" -"layout(std430) buffer;\n" -"\n" -"struct vertex {\n" -" vec2 pos;\n" -" vec4 cubic;\n" -" vec2 uv;\n" -" vec4 color;\n" -" vec4 clip;\n" -" int zIndex;\n" -"};\n" -"\n" -"layout(binding = 0) buffer vertexBufferSSBO {\n" -" vertex elements[];\n" -"} vertexBuffer ;\n" -"\n" -"layout(binding = 1) buffer indexBufferSSBO {\n" -" uint elements[];\n" -"} indexBuffer ;\n" -"\n" -"layout(binding = 2) coherent buffer tileCounterBufferSSBO {\n" -" uint elements[];\n" -"} tileCounterBuffer ;\n" -"\n" -"layout(binding = 3) coherent buffer tileArrayBufferSSBO {\n" -" uint elements[];\n" -"} tileArrayBuffer ;\n" -"\n" -"layout(location = 0) uniform uint indexCount;\n" -"layout(location = 1) uniform uvec2 tileCount;\n" -"layout(location = 2) uniform uint tileSize;\n" -"layout(location = 3) uniform uint tileArraySize;\n" -"\n" -"void main()\n" -"{\n" -" uint tileIndex = gl_WorkGroupID.y * tileCount.x + gl_WorkGroupID.x;\n" -" uint tileArrayOffset = tileArraySize * tileIndex;\n" -"\n" -" vec4 tileBox = vec4(gl_WorkGroupID.x * tileSize,\n" -" gl_WorkGroupID.y * tileSize,\n" -" gl_WorkGroupID.x * tileSize + tileSize,\n" -" gl_WorkGroupID.y * tileSize + tileSize);\n" -"\n" -" uint tileCounter = 0u;\n" -"\n" -" for(uint triangleIndex = 0u; triangleIndex < indexCount; triangleIndex += 3u)\n" -" {\n" -" uint i0 = indexBuffer.elements[triangleIndex];\n" -" uint i1 = indexBuffer.elements[triangleIndex+1u];\n" -" uint i2 = indexBuffer.elements[triangleIndex+2u];\n" -"\n" -" vec2 p0 = vertexBuffer.elements[i0].pos;\n" -" vec2 p1 = vertexBuffer.elements[i1].pos;\n" -" vec2 p2 = vertexBuffer.elements[i2].pos;\n" -"\n" -" vec4 bbox = vec4(min(min(p0.x, p1.x), p2.x),\n" -" min(min(p0.y, p1.y), p2.y),\n" -" max(max(p0.x, p1.x), p2.x),\n" -" max(max(p0.y, p1.y), p2.y));\n" -"\n" -" if(!( bbox.x > tileBox.z\n" -" || bbox.z < tileBox.x\n" -" || bbox.y > tileBox.w\n" -" || bbox.w < tileBox.y))\n" -" {\n" -" tileArrayBuffer.elements[tileArrayOffset + tileCounter] = triangleIndex;\n" -" tileCounter++;\n" -" }\n" -" }\n" -" tileCounterBuffer.elements[tileIndex] = tileCounter;\n" -"\n" -"// tileCounterBuffer.elements[tileIndex] = 1u;\n" -"}\n"; - -#endif // __GLES_CANVAS_SHADERS_H__ diff --git a/src/gles_canvas_shaders/gles_canvas_blit_fragment.glsl b/src/gles_canvas_shaders/gles_canvas_blit_fragment.glsl new file mode 100644 index 0000000..910bd96 --- /dev/null +++ b/src/gles_canvas_shaders/gles_canvas_blit_fragment.glsl @@ -0,0 +1,13 @@ +#version 310 es + +precision mediump float; + +in vec2 uv; +out vec4 fragColor; + +layout(location=0) uniform sampler2D tex; + +void main() +{ + fragColor = texture(tex, uv); +} diff --git a/src/gles_canvas_shaders/gles_canvas_vertex.glsl b/src/gles_canvas_shaders/gles_canvas_blit_vertex.glsl similarity index 83% rename from src/gles_canvas_shaders/gles_canvas_vertex.glsl rename to src/gles_canvas_shaders/gles_canvas_blit_vertex.glsl index fb1eb4f..e4af48a 100644 --- a/src/gles_canvas_shaders/gles_canvas_vertex.glsl +++ b/src/gles_canvas_shaders/gles_canvas_blit_vertex.glsl @@ -2,10 +2,13 @@ precision mediump float; +out vec2 uv; + void main() { float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u); float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u); gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f); + uv = vec2(x, y); } diff --git a/src/gles_canvas_shaders/gles_canvas_clear_counters.glsl b/src/gles_canvas_shaders/gles_canvas_clear_counters.glsl new file mode 100644 index 0000000..9e7fd01 --- /dev/null +++ b/src/gles_canvas_shaders/gles_canvas_clear_counters.glsl @@ -0,0 +1,15 @@ +#version 310 es +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +precision mediump float; +layout(std430) buffer; + +layout(binding = 0) coherent restrict writeonly buffer tileCounterBufferSSBO { + uint elements[]; +} tileCounterBuffer ; + +void main() +{ + uint tileIndex = gl_WorkGroupID.x; + tileCounterBuffer.elements[tileIndex] = 0u; +} diff --git a/src/gles_canvas_shaders/gles_canvas_fragment.glsl b/src/gles_canvas_shaders/gles_canvas_draw.glsl similarity index 70% rename from src/gles_canvas_shaders/gles_canvas_fragment.glsl rename to src/gles_canvas_shaders/gles_canvas_draw.glsl index ca1b0b6..a7f1556 100644 --- a/src/gles_canvas_shaders/gles_canvas_fragment.glsl +++ b/src/gles_canvas_shaders/gles_canvas_draw.glsl @@ -1,6 +1,9 @@ #version 310 es +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; precision mediump float; +precision mediump image2D; + layout(std430) buffer; struct vertex { @@ -12,19 +15,19 @@ struct vertex { int zIndex; }; -layout(binding = 0) buffer vertexBufferSSBO { +layout(binding = 0) restrict readonly buffer vertexBufferSSBO { vertex elements[]; } vertexBuffer ; -layout(binding = 1) buffer indexBufferSSBO { +layout(binding = 1) restrict readonly buffer indexBufferSSBO { uint elements[]; } indexBuffer ; -layout(binding = 2) coherent buffer tileCounterBufferSSBO { +layout(binding = 2) restrict readonly buffer tileCounterBufferSSBO { uint elements[]; } tileCounterBuffer ; -layout(binding = 3) coherent buffer tileArrayBufferSSBO { +layout(binding = 3) restrict readonly buffer tileArrayBufferSSBO { uint elements[]; } tileArrayBuffer ; @@ -32,9 +35,14 @@ layout(location = 0) uniform uint indexCount; layout(location = 1) uniform uvec2 tileCount; layout(location = 2) uniform uint tileSize; layout(location = 3) uniform uint tileArraySize; +layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture; -layout(location = 0) out vec4 fragColor; +void main() +{} + + +#if 0 bool is_top_left(ivec2 a, ivec2 b) { @@ -49,14 +57,21 @@ int orient2d(ivec2 a, ivec2 b, ivec2 p) void main() { - uvec2 tileCoord = uvec2(gl_FragCoord.xy)/tileSize; + ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy); + + imageStore(outTexture, pixelCoord, vec4(1, 0, 1, 1)); + return; + + uvec2 tileCoord = uvec2(pixelCoord) / tileSize; + uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x; uint tileCounter = tileCounterBuffer.elements[tileIndex]; const float subPixelFactor = 16.; - const int sampleCount = 8; + ivec2 centerPoint = ivec2(round((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor)); - ivec2 centerPoint = ivec2(round(gl_FragCoord.xy * subPixelFactor)); +/* + const int sampleCount = 8; ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3), centerPoint + ivec2(-1, -3), centerPoint + ivec2(5, -1), @@ -65,28 +80,38 @@ void main() centerPoint + ivec2(-7, 1), centerPoint + ivec2(3, -7), centerPoint + ivec2(7, 7)); - - +*/ + const int sampleCount = 4; + ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(-2, 6), + centerPoint + ivec2(6, 2), + centerPoint + ivec2(-6, -2), + centerPoint + ivec2(2, -6)); //DEBUG +//* + { + vec4 fragColor = vec4(0); /* - if( int(gl_FragCoord.x - 0.5) % 16 == 0 - ||int(gl_FragCoord.y - 0.5) % 16 == 0) - { - fragColor = vec4(0, 0, 0, 1); + if( pixelCoord.x % 16 == 0 + ||pixelCoord.y % 16 == 0) + { + fragColor = vec4(0, 0, 0, 1); + } + else if(tileCounterBuffer.elements[tileIndex] == 0xffffu) + { + fragColor = vec4(1, 0, 1, 1); + } + else if(tileCounter != 0u) + { + fragColor = vec4(0, 1, 0, 1); + } + else + { + fragColor = vec4(1, 0, 0, 1); + } +*/ + imageStore(outTexture, pixelCoord, fragColor); + return; } - else if(tileCounterBuffer.elements[tileIndex] == 2u) - { - fragColor = vec4(1, 1, 0, 1); - } - else if(tileCounter != 0u) - { - fragColor = vec4(0, 1, 0, 1); - } - else - { - fragColor = vec4(1, 0, 0, 1); - } - return; //*/ //---- @@ -181,5 +206,8 @@ void main() } pixelColor += sampleColor[sampleIndex]; } - fragColor = pixelColor/float(sampleCount); + + imageStore(outTexture, pixelCoord, pixelColor/float(sampleCount)); } + +#endif diff --git a/src/gles_canvas_shaders/gles_canvas_sort.glsl b/src/gles_canvas_shaders/gles_canvas_sort.glsl new file mode 100644 index 0000000..2b3f1df --- /dev/null +++ b/src/gles_canvas_shaders/gles_canvas_sort.glsl @@ -0,0 +1,83 @@ +#version 310 es +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +precision mediump float; +layout(std430) buffer; + +struct vertex { + vec2 pos; + vec4 cubic; + vec2 uv; + vec4 color; + vec4 clip; + int zIndex; +}; + +layout(binding = 0) restrict readonly buffer vertexBufferSSBO { + vertex elements[]; +} vertexBuffer ; + +layout(binding = 1) restrict readonly buffer indexBufferSSBO { + uint elements[]; +} indexBuffer ; + +layout(binding = 2) coherent readonly restrict buffer tileCounterBufferSSBO { + uint elements[]; +} tileCounterBuffer ; + +layout(binding = 3) coherent restrict buffer tileArrayBufferSSBO { + uint elements[]; +} tileArrayBuffer ; + +layout(location = 0) uniform uint indexCount; +layout(location = 1) uniform uvec2 tileCount; +layout(location = 2) uniform uint tileSize; +layout(location = 3) uniform uint tileArraySize; + +int get_zindex(uint tileArrayOffset, uint tileArrayIndex) +{ + uint triangleIndex = tileArrayBuffer.elements[tileArrayOffset + tileArrayIndex]; + uint i0 = indexBuffer.elements[triangleIndex]; + int zIndex = vertexBuffer.elements[i0].zIndex; + return(zIndex); +} + +void main() +{ + uint tileIndex = gl_WorkGroupID.x; + uint tileArrayOffset = tileArraySize * tileIndex; + uint tileArrayCount = tileCounterBuffer.elements[tileIndex]; + + for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++) + { + for(uint sortIndex = tileArrayIndex; sortIndex > 0u; sortIndex--) + { + int zIndex = get_zindex(tileArrayOffset, sortIndex); + int prevZIndex = get_zindex(tileArrayOffset, sortIndex-1u); + + if(zIndex >= prevZIndex) + { + break; + } + uint tmp = tileArrayBuffer.elements[tileArrayOffset + sortIndex]; + tileArrayBuffer.elements[tileArrayOffset + sortIndex] = tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u]; + tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u] = tmp; + } + } + + //DEBUG + /* + int prevZIndex = -1; + for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++) + { + int zIndex = get_zindex(tileArrayOffset, tileArrayIndex); + + if(zIndex < prevZIndex) + { + tileCounterBuffer.elements[tileIndex] = 0xffffu; + break; + } + prevZIndex = zIndex; + } + //*/ +} diff --git a/src/gles_canvas_shaders/gles_canvas_tile.glsl b/src/gles_canvas_shaders/gles_canvas_tile.glsl index b326968..49fd95d 100644 --- a/src/gles_canvas_shaders/gles_canvas_tile.glsl +++ b/src/gles_canvas_shaders/gles_canvas_tile.glsl @@ -13,19 +13,19 @@ struct vertex { int zIndex; }; -layout(binding = 0) buffer vertexBufferSSBO { +layout(binding = 0) restrict readonly buffer vertexBufferSSBO { vertex elements[]; } vertexBuffer ; -layout(binding = 1) buffer indexBufferSSBO { +layout(binding = 1) restrict readonly buffer indexBufferSSBO { uint elements[]; } indexBuffer ; -layout(binding = 2) coherent buffer tileCounterBufferSSBO { +layout(binding = 2) coherent restrict buffer tileCounterBufferSSBO { uint elements[]; } tileCounterBuffer ; -layout(binding = 3) coherent buffer tileArrayBufferSSBO { +layout(binding = 3) coherent restrict writeonly buffer tileArrayBufferSSBO { uint elements[]; } tileArrayBuffer ; @@ -36,41 +36,35 @@ layout(location = 3) uniform uint tileArraySize; void main() { - uint tileIndex = gl_WorkGroupID.y * tileCount.x + gl_WorkGroupID.x; - uint tileArrayOffset = tileArraySize * tileIndex; + uint triangleIndex = gl_WorkGroupID.x * 3u; - vec4 tileBox = vec4(gl_WorkGroupID.x * tileSize, - gl_WorkGroupID.y * tileSize, - gl_WorkGroupID.x * tileSize + tileSize, - gl_WorkGroupID.y * tileSize + tileSize); + uint i0 = indexBuffer.elements[triangleIndex]; + uint i1 = indexBuffer.elements[triangleIndex+1u]; + uint i2 = indexBuffer.elements[triangleIndex+2u]; - uint tileCounter = 0u; + vec2 p0 = vertexBuffer.elements[i0].pos; + vec2 p1 = vertexBuffer.elements[i1].pos; + vec2 p2 = vertexBuffer.elements[i2].pos; - for(uint triangleIndex = 0u; triangleIndex < indexCount; triangleIndex += 3u) + vec4 fbox = vec4(min(min(p0.x, p1.x), p2.x), + min(min(p0.y, p1.y), p2.y), + max(max(p0.x, p1.x), p2.x), + max(max(p0.y, p1.y), p2.y)); + + uvec4 box = uvec4(floor(fbox))/tileSize; + + uint xMin = max(0u, box.x); + uint yMin = max(0u, box.y); + uint xMax = min(box.z, tileCount.x - 1u); + uint yMax = min(box.w, tileCount.y - 1u); + + for(uint y = yMin; y <= yMax; y++) { - uint i0 = indexBuffer.elements[triangleIndex]; - uint i1 = indexBuffer.elements[triangleIndex+1u]; - uint i2 = indexBuffer.elements[triangleIndex+2u]; - - vec2 p0 = vertexBuffer.elements[i0].pos; - vec2 p1 = vertexBuffer.elements[i1].pos; - vec2 p2 = vertexBuffer.elements[i2].pos; - - vec4 bbox = vec4(min(min(p0.x, p1.x), p2.x), - min(min(p0.y, p1.y), p2.y), - max(max(p0.x, p1.x), p2.x), - max(max(p0.y, p1.y), p2.y)); - - if(!( bbox.x > tileBox.z - || bbox.z < tileBox.x - || bbox.y > tileBox.w - || bbox.w < tileBox.y)) + for(uint x = xMin ; x <= xMax; x++) { - tileArrayBuffer.elements[tileArrayOffset + tileCounter] = triangleIndex; - tileCounter++; + uint tileIndex = y*tileCount.x + x; + uint tileCounter = atomicAdd(tileCounterBuffer.elements[tileIndex], 1u); + tileArrayBuffer.elements[tileArraySize*tileIndex + tileCounter] = triangleIndex; } } - tileCounterBuffer.elements[tileIndex] = tileCounter; - -// tileCounterBuffer.elements[tileIndex] = 1u; } diff --git a/src/win32_gles_surface.c b/src/win32_gles_surface.c index 22a6600..ea5b7d9 100644 --- a/src/win32_gles_surface.c +++ b/src/win32_gles_surface.c @@ -125,6 +125,7 @@ mg_surface mg_gles_surface_create_for_window(mp_window window) //TODO: reactivate this when finished testing! // eglSwapInterval(surface->eglDisplay, 1); + eglSwapInterval(surface->eglDisplay, 0); res = mg_surface_alloc_handle((mg_surface_data*)surface); }