[VideoOut] Scope the AMD integrated-GPU penalty to Windows (#339)

* [VideoOut] Prefer real integrated GPUs over software rasterizers (#325)

Penalize only AMD integrated GPUs (the #97 vkCreateGraphicsPipelines
crash) instead of all integrated devices, so Intel/Apple/Qualcomm iGPUs
outrank Cpu-type software rasterizers (Mesa lavapipe). Hoist
ScorePhysicalDevice to the outer class and add unit tests for the
ordering.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [VideoOut] Scope AMD iGPU penalty to Windows via a penalty helper

Extract ComputeDevicePenalty (the value subtracted from a device's base
score) and gate the #97 AMD-integrated penalty on Windows only. Mesa RADV
on Linux (e.g. the Steam Deck's AMD APU) is a different, working driver
and should keep its full integrated score. Add a Steam Deck test case and
drop inline comments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [VideoOut] Move device-scoring helpers out of the const block

Relocate ScorePhysicalDevice and ComputeDevicePenalty below the leading
const cluster instead of splitting it, and trim the vendor-ID reference
comment to adapters an x86-64 host can realistically enumerate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Raiyan
2026-07-17 22:48:09 +07:00
committed by GitHub
parent a9a4366ef4
commit b9eee497aa
2 changed files with 142 additions and 27 deletions
@@ -0,0 +1,94 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.Libs.VideoOut;
using Silk.NET.Vulkan;
using Xunit;
namespace SharpEmu.Libs.Tests.VideoOut;
public sealed class VulkanPhysicalDeviceScoringTests
{
private const uint NvidiaVendorId = 0x10DE;
private const uint AmdVendorId = 0x1002;
private const uint IntelVendorId = 0x8086;
private const uint QualcommVendorId = 0x5143;
private static PhysicalDeviceProperties Device(PhysicalDeviceType type, uint vendorId = 0)
=> new() { DeviceType = type, VendorID = vendorId };
private static int Score(PhysicalDeviceType type, uint vendorId = 0)
=> VulkanVideoPresenter.ScorePhysicalDevice(Device(type, vendorId), name: string.Empty, deviceOverride: null);
[Fact]
public void RealIntegratedGpuOutranksSoftwareRasterizer()
{
Assert.True(Score(PhysicalDeviceType.IntegratedGpu) > Score(PhysicalDeviceType.Cpu));
}
[Theory]
[InlineData(IntelVendorId)]
[InlineData(QualcommVendorId)]
[InlineData(0u)]
public void NonAmdIntegratedGpuBeatsSoftware(uint vendorId)
{
Assert.True(Score(PhysicalDeviceType.IntegratedGpu, vendorId) > Score(PhysicalDeviceType.Cpu));
}
[Fact]
public void DiscreteGpuOutranksIntegratedGpu()
{
Assert.True(Score(PhysicalDeviceType.DiscreteGpu) > Score(PhysicalDeviceType.IntegratedGpu));
}
[Fact]
public void NvidiaDiscreteGpuScoresHighest()
{
var nvidia = Score(PhysicalDeviceType.DiscreteGpu, NvidiaVendorId);
Assert.True(nvidia > Score(PhysicalDeviceType.DiscreteGpu));
Assert.True(nvidia > Score(PhysicalDeviceType.IntegratedGpu));
}
[Fact]
public void DeviceOverridePinsMatchingAdapterAndExcludesOthers()
{
var properties = Device(PhysicalDeviceType.Cpu);
Assert.Equal(1000, VulkanVideoPresenter.ScorePhysicalDevice(properties, "Radeon Graphics", "radeon"));
Assert.Equal(-1000, VulkanVideoPresenter.ScorePhysicalDevice(properties, "Radeon Graphics", "nvidia"));
}
[Fact]
public void AmdIntegratedGpuIsLastResortOnWindows()
{
var penalty = VulkanVideoPresenter.ComputeDevicePenalty(
Device(PhysicalDeviceType.IntegratedGpu, AmdVendorId), isWindows: true);
Assert.True(penalty > 0);
Assert.True(50 - penalty < 10);
}
[Fact]
public void AmdApuIsNotPenalizedOffWindows()
{
var penalty = VulkanVideoPresenter.ComputeDevicePenalty(
Device(PhysicalDeviceType.IntegratedGpu, AmdVendorId), isWindows: false);
Assert.Equal(0, penalty);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void AmdDiscreteGpuIsNeverPenalized(bool isWindows)
{
Assert.Equal(0, VulkanVideoPresenter.ComputeDevicePenalty(
Device(PhysicalDeviceType.DiscreteGpu, AmdVendorId), isWindows));
}
[Theory]
[InlineData(IntelVendorId)]
[InlineData(QualcommVendorId)]
public void NonAmdIntegratedGpuIsNeverPenalized(uint vendorId)
{
Assert.Equal(0, VulkanVideoPresenter.ComputeDevicePenalty(
Device(PhysicalDeviceType.IntegratedGpu, vendorId), isWindows: true));
}
}