diff --git a/examples/win_canvas/main.c b/examples/win_canvas/main.c index 202776f..cb3209b 100644 --- a/examples/win_canvas/main.c +++ b/examples/win_canvas/main.c @@ -80,7 +80,6 @@ int main() f32 x = 400, y = 300; f32 dx = 5, dy = 5; -// f32 dx = 0, dy = 0; f64 frameTime = 0; @@ -168,7 +167,6 @@ int main() mg_circle_fill(x, y, 200); // smile - f32 frown = frameTime > 0.033 ? 100 : 0; mg_set_color_rgba(0, 0, 0, 1); @@ -183,7 +181,6 @@ 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); @@ -195,7 +192,6 @@ int main() 1./frameTime); mg_text_outlines(text); mg_fill(); -//*/ printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", frameTime, diff --git a/src/gl_canvas.c b/src/gl_canvas.c index 44c1c5e..304a508 100644 --- a/src/gl_canvas.c +++ b/src/gl_canvas.c @@ -19,6 +19,7 @@ typedef struct mg_gl_canvas_backend GLint dummyVertexBuffer; GLint vertexBuffer; + GLint shapeBuffer; GLint indexBuffer; GLint tileCounterBuffer; GLint tileArrayBuffer; @@ -32,6 +33,7 @@ typedef struct mg_gl_canvas_backend char* indexMapping; char* vertexMapping; + char* shapeMapping; } mg_gl_canvas_backend; @@ -49,15 +51,19 @@ mg_gl_surface* mg_gl_canvas_get_surface(mg_gl_canvas_backend* canvas) //NOTE: debugger typedef struct debug_vertex { - vec2 pos; - vec2 uv; vec4 cubic; - vec4 color; - vec4 clip; + vec2 pos; int zIndex; - u8 align2[12]; + u8 pad[4]; } debug_vertex; +typedef struct debug_shape +{ + vec4 color; + vec4 clip; + vec2 uv; + u8 pad[8]; +} debug_shape; #define LayoutNext(prevName, prevType, nextType) \ AlignUpOnPow2(_cat3_(LAYOUT_, prevName, _OFFSET)+_cat3_(LAYOUT_, prevType, _SIZE), _cat3_(LAYOUT_, nextType, _ALIGN)) @@ -70,20 +76,23 @@ enum { LAYOUT_INT_SIZE = 4, LAYOUT_INT_ALIGN = 4, - LAYOUT_POS_OFFSET = 0, - LAYOUT_UV_OFFSET = LayoutNext(POS, VEC2, VEC2), - LAYOUT_CUBIC_OFFSET = LayoutNext(UV, VEC2, VEC4), - LAYOUT_COLOR_OFFSET = LayoutNext(CUBIC, VEC4, VEC4), - LAYOUT_CLIP_OFFSET = LayoutNext(COLOR, VEC4, VEC4), - LAYOUT_ZINDEX_OFFSET = LayoutNext(CLIP, VEC4, INT), - + LAYOUT_CUBIC_OFFSET = 0, + LAYOUT_POS_OFFSET = LayoutNext(CUBIC, VEC4, VEC2), + LAYOUT_ZINDEX_OFFSET = LayoutNext(POS, VEC2, INT), LAYOUT_VERTEX_ALIGN = 16, LAYOUT_VERTEX_SIZE = LayoutNext(ZINDEX, INT, VERTEX), + + LAYOUT_COLOR_OFFSET = 0, + LAYOUT_CLIP_OFFSET = LayoutNext(COLOR, VEC4, VEC4), + LAYOUT_UV_OFFSET = LayoutNext(CLIP, VEC4, VEC2), + LAYOUT_SHAPE_ALIGN = 16, + LAYOUT_SHAPE_SIZE = LayoutNext(UV, VEC2, SHAPE) }; enum { MG_GL_CANVAS_DEFAULT_BUFFER_LENGTH = 1<<20, MG_GL_CANVAS_VERTEX_BUFFER_SIZE = MG_GL_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_VERTEX_SIZE, + MG_GL_CANVAS_SHAPE_BUFFER_SIZE = MG_GL_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_SHAPE_SIZE, MG_GL_CANVAS_INDEX_BUFFER_SIZE = MG_GL_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_INT_SIZE, MG_GL_CANVAS_TILE_COUNTER_BUFFER_SIZE = 65536, MG_GL_CANVAS_TILE_ARRAY_SIZE = sizeof(int)*4096, @@ -99,23 +108,28 @@ void mg_gl_canvas_update_vertex_layout(mg_gl_canvas_backend* backend) .posStride = LAYOUT_VERTEX_SIZE, .cubicBuffer = backend->vertexMapping + LAYOUT_CUBIC_OFFSET, .cubicStride = LAYOUT_VERTEX_SIZE, - .uvBuffer = backend->vertexMapping + LAYOUT_UV_OFFSET, - .uvStride = LAYOUT_VERTEX_SIZE, - .colorBuffer = backend->vertexMapping + LAYOUT_COLOR_OFFSET, - .colorStride = LAYOUT_VERTEX_SIZE, - .clipBuffer = backend->vertexMapping + LAYOUT_CLIP_OFFSET, - .clipStride = LAYOUT_VERTEX_SIZE, .zIndexBuffer = backend->vertexMapping + LAYOUT_ZINDEX_OFFSET, .zIndexStride = LAYOUT_VERTEX_SIZE, + + .colorBuffer = backend->shapeMapping + LAYOUT_COLOR_OFFSET, + .colorStride = LAYOUT_SHAPE_SIZE, + .clipBuffer = backend->shapeMapping + LAYOUT_CLIP_OFFSET, + .clipStride = LAYOUT_SHAPE_SIZE, + .uvBuffer = backend->shapeMapping + LAYOUT_UV_OFFSET, + .uvStride = LAYOUT_SHAPE_SIZE, + .indexBuffer = backend->indexMapping, .indexStride = LAYOUT_INT_SIZE}; } -void mg_gl_send_buffers(mg_gl_canvas_backend* backend, int vertexCount, int indexCount) +void mg_gl_send_buffers(mg_gl_canvas_backend* backend, int shapeCount, int vertexCount, int indexCount) { glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->vertexBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, LAYOUT_VERTEX_SIZE*vertexCount, backend->vertexMapping, GL_STREAM_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->shapeBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, LAYOUT_SHAPE_SIZE*shapeCount, backend->shapeMapping, GL_STREAM_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, LAYOUT_INT_SIZE*indexCount, backend->indexMapping, GL_STREAM_DRAW); } @@ -150,7 +164,7 @@ void mg_gl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor) glClear(GL_COLOR_BUFFER_BIT); } -void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 indexCount) +void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 vertexCount, u32 indexCount) { mg_gl_canvas_backend* backend = (mg_gl_canvas_backend*)interface; mg_gl_surface* surface = mg_gl_canvas_get_surface(backend); @@ -161,9 +175,10 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 /*NOTE: if we want debug_vertex while debugging, the following ensures the struct def doesn't get stripped away debug_vertex vertex; - printf("foo %p\n", &vertex); + debug_shape shape; + printf("foo %p, bar %p\n", &vertex, &shape); //*/ - mg_gl_send_buffers(backend, vertexCount, indexCount); + mg_gl_send_buffers(backend, shapeCount, vertexCount, indexCount); mp_rect frame = mg_surface_get_frame(backend->surface); @@ -184,9 +199,10 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 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); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileArrayBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->shapeBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->indexBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileCounterBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->tileArrayBuffer); glUniform1ui(0, indexCount); glUniform2ui(1, tileCountX, tileCountY); @@ -198,12 +214,7 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 //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); @@ -211,16 +222,9 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 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); - + //NOTE: then we fire the fragment shader that will select only triangles in its tile glUseProgram(backend->drawProgram); -/* - 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); -*/ + glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glUniform1ui(0, indexCount); @@ -309,6 +313,10 @@ mg_canvas_backend* mg_gl_canvas_create(mg_surface surface) glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->vertexBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_CANVAS_VERTEX_BUFFER_SIZE, 0, GL_STREAM_DRAW); + glGenBuffers(1, &backend->shapeBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->shapeBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_CANVAS_SHAPE_BUFFER_SIZE, 0, GL_STREAM_DRAW); + glGenBuffers(1, &backend->indexBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_CANVAS_INDEX_BUFFER_SIZE, 0, GL_STREAM_DRAW); @@ -440,6 +448,7 @@ mg_canvas_backend* mg_gl_canvas_create(mg_surface surface) } backend->vertexMapping = malloc_array(char, 1<<30); + backend->shapeMapping = malloc_array(char, 1<<30); backend->indexMapping = malloc_array(char, 1<<30); mg_gl_canvas_update_vertex_layout(backend); diff --git a/src/gles_canvas_shaders/gles_canvas_draw.glsl b/src/gles_canvas_shaders/gles_canvas_draw.glsl index fa0f0ae..43ccd90 100644 --- a/src/gles_canvas_shaders/gles_canvas_draw.glsl +++ b/src/gles_canvas_shaders/gles_canvas_draw.glsl @@ -7,27 +7,34 @@ precision mediump float; layout(std430) buffer; struct vertex { - vec2 pos; - vec2 uv; vec4 cubic; + vec2 pos; + int zIndex; +}; + +struct shape { vec4 color; vec4 clip; - int zIndex; + vec2 uv; }; layout(binding = 0) restrict readonly buffer vertexBufferSSBO { vertex elements[]; } vertexBuffer ; -layout(binding = 1) restrict readonly buffer indexBufferSSBO { +layout(binding = 1) restrict readonly buffer shapeBufferSSBO { + shape elements[]; +} shapeBuffer ; + +layout(binding = 2) restrict readonly buffer indexBufferSSBO { uint elements[]; } indexBuffer ; -layout(binding = 2) restrict readonly buffer tileCounterBufferSSBO { +layout(binding = 3) restrict readonly buffer tileCounterBufferSSBO { uint elements[]; } tileCounterBuffer ; -layout(binding = 3) restrict readonly buffer tileArrayBufferSSBO { +layout(binding = 4) restrict readonly buffer tileArrayBufferSSBO { uint elements[]; } tileArrayBuffer ; @@ -130,7 +137,7 @@ void main() ivec2 p2 = ivec2(vertexBuffer.elements[i2].pos * subPixelFactor + vec2(0.5, 0.5)); int zIndex = vertexBuffer.elements[i0].zIndex; - vec4 color = vertexBuffer.elements[i0].color; + vec4 color = shapeBuffer.elements[zIndex].color; //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge int cw = (p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x; diff --git a/src/gles_canvas_shaders/gles_canvas_sort.glsl b/src/gles_canvas_shaders/gles_canvas_sort.glsl index 4b58e28..43f3c34 100644 --- a/src/gles_canvas_shaders/gles_canvas_sort.glsl +++ b/src/gles_canvas_shaders/gles_canvas_sort.glsl @@ -5,27 +5,34 @@ precision mediump float; layout(std430) buffer; struct vertex { - vec2 pos; - vec2 uv; vec4 cubic; + vec2 pos; + int zIndex; +}; + +struct shape { vec4 color; vec4 clip; - int zIndex; + vec2 uv; }; layout(binding = 0) restrict readonly buffer vertexBufferSSBO { vertex elements[]; } vertexBuffer ; -layout(binding = 1) restrict readonly buffer indexBufferSSBO { +layout(binding = 1) restrict readonly buffer shapeBufferSSBO { + shape elements[]; +} shapeBuffer ; + +layout(binding = 2) restrict readonly buffer indexBufferSSBO { uint elements[]; } indexBuffer ; -layout(binding = 2) coherent readonly restrict buffer tileCounterBufferSSBO { +layout(binding = 3) coherent readonly restrict buffer tileCounterBufferSSBO { uint elements[]; } tileCounterBuffer ; -layout(binding = 3) coherent restrict buffer tileArrayBufferSSBO { +layout(binding = 4) coherent restrict buffer tileArrayBufferSSBO { uint elements[]; } tileArrayBuffer ; diff --git a/src/gles_canvas_shaders/gles_canvas_tile.glsl b/src/gles_canvas_shaders/gles_canvas_tile.glsl index a96fe76..3342898 100644 --- a/src/gles_canvas_shaders/gles_canvas_tile.glsl +++ b/src/gles_canvas_shaders/gles_canvas_tile.glsl @@ -5,27 +5,34 @@ precision mediump float; layout(std430) buffer; struct vertex { - vec2 pos; - vec2 uv; vec4 cubic; + vec2 pos; + int zIndex; +}; + +struct shape { vec4 color; vec4 clip; - int zIndex; + vec2 uv; }; layout(binding = 0) restrict readonly buffer vertexBufferSSBO { vertex elements[]; } vertexBuffer ; -layout(binding = 1) restrict readonly buffer indexBufferSSBO { +layout(binding = 1) restrict readonly buffer shapeBufferSSBO { + shape elements[]; +} shapeBuffer ; + +layout(binding = 2) restrict readonly buffer indexBufferSSBO { uint elements[]; } indexBuffer ; -layout(binding = 2) coherent restrict buffer tileCounterBufferSSBO { +layout(binding = 3) coherent restrict buffer tileCounterBufferSSBO { uint elements[]; } tileCounterBuffer ; -layout(binding = 3) coherent restrict writeonly buffer tileArrayBufferSSBO { +layout(binding = 4) coherent restrict writeonly buffer tileArrayBufferSSBO { uint elements[]; } tileArrayBuffer ; diff --git a/src/graphics.c b/src/graphics.c index d65e094..7e77d23 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -422,22 +422,38 @@ void mg_path_push_element(mg_canvas_data* canvas, mg_path_elt elt) mg_path_push_elements(canvas, 1, &elt); } +/////////////////////////////////////// WIP ///////////////////////////////////////////////////////////////////////// + void mg_reset_z_index(mg_canvas_data* canvas) { canvas->nextZIndex = 1; } -u32 mg_get_next_z_index(mg_canvas_data* canvas) +u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color) { - return(canvas->nextZIndex++); + //TODO: push color, uv, clip + + int index = canvas->nextZIndex; + canvas->nextZIndex++; + + mg_vertex_layout* layout = &canvas->backend->vertexLayout; + + *(vec2*)(((char*)layout->uvBuffer) + index*layout->uvStride) = uv; + *(mg_color*)(((char*)layout->colorBuffer) + index*layout->colorStride) = color; + *(mp_rect*)(((char*)layout->clipBuffer) + index*layout->clipStride) = canvas->clip; + + return(index); } -/////////////////////////////////////// WIP ///////////////////////////////////////////////////////////////////////// +u32 mg_next_shape(mg_canvas_data* canvas, mg_color color) +{ + return(mg_next_shape_textured(canvas, (vec2){0, 0}, color)); +} //TODO(martin): rename with something more explicit u32 mg_vertices_base_index(mg_canvas_data* canvas) { - return(canvas->batchBaseIndex + canvas->vertexCount); + return(canvas->vertexCount); } int* mg_reserve_indices(mg_canvas_data* canvas, u32 indexCount) @@ -452,29 +468,19 @@ int* mg_reserve_indices(mg_canvas_data* canvas, u32 indexCount) return(base); } -void mg_push_textured_vertex(mg_canvas_data* canvas, vec2 pos, vec4 cubic, vec2 uv, mg_color color, u64 zIndex) +void mg_push_vertex(mg_canvas_data* canvas, vec2 pos, vec4 cubic, u64 zIndex) { mg_vertex_layout* layout = &canvas->backend->vertexLayout; - DEBUG_ASSERT(canvas->vertexCount < layout->maxVertexCount); u32 offset = canvas->vertexCount; *(vec2*)(((char*)layout->posBuffer) + offset*layout->posStride) = pos; *(vec4*)(((char*)layout->cubicBuffer) + offset*layout->cubicStride) = cubic; - *(vec2*)(((char*)layout->uvBuffer) + offset*layout->uvStride) = uv; - *(mg_color*)(((char*)layout->colorBuffer) + offset*layout->colorStride) = color; *(u32*)(((char*)layout->zIndexBuffer) + offset*layout->zIndexStride) = zIndex; - *(mp_rect*)(((char*)layout->clipBuffer) + offset*layout->clipStride) = canvas->clip; canvas->vertexCount++; } - -void mg_push_vertex(mg_canvas_data* canvas, vec2 pos, vec4 cubic, mg_color color, u64 zIndex) -{ - mg_push_textured_vertex(canvas, pos, cubic, (vec2){0, 0}, color, zIndex); -} - //----------------------------------------------------------------------------------------------------------- // Path Filling //----------------------------------------------------------------------------------------------------------- @@ -492,19 +498,16 @@ void mg_render_fill_quadratic(mg_canvas_data* canvas, vec2 p[3], u32 zIndex, mg_ mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[0].x, p[0].y}), (vec4){0, 0, 0, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[1].x, p[1].y}), (vec4){0.5, 0, 0.5, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[2].x, p[2].y}), (vec4){1, 1, 1, 1}, - color, zIndex); indices[0] = baseIndex + 0; @@ -549,19 +552,16 @@ void mg_split_and_fill_cubic(mg_canvas_data* canvas, vec2 p[4], f32 tSplit, u32 mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[0].x, p[0].y}), (vec4){1, 1, 1, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){split.x, split.y}), (vec4){1, 1, 1, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[3].x, p[3].y}), (vec4){1, 1, 1, 1}, - color, zIndex); indices[0] = baseIndex + 0; @@ -931,7 +931,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, mg_colo vec2 pos = mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[i]]); vec4 cubic = testCoords[orderedHullIndices[i]]; cubic.w = outsideTest; - mg_push_vertex(canvas, pos, cubic, color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); indices[i] = baseIndex + i; } @@ -961,37 +961,31 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, mg_colo mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[0]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[0]]), outsideTest1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[1]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[1]]), outsideTest1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[2]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[2]]), outsideTest1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[0]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[0]]), outsideTest2}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[2]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[2]]), outsideTest2}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[3]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[3]]), outsideTest2}, - color, zIndex); indices[0] = baseIndex + 0; @@ -1018,7 +1012,6 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, mg_colo mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p[orderedHullIndices[i]]), (vec4){vec4_expand_xyz(testCoords[orderedHullIndices[i]]), outsideTest}, - color, zIndex); } @@ -1088,7 +1081,7 @@ void mg_render_fill(mg_canvas_data* canvas, mg_path_elt* elements, mg_path_descr for(int i=0; i<3; i++) { - mg_push_vertex(canvas, pos[i], cubic, color, zIndex); + mg_push_vertex(canvas, pos[i], cubic, zIndex); indices[i] = baseIndex + i; } @@ -1120,25 +1113,21 @@ void mg_render_stroke_line(mg_canvas_data* canvas, vec2 p[2], u32 zIndex, mg_att mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[0].x + n0.x, p[0].y + n0.y}), (vec4){1, 1, 1, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[1].x + n0.x, p[1].y + n0.y}), (vec4){1, 1, 1, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[1].x - n0.x, p[1].y - n0.y}), (vec4){1, 1, 1, 1}, - color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p[0].x - n0.x, p[0].y - n0.y}), (vec4){1, 1, 1, 1}, - color, zIndex); indices[0] = baseIndex; @@ -1326,7 +1315,7 @@ void mg_render_stroke_quadratic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, m { //NOTE(martin): push the actual fill commands for the offset contour - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_fill_quadratic(canvas, positiveOffsetHull, zIndex, attributes->color); mg_render_fill_quadratic(canvas, negativeOffsetHull, zIndex, attributes->color); @@ -1338,25 +1327,21 @@ void mg_render_stroke_quadratic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, m mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, positiveOffsetHull[0]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, positiveOffsetHull[2]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, negativeOffsetHull[2]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, negativeOffsetHull[0]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); indices[0] = baseIndex + 0; @@ -1485,7 +1470,7 @@ void mg_render_stroke_cubic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, mg_at else { //NOTE(martin): push the actual fill commands for the offset contour - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_fill_cubic(canvas, positiveOffsetHull, zIndex, attributes->color); mg_render_fill_cubic(canvas, negativeOffsetHull, zIndex, attributes->color); @@ -1498,25 +1483,21 @@ void mg_render_stroke_cubic(mg_canvas_data* canvas, vec2 p[4], u32 zIndex, mg_at mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, positiveOffsetHull[0]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, positiveOffsetHull[3]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, negativeOffsetHull[3]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, negativeOffsetHull[0]), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); indices[0] = baseIndex + 0; @@ -1542,7 +1523,7 @@ void mg_stroke_cap(mg_canvas_data* canvas, vec2 p0, vec2 direction, mg_attribute vec2 m0 = {alpha*direction.x, alpha*direction.y}; - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); u32 baseIndex = mg_vertices_base_index(canvas); i32* indices = mg_reserve_indices(canvas, 6); @@ -1550,25 +1531,21 @@ void mg_stroke_cap(mg_canvas_data* canvas, vec2 p0, vec2 direction, mg_attribute mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n0.x, p0.y + n0.y}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n0.x + m0.x, p0.y + n0.y + m0.y}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x - n0.x + m0.x, p0.y - n0.y + m0.y}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x - n0.x, p0.y - n0.y}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); indices[0] = baseIndex; @@ -1608,7 +1585,7 @@ void mg_stroke_joint(mg_canvas_data* canvas, n1.y *= -1; } - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); //NOTE(martin): use the same code as hull offset to find mitter point... /*NOTE(martin): let vector u = (n0+n1) and vector v = pIntersect - p1 @@ -1634,25 +1611,21 @@ void mg_stroke_joint(mg_canvas_data* canvas, mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, p0), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, mitterPoint), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); indices[0] = baseIndex; @@ -1669,21 +1642,18 @@ void mg_stroke_joint(mg_canvas_data* canvas, i32* indices = mg_reserve_indices(canvas, 3); mg_push_vertex(canvas, - mg_mat2x3_mul(canvas->transform, p0), - (vec4){1, 1, 1, 1}, - attributes->color, - zIndex); + mg_mat2x3_mul(canvas->transform, p0), + (vec4){1, 1, 1, 1}, + zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); mg_push_vertex(canvas, mg_mat2x3_mul(canvas->transform, (vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW}), (vec4){1, 1, 1, 1}, - attributes->color, zIndex); DEBUG_ASSERT(!isnan(n0.x) && !isnan(n0.y) && !isnan(n1.x) && !isnan(n1.y)); @@ -1704,7 +1674,7 @@ void mg_render_stroke_element(mg_canvas_data* canvas, { vec2 controlPoints[4] = {currentPoint, element->p[0], element->p[1], element->p[2]}; int endPointIndex = 0; - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); switch(element->type) { @@ -1837,7 +1807,7 @@ void mg_render_rectangle_fill(mg_canvas_data* canvas, mp_rect rect, mg_attribute u32 baseIndex = mg_vertices_base_index(canvas); i32* indices = mg_reserve_indices(canvas, 6); - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); vec2 points[4] = {{rect.x, rect.y}, {rect.x + rect.w, rect.y}, @@ -1848,7 +1818,7 @@ void mg_render_rectangle_fill(mg_canvas_data* canvas, mp_rect rect, mg_attribute for(int i=0; i<4; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, points[i]); - mg_push_vertex(canvas, pos, cubic, attributes->color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); } indices[0] = baseIndex + 0; indices[1] = baseIndex + 1; @@ -1864,7 +1834,7 @@ void mg_render_rectangle_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribu u32 baseIndex = mg_vertices_base_index(canvas); i32* indices = mg_reserve_indices(canvas, 12); - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); //NOTE(martin): limit stroke width to the minimum dimension of the rectangle f32 width = minimum(attributes->width, minimum(rect.w, rect.h)); @@ -1884,13 +1854,13 @@ void mg_render_rectangle_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribu for(int i=0; i<4; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, outerPoints[i]); - mg_push_vertex(canvas, pos, cubic, attributes->color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); } for(int i=0; i<4; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, innerPoints[i]); - mg_push_vertex(canvas, pos, cubic, attributes->color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); } indices[0] = baseIndex + 0; @@ -1929,7 +1899,7 @@ void mg_render_fill_arc_corner(mg_canvas_data* canvas, f32 x, f32 y, f32 rx, f32 for(int i=0; i<4; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, points[i]); - mg_push_vertex(canvas, pos, cubics[i], color, zIndex); + mg_push_vertex(canvas, pos, cubics[i], zIndex); } indices[0] = baseIndex + 0; indices[1] = baseIndex + 1; @@ -1965,7 +1935,7 @@ void mg_render_rounded_rectangle_fill_with_z_index(mg_canvas_data* canvas, for(int i=0; i<8; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, points[i]); - mg_push_vertex(canvas, pos, cubic, attributes->color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); } static const i32 fanIndices[18] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7 }; // inner fan @@ -1985,7 +1955,7 @@ void mg_render_rounded_rectangle_fill(mg_canvas_data* canvas, mg_rounded_rect rect, mg_attributes* attributes) { - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_rounded_rectangle_fill_with_z_index(canvas, rect, attributes, zIndex); } @@ -2000,7 +1970,7 @@ void mg_render_rounded_rectangle_stroke(mg_canvas_data* canvas, mg_rounded_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width, rect.r - halfW}; mg_rounded_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width, rect.r + halfW}; - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_rounded_rectangle_fill_with_z_index(canvas, outer, attributes, zIndex); mg_render_rounded_rectangle_fill_with_z_index(canvas, inner, attributes, zIndex); } @@ -2029,7 +1999,7 @@ void mg_render_ellipse_fill_with_z_index(mg_canvas_data* canvas, for(int i=0; i<4; i++) { vec2 pos = mg_mat2x3_mul(canvas->transform, points[i]); - mg_push_vertex(canvas, pos, cubic, attributes->color, zIndex); + mg_push_vertex(canvas, pos, cubic, zIndex); } indices[0] = baseIndex + 0; @@ -2047,7 +2017,7 @@ void mg_render_ellipse_fill_with_z_index(mg_canvas_data* canvas, void mg_render_ellipse_fill(mg_canvas_data* canvas, mp_rect rect, mg_attributes* attributes) { - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_ellipse_fill_with_z_index(canvas, rect, attributes, zIndex); } @@ -2060,13 +2030,15 @@ void mg_render_ellipse_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribute mp_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width}; mp_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width}; - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); mg_render_ellipse_fill_with_z_index(canvas, outer, attributes, zIndex); mg_render_ellipse_fill_with_z_index(canvas, inner, attributes, zIndex); } void mg_render_image(mg_canvas_data* canvas, mg_image image, mp_rect rect) { +//TODO +/* mg_image_data* imageData = mg_image_ptr_from_handle(canvas, image); if(!imageData) { @@ -2076,7 +2048,7 @@ void mg_render_image(mg_canvas_data* canvas, mg_image image, mp_rect rect) u32 baseIndex = mg_vertices_base_index(canvas); i32* indices = mg_reserve_indices(canvas, 6); - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, attributes->color); vec2 points[4] = {{rect.x, rect.y}, {rect.x + rect.w, rect.y}, @@ -2104,10 +2076,13 @@ void mg_render_image(mg_canvas_data* canvas, mg_image image, mp_rect rect) indices[3] = baseIndex + 0; indices[4] = baseIndex + 2; indices[5] = baseIndex + 3; +*/ } void mg_render_rounded_image(mg_canvas_data* canvas, mg_image image, mg_rounded_rect rect, mg_attributes* attributes) { + //TODO + /* mg_image_data* imageData = mg_image_ptr_from_handle(canvas, image); if(!imageData) { @@ -2148,7 +2123,7 @@ void mg_render_rounded_image(mg_canvas_data* canvas, mg_image image, mg_rounded_ *uv = mappedUV; } - + */ } //------------------------------------------------------------------------------------------ @@ -2817,10 +2792,9 @@ void mg_flush_batch(mg_canvas_data* canvas) { if(canvas->backend && canvas->backend->drawBatch) { - canvas->backend->drawBatch(canvas->backend, canvas->vertexCount, canvas->indexCount); + canvas->backend->drawBatch(canvas->backend, canvas->nextZIndex, canvas->vertexCount, canvas->indexCount); } - - canvas->batchBaseIndex += canvas->vertexCount; + mg_reset_z_index(canvas); canvas->vertexCount = 0; canvas->indexCount = 0; } @@ -2871,14 +2845,13 @@ void mg_flush() //NOTE(martin): clear buffers canvas->vertexCount = 0; canvas->indexCount = 0; - canvas->batchBaseIndex = 0; canvas->backend->clear(canvas->backend, primitive->attributes.color); } break; case MG_CMD_FILL: { - u32 zIndex = mg_get_next_z_index(canvas); + u32 zIndex = mg_next_shape(canvas, primitive->attributes.color); mg_render_fill(canvas, canvas->pathElements + primitive->path.startIndex, &primitive->path, diff --git a/src/graphics_internal.h b/src/graphics_internal.h index ab619b2..7392a02 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -225,7 +225,7 @@ typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend); typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend); typedef void (*mg_canvas_backend_end_proc)(mg_canvas_backend* backend); typedef void (*mg_canvas_backend_clear_proc)(mg_canvas_backend* backend, mg_color clearColor); -typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend, u32 vertexCount, u32 indexCount); +typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend, u32 vertexCount, u32 shapeCount, u32 indexCount); typedef void (*mg_canvas_backend_atlas_upload_proc)(mg_canvas_backend* backend, mp_rect rect, u8* bytes); typedef struct mg_canvas_backend @@ -270,7 +270,6 @@ typedef struct mg_canvas_data u32 vertexCount; u32 indexCount; - u32 batchBaseIndex; mg_image_data images[MG_IMAGE_MAX_COUNT]; u32 imageNextIndex; diff --git a/todo.txt b/todo.txt index 54ffa98..a2127c3 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,21 @@ -WIP ---- -[ ] Split vertex data into per-vertex and per-shape data. Keep only pos, cubics, and shapeID in vertex data -[?] use half-floats or short fixed-point for pos and uv, packing them in two ints +Canvas renderer perf +-------------------- +[.] Perf + [x] Split vertex data into per-vertex and per-shape data. Keep only pos, cubics, and shapeID in vertex data + [>] make zIndex implicit when calling push_vertex + [>] rename zIndex with "shapeIndex" everywhere + [>] remove color args in functions that don't need it anymore + [?] use half-floats or short fixed-point for pos and uv, packing them in two ints + [?] pre-compute triangle edges/bounding boxes? + +[ ] Use clip rects +[ ] Clean shaders (folder/filenames, version string, debug flags, ...) +[ ] Correctly handle surface size +[ ] Add surface scaling for high dpi surfaces +[ ] Allow setting swap interval + + ----------- [.] Check changes in macos version diff --git a/vector_renderer_notes.txt b/vector_renderer_notes.txt index 3c5b021..562dde4 100644 --- a/vector_renderer_notes.txt +++ b/vector_renderer_notes.txt @@ -92,3 +92,5 @@ Quick measurement on perf_text.exe -> Stutter is with GL_MAP_INVALIDATE_BUFFER_BIT isn't reassuring. Stick to glBufferData for now. -> May be worth it to try persistently mapped buffers later. + +* Splitting vertex data and shape data (using glBufferData) --> ~10ms