Skip to content

Add graphics adapter (GPU) selection#1845

Open
naughtyGitCat wants to merge 2 commits into
mltframework:masterfrom
naughtyGitCat:gpu-adapter-selection-pr
Open

Add graphics adapter (GPU) selection#1845
naughtyGitCat wants to merge 2 commits into
mltframework:masterfrom
naughtyGitCat:gpu-adapter-selection-pr

Conversation

@naughtyGitCat

Copy link
Copy Markdown

What

Adds a Settings → Graphics Adapter submenu to choose which physical GPU Shotcut renders and encodes with.

Why

On a desktop where a low-power integrated GPU drives the display while a more capable discrete GPU is also installed (e.g. an NVIDIA card with no monitor attached), Shotcut renders the preview — and, depending on the chosen encoder, exports — on the integrated GPU, with no way to direct the work to the discrete GPU. This adds that choice.

How

  • Enumeration (gpuinfo.{h,cpp}, new): list physical adapters via DXGI. Some drivers (notably AMD integrated graphics) report the same physical GPU many times with different LUIDs, so adapters are de-duplicated by their stable hardware identity (vendor + device + subsys + revision).
  • Preview / UI: the chosen GPU is applied by setting QT_D3D_ADAPTER_INDEX before the RHI is initialized, so the Direct3D scene graph (the default backend on Windows) creates its device on that adapter.
  • Stable selection: the raw DXGI adapter index is not stable across runs on some systems (the number of duplicate integrated-GPU entries varies), so the selection is persisted as the GPU's vendor + device id and the live index is resolved at startup.
  • Export: when a specific GPU is selected, export uses the hardware encoder family matching that vendor (NVIDIA → *_nvenc, AMD → *_amf, Intel → *_qsv), and hardware encoding defaults on.
  • UI: Settings > Graphics Adapter with the usual restart prompt, following the existing "Display Method" menu pattern.

Scope / notes

  • Currently implemented for the Windows Direct3D backend; enumerateGpuAdapters() returns empty elsewhere and the menu is hidden, so other platforms are unaffected.
  • New gpuinfo.{h,cpp} carry the Meltytech copyright header; formatted with clang-format 14.
  • UI translations are intentionally not included (handled via Transifex).

Tests

Adds a QtTest suite (tests/test_gpuinfo.cpp, 11 cases) covering encoder-family selection, codec-type matching, fallbacks, adapter de-duplication and live index resolution, behind a new off-by-default SHOTCUT_BUILD_TESTS option (default/official builds unchanged):

cmake -B build -DSHOTCUT_BUILD_TESTS=ON .
ninja -C build test_gpuinfo && ctest --test-dir build --output-on-failure

Manually verified on an AMD iGPU + NVIDIA RTX 3090 machine: selecting the 3090 moves preview rendering to it (confirmed via nvidia-smi) and routes hardware export through NVENC.

🤖 Generated with Claude Code

@ddennedy

ddennedy commented Jun 6, 2026

Copy link
Copy Markdown
Member

Thank you for your contribution. It is a good idea, but it would nice to have some cross-platform support, particularly on Linux. I do not think it matters much on macOS any more since the advent of Apple Silicon. In any case, I just had to push a fix for the next release that created a merge conflict. Please fix that. Then, I will not be able to merge this until after the next release due by end of the month plus a quiet week. I require that I am able to test and support nearly everything in Shotcut because I cannot trust any outsider to be there to help. Currently, I do not have any multi-GPU system, but I have a couple that I can swap a PCIe card if the power supply supports it. So, in the meantime, I will try to get there in position to test and support it and possibly extend to Linux.

Comment thread src/docks/encodedock.cpp Outdated
Comment thread src/gpuinfo.cpp Outdated
Comment thread src/docks/encodedock.cpp Outdated
Comment thread src/main.cpp Outdated
@naughtyGitCat naughtyGitCat force-pushed the gpu-adapter-selection-pr branch from f070361 to defc1d0 Compare June 8, 2026 02:23
@naughtyGitCat

Copy link
Copy Markdown
Author

Thanks for the detailed review — much appreciated. I've pushed an update (rebased onto master):

  1. Merge conflict — rebased onto the latest master, so it now includes your "Fix 10-bit H.264 hardware encode fails" change.

  2. Auto-enabling hardware encoding — removed. You're right that it effectively turned the opt-in hardware encoding into opt-out, and as you noted it would rarely trigger anyway. The checkbox is back to being driven purely by the user's saved preference; only the vendor matching among already-configured hardware encoders remains.

  3. 10-bit H.264 — folded your is10bit guard into the encoder-selection helper, so a 10-bit pix_fmt skips H.264 hardware encoders (HEVC/AV1 hardware are unaffected).

On the broader point: you're right that this currently only affects the UI/display adapter and the optional encoder, not hardware decoding or the GPU (Movit) processing mode. I scoped it conservatively for that reason — enumerateGpuAdapters() returns empty on non-Windows / non-D3D backends, so the menu is simply hidden and other configurations are unaffected. I'm happy to extend it to cover hardware decode and the GPU processing mode, and to add a Vulkan path for Linux (QT_VK_PHYSICAL_DEVICE_INDEX) — though real multi-GPU testing there needs the hardware. No rush on my end; I understand this is post-release, and I'm glad to iterate once you're set up to test.

Add a "Graphics Adapter" submenu under Settings to choose which physical GPU
Shotcut renders, decodes, and encodes with. On systems where a low-power
integrated GPU drives the display while a more capable discrete GPU is also
present (e.g. an NVIDIA card with no monitor attached), this lets the user direct
preview rendering, hardware decoding and hardware export to the discrete GPU.

- gpuinfo.{h,cpp} (new): enumerate physical adapters via DXGI, de-duplicating
  the same GPU that some drivers report multiple times; resolve a GPU's live
  DXGI adapter index from its stable vendor+device id (the raw index is not
  stable across runs on some systems); and pick the hardware encoder family
  matching the selected vendor (NVIDIA->nvenc, AMD->amf, Intel->qsv), skipping
  H.264 hardware encoders for 10-bit video since they do not support it.
- main.cpp: set QT_D3D_ADAPTER_INDEX (Qt RHI preview/UI) and
  MLT_AVFORMAT_HWACCEL_DEVICE (FFmpeg hardware decoder) to the selected GPU
  before the RHI is initialized (Windows Direct3D backend).
- docks/encodedock.cpp: when hardware encoding is enabled, prefer the encoder
  family matching the selected GPU.
- mainwindow: Settings > Graphics Adapter menu with a restart prompt.
- tests: a QtTest suite for the encoder selection and adapter logic, built
  behind the off-by-default SHOTCUT_BUILD_TESTS option (configure with
  -DSHOTCUT_BUILD_TESTS=ON, run with ctest).

UI translations are intentionally omitted (handled via Transifex).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@naughtyGitCat naughtyGitCat force-pushed the gpu-adapter-selection-pr branch from defc1d0 to e752f50 Compare June 9, 2026 13:05
@naughtyGitCat

Copy link
Copy Markdown
Author

Thanks — good call. I've set MLT_AVFORMAT_HWACCEL_DEVICE to the same resolved adapter index alongside QT_D3D_ADAPTER_INDEX in main.cpp, so the hardware decoder now targets the selected GPU as well. Since the melt export subprocess inherits the environment, it applies to both preview and export.

One note on the Linux CI: the build job failed at git checkout origin/gpu-adapter-selection-pr (pathspec ... did not match), which I believe is because the branch only exists on the fork rather than the upstream remote the build script checks out — not a compile error. Happy to adjust anything on my end if that's not expected.

@ddennedy ddennedy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I successfully tested this and will merge it a few days after the next release.

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.

2 participants