/* * Copyright (c) 2026 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Radoslaw Kujawa. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * vrperf - veritemesa driver-layer performance instrumentation. */ #ifndef VRPERF_H #define VRPERF_H enum { VRP_FB_TEX_HWOK, /* texture enabled but not PE-expressible */ VRP_FB_BLEND, /* blend func not in the PE map */ VRP_FB_ALPHAFUNC, /* alpha func not GREATER/GEQUAL/NEVER/ALWAYS */ VRP_FB_DEPTHFUNC, /* depth func not LESS/LEQUAL/ALWAYS */ VRP_FB_STIPPLE, /* DD_TRI_STIPPLE */ VRP_FB_SMOOTH, /* DD_TRI_SMOOTH */ VRP_FB_TWOSIDE, /* DD_TRI_LIGHT_TWOSIDE */ VRP_FB_SPECULAR, /* DD_SEPARATE_SPECULAR */ VRP_FB_UNFILLED_SUB, /* unfilled poly + a sub-mode HW can't do */ VRP_FB_RENDERMODE, /* RenderMode != GL_RENDER */ VRP_FB_TEX_RESIDENCY, /* gate passed but vrTexValidate could not fit */ VRP_FB_TRI_ALPHAGRAD, /* per-tri: real alpha gradient -> _swrast_Triangle */ VRP_FB__N }; enum { VRP_Z_PIPELINE, /* whole _tnl_run_pipeline (all CPU/frame) */ VRP_Z_RENDER_START, /* vr_render_start: our validate + texvalidate */ VRP_Z_TEXVALIDATE, /* vrTexValidate: texture convert/upload CPU */ VRP_Z_TRI_EMIT, /* per-tri vr_tri (level >= 3 only) */ VRP_Z__N }; #ifdef VERITE_INSTRUMENT #include struct vrperf { int on; /* VRMESA_PROF >= 1 (gates hot sites) */ int level; /* full VRMESA_PROF value */ int printed; /* atexit/destroy double-print guard */ struct rlgl *rl; /* borrowed: surface librlgl/libv3d stats */ uint64_t fb[VRP_FB__N]; /* swrast-fallback histogram */ uint64_t frames; /* our own swap count */ /* state-churn / stall counters */ uint64_t fgcolor_writes; /* per-tri FGColor writes (vrtris.c) */ uint64_t mip_binds; /* per-poly level binds */ uint64_t filt_changes; /* per-poly filter switches */ uint64_t fences; /* vrFence real PE stalls (vrspan.c) */ /* texture-validate classification (the 1->19 fps diagnostic set) */ uint64_t tv_dirty; /* data changed -> re-upload */ uint64_t tv_nlevels; /* resident but fewer levels than wanted */ uint64_t tv_evict; /* an LRU victim was unloaded */ uint64_t tv_first; /* never-resident first upload */ uint64_t tv_bindonly; /* resident, no upload (fast path) */ uint64_t tv_creates; /* new vr_texture objects made */ uint64_t tv_failv; /* validate failed: could not fit base */ uint64_t tv_failu; /* validate failed: an upload errored */ uint64_t zone[VRP_Z__N]; uint64_t zone_t0[VRP_Z__N]; uint64_t tb0, ns0; /* one-time ns calibration anchors */ }; extern struct vrperf g_vrp; #if defined(__powerpc__) static __inline uint32_t vrp_tb(void) { uint32_t t; __asm__ volatile("mftb %0" : "=r"(t)); return t; } static __inline uint64_t vrp_tb64(void) { uint32_t hi, lo, hi2; do { __asm__ volatile("mftbu %0" : "=r"(hi)); __asm__ volatile("mftb %0" : "=r"(lo)); __asm__ volatile("mftbu %0" : "=r"(hi2)); } while (hi != hi2); return ((uint64_t)hi << 32) | lo; } #else static __inline uint32_t vrp_tb(void) { return (uint32_t)v3d_now_ns(); } static __inline uint64_t vrp_tb64(void) { return v3d_now_ns(); } #endif /* * Counter tiers. */ #define VRP_COUNT(f) (g_vrp.f++) #define VRP_ADD(f, n) (g_vrp.f += (uint64_t)(n)) #define VRP_FALLBACK(r) (g_vrp.fb[r]++) /* gated fallback bump for per-primitive sites (vr_tri alpha gradient) */ #define VRP_FALLBACK_HOT(r) do { if (g_vrp.on) g_vrp.fb[r]++; } while (0) #define VRP_HOT(f) do { if (g_vrp.on) g_vrp.f++; } while (0) #define VRP_ZE(z) do { if (g_vrp.on) g_vrp.zone_t0[z] = vrp_tb(); } while (0) #define VRP_ZX(z) do { if (g_vrp.on) \ g_vrp.zone[z] += (uint32_t)(vrp_tb() - g_vrp.zone_t0[z]); } while (0) #define VRP_ZE3(z) do { if (g_vrp.level >= 3) g_vrp.zone_t0[z] = vrp_tb(); } while (0) #define VRP_ZX3(z) do { if (g_vrp.level >= 3) \ g_vrp.zone[z] += (uint32_t)(vrp_tb() - g_vrp.zone_t0[z]); } while (0) struct vrmesa_context; extern void vrPerfInit(struct vrmesa_context *); extern void vrPerfSwap(struct vrmesa_context *); extern void vrPerfDump(void); #else /* !VERITE_INSTRUMENT */ #define VRP_COUNT(f) ((void)0) #define VRP_ADD(f, n) ((void)0) #define VRP_FALLBACK(r) ((void)0) #define VRP_FALLBACK_HOT(r) ((void)0) #define VRP_HOT(f) ((void)0) #define VRP_ZE(z) ((void)0) #define VRP_ZX(z) ((void)0) #define VRP_ZE3(z) ((void)0) #define VRP_ZX3(z) ((void)0) #define vrPerfInit(vm) ((void)0) #define vrPerfSwap(vm) ((void)0) #define vrPerfDump() ((void)0) #endif /* VERITE_INSTRUMENT */ #endif /* VRPERF_H */