[GPU] Compile wave64 compute for 32-lane subgroups when the host lacks wave64

This commit is contained in:
ParantezTech 2026-10-11 01:35:14 +03:00
parent 08891b1fef
commit d24f6c6a85
4 changed files with 14 additions and 5 deletions

View File

@ -39,6 +39,8 @@ internal interface IShaderPipelineHost
// True when a 64-invocation wave64 compute workgroup runs as one 64-lane host subgroup.
bool ComputeWave64SubgroupNative => false;
bool ComputeRunsOn32LaneSubgroups(ComputeInputInfo input) => false;
bool GraphicsSubgroupOperationsEnabled { get; }
// The device supports shaderSharedInt64Atomics, so LDS 64-bit atomics can be

View File

@ -685,7 +685,8 @@ internal sealed class ShaderProgramCache
default:
return BuildComputeRequest(entry.Plan, resources, layout, options.ComputeInfo!, options.ComputeSystemRegisters,
sharedInt64Atomics, _host.ExecGuardElisionEnabled, signedZeroInfNanPreserve, _host.ComputeWave64SubgroupNative);
sharedInt64Atomics, _host.ExecGuardElisionEnabled, signedZeroInfNanPreserve, _host.ComputeWave64SubgroupNative,
_host.ComputeRunsOn32LaneSubgroups(options.ComputeInfo!));
}
}
@ -702,11 +703,12 @@ internal sealed class ShaderProgramCache
private static ShaderCompileRequest BuildComputeRequest(ShaderResourcePlan plan, SpecializedResourceInfo resources, BindingLayout layout,
ComputeInputInfo info, Gen5ComputeSystemRegisters? systemRegisters, bool sharedInt64Atomics, bool execGuardElision,
bool signedZeroInfNanPreserve, bool hostWave64Supported = false) =>
bool signedZeroInfNanPreserve, bool hostWave64Supported = false, bool hostComputeSubgroup32 = false) =>
new(plan, resources, layout)
{
WaveSize = info.WaveSize,
HostWave64Supported = info.WaveSize == 64 && hostWave64Supported,
HostComputeSubgroup32 = info.WaveSize == 64 && !hostWave64Supported && hostComputeSubgroup32,
EnableExecGuardElision = info.WaveSize != 64 || execGuardElision,
TraceDeviceAddressFaults = SharpEmu.HLE.GpuMemory.GuestGpuMemoryHook.TraceEnabled,
ScratchDwords = info.ScratchDwords,
@ -721,7 +723,7 @@ internal sealed class ShaderProgramCache
internal static bool TryCompilePrewarm(ComputePrewarmRecord record, ShaderCodeCapture code, IGuestGpuBackend compiler,
bool sharedInt64Atomics, bool execGuardElision, bool signedZeroInfNanPreserve, out IGuestCompiledShader? compiled,
out BindingLayout? layout, out string error, bool hostWave64Supported = false)
out BindingLayout? layout, out string error, bool hostWave64Supported = false, bool hostComputeSubgroup32 = false)
{
compiled = null;
layout = null;
@ -738,7 +740,7 @@ internal sealed class ShaderProgramCache
layout = AllocateLayout(program, plan, resources, record.UserDataBase, record.UserDataCount, record.PushDataCursor,
record.Info.DispatchThreadDimensions);
var request = BuildComputeRequest(plan, resources, layout, record.Info, record.SystemRegisters,
sharedInt64Atomics, execGuardElision, signedZeroInfNanPreserve, hostWave64Supported);
sharedInt64Atomics, execGuardElision, signedZeroInfNanPreserve, hostWave64Supported, hostComputeSubgroup32);
return compiler.TryCompileProgram(request, out compiled, out error) && compiled is not null;
}
catch (Exception exception)

View File

@ -72,6 +72,10 @@ internal static unsafe partial class VulkanVideoPresenter
bool IShaderPipelineHost.ComputeWave64Supported => Volatile.Read(ref _nativeSubgroupSize) >= 64;
bool IShaderPipelineHost.ComputeRunsOn32LaneSubgroups(ComputeInputInfo input) =>
RequiresComputeSubgroup32(input) ||
(Volatile.Read(ref _nativeSubgroupSize) == RdnaSubgroupSize && !RequiresComputeSubgroup64(input));
// Wave32 compute maps a guest wave to 32-lane host subgroups, and a 64-lane host subgroup
// (AMD's default) left lanes 32..63 inactive, so those pipelines are pinned to 32. Wave64
// compute is pinned to 64 instead when the host runs it natively.

View File

@ -164,7 +164,8 @@ internal static unsafe partial class VulkanVideoPresenter
if (!ShaderProgramCache.TryCompilePrewarm(
record, code, compiler, sharedInt64Atomics, execGuardElision,
_supportsShaderSignedZeroInfNanPreserveFloat32, out var compiled, out var layout, out var error,
((IShaderPipelineHost)this).ComputeWave64SubgroupNative))
((IShaderPipelineHost)this).ComputeWave64SubgroupNative,
((IShaderPipelineHost)this).ComputeRunsOn32LaneSubgroups(record.Info)))
{
NoteShaderPrewarmFailure(record, error);
return;