diff options
| author | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
|---|---|---|
| committer | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
| commit | 2702c90d7a39fca2a3319c5e915fd290cb31fc70 (patch) | |
| tree | 283c4d851efef7e3a7cd03ba80c87e2bffcdbb2c /src/mesa/drivers/verite/vrapi.c | |
| parent | 836167945ec2c7ad5acdf0aa17ce35ec1b9428a6 (diff) | |
Initial import.
Diffstat (limited to 'src/mesa/drivers/verite/vrapi.c')
| -rw-r--r-- | src/mesa/drivers/verite/vrapi.c | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/mesa/drivers/verite/vrapi.c b/src/mesa/drivers/verite/vrapi.c new file mode 100644 index 0000000..b2aa74d --- /dev/null +++ b/src/mesa/drivers/verite/vrapi.c @@ -0,0 +1,319 @@ +/* + * 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. + */ + +/* + * veritemesa public API + */ + +#include <stdlib.h> +#ifdef VERITE_INSTRUMENT +#include <stdio.h> +#endif + +#include "vrdrv.h" + +#include "GL/vrmesa.h" +#include "context.h" +#include "extensions.h" +#include "imports.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#include "drivers/common/driverfuncs.h" + +#ifdef VERITE_INSTRUMENT +/* + * The single driver-layer perf accumulator (vrperf.h). + */ +struct vrperf g_vrp; + +/* + * RunPipeline wrapper + */ +static void +vr_run_pipeline(GLcontext *ctx) +{ + + VRP_ZE(VRP_Z_PIPELINE); + _tnl_run_pipeline(ctx); + VRP_ZX(VRP_Z_PIPELINE); +} + +void +vrPerfInit(vrmesa_context *vm) +{ + const char *p = getenv("VRMESA_PROF"); + + g_vrp.level = p ? atoi(p) : 0; + g_vrp.on = g_vrp.level >= 1; + g_vrp.rl = &vm->rl; + g_vrp.tb0 = vrp_tb64(); + g_vrp.ns0 = v3d_now_ns(); + /* + * Bridge the librlgl/libv3d _ns timers into VRPERF + */ + if (g_vrp.on && vm->rl.v.opt_stats == 0) + vm->rl.v.opt_stats = 1; + atexit(vrPerfDump); +} + +void +vrPerfSwap(vrmesa_context *vm) +{ + + (void)vm; + g_vrp.frames++; + /* cumulative snapshot, diff two lines to isolate a demo window */ + if (g_vrp.level >= 2 && (g_vrp.frames & 127) == 0) + printf("VRPERFSNAP frame=%llu texres=%llu zfunc=%llu " + "blend=%llu fgcolor=%llu fences=%llu\n", + (unsigned long long)g_vrp.frames, + (unsigned long long)g_vrp.fb[VRP_FB_TEX_RESIDENCY], + (unsigned long long)g_vrp.fb[VRP_FB_DEPTHFUNC], + (unsigned long long)g_vrp.fb[VRP_FB_BLEND], + (unsigned long long)g_vrp.fgcolor_writes, + (unsigned long long)g_vrp.fences); +} + +void +vrPerfDump(void) +{ + static const char *zname[VRP_Z__N] = { + "pipeline", "render_start", "texvalidate", "tri_emit" + }; + struct rlgl *rl = g_vrp.rl; + double tick_ns, nf; + uint64_t dtb; + int i; + + if (g_vrp.printed || g_vrp.level < 1) + return; + g_vrp.printed = 1; + + dtb = vrp_tb64() - g_vrp.tb0; + tick_ns = dtb ? (double)(v3d_now_ns() - g_vrp.ns0) / (double)dtb : 0.0; + nf = g_vrp.frames > 0 ? (double)g_vrp.frames : 1.0; + + printf("VRPERF frames=%llu\n", (unsigned long long)g_vrp.frames); + printf("VRPERF fallback tex=%llu blend=%llu afunc=%llu zfunc=%llu " + "stipple=%llu smooth=%llu twoside=%llu specular=%llu " + "unfilled=%llu rmode=%llu texres=%llu alphagrad=%llu\n", + (unsigned long long)g_vrp.fb[VRP_FB_TEX_HWOK], + (unsigned long long)g_vrp.fb[VRP_FB_BLEND], + (unsigned long long)g_vrp.fb[VRP_FB_ALPHAFUNC], + (unsigned long long)g_vrp.fb[VRP_FB_DEPTHFUNC], + (unsigned long long)g_vrp.fb[VRP_FB_STIPPLE], + (unsigned long long)g_vrp.fb[VRP_FB_SMOOTH], + (unsigned long long)g_vrp.fb[VRP_FB_TWOSIDE], + (unsigned long long)g_vrp.fb[VRP_FB_SPECULAR], + (unsigned long long)g_vrp.fb[VRP_FB_UNFILLED_SUB], + (unsigned long long)g_vrp.fb[VRP_FB_RENDERMODE], + (unsigned long long)g_vrp.fb[VRP_FB_TEX_RESIDENCY], + (unsigned long long)g_vrp.fb[VRP_FB_TRI_ALPHAGRAD]); + printf("VRPERF texval dirty=%llu nlvl=%llu evict=%llu first=%llu " + "bindonly=%llu creates=%llu failv=%llu failu=%llu\n", + (unsigned long long)g_vrp.tv_dirty, + (unsigned long long)g_vrp.tv_nlevels, + (unsigned long long)g_vrp.tv_evict, + (unsigned long long)g_vrp.tv_first, + (unsigned long long)g_vrp.tv_bindonly, + (unsigned long long)g_vrp.tv_creates, + (unsigned long long)g_vrp.tv_failv, + (unsigned long long)g_vrp.tv_failu); + printf("VRPERF churn fgcolor=%llu mipbind=%llu filt=%llu fences=%llu\n", + (unsigned long long)g_vrp.fgcolor_writes, + (unsigned long long)g_vrp.mip_binds, + (unsigned long long)g_vrp.filt_changes, + (unsigned long long)g_vrp.fences); + printf("VRPERF cpu_ms_per_frame tick_ns=%.3f", tick_ns); + for (i = 0; i < VRP_Z__N; i++) + printf(" %s=%.2f", zname[i], + (double)g_vrp.zone[i] * tick_ns / nf / 1e6); + printf("\n"); + if (rl != NULL) + printf("VRPERF gpu_wait_ms_per_frame submit=%.2f sync=%.2f " + "flip=%.2f | tris=%llu st_calls=%llu texbinds=%llu " + "submit_kb=%llu\n", + (double)rl->v.st.submit_ns / nf / 1e6, + (double)rl->v.st.sync_ns / nf / 1e6, + (double)rl->v.st.flip_ns / nf / 1e6, + (unsigned long long)rl->tris, + (unsigned long long)rl->v.st.st_calls, + (unsigned long long)rl->v.st.texbinds, + (unsigned long long)(rl->v.st.submit_bytes / 1024)); +} +#endif /* VERITE_INSTRUMENT */ + +vrMesaContext +vrMesaCreateContext(const char *ucodepath) +{ + vrmesa_context *vmesa; + GLcontext *ctx; + struct dd_function_table functions; + + if (ucodepath == NULL) + ucodepath = getenv("VERITE_UCODE"); + if (ucodepath == NULL) { + _mesa_printf("vrMesaCreateContext: no microcode " + "(pass a path or set VERITE_UCODE)\n"); + return NULL; + } + + vmesa = CALLOC_STRUCT(vrmesa_context); + if (vmesa == NULL) + return NULL; + + if (rlgl_init(&vmesa->rl, ucodepath) != 0) { + _mesa_free(vmesa); + return NULL; + } + vmesa->fg_alpha = ~0u; /* FGColor alpha cache: unset */ + + if (!_mesa_initialize_visual(&vmesa->glvis, + GL_TRUE, /* rgb */ + GL_TRUE, /* double buffered */ + GL_FALSE, /* stereo */ + 5, 6, 5, 0, /* rgba bits */ + 0, /* index bits */ + 16, /* depth bits */ + 0, /* stencil */ + 0, 0, 0, 0, /* accum */ + 0)) { /* samples */ + rlgl_shutdown(&vmesa->rl); + _mesa_free(vmesa); + return NULL; + } + + _mesa_init_driver_functions(&functions); + vrInitDDFuncs(&functions); + + if (!_mesa_initialize_context(&vmesa->glctx, &vmesa->glvis, NULL, + &functions, (void *)vmesa)) { + rlgl_shutdown(&vmesa->rl); + _mesa_free(vmesa); + return NULL; + } + ctx = &vmesa->glctx; + + vrInitTexConsts(ctx); + + /* hardware depth+color, no software stencil/accum/alpha planes */ + _mesa_initialize_framebuffer(&vmesa->glfb, &vmesa->glvis, + GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + _swrast_CreateContext(ctx); + _ac_CreateContext(ctx); + _tnl_CreateContext(ctx); + _swsetup_CreateContext(ctx); + _swsetup_Wakeup(ctx); + + /* + * The PE fog unit iterates a per-vertex factor (KFXYZUVQ f term) + */ + _tnl_allow_vertex_fog(ctx, GL_TRUE); + _tnl_allow_pixel_fog(ctx, GL_FALSE); + + vrInitSpanFuncs(ctx); + vrInitTriFuncs(ctx); + +#ifdef VERITE_INSTRUMENT + TNL_CONTEXT(ctx)->Driver.RunPipeline = vr_run_pipeline; +#else + TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; +#endif + + _mesa_enable_sw_extensions(ctx); + + vrPerfInit(vmesa); + + return (vrMesaContext)vmesa; +} + +void +vrMesaDestroyContext(vrMesaContext vrctx) +{ + vrmesa_context *vmesa = (vrmesa_context *)vrctx; + GLcontext *ctx; + + if (vmesa == NULL) + return; + ctx = &vmesa->glctx; + + if (vrMesaGetCurrentContext() == vrctx) + _mesa_make_current2(NULL, NULL, NULL); + + _swsetup_DestroyContext(ctx); + _tnl_DestroyContext(ctx); + _ac_DestroyContext(ctx); + _swrast_DestroyContext(ctx); + + _mesa_free_framebuffer_data(&vmesa->glfb); + _mesa_free_context_data(ctx); + vrPerfDump(); /* while g_vrp.rl is still valid */ + rlgl_shutdown(&vmesa->rl); + _mesa_free(vmesa); +} + +vrMesaContext +vrMesaGetCurrentContext(void) +{ + GET_CURRENT_CONTEXT(ctx); + return (vrMesaContext)ctx; +} + +void +vrMesaMakeCurrent(vrMesaContext vrctx) +{ + vrmesa_context *vmesa = (vrmesa_context *)vrctx; + + if (vmesa == NULL) { + _mesa_make_current2(NULL, NULL, NULL); + return; + } + _mesa_make_current2(&vmesa->glctx, &vmesa->glfb, &vmesa->glfb); +} + +void +vrMesaSwapBuffers(void) +{ + GET_CURRENT_CONTEXT(ctx); + vrmesa_context *vmesa; + + if (ctx == NULL) + return; + vmesa = VRMESA_CONTEXT(ctx); + _mesa_notifySwapBuffers(ctx); + rlgl_swap(&vmesa->rl); + /* rlgl_swap fences the engine before flipping */ + vmesa->engine_dirty = GL_FALSE; + vrPerfSwap(vmesa); +} |
