diff --git a/examples/perf_text/main.c b/examples/perf_text/main.c index d2a7df2..5be9425 100644 --- a/examples/perf_text/main.c +++ b/examples/perf_text/main.c @@ -10,32 +10,54 @@ #define LOG_SUBSYSTEM "Main" static const char* TEST_STRING = -"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam.\n" \ -"Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend\n" \ -"nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a.\n" -"Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n" \ -"\n" \ -"Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit\n" \ -"ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed\n" \ -"vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet\n" \ -"quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed \n" \ -"aliquam faucibus magna.\n" \ -"\n" \ -"Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit\n" \ -"amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat,\n" \ -"neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in.\n" \ -"Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in.\n" \ -"Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, \n" \ -"lacinia ultricies nibh sodales nec.\n" \ -"\n" \ -"Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum.\n" \ -"Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu\n" \ -"turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur\n" \ -"elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper\n" \ -"eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit,\n" \ -"enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur\n" \ -"quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis\n" \ -"purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim."; +"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam. " +"Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend " +"nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a. " +"Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n" +"\n" +"Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit " +"ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed " +"vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet " +"quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed " +"aliquam faucibus magna.\n" +"\n" +"Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit " +"amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat, " +"neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in. " +"Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in. " +"Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, " +"lacinia ultricies nibh sodales nec.\n" +"\n" +"Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum. " +"Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu " +"turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur " +"elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper " +"eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit, " +"enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur " +"quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis " +"purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim.\n" +"\n" +"Aliquam sed tortor a justo pulvinar dictum consectetur eu felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices " +"posuere cubilia curae; Etiam vehicula porttitor volutpat. Morbi fringilla tortor nec accumsan aliquet. Aliquam in commodo neque. " +"Sed laoreet tellus in consectetur aliquet. Nullam nibh eros, feugiat sit amet aliquam non, malesuada vel urna. Ut vel egestas nunc. " +"Pellentesque vitae ante quis ante pharetra pretium. Nam quis eros commodo, mattis enim sed, finibus ante. Quisque lacinia tortor ut " +"odio laoreet, vel viverra libero porttitor. Vestibulum vitae dapibus ex. Phasellus varius lorem sed justo sollicitudin faucibus. " +"Etiam aliquam lacinia consectetur. Phasellus nulla ipsum, viverra non nulla in, rhoncus posuere nunc.\n" +"\n" +"Phasellus efficitur commodo tellus, eget lobortis erat porta quis. Aenean condimentum tortor ut neque dapibus, vitae vulputate quam " +"condimentum. Aliquam elementum vitae nulla vitae tristique. Suspendisse feugiat turpis ac magna dapibus, ut blandit diam tincidunt. " +"Integer id dui id enim ullamcorper dictum. Maecenas malesuada vitae ex pharetra iaculis. Curabitur eu dolor consectetur, tempus augue " +"sed, finibus est. Nulla facilisi. Vivamus sed lacinia turpis, in gravida dolor. Aenean interdum consectetur enim a malesuada. Sed turpis " +"nisi, lacinia et fermentum nec, pharetra id dui. Vivamus neque ligula, iaculis sed tempor eget, vehicula blandit quam. Morbi rhoncus quam " +"semper magna mollis luctus. Donec eu dolor ut ante ullamcorper porta. Mauris et est tristique libero pharetra faucibus.\n" +"\n" +"Duis ut elementum sem. Praesent commodo erat nec sem ultricies sollicitudin. Suspendisse a pellentesque sapien. Nunc ac magna a dui " +"elementum luctus non a mi. Cras elementum nunc sed nunc gravida, sit amet accumsan tortor pulvinar. Etiam elit arcu, pellentesque non ex " +"id, vestibulum pellentesque velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus " +"et netus et malesuada fames ac turpis egestas. Proin sit amet velit eget tellus vulputate sagittis eget non massa. Cras accumsan tempor " +"tortor, quis rutrum neque placerat id. Nullam a egestas eros, eu porta nisi. Aenean rutrum, sapien quis fermentum tempus, dolor orci " +"faucibus eros, vel luctus justo leo vitae ante. Curabitur aliquam condimentum ipsum sit amet ultrices. Nullam ac velit semper, dapibus urna " +"sit amet, malesuada enim. Mauris ultricies nibh orci."; mg_font create_font() @@ -106,6 +128,15 @@ int main() u32* codePoints = malloc_array(utf32, codePointCount); utf8_to_codepoints(codePointCount, codePoints, str8_from_cstring((char*)TEST_STRING)); + u32 glyphCount = 0; + for(int i=0; i 2048. +// Unfortunately this is costly. +// Another way is to precompute triangle edges (b - a) in full precision +// once to avoid doing it all the time... +////////////////////////////////////////////////////////////////////////////// +int orient2d(ivec2 a, ivec2 b, ivec2 p) { return((b.x-a.x)*(p.y-a.y) - (b.y-a.y)*(p.x-a.x)); } -int64_t is_clockwise(i64vec2 p0, i64vec2 p1, i64vec2 p2) +int is_clockwise(ivec2 p0, ivec2 p1, ivec2 p2) { return((p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x); } @@ -68,21 +75,21 @@ void main() ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy); uvec2 tileCoord = uvec2(pixelCoord) / tileSize; uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x; - uint tileCounter = tileCounterBuffer.elements[tileIndex]; + uint tileCounter = min(tileCounterBuffer.elements[tileIndex], tileArraySize); - const float subPixelFactor = 256.; + const float subPixelFactor = 16.; ivec2 centerPoint = ivec2((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor); //* const int sampleCount = 8; - ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3)*16, - centerPoint + ivec2(-1, -3)*16, - centerPoint + ivec2(5, -1)*16, - centerPoint + ivec2(-3, 5)*16, - centerPoint + ivec2(-5, -5)*16, - centerPoint + ivec2(-7, 1)*16, - centerPoint + ivec2(3, -7)*16, - centerPoint + ivec2(7, 7)*16); + ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3), + centerPoint + ivec2(-1, -3), + centerPoint + ivec2(5, -1), + centerPoint + ivec2(-3, 5), + centerPoint + ivec2(-5, -5), + 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), @@ -148,7 +155,7 @@ void main() ivec4 clip = ivec4(round((shapeBuffer.elements[zIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor)); //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge - int64_t cw = is_clockwise(p0, p1, p2); + int cw = is_clockwise(p0, p1, p2); if(cw < 0) { uint tmpIndex = i1; @@ -164,9 +171,9 @@ void main() vec4 cubic1 = vertexBuffer.elements[i1].cubic; vec4 cubic2 = vertexBuffer.elements[i2].cubic; - int64_t bias0 = is_top_left(p1, p2) ? 0 : -1; - int64_t bias1 = is_top_left(p2, p0) ? 0 : -1; - int64_t bias2 = is_top_left(p0, p1) ? 0 : -1; + int bias0 = is_top_left(p1, p2) ? 0 : -1; + int bias1 = is_top_left(p2, p0) ? 0 : -1; + int bias2 = is_top_left(p0, p1) ? 0 : -1; for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) { @@ -180,9 +187,9 @@ void main() continue; } - int64_t w0 = orient2d(p1, p2, samplePoint); - int64_t w1 = orient2d(p2, p0, samplePoint); - int64_t w2 = orient2d(p0, p1, samplePoint); + int w0 = orient2d(p1, p2, samplePoint); + int w1 = orient2d(p2, p0, samplePoint); + int w2 = orient2d(p0, p1, samplePoint); if((w0+bias0) >= 0 && (w1+bias1) >= 0 && (w2+bias2) >= 0) { diff --git a/src/gles_canvas_shaders/gles_canvas_sort.glsl b/src/gles_canvas_shaders/gles_canvas_sort.glsl index 43f3c34..208addc 100644 --- a/src/gles_canvas_shaders/gles_canvas_sort.glsl +++ b/src/gles_canvas_shaders/gles_canvas_sort.glsl @@ -53,7 +53,7 @@ void main() { uint tileIndex = gl_WorkGroupID.x; uint tileArrayOffset = tileArraySize * tileIndex; - uint tileArrayCount = tileCounterBuffer.elements[tileIndex]; + uint tileArrayCount = min(tileCounterBuffer.elements[tileIndex], tileArraySize); for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++) { diff --git a/src/gles_canvas_shaders/gles_canvas_tile.glsl b/src/gles_canvas_shaders/gles_canvas_tile.glsl index 3600ef4..5362fea 100644 --- a/src/gles_canvas_shaders/gles_canvas_tile.glsl +++ b/src/gles_canvas_shaders/gles_canvas_tile.glsl @@ -66,20 +66,25 @@ void main() min(max(max(p0.x, p1.x), p2.x), clip.z), min(max(max(p0.y, p1.y), p2.y), clip.w)); - uvec4 box = uvec4(floor(fbox))/tileSize; + ivec4 box = ivec4(floor(fbox))/int(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); + //NOTE(martin): it's importat to do the computation with signed int, so that we can have negative xMax/yMax + // otherwise all triangles on the left or below the x/y axis are attributed to tiles on row/column 0. + int xMin = max(0, box.x); + int yMin = max(0, box.y); + int xMax = min(box.z, int(tileCount.x) - 1); + int yMax = min(box.w, int(tileCount.y) - 1); - for(uint y = yMin; y <= yMax; y++) + for(int y = yMin; y <= yMax; y++) { - for(uint x = xMin ; x <= xMax; x++) + for(int x = xMin ; x <= xMax; x++) { - uint tileIndex = y*tileCount.x + x; + uint tileIndex = uint(y)*tileCount.x + uint(x); uint tileCounter = atomicAdd(tileCounterBuffer.elements[tileIndex], 1u); - tileArrayBuffer.elements[tileArraySize*tileIndex + tileCounter] = triangleIndex; + if(tileCounter < tileArraySize) + { + tileArrayBuffer.elements[tileArraySize*tileIndex + tileCounter] = triangleIndex; + } } } } diff --git a/todo.txt b/todo.txt index 2268a22..304d691 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,9 @@ Overview -------- -[ ] Pan/Zoom on text example +[x] Pan/Zoom on text example [ ] Clean+Fixes of canvas code and examples [ ] Make backend selection easier -[ ] Investigate and fix artifact when seam is aligned to tile boundary? [ ] Image API and backend [ ] Build image atlas on top @@ -24,15 +23,29 @@ Clean+Fixes [ ] Clean shaders (folder/filenames, version string, debug flags, ...) -[ ] Fix resource loading path in examples (to load font relative to executable) +[x] Fix resource loading path in examples (to load font relative to executable) [ ] GL loader: allow using different GL versions (eg using a desktop GL surface and a GLES surface in the same app). [ ] Clean up surface backend and canvas backend compile-time and run-time selections [!] Investigate artifact when shifting positions of vertices by (0.5, 0.5) before multiplying by subpixel precision and truncating... -> ie sampling at the middle of pixels vs at integer coordinates... + > seems to happen on tile boundaries [ ] What alignment gives crisp-ier lines? +[!] decide how to handle overflow in cross-product computation in triangle rasterizing code + - could reduce subpixel precision (but only to some extent, since we need subpixel precision for msaa) + - could try to center all coords around 0 to maximize usable range + - could use int64_t and i64vec (but it has a big perf cost) + - could precompute some int64_t computation... + +[!] handle pathological case where there are a lot of triangle on the same tile + > can we detect the first solid triangle covering the whole tile? + +[!] handle pathological case where there are a lot of very small triangles (eg when zooming out) + > do we need the same precision then? + +[!] Investigate why WM_MOUSEMOVE messages seem to lag behing mouse cursor Canvas renderer ---------------