Skip to content

fix(spectrum): make AETHER_NO_GPU select OpenGL backend on Windows (#3597)#3987

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
motoham88:fix/3597-windows-software-render
Jul 4, 2026
Merged

fix(spectrum): make AETHER_NO_GPU select OpenGL backend on Windows (#3597)#3987
ten9876 merged 1 commit into
aethersdr:mainfrom
motoham88:fix/3597-windows-software-render

Conversation

@motoham88

Copy link
Copy Markdown
Contributor

Summary

AETHER_NO_GPU=1 is documented as the runtime escape hatch to force software rendering, but on Windows it is a silent no-op. main.cpp only sets QT_OPENGL=software, which is an OpenGL-context hint — but the spectrum is a QRhiWidget that has no setApi() call on Windows, so it defaults to the D3D11 backend and ignores QT_OPENGL entirely. There is no runtime path to move the spectrum off the GPU.

This surfaced in #3597: on a weak GPU (reporter's GeForce GT 220, a 2009 DX10.1 part) the D3D11 QRhi spectrum + waterfall + overlay pipeline saturates the GPU (~89%), and setting AETHER_NO_GPU=1 changed nothing — confirmed by the reporter.

Change

In the SpectrumWidget constructor's non-macOS branch, when software OpenGL is requested (qtSoftwareOpenGlRequested()), explicitly setApi(QRhiWidget::Api::OpenGL). Combined with the QT_OPENGL=software set in main.cpp, this drives the spectrum through the software OpenGL rasterizer instead of D3D11.

  • The bundled .qsb shaders already contain GLSL variants (GLSL 100es/120/150 alongside SPIR-V/HLSL/MSL), so pipeline creation succeeds on the OpenGL backend.
  • No behavior change on Linux, whose QRhiWidget default backend is already OpenGL — this just makes the two platforms share one explicit code path.

src/gui/SpectrumWidget.cpp — 1 file, ~10 lines (comment + guarded setApi).

Scope / what this does NOT claim

Testing

Refs #3597

🤖 Generated with Claude Code

…ethersdr#3597)

AETHER_NO_GPU=1 only sets QT_OPENGL=software in main.cpp, but on Windows
QRhiWidget defaults to the D3D11 backend and ignores QT_OPENGL, so the
documented software-render escape hatch was a silent no-op there. On a
weak GPU (reporter: GeForce GT 220) the spectrum still saturated the GPU
via D3D11 with no runtime way to fall back.

Force QRhiWidget::Api::OpenGL when software OpenGL is requested, so the
software rasterizer set up in main.cpp actually drives the spectrum. The
GLSL variants are already bundled in the .qsb shaders, so pipeline
creation succeeds on the OpenGL backend. No change on Linux, whose
default backend is already OpenGL.

Note: this makes the flag functional; it does not by itself resolve the
performance complaint on weak GPU+CPU hardware, for which an FFT-FPS
throttle is tracked separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped fix. I traced the whole chain and it holds up:

  • Premise confirmed. main.cpp:87-88 sets QT_OPENGL=software for AETHER_NO_GPU, but that's only an OpenGL-context hint — a QRhiWidget with no setApi() does default to D3D11 on Windows and ignore it. So the flag really was a silent no-op there, exactly as described.
  • Correct placement. The setApi() call sits in the #ifdef AETHER_GPU_SPECTRUM / non-Q_OS_MAC branch, mirroring the existing macOS setApi(Metal) a few lines up, and is called in the constructor before first show — the right point for QRhiWidget::setApi().
  • Reuses the existing qtSoftwareOpenGlRequested() helper (already used by rendererDescription()), so detection stays consistent with how the renderer reports itself.
  • No Linux regression. The branch also covers Linux, but its QRhiWidget backend already defaults to OpenGL, so this is a harmless explicit restatement — good for keeping both platforms on one path.

I also checked the one dependency this introduces: the forced OpenGL backend + QT_OPENGL=software needs Qt's software rasterizer DLL present at runtime. .github/workflows/windows-installer.yml:127 runs windeployqt without --no-opengl-sw, so opengl32sw.dll is bundled by default. The dependency is satisfied on packaged builds. 👍

No AppSettings/RAII/lifetime concerns, and the file is the only one touched — scope matches the stated intent.

One note, not blocking: as you already call out, this makes the flag functional on Windows but won't help the #3597 reporter's perf complaint if their CPU is also weak — software-rasterizing the 60 fps per-pixel FFT pipeline just moves the saturation from GPU to CPU. Worth being explicit with @EA7JQA that the ask here is "does the panadapter render and does panstats renderer report software OpenGL," separate from the load question (the FFT-FPS cap tracked separately is the real lever for that).

Since the failure mode is Windows-only and unverifiable in CI/on Linux, reporter confirmation is the right gate before merge. Thanks for the clear writeup and the honest scoping, @motoham88.


🤖 aethersdr-agent · cost: $4.2941 · model: claude-opus-4-8

@NF0T

NF0T commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

@NF0T review — PR #3987

Well-researched root cause and honest scoping. Independent verification:

  • Silent no-op confirmed. main.cpp:87-88 sets QT_OPENGL=software only. On Windows, QRhiWidget without setApi() defaults to D3D11 and ignores QT_OPENGL entirely — the diagnosis is correct.
  • Placement correct. Constructor, before first show, in the #ifdef AETHER_GPU_SPECTRUM / #else [non-macOS] branch — mirrors the existing setApi(Metal) a few lines up. Right place, right time for QRhiWidget::setApi().
  • Helper is right. qtSoftwareOpenGlRequested() already drives rendererDescription() / panstats renderer, so detection stays consistent with how the renderer self-reports.
  • Shaders. qt_add_shaders in CMakeLists.txt has no GLSL restriction — Qt compiles GLSL alongside SPIR-V/HLSL/MSL by default. OpenGL backend can use the shaders as-is.
  • opengl32sw.dll. windows-installer.yml:127 runs windeployqt without --no-opengl-sw — software rasterizer DLL is deployed in packaged builds. Runtime dependency satisfied.
  • Linux. qtSoftwareOpenGlRequested() returns false under normal operation; setApi() doesn't fire. If the flag is set on Linux, setApi(OpenGL) is a harmless no-op on a backend already defaulting to OpenGL.

What @EA7JQA's test tells us: "the panadapter renders" with AETHER_NO_GPU=1. Since the reporter previously confirmed the flag "changed nothing" (D3D11 ran regardless), a rendering panadapter means the fix engaged the OpenGL path. That's confirmation the fix is functional.

One piece missing for a clean Principle XI close: the panstats renderer field — or equivalently, the log line the PR itself emits: "SpectrumWidget: AETHER_NO_GPU/QT_OPENGL=software — forcing OpenGL QRhi backend". If @EA7JQA can share either, we can confirm the backend actually switched at runtime rather than inferring it. See my comment on #3597.

Holding merge pending that confirmation.

For future reference: comment block is 5 lines; AGENTS.md style is one short line max. The WHY here is non-obvious enough to warrant something, but it could be trimmed. Not a blocker.

CI 6/6 green. Tier 3 only. Will revisit once the log line is confirmed.

@NF0T NF0T self-assigned this Jul 4, 2026
@jensenpat

jensenpat commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

I'm not understanding this PR at all. Why would an env var to turn off the GPU ever invoke OpenGL? (which then invokes a GPU) Is this the right fix? As I understand it, the goal is to invoke a software renderer.

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, minimal fix for a real silent-no-op bug: setApi(OpenGL) under AETHER_GPU_SPECTRUM's non-Mac branch makes AETHER_NO_GPU/QT_OPENGL=software actually switch the QRhi backend to OpenGL on Windows (was defaulting to D3D11 regardless). Correctly guarded, uses the existing qtSoftwareOpenGlRequested() helper, right setApi timing, Linux is a harmless restatement. LGTM.

@ten9876 ten9876 merged commit 3224f6d into aethersdr:main Jul 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants