mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-26 04:39:17 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b7df8623a | |||
| 3c2134474d | |||
| 298ef01809 | |||
| 2060dacaf1 |
@@ -83,7 +83,6 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime
|
||||
ImportTraceLimit = Math.Max(0, options.ImportTraceLimit),
|
||||
};
|
||||
var moduleManager = new ModuleManager();
|
||||
moduleManager.RegisterFromAssembly(typeof(VideoOutExports).Assembly, Generation.Gen4 | Generation.Gen5, Aerolib.Instance);
|
||||
moduleManager.RegisterFromAssembly(typeof(KernelExports).Assembly, Generation.Gen4 | Generation.Gen5, Aerolib.Instance);
|
||||
moduleManager.Freeze();
|
||||
|
||||
|
||||
@@ -718,7 +718,7 @@ internal static class Gen5ShaderTranslator
|
||||
}
|
||||
|
||||
var src0 = word & 0x1FF;
|
||||
sizeDwords = opcode is 0x20 or 0x21 || src0 is 0xF9 or 0xFA or 0xFF ? 2u : 1u;
|
||||
sizeDwords = opcode is 0x20 or 0x21 or 0x2C or 0x2D || src0 is 0xF9 or 0xFA or 0xFF ? 2u : 1u;
|
||||
error = string.Empty;
|
||||
name = opcode switch
|
||||
{
|
||||
@@ -757,7 +757,9 @@ internal static class Gen5ShaderTranslator
|
||||
0x28 => "VAddcU32",
|
||||
0x29 => "VSubbU32",
|
||||
0x2A => "VSubbrevU32",
|
||||
0x2B => "VLdexpF32",
|
||||
0x2B => "VFmacF32",
|
||||
0x2C => "VFmamkF32",
|
||||
0x2D => "VFmaakF32",
|
||||
0x2F => "VCvtPkrtzF16F32",
|
||||
0x30 => "VCvtPkU16U32",
|
||||
0x31 => "VCvtPkI16I32",
|
||||
@@ -870,6 +872,7 @@ internal static class Gen5ShaderTranslator
|
||||
0x10F => "VMinF32",
|
||||
0x110 => "VMaxF32",
|
||||
0x11F => "VMacF32",
|
||||
0x12B => "VFmacF32",
|
||||
0x12F => "VCvtPkrtzF16F32",
|
||||
0x141 => "VMadF32",
|
||||
0x143 => "VMadU32U24",
|
||||
@@ -1379,7 +1382,7 @@ internal static class Gen5ShaderTranslator
|
||||
Gen5Operand.Source(word & 0x1FF, literal),
|
||||
Gen5Operand.Vector((word >> 9) & 0xFF),
|
||||
];
|
||||
if (opcode == "VMadMkF32" && literal.HasValue)
|
||||
if (opcode is "VMadMkF32" or "VFmamkF32" && literal.HasValue)
|
||||
{
|
||||
sources =
|
||||
[
|
||||
@@ -1388,7 +1391,7 @@ internal static class Gen5ShaderTranslator
|
||||
sources[1],
|
||||
];
|
||||
}
|
||||
else if (opcode == "VMadAkF32" && literal.HasValue)
|
||||
else if (opcode is "VMadAkF32" or "VFmaakF32" && literal.HasValue)
|
||||
{
|
||||
sources =
|
||||
[
|
||||
|
||||
@@ -255,6 +255,8 @@ internal static partial class Gen5SpirvTranslator
|
||||
case "VFmaF32":
|
||||
case "VMadMkF32":
|
||||
case "VMadAkF32":
|
||||
case "VFmamkF32":
|
||||
case "VFmaakF32":
|
||||
result = EmitFloatResult(
|
||||
instruction,
|
||||
Ext(
|
||||
@@ -265,6 +267,7 @@ internal static partial class Gen5SpirvTranslator
|
||||
GetFloatSource(instruction, 2)));
|
||||
break;
|
||||
case "VMacF32":
|
||||
case "VFmacF32":
|
||||
{
|
||||
var addend = Bitcast(_floatType, LoadV(destination));
|
||||
result = EmitFloatResult(
|
||||
|
||||
@@ -178,6 +178,7 @@ internal static unsafe class VulkanVideoPresenter
|
||||
private static uint _windowHeight;
|
||||
private static bool _closed;
|
||||
private const string DebugUtilsExtensionName = "VK_EXT_debug_utils";
|
||||
private const uint NvidiaVendorId = 0x10DE;
|
||||
private static bool _splashHidden;
|
||||
private static long _enqueuedGuestWorkSequence;
|
||||
private static long _completedGuestWorkSequence;
|
||||
@@ -1502,6 +1503,13 @@ internal static unsafe class VulkanVideoPresenter
|
||||
Check(_vk.EnumeratePhysicalDevices(_instance, &deviceCount, devicePointer), "vkEnumeratePhysicalDevices");
|
||||
}
|
||||
|
||||
// Hybrid laptops enumerate the iGPU first, and AMD's integrated driver
|
||||
// segfaults compiling some translated shaders, so rank rather than take
|
||||
// the first hit. SHARPEMU_VK_DEVICE=<substring> pins an adapter by name.
|
||||
var deviceOverride = Environment.GetEnvironmentVariable("SHARPEMU_VK_DEVICE");
|
||||
var bestScore = int.MinValue;
|
||||
var found = false;
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
uint queueCount = 0;
|
||||
@@ -1521,13 +1529,60 @@ internal static unsafe class VulkanVideoPresenter
|
||||
continue;
|
||||
}
|
||||
|
||||
_physicalDevice = device;
|
||||
_queueFamilyIndex = index;
|
||||
return;
|
||||
_vk.GetPhysicalDeviceProperties(device, out var properties);
|
||||
var name = SilkMarshal.PtrToString((nint)properties.DeviceName) ?? string.Empty;
|
||||
var score = ScorePhysicalDevice(properties, name, deviceOverride);
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER][INFO] Vulkan candidate: {name} ({properties.DeviceType}) score={score}");
|
||||
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
_physicalDevice = device;
|
||||
_queueFamilyIndex = index;
|
||||
found = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("No Vulkan graphics/present queue was found.");
|
||||
if (!found)
|
||||
{
|
||||
throw new InvalidOperationException("No Vulkan graphics/present queue was found.");
|
||||
}
|
||||
|
||||
_vk.GetPhysicalDeviceProperties(_physicalDevice, out var selected);
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER][INFO] Vulkan device: {SilkMarshal.PtrToString((nint)selected.DeviceName)} ({selected.DeviceType})");
|
||||
}
|
||||
|
||||
private static int ScorePhysicalDevice(
|
||||
PhysicalDeviceProperties properties,
|
||||
string name,
|
||||
string? deviceOverride)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(deviceOverride))
|
||||
{
|
||||
return name.Contains(deviceOverride, StringComparison.OrdinalIgnoreCase) ? 1000 : -1000;
|
||||
}
|
||||
|
||||
var score = properties.DeviceType switch
|
||||
{
|
||||
PhysicalDeviceType.DiscreteGpu => 300,
|
||||
PhysicalDeviceType.VirtualGpu => 100,
|
||||
PhysicalDeviceType.Cpu => 50,
|
||||
// Last resort: only picked when nothing else can present.
|
||||
PhysicalDeviceType.IntegratedGpu => -100,
|
||||
_ => 10,
|
||||
};
|
||||
|
||||
if (properties.VendorID == NvidiaVendorId)
|
||||
{
|
||||
score += 500;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private void CreateDevice()
|
||||
|
||||
Reference in New Issue
Block a user