Skip to content

GPU-accelerated spectrum/waterfall rendering via QRhi #391

Description

@ten9876

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImprovement to existing featurepriority: lowLow priorityspectrumPanadapter and waterfall

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions