Vulkan: fix guest storage image and render-state handling (#332)

This commit is contained in:
lilp
2026-07-17 20:54:52 -03:00
committed by GitHub
parent b479dc0466
commit c9d018db8e
8 changed files with 806 additions and 147 deletions
@@ -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(