Skip to content

Conversation

@oritwoen
Copy link
Owner

Summary

Add explicit GPU backend selection via --backend CLI flag to work around wgpu DX12 panic on Windows.

Closes #24

Changes

  • Add GpuBackend enum with variants: Auto, Vulkan, Dx12, Metal, Gl
  • Add --backend CLI flag (default: auto)
  • Auto mode tries backends in order: Vulkan → Metal → DX12 → GL
  • Auto mode prefers hardware GPUs over software renderers (llvmpipe, SwiftShader)
  • Refactor GpuContext::new() to accept backend parameter

Usage

# Default auto mode
kangaroo --target boha:b1000/135

# Force specific backend
kangaroo --backend vulkan --target boha:b1000/135

Testing

  • cargo build --all-features
  • cargo test --all-features
  • cargo run -- --help shows --backend option ✓

Co-Authored-By: Aei aei@oad.earth

Add explicit GPU backend selection to work around wgpu DX12 panic on
Windows (issue #24). Users can now specify --backend vulkan/dx12/metal/gl
or use --backend auto (default) which tries backends in order:
Vulkan → Metal → DX12 → GL.

Auto mode prioritizes hardware GPUs over software renderers (llvmpipe,
SwiftShader, etc.), falling back to software only when no hardware is
available.

Co-Authored-By: Aei <aei@oad.earth>
@oritwoen oritwoen added this to the v0.5.0 milestone Jan 16, 2026
@oritwoen oritwoen self-assigned this Jan 16, 2026
@oritwoen oritwoen added the enhancement New feature or request label Jan 16, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

The changes introduce a new GPU backend abstraction (GpuBackend enum) allowing users to explicitly select which graphics API—Vulkan, DirectX 12, Metal, OpenGL, or Auto with fallback logic—to use when initializing GPU contexts. Adapter discovery now filters and prioritizes by backend, with enhanced error handling and a CLI option for backend selection.

Changes

Cohort / File(s) Summary
Core GPU Backend Abstraction
src/gpu_crypto/context.rs, src/gpu_crypto/mod.rs
Introduced public GpuBackend enum with Auto, Vulkan, Dx12, Metal, Gl variants; added conversion to wgpu::Backends; implemented Display for human-readable names. Extended GpuContext::new() signature to require backend parameter. Added internal helpers: new_with_fallback() for auto-selection with retries, new_with_backend() for specific backend, try_backend() for adapter enumeration with backend-aware filtering, is_software_adapter() for detection. Enhanced adapter selection by device type (Discrete > Virtual > Integrated > Cpu) and backend priority. Added public backend() method on GpuContext.
CLI Integration & Main Entry Points
src/lib.rs, examples/debug_run.rs
Exposed GpuBackend in public exports. Added backend field to CLI Args struct with clap attributes (default "auto"). Updated run_benchmark() signature to accept backend parameter. Propagated backend through GPU context initialization in both benchmark and standard paths.
Test Updates
tests/cpu_vs_gpu.rs, tests/puzzle_solve.rs
Added GpuBackend import from kangaroo crate. Updated all GpuContext::new() calls to pass explicit backend argument (GpuBackend::Auto), aligning with new two-parameter API signature.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/CLI
    participant Main as Main Entry
    participant GpuCtx as GpuContext::new()
    participant Fallback as new_with_fallback()
    participant TryBack as try_backend()
    participant wgpu as wgpu Instance
    participant Adapt as Adapter Selection

    User->>Main: Specify backend (or default Auto)
    Main->>GpuCtx: new(device_index, backend)
    
    alt Backend is Auto
        GpuCtx->>Fallback: Attempt fallback chain
        loop For each backend in order (Vulkan, Metal, Dx12, GL)
            Fallback->>TryBack: try_backend(hw_only=true)
            TryBack->>wgpu: Create Instance with backend
            TryBack->>Adapt: Enumerate & filter adapters by backend
            Adapt-->>TryBack: Adapters found or empty
            alt Adapters found
                TryBack-->>Fallback: Success, return adapter
            else No adapters
                TryBack-->>Fallback: Continue to next backend
            end
        end
        
        alt Still no hardware adapters
            Fallback->>TryBack: try_backend(hw_only=false)
            TryBack->>wgpu: Create Instance with backend
            TryBack->>Adapt: Enumerate all adapters (incl. software)
            Adapt-->>TryBack: Adapters with software renderers
            TryBack-->>Fallback: Return first adapter
        end
    else Backend is specific (Vulkan/Dx12/Metal/GL)
        GpuCtx->>TryBack: try_backend(hw_only=true)
        TryBack->>wgpu: Create Instance with specified backend
        TryBack->>Adapt: Enumerate & filter by backend
        Adapt-->>TryBack: Adapters or error
    end
    
    TryBack->>wgpu: Create Device from selected adapter
    wgpu-->>TryBack: Device instance
    TryBack-->>GpuCtx: GpuContext initialized with backend
    GpuCtx-->>Main: Ready for GPU operations
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops of joy for backends bright,
Auto, Vulkan, Metal's might,
Dx12, GL in sight,
Pick your graphics with delight!
Fallback chains through the night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.47% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(gpu): add --backend flag' directly summarizes the main change - adding a CLI flag for GPU backend selection, which is the primary objective of this PR.
Description check ✅ Passed The description is well-related to the changeset, explaining the summary, changes, usage examples, and testing performed for the --backend flag feature.
Linked Issues check ✅ Passed The PR successfully addresses issue #24 by enabling GPU backend selection to work around the DX12 panic. Users can now force non-DX12 backends (Vulkan, Metal, GL) or use Auto with Vulkan priority to avoid the problematic DX12 adapter code.
Out of Scope Changes check ✅ Passed All changes are directly related to the backend selection feature: GpuBackend enum creation, CLI flag addition, context initialization refactoring, and test updates align with the PR objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/backend-selection

🧹 Recent nitpick comments
tests/puzzle_solve.rs (1)

59-63: Use GpuBackend::Gl in try_software_context instead of GpuBackend::Auto.

The function retries with GpuBackend::Auto, but this is redundant—Auto exhausts the same fallback sequence (Vulkan → Metal → DX12 → GL) regardless of when it's called. If it fails in init_context, retrying with Auto will fail identically. Since the goal is a software fallback, use GpuBackend::Gl explicitly, which is already defined as the OpenGL fallback.

src/gpu_crypto/context.rs (2)

9-63: LGTM! Well-designed enum with clean API.

The GpuBackend enum is well-structured with appropriate derives for CLI integration (ValueEnum) and sensible fallback ordering. The prioritization of Vulkan → Metal → DX12 → GL aligns well with cross-platform availability and stability.

Minor nit: name() returns inconsistent casing ("auto" lowercase vs "Vulkan", "DX12" mixed case). Consider normalizing for consistent log output.


120-131: Reasonable heuristic for software adapter detection.

The combination of DeviceType::Cpu check and name-based detection for known software renderers (llvmpipe, SwiftShader, lavapipe) covers common cases well.

Consider adding "warp" to catch Windows' WARP (Windows Advanced Rasterization Platform) software renderer, though it may already report as DeviceType::Cpu.

Optional: Add WARP detection
         || name_lower.contains("lavapipe")
         || name_lower.contains("mesa software")
+        || name_lower.contains("warp")
📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58ed467 and 970c851.

📒 Files selected for processing (6)
  • examples/debug_run.rs
  • src/gpu_crypto/context.rs
  • src/gpu_crypto/mod.rs
  • src/lib.rs
  • tests/cpu_vs_gpu.rs
  • tests/puzzle_solve.rs
🧰 Additional context used
🧬 Code graph analysis (5)
src/lib.rs (1)
src/gpu_crypto/context.rs (2)
  • backend (218-220)
  • new (75-80)
tests/cpu_vs_gpu.rs (1)
src/gpu_crypto/context.rs (1)
  • new (75-80)
tests/puzzle_solve.rs (1)
src/gpu_crypto/context.rs (1)
  • new (75-80)
examples/debug_run.rs (1)
src/gpu_crypto/context.rs (1)
  • new (75-80)
src/gpu_crypto/context.rs (1)
src/gpu/buffers.rs (5)
  • std (75-75)
  • std (76-76)
  • ctx (53-53)
  • ctx (60-60)
  • ctx (79-79)
🔇 Additional comments (17)
examples/debug_run.rs (1)

1-20: LGTM!

The import and GpuContext::new call are correctly updated to use the new two-parameter API with GpuBackend::Auto, which is appropriate for a debug example.

src/gpu_crypto/mod.rs (1)

5-5: LGTM!

The public re-export of GpuBackend alongside GpuContext correctly broadens the API surface to support the new backend selection feature.

tests/cpu_vs_gpu.rs (2)

5-7: LGTM!

The import is correctly updated to include GpuBackend.


77-77: LGTM!

The GpuContext::new call correctly uses the new two-parameter API with GpuBackend::Auto.

tests/puzzle_solve.rs (2)

9-11: LGTM!

The import is correctly updated to include GpuBackend.


106-106: LGTM!

The GpuContext::new call correctly uses the new two-parameter API.

src/lib.rs (5)

20-20: LGTM!

The public re-export of GpuBackend correctly exposes the new type in the crate's public API.


70-72: LGTM!

The new --backend CLI flag is well-integrated with appropriate clap attributes. The value_enum derive enables parsing from string values, and default_value = "auto" provides sensible default behavior.


355-359: LGTM!

The benchmark function signature and GpuContext::new call are correctly updated to pass the backend parameter through.


420-420: LGTM!

The call to run_benchmark correctly passes the backend from CLI args.


521-521: LGTM!

The GpuContext::new call correctly uses the backend from CLI args, enabling users to force a specific backend via --backend vulkan etc. as documented in the PR.

src/gpu_crypto/context.rs (6)

1-7: LGTM!

Imports are appropriate for the new functionality: clap::ValueEnum for CLI integration, tracing for logging the backend selection process.


73-80: LGTM!

Clean delegation pattern: Auto mode uses fallback logic, explicit backends use direct creation. The API change is breaking but the PR summary indicates downstream code has been updated.


82-118: Two-pass fallback logic looks solid.

The approach of preferring hardware GPUs first, then falling back to software renderers, is well-designed and addresses the issue #24 scenario where DX12 might panic but Vulkan could work.

Consideration: When device_index > 0 is specified with Auto mode, the index applies to the sorted adapter list within each backend attempt. This means --device 1 might select different physical hardware depending on which backend succeeds first. If this is intentional, consider documenting this behavior; if not, you may want to enumerate all adapters across all backends first, then sort and select by index.


209-212: LGTM!

When a user explicitly requests a backend, accepting software renderers is the right choice—they may intentionally want to use lavapipe or SwiftShader for testing.


214-220: LGTM!

The backend() getter provides useful visibility into which backend was actually selected, which is valuable for diagnostics and logging.


133-207: Well-structured backend initialization with proper adapter sorting.

The sorting strategy (discrete > virtual > integrated > cpu, then by backend priority) ensures optimal GPU selection. The enumerate_adapters API usage is correct for wgpu 28, which provides async enumeration. Error messages are clear and contextual.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 6 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@oritwoen oritwoen merged commit f817f9d into main Jan 16, 2026
4 checks passed
@oritwoen oritwoen deleted the feat/backend-selection branch January 16, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dx12 wgpu

2 participants