Skip to content

Global setting: choose the GPU (Automatic / Integrated / Discrete), and the device recreation it needs #114

Description

@relmer

On a laptop with both an integrated and a discrete GPU, Casso takes whatever
adapter Windows hands it. The desk scene is the first presentation heavy
enough for that choice to matter — and it is exactly the kind of app where a
user might reasonably want either answer (the discrete part for the smoothest
scene, the integrated one to stop the fans and save battery).

What to add

A global preference — the host's graphics budget is a property of the machine
Casso is running ON, not of the machine it is emulating, so this belongs
beside the antialiasing setting rather than per emulated machine or per
monitor.

Three-way, defaulting to Automatic:

  • Automatic — whatever Windows picks (today's behavior)
  • IntegratedDXGI_GPU_PREFERENCE_MINIMUM_POWER
  • DiscreteDXGI_GPU_PREFERENCE_HIGH_PERFORMANCE

Deliberately NOT an AC/battery auto-switch. Windows already has a per-app
graphics preference, and a second policy fighting it tends to surprise people
more than it helps.

Prior art

MatrixRain (peer repo) already solved the enumeration half:
MatrixRainCore/WindowsAdapterProvider.cpp walks EnumAdapters1, filters
DXGI_ADAPTER_FLAG_SOFTWARE, and resolves the system default through
IDXGIFactory6::EnumAdapterByGpuPreference(UNSPECIFIED) — all behind an
IAdapterProvider interface so tests drive it from a vector rather than from
real hardware. That shape ports over directly.

The real work: device recreation

Honouring a changed preference means tearing down the D3D device and building
a new one, which is the same machinery as device-loss recovery — still
open from the superseded spec 008:

FR-018: The mesh renderer MUST handle D3D device loss and recreation by
rebuilding shaders, depth target, mesh registry, and faceplate
render-textures without leaking resources.

That spec's adjacent edge cases belong with it: a minimized / zero-client-area
window must skip the 3D pass cleanly without depth-buffer churn, and a runtime
DPI change must re-rasterize so labels stay crisp.

The scene has accumulated a lot of device-owned state since 008 was written,
and all of it dies with the device:

  • the multisampled scene target, its resolve texture, and the depth buffer
  • the two cached scene plates (DeskScene::m_backPlate* / m_frontPlate*)
  • every Dxui3DRenderer::StaticMesh vertex buffer — note these are keyed by a
    revision counter, so after a device change the cache would happily hand back
    ComPtrs belonging to a destroyed device with the revision unchanged. This
    one is a silent failure rather than a loud one, and needs an explicit
    invalidation hook.
  • CrtPostProcess's ping-pong textures and the offscreen scene-content target

Testing note

Device recreation is the part that cannot be proven on a single-adapter
machine. The interface split MatrixRain uses makes the selection logic
unit-testable without hardware, but the teardown/rebuild path wants a real
dual-GPU laptop to validate against.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestimpact: engineeringInternal only: testability, architecture, maintainabilitypriority: lowDev / power-user / infrastructure (end-user-value triage)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions