mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-01 15:39:47 +08:00
Vulkan: fix guest storage image and render-state handling (#332)
This commit is contained in:
@@ -162,6 +162,11 @@ public static partial class Gen5SpirvTranslator
|
||||
return context.TryCompile(out shader, out error);
|
||||
}
|
||||
|
||||
internal static SpirvImageFormat DecodeStorageImageFormat(
|
||||
uint dataFormat,
|
||||
uint numberType) =>
|
||||
CompilationContext.DecodeStorageImageFormat(dataFormat, numberType);
|
||||
|
||||
private sealed partial class CompilationContext
|
||||
{
|
||||
private const uint ImageDescriptorDwords = 8;
|
||||
@@ -279,6 +284,7 @@ public static partial class Gen5SpirvTranslator
|
||||
private uint _workGroupIdInput;
|
||||
private uint _computeDispatchLimit;
|
||||
private uint _pushConstantUintPointer;
|
||||
private uint _subgroupSizeInput;
|
||||
private uint _subgroupInvocationIdInput;
|
||||
private uint _waveMaskScratch;
|
||||
private uint _waveMaskScratchElementPointer;
|
||||
@@ -961,8 +967,9 @@ public static partial class Gen5SpirvTranslator
|
||||
{
|
||||
var binding = _evaluation.ImageBindings[index];
|
||||
_imageBindingByPc.TryAdd(binding.Pc, index);
|
||||
var isStorage =
|
||||
Gen5ShaderTranslator.IsStorageImageOperation(binding.Opcode);
|
||||
var isStorage = Gen5ShaderTranslator.RequiresStorageImage(
|
||||
binding,
|
||||
_evaluation.ImageBindings);
|
||||
var (format, componentKind) =
|
||||
DecodeImageFormat(binding.ResourceDescriptor);
|
||||
var componentType = componentKind switch
|
||||
@@ -1044,58 +1051,62 @@ public static partial class Gen5SpirvTranslator
|
||||
return (SpirvImageFormat.Unknown, ImageComponentKind.Float);
|
||||
}
|
||||
|
||||
return (dataFormat, numberType) switch
|
||||
var kind = numberType switch
|
||||
{
|
||||
(1, _) => (SpirvImageFormat.R8, ImageComponentKind.Float),
|
||||
(2, _) => (SpirvImageFormat.R16f, ImageComponentKind.Float),
|
||||
(3, _) => (SpirvImageFormat.Rg8, ImageComponentKind.Float),
|
||||
(4, 4) => (SpirvImageFormat.R32ui, ImageComponentKind.Uint),
|
||||
(4, 5) => (SpirvImageFormat.R32i, ImageComponentKind.Sint),
|
||||
(4, _) => (SpirvImageFormat.R32f, ImageComponentKind.Float),
|
||||
(5, 4) => (SpirvImageFormat.Rg16ui, ImageComponentKind.Uint),
|
||||
(5, 5) => (SpirvImageFormat.Rg16i, ImageComponentKind.Sint),
|
||||
(5, 0) => (SpirvImageFormat.Rg16, ImageComponentKind.Float),
|
||||
(5, _) => (SpirvImageFormat.Rg16f, ImageComponentKind.Float),
|
||||
(6 or 7, _) => (
|
||||
SpirvImageFormat.R11fG11fB10f,
|
||||
ImageComponentKind.Float),
|
||||
(9, 4) => (SpirvImageFormat.Rgb10A2ui, ImageComponentKind.Uint),
|
||||
(9, _) => (SpirvImageFormat.Rgb10A2, ImageComponentKind.Float),
|
||||
(10, 4) => (SpirvImageFormat.Rgba8ui, ImageComponentKind.Uint),
|
||||
(10, 5) => (SpirvImageFormat.Rgba8i, ImageComponentKind.Sint),
|
||||
(10, _) => (SpirvImageFormat.Rgba8, ImageComponentKind.Float),
|
||||
(11, 4) => (SpirvImageFormat.Rg32ui, ImageComponentKind.Uint),
|
||||
(11, 5) => (SpirvImageFormat.Rg32i, ImageComponentKind.Sint),
|
||||
(11, _) => (SpirvImageFormat.Rg32f, ImageComponentKind.Float),
|
||||
(12, 4) => (SpirvImageFormat.Rgba16ui, ImageComponentKind.Uint),
|
||||
(12, 5) => (SpirvImageFormat.Rgba16i, ImageComponentKind.Sint),
|
||||
(12, 0) => (SpirvImageFormat.Rgba16, ImageComponentKind.Float),
|
||||
(12, _) => (SpirvImageFormat.Rgba16f, ImageComponentKind.Float),
|
||||
(13 or 14, 4) => (
|
||||
SpirvImageFormat.Rgba32ui,
|
||||
ImageComponentKind.Uint),
|
||||
(13 or 14, 5) => (
|
||||
SpirvImageFormat.Rgba32i,
|
||||
ImageComponentKind.Sint),
|
||||
(13 or 14, _) => (
|
||||
SpirvImageFormat.Rgba32f,
|
||||
ImageComponentKind.Float),
|
||||
(20, _) => (SpirvImageFormat.R32ui, ImageComponentKind.Uint),
|
||||
(22, _) => (SpirvImageFormat.Rgba16f, ImageComponentKind.Float),
|
||||
(29, _) => (SpirvImageFormat.R32f, ImageComponentKind.Float),
|
||||
(36, _) => (SpirvImageFormat.R8, ImageComponentKind.Float),
|
||||
(49, _) => (SpirvImageFormat.R8ui, ImageComponentKind.Uint),
|
||||
(56 or 62 or 64, _) => (
|
||||
SpirvImageFormat.Rgba8,
|
||||
ImageComponentKind.Float),
|
||||
(71, _) => (SpirvImageFormat.Rgba16f, ImageComponentKind.Float),
|
||||
(75, _) => (SpirvImageFormat.Rg32f, ImageComponentKind.Float),
|
||||
(_, 4) => (SpirvImageFormat.Unknown, ImageComponentKind.Uint),
|
||||
(_, 5) => (SpirvImageFormat.Unknown, ImageComponentKind.Sint),
|
||||
_ => (SpirvImageFormat.Unknown, ImageComponentKind.Float),
|
||||
4 => ImageComponentKind.Uint,
|
||||
5 => ImageComponentKind.Sint,
|
||||
_ => ImageComponentKind.Float,
|
||||
};
|
||||
return (DecodeStorageImageFormat(dataFormat, numberType), kind);
|
||||
}
|
||||
|
||||
internal static SpirvImageFormat DecodeStorageImageFormat(
|
||||
uint dataFormat,
|
||||
uint numberType) =>
|
||||
(dataFormat, numberType) switch
|
||||
{
|
||||
(1, 0 or 9) => SpirvImageFormat.R8,
|
||||
(1, 1) => SpirvImageFormat.R8Snorm,
|
||||
(1, 4) => SpirvImageFormat.R8ui,
|
||||
(1, 5) => SpirvImageFormat.R8i,
|
||||
(2, 0) => SpirvImageFormat.R16,
|
||||
(2, 1) => SpirvImageFormat.R16Snorm,
|
||||
(2, 4) => SpirvImageFormat.R16ui,
|
||||
(2, 5) => SpirvImageFormat.R16i,
|
||||
(2, 7) => SpirvImageFormat.R16f,
|
||||
(3, 0 or 9) => SpirvImageFormat.Rg8,
|
||||
(3, 1) => SpirvImageFormat.Rg8Snorm,
|
||||
(3, 4) => SpirvImageFormat.Rg8ui,
|
||||
(3, 5) => SpirvImageFormat.Rg8i,
|
||||
(4, 4) => SpirvImageFormat.R32ui,
|
||||
(4, 5) => SpirvImageFormat.R32i,
|
||||
(4, 7) => SpirvImageFormat.R32f,
|
||||
(5, 0) => SpirvImageFormat.Rg16,
|
||||
(5, 1) => SpirvImageFormat.Rg16Snorm,
|
||||
(5, 4) => SpirvImageFormat.Rg16ui,
|
||||
(5, 5) => SpirvImageFormat.Rg16i,
|
||||
(5, 7) => SpirvImageFormat.Rg16f,
|
||||
(6 or 7, 7) => SpirvImageFormat.R11fG11fB10f,
|
||||
(8 or 9, 0) => SpirvImageFormat.Rgb10A2,
|
||||
(8 or 9, 4) => SpirvImageFormat.Rgb10A2ui,
|
||||
(10, 0 or 9) => SpirvImageFormat.Rgba8,
|
||||
(10, 1) => SpirvImageFormat.Rgba8Snorm,
|
||||
(10, 4) => SpirvImageFormat.Rgba8ui,
|
||||
(10, 5) => SpirvImageFormat.Rgba8i,
|
||||
(11, 4) => SpirvImageFormat.Rg32ui,
|
||||
(11, 5) => SpirvImageFormat.Rg32i,
|
||||
(11, 7) => SpirvImageFormat.Rg32f,
|
||||
(12, 0) => SpirvImageFormat.Rgba16,
|
||||
(12, 1) => SpirvImageFormat.Rgba16Snorm,
|
||||
(12, 4) => SpirvImageFormat.Rgba16ui,
|
||||
(12, 5) => SpirvImageFormat.Rgba16i,
|
||||
(12, 7) => SpirvImageFormat.Rgba16f,
|
||||
(13 or 14, 4) => SpirvImageFormat.Rgba32ui,
|
||||
(13 or 14, 5) => SpirvImageFormat.Rgba32i,
|
||||
(13 or 14, 7) => SpirvImageFormat.Rgba32f,
|
||||
_ => SpirvImageFormat.Unknown,
|
||||
};
|
||||
|
||||
private void DeclareStageInterface()
|
||||
{
|
||||
if (UsesSubgroupOperations())
|
||||
@@ -1111,6 +1122,18 @@ public static partial class Gen5SpirvTranslator
|
||||
(uint)SpirvBuiltIn.SubgroupLocalInvocationId);
|
||||
_interfaces.Add(_subgroupInvocationIdInput);
|
||||
|
||||
if (_emulateWave64)
|
||||
{
|
||||
_subgroupSizeInput = _module.AddGlobalVariable(
|
||||
subgroupPointer,
|
||||
SpirvStorageClass.Input);
|
||||
_module.AddDecoration(
|
||||
_subgroupSizeInput,
|
||||
SpirvDecoration.BuiltIn,
|
||||
(uint)SpirvBuiltIn.SubgroupSize);
|
||||
_interfaces.Add(_subgroupSizeInput);
|
||||
}
|
||||
|
||||
if (_waveLaneCount == 64)
|
||||
{
|
||||
_localInvocationIndexInput = _module.AddGlobalVariable(
|
||||
@@ -3091,12 +3114,14 @@ public static partial class Gen5SpirvTranslator
|
||||
return true;
|
||||
}
|
||||
|
||||
var imageLoad = Gen5ShaderTranslator.IsImageLoadOperation(instruction.Opcode);
|
||||
var storage = Gen5ShaderTranslator.IsStorageImageOperation(instruction.Opcode);
|
||||
for (var index = 0; index < _evaluation.ImageBindings.Count; index++)
|
||||
{
|
||||
var candidate = _evaluation.ImageBindings[index];
|
||||
if (candidate.Control.ScalarResource != control.ScalarResource ||
|
||||
candidate.Control.ScalarSampler != control.ScalarSampler ||
|
||||
Gen5ShaderTranslator.IsImageLoadOperation(candidate.Opcode) != imageLoad ||
|
||||
Gen5ShaderTranslator.IsStorageImageOperation(candidate.Opcode) != storage ||
|
||||
!HasSameScalarDefinitions(
|
||||
candidate.Pc,
|
||||
@@ -5097,12 +5122,14 @@ public static partial class Gen5SpirvTranslator
|
||||
SpirvOp.UConvert,
|
||||
_ulongType,
|
||||
maskedLane));
|
||||
return _module.AddInstruction(
|
||||
SpirvOp.Select,
|
||||
_ulongType,
|
||||
IsCurrentLaneInRdnaWave(),
|
||||
shifted,
|
||||
_module.Constant64(_ulongType, 0));
|
||||
return _emulateWave64
|
||||
? shifted
|
||||
: _module.AddInstruction(
|
||||
SpirvOp.Select,
|
||||
_ulongType,
|
||||
IsCurrentLaneInRdnaWave(),
|
||||
shifted,
|
||||
_module.Constant64(_ulongType, 0));
|
||||
}
|
||||
|
||||
private uint IsCurrentLaneInRdnaWave() =>
|
||||
@@ -5139,6 +5166,11 @@ public static partial class Gen5SpirvTranslator
|
||||
0);
|
||||
if (_emulateWave64)
|
||||
{
|
||||
var high = _module.AddInstruction(
|
||||
SpirvOp.CompositeExtract,
|
||||
_uintType,
|
||||
ballot,
|
||||
1);
|
||||
var subgroupLane =
|
||||
Load(_uintType, _subgroupInvocationIdInput);
|
||||
var firstLane = _module.AddInstruction(
|
||||
@@ -5150,6 +5182,16 @@ public static partial class Gen5SpirvTranslator
|
||||
EmitConditional(firstLane, () =>
|
||||
{
|
||||
Store(WaveMaskScratchPointer(half), low);
|
||||
|
||||
var nativeWave64 = _module.AddInstruction(
|
||||
SpirvOp.UGreaterThanEqual,
|
||||
_boolType,
|
||||
Load(_uintType, _subgroupSizeInput),
|
||||
UInt(64));
|
||||
EmitConditional(nativeWave64, () =>
|
||||
{
|
||||
Store(WaveMaskScratchPointer(UInt(1)), high);
|
||||
});
|
||||
});
|
||||
EmitWave64Barrier();
|
||||
var lowMask = Load(
|
||||
|
||||
Reference in New Issue
Block a user