diff options
| author | 3gg <3gg@shellblade.net> | 2026-02-08 18:29:34 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2026-02-08 18:29:34 -0800 |
| commit | 27378f3537e9dbe0bfeb1ebb8a653e6050f2ea4a (patch) | |
| tree | 1b39e524d6c8fb75fac7f1dd597c44d1afce3de2 | |
| parent | 85a5ad70b7fa4844e37fe06463ea82d8e6f1abaf (diff) | |
Implement basic perf counters
| -rw-r--r-- | include/swgfx.h | 13 | ||||
| -rw-r--r-- | src/swgfx.c | 21 |
2 files changed, 34 insertions, 0 deletions
diff --git a/include/swgfx.h b/include/swgfx.h index 9c3361d..72164b1 100644 --- a/include/swgfx.h +++ b/include/swgfx.h | |||
| @@ -22,6 +22,8 @@ Multi-threading: | |||
| 22 | #include <stddef.h> | 22 | #include <stddef.h> |
| 23 | #include <stdint.h> | 23 | #include <stdint.h> |
| 24 | 24 | ||
| 25 | #define SWGFX_PROFILING 1 // TODO: Move this to client project cmake. | ||
| 26 | |||
| 25 | typedef float R; | 27 | typedef float R; |
| 26 | 28 | ||
| 27 | typedef struct sgVec2i { int x, y; } sgVec2i; | 29 | typedef struct sgVec2i { int x, y; } sgVec2i; |
| @@ -66,6 +68,15 @@ typedef struct sgImage { | |||
| 66 | 68 | ||
| 67 | typedef struct swgfx swgfx; | 69 | typedef struct swgfx swgfx; |
| 68 | 70 | ||
| 71 | #if SWGFX_PROFILING | ||
| 72 | typedef struct sgCounters { | ||
| 73 | uint64_t frames; // Frames drawn. | ||
| 74 | uint64_t triangles3; // 3D triangles processed. | ||
| 75 | uint64_t triangles2; // 2D triangles processed. | ||
| 76 | uint64_t pixels; // Pixels written. | ||
| 77 | } sgCounters; | ||
| 78 | #endif // SWGFX_PROFILING | ||
| 79 | |||
| 69 | size_t sgMem(int width, int height); // Get memory requirements. | 80 | size_t sgMem(int width, int height); // Get memory requirements. |
| 70 | swgfx* sgNew(int width, int height, void* mem); | 81 | swgfx* sgNew(int width, int height, void* mem); |
| 71 | void sgDel(swgfx**); | 82 | void sgDel(swgfx**); |
| @@ -98,4 +109,6 @@ void sgTrianglesIndexedNonUniform(swgfx*, size_t numTris, const sgTriIdx* tris, | |||
| 98 | void sgGamma (swgfx*, sgPixel*, int width, int height); | 109 | void sgGamma (swgfx*, sgPixel*, int width, int height); |
| 99 | void sgGammaInv(swgfx*, sgPixel*, int width, int height); | 110 | void sgGammaInv(swgfx*, sgPixel*, int width, int height); |
| 100 | 111 | ||
| 112 | sgCounters sgGetCounters(const swgfx*); | ||
| 113 | |||
| 101 | void sgCheck(swgfx*); | 114 | void sgCheck(swgfx*); |
diff --git a/src/swgfx.c b/src/swgfx.c index bbf9a5b..78d5434 100644 --- a/src/swgfx.c +++ b/src/swgfx.c | |||
| @@ -19,6 +19,8 @@ Coordinate systems: | |||
| 19 | #include <stdint.h> | 19 | #include <stdint.h> |
| 20 | #include <string.h> | 20 | #include <string.h> |
| 21 | 21 | ||
| 22 | |||
| 23 | |||
| 22 | static constexpr sgVec3 Up3 = (sgVec3){0,1,0}; | 24 | static constexpr sgVec3 Up3 = (sgVec3){0,1,0}; |
| 23 | 25 | ||
| 24 | typedef struct sgViewport_t { int x0, y0, width, height; } sgViewport_t; | 26 | typedef struct sgViewport_t { int x0, y0, width, height; } sgViewport_t; |
| @@ -50,6 +52,7 @@ typedef struct swgfx { | |||
| 50 | sgTextureFilter textureFilter; // Filter method for the texture. | 52 | sgTextureFilter textureFilter; // Filter method for the texture. |
| 51 | sgImage defaultTexture; // A default for when no texture is provided. | 53 | sgImage defaultTexture; // A default for when no texture is provided. |
| 52 | sgPixel defaultPixel; // The single-pixel of the default texture. | 54 | sgPixel defaultPixel; // The single-pixel of the default texture. |
| 55 | sgCounters counters; | ||
| 53 | } swgfx; | 56 | } swgfx; |
| 54 | 57 | ||
| 55 | static inline int mod(int a, int m) { return (m + (a % m)) % m; } | 58 | static inline int mod(int a, int m) { return (m + (a % m)) % m; } |
| @@ -306,6 +309,9 @@ static inline R* Depth(swgfx* gfx, int x, int y) { | |||
| 306 | static inline void SetPixel(swgfx* gfx, const sgVec2i p, sgPixel colour) { | 309 | static inline void SetPixel(swgfx* gfx, const sgVec2i p, sgPixel colour) { |
| 307 | assert(gfx); | 310 | assert(gfx); |
| 308 | *Pixel(gfx, p.x, p.y) = colour; | 311 | *Pixel(gfx, p.x, p.y) = colour; |
| 312 | #if SWGFX_PROFILING | ||
| 313 | gfx->counters.pixels++; | ||
| 314 | #endif // SWGFX_PROFILING | ||
| 309 | } | 315 | } |
| 310 | 316 | ||
| 311 | static inline void SetDepth(swgfx* gfx, const sgVec2i p, R depth) { | 317 | static inline void SetDepth(swgfx* gfx, const sgVec2i p, R depth) { |
| @@ -448,6 +454,9 @@ static void DrawTriangle2(swgfx* gfx, const sgTri2* const tri) { | |||
| 448 | } | 454 | } |
| 449 | } | 455 | } |
| 450 | } | 456 | } |
| 457 | #if SWGFX_PROFILING | ||
| 458 | gfx->counters.triangles2++; | ||
| 459 | #endif // SWGFX_PROFILING | ||
| 451 | } | 460 | } |
| 452 | 461 | ||
| 453 | static inline sgVec4 PerspDivide(sgVec4 v) { | 462 | static inline sgVec4 PerspDivide(sgVec4 v) { |
| @@ -677,6 +686,9 @@ static void DrawTriangle3(swgfx* gfx, const sgTri3* const tri) { | |||
| 677 | for (int i = 0; i < numTris; ++i) { | 686 | for (int i = 0; i < numTris; ++i) { |
| 678 | DrawTriangle3PostClip(gfx, &tris[i]); | 687 | DrawTriangle3PostClip(gfx, &tris[i]); |
| 679 | } | 688 | } |
| 689 | #if SWGFX_PROFILING | ||
| 690 | gfx->counters.triangles3++; | ||
| 691 | #endif // SWGFX_PROFILING | ||
| 680 | } | 692 | } |
| 681 | 693 | ||
| 682 | #define is_pow2_or_0(X) ((X & (X - 1)) == 0) | 694 | #define is_pow2_or_0(X) ((X & (X - 1)) == 0) |
| @@ -768,6 +780,10 @@ void sgPresent(swgfx* gfx, sgVec2i dimensions, sgScreenPixel* screen) { | |||
| 768 | } | 780 | } |
| 769 | } | 781 | } |
| 770 | } | 782 | } |
| 783 | |||
| 784 | #if SWGFX_PROFILING | ||
| 785 | gfx->counters.frames++; | ||
| 786 | #endif // SWGFX_PROFILING | ||
| 771 | } | 787 | } |
| 772 | 788 | ||
| 773 | static void sgUpdateViewProjection(swgfx* gfx) { | 789 | static void sgUpdateViewProjection(swgfx* gfx) { |
| @@ -930,6 +946,11 @@ static bool ViewportWithinBuffer(swgfx* gfx) { | |||
| 930 | ((vp.y0 + vp.height) <= gfx->dims.y); | 946 | ((vp.y0 + vp.height) <= gfx->dims.y); |
| 931 | } | 947 | } |
| 932 | 948 | ||
| 949 | sgCounters sgGetCounters(const swgfx* gfx) { | ||
| 950 | assert(gfx); | ||
| 951 | return gfx->counters; | ||
| 952 | } | ||
| 953 | |||
| 933 | void sgCheck(swgfx* gfx) { | 954 | void sgCheck(swgfx* gfx) { |
| 934 | assert(gfx); | 955 | assert(gfx); |
| 935 | assert(ViewportWithinBuffer(gfx)); | 956 | assert(ViewportWithinBuffer(gfx)); |
