ui: add burn in debug mode (#36625)

* ui: add burn in debug mode

* scary

* lil less

* lil cleanup

* revert that

* cleanup
master
Adeeb Shihadeh 20 hours ago committed by GitHub
parent 81be78cd4d
commit d0c6f845da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      system/ui/README.md
  2. 56
      system/ui/lib/application.py
  3. 16
      system/ui/lib/shader_polygon.py

@ -6,6 +6,7 @@ Quick start:
* set `SHOW_FPS=1` to show the FPS
* set `STRICT_MODE=1` to kill the app if it drops too much below 60fps
* set `SCALE=1.5` to scale the entire UI by 1.5x
* set `BURN_IN=1` to get a burn-in heatmap version of the UI
* https://www.raylib.com/cheatsheet/cheatsheet.html
* https://electronstudio.github.io/raylib-python-cffi/README.html#quickstart

@ -6,6 +6,7 @@ import signal
import sys
import pyray as rl
import threading
import platform
from contextlib import contextmanager
from collections.abc import Callable
from collections import deque
@ -34,6 +35,43 @@ SCALE = float(os.getenv("SCALE", "1.0"))
PROFILE_RENDER = int(os.getenv("PROFILE_RENDER", "0"))
PROFILE_STATS = int(os.getenv("PROFILE_STATS", "100")) # Number of functions to show in profile output
GL_VERSION = """
#version 300 es
precision highp float;
"""
if platform.system() == "Darwin":
GL_VERSION = """
#version 330 core
"""
BURN_IN_MODE = "BURN_IN" in os.environ
BURN_IN_VERTEX_SHADER = GL_VERSION + """
in vec3 vertexPosition;
in vec2 vertexTexCoord;
uniform mat4 mvp;
out vec2 fragTexCoord;
void main() {
fragTexCoord = vertexTexCoord;
gl_Position = mvp * vec4(vertexPosition, 1.0);
}
"""
BURN_IN_FRAGMENT_SHADER = GL_VERSION + """
in vec2 fragTexCoord;
uniform sampler2D texture0;
out vec4 fragColor;
void main() {
vec4 sampled = texture(texture0, fragTexCoord);
float intensity = sampled.b;
// Map blue intensity to green -> yellow -> red to highlight burn-in risk.
vec3 start = vec3(0.0, 1.0, 0.0);
vec3 middle = vec3(1.0, 1.0, 0.0);
vec3 end = vec3(1.0, 0.0, 0.0);
vec3 gradient = mix(start, middle, clamp(intensity * 2.0, 0.0, 1.0));
gradient = mix(gradient, end, clamp((intensity - 0.5) * 2.0, 0.0, 1.0));
fragColor = vec4(gradient, sampled.a);
}
"""
DEFAULT_TEXT_SIZE = 60
DEFAULT_TEXT_COLOR = rl.WHITE
@ -155,6 +193,7 @@ class GuiApplication:
self._scaled_width = int(self._width * self._scale)
self._scaled_height = int(self._height * self._scale)
self._render_texture: rl.RenderTexture | None = None
self._burn_in_shader: rl.Shader | None = None
self._textures: dict[str, rl.Texture] = {}
self._target_fps: int = _DEFAULT_FPS
self._last_fps_log_time: float = time.monotonic()
@ -212,8 +251,10 @@ class GuiApplication:
rl.set_config_flags(flags)
rl.init_window(self._scaled_width, self._scaled_height, title)
needs_render_texture = self._scale != 1.0 or BURN_IN_MODE
if self._scale != 1.0:
rl.set_mouse_scale(1 / self._scale, 1 / self._scale)
if needs_render_texture:
self._render_texture = rl.load_render_texture(self._width, self._height)
rl.set_texture_filter(self._render_texture.texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR)
rl.set_target_fps(fps)
@ -222,6 +263,8 @@ class GuiApplication:
self._set_styles()
self._load_fonts()
self._patch_text_functions()
if BURN_IN_MODE and self._burn_in_shader is None:
self._burn_in_shader = rl.load_shader_from_memory(BURN_IN_VERTEX_SHADER, BURN_IN_FRAGMENT_SHADER)
if not PC:
self._mouse.start()
@ -337,6 +380,10 @@ class GuiApplication:
rl.unload_render_texture(self._render_texture)
self._render_texture = None
if self._burn_in_shader:
rl.unload_shader(self._burn_in_shader)
self._burn_in_shader = None
if not PC:
self._mouse.stop()
@ -395,7 +442,14 @@ class GuiApplication:
rl.clear_background(rl.BLACK)
src_rect = rl.Rectangle(0, 0, float(self._width), -float(self._height))
dst_rect = rl.Rectangle(0, 0, float(self._scaled_width), float(self._scaled_height))
rl.draw_texture_pro(self._render_texture.texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE)
texture = self._render_texture.texture
if texture:
if BURN_IN_MODE and self._burn_in_shader:
rl.begin_shader_mode(self._burn_in_shader)
rl.draw_texture_pro(texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE)
rl.end_shader_mode()
else:
rl.draw_texture_pro(texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE)
if self._show_fps:
rl.draw_fps(10, 10)

@ -1,9 +1,8 @@
import platform
import pyray as rl
import numpy as np
from dataclasses import dataclass
from typing import Any, Optional, cast
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, GL_VERSION
MAX_GRADIENT_COLORS = 20 # includes stops as well
@ -29,16 +28,7 @@ class Gradient:
self.stops = [i / max(1, color_count - 1) for i in range(color_count)]
VERSION = """
#version 300 es
precision highp float;
"""
if platform.system() == "Darwin":
VERSION = """
#version 330 core
"""
FRAGMENT_SHADER = VERSION + """
FRAGMENT_SHADER = GL_VERSION + """
in vec2 fragTexCoord;
out vec4 finalColor;
@ -83,7 +73,7 @@ void main() {
"""
# Default vertex shader
VERTEX_SHADER = VERSION + """
VERTEX_SHADER = GL_VERSION + """
in vec3 vertexPosition;
in vec2 vertexTexCoord;
out vec2 fragTexCoord;

Loading…
Cancel
Save