Overview
Migrate SpectrumWidget rendering from CPU-based QPainter to GPU-accelerated rendering via Qt6's QRhi abstraction layer. This offloads FFT spectrum, waterfall scrolling, and overlay compositing to the GPU, significantly reducing CPU load.
Motivation
Current SpectrumWidget::paintEvent runs entirely on the CPU:
- Waterfall scroll: CPU copies/shifts ~1MB QImage every row, 25x/sec — biggest CPU hog
- FFT polyline: QPainter software-rasterizes 1000+ point polyline each frame
- Overlays: filter passband, spots, TNFs, band plan — all alpha-blended in software
Estimated CPU reduction: 30-50% of SpectrumWidget CPU time, more significant at higher resolutions and FPS.
Why QRhi (not raw OpenGL or Vulkan)
| Platform |
QRhi Backend |
Notes |
| Linux x64 |
OpenGL |
Mesa drivers, works everywhere |
| Linux ARM (Raspberry Pi) |
OpenGL ES |
Pi 4/5 V3D GPU, Qt6 on Pi OS uses EGL/GLES |
| macOS (Apple Silicon) |
Metal |
Apple deprecated OpenGL in 10.14 — raw GL is a dead end on macOS |
| Windows x64 |
D3D11 |
Works in VMs/RDP via WARP software renderer |
QRhi is Qt6's render hardware interface — one API, correct backend selected per platform automatically. Avoids:
- OpenGL deprecation risk on macOS
- OpenGL ES vs desktop GL differences on Pi
- Raw Vulkan complexity for a simple rendering workload
GPU Rendering Plan
Waterfall (biggest win)
- Allocate a GPU texture (width × history_rows)
- New waterfall row → upload single texture row (~4KB), advance row index
- Render as a textured quad with UV offset for scrolling — zero CPU copy
- Color mapping via fragment shader (intensity → color LUT texture)
FFT Spectrum
- Upload bin values as a vertex buffer (~2000 floats)
- Draw as
GL_LINE_STRIP with smoothing
- Grid lines as a separate line batch
Overlays
- Filter passband, spots, TNFs, band plan → textured/colored quads with alpha
- Text labels → pre-rendered texture atlas or continue using QPainter overlay on top of the GL surface
Hybrid Approach
Qt allows QPainter on top of a QRhiWidget for text and complex UI elements. Render the heavy stuff (waterfall texture, FFT polyline) on GPU, overlay text labels and spots with QPainter. This avoids the complexity of a text rendering pipeline on GPU.
Pop-out Consideration
If we use QRhi, popping out the spectrum to a floating window (#246) is cleaner than raw OpenGL — QRhi manages the render target, and creating a new swapchain on a new window doesn't require re-uploading textures.
Estimated Effort
Medium-high. ~300-400 lines for the QRhi rendering code, plus testing on all 4 platforms. The QPainter fallback should be kept as a compile-time option for headless/CI builds.
Dependencies
- Qt 6.6+ for stable QRhiWidget API
- No external libraries — QRhi is bundled with Qt6
Priority
Post-1.0. Current QPainter rendering works correctly on all platforms. This is a performance optimization, not a functional requirement.
73, Jeremy KK7GWY & Claude (AI dev partner)
Overview
Migrate SpectrumWidget rendering from CPU-based QPainter to GPU-accelerated rendering via Qt6's QRhi abstraction layer. This offloads FFT spectrum, waterfall scrolling, and overlay compositing to the GPU, significantly reducing CPU load.
Motivation
Current
SpectrumWidget::paintEventruns entirely on the CPU:Estimated CPU reduction: 30-50% of SpectrumWidget CPU time, more significant at higher resolutions and FPS.
Why QRhi (not raw OpenGL or Vulkan)
QRhi is Qt6's render hardware interface — one API, correct backend selected per platform automatically. Avoids:
GPU Rendering Plan
Waterfall (biggest win)
FFT Spectrum
GL_LINE_STRIPwith smoothingOverlays
Hybrid Approach
Qt allows QPainter on top of a
QRhiWidgetfor text and complex UI elements. Render the heavy stuff (waterfall texture, FFT polyline) on GPU, overlay text labels and spots with QPainter. This avoids the complexity of a text rendering pipeline on GPU.Pop-out Consideration
If we use QRhi, popping out the spectrum to a floating window (#246) is cleaner than raw OpenGL — QRhi manages the render target, and creating a new swapchain on a new window doesn't require re-uploading textures.
Estimated Effort
Medium-high. ~300-400 lines for the QRhi rendering code, plus testing on all 4 platforms. The QPainter fallback should be kept as a compile-time option for headless/CI builds.
Dependencies
Priority
Post-1.0. Current QPainter rendering works correctly on all platforms. This is a performance optimization, not a functional requirement.
73, Jeremy KK7GWY & Claude (AI dev partner)