aboutsummaryrefslogtreecommitdiff
path: root/src/mesa/drivers/verite/vrapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/verite/vrapi.c')
-rw-r--r--src/mesa/drivers/verite/vrapi.c319
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);
+}