[spirvtranslator] added DsReadI8 instruction

This commit is contained in:
ParantezTech 2026-09-20 20:17:13 +03:00
parent aed8be3568
commit d74cd30faa
3 changed files with 171 additions and 3 deletions

View File

@ -1158,6 +1158,24 @@ public static partial class Gen5SpirvTranslator
case "DsReadB32":
StoreV(instruction.Destinations[0].Value, LoadBlockWord(_globalDataShare, GlobalDataShareIndex(GetRawSource(instruction, 0), control.SingleOffsetBytes)));
return true;
case "DsReadI8":
{
var address = GetRawSource(instruction, 0);
var byteAddress = control.SingleOffsetBytes == 0
? address
: IAdd(address, UInt(control.SingleOffsetBytes));
var word = LoadBlockWord(_globalDataShare, GlobalDataShareIndex(address, control.SingleOffsetBytes));
var shift = ShiftLeftLogical(BitwiseAnd(byteAddress, UInt(3)), UInt(3));
var packed = ShiftRightLogical(word, shift);
var signedByte = _module.AddInstruction(
SpirvOp.BitFieldSExtract,
_intType,
Bitcast(_intType, packed),
UInt(0),
UInt(8));
StoreV(instruction.Destinations[0].Value, Bitcast(_uintType, signedByte));
return true;
}
case "DsReadB64":
{
var index = GlobalDataShareIndex(GetRawSource(instruction, 0), control.SingleOffsetBytes);

View File

@ -1610,6 +1610,30 @@ public static partial class Gen5SpirvTranslator
StoreV(instruction.Destinations[0].Value, value);
return true;
}
case "DsReadI8":
{
if (instruction.Destinations.Count < 1 || instruction.Sources.Count < 1)
{
error = "missing LDS signed byte read operand";
return false;
}
var address = GetRawSource(instruction, 0);
var byteAddress = control.SingleOffsetBytes == 0
? address
: IAdd(address, UInt(control.SingleOffsetBytes));
var word = Load(_uintType, LdsPointer(address, control.SingleOffsetBytes));
var shift = ShiftLeftLogical(BitwiseAnd(byteAddress, UInt(3)), UInt(3));
var packed = ShiftRightLogical(word, shift);
var signedByte = _module.AddInstruction(
SpirvOp.BitFieldSExtract,
_intType,
Bitcast(_intType, packed),
UInt(0),
UInt(8));
StoreV(instruction.Destinations[0].Value, Bitcast(_uintType, signedByte));
return true;
}
case "DsReadB64":
case "DsReadB96":
case "DsReadB128":
@ -1971,6 +1995,65 @@ public static partial class Gen5SpirvTranslator
_module.AddLabel(mergeLabel);
}
private uint EmitBufferFloatAtomic(
uint pointer,
uint value,
bool maxValue,
uint scope,
uint semantics)
{
var preheader = _module.AllocateId();
var header = _module.AllocateId();
var continueLabel = _module.AllocateId();
var mergeLabel = _module.AllocateId();
var exchanged = _module.AllocateId();
_module.AddStatement(SpirvOp.Branch, preheader);
_module.AddLabel(preheader);
var initial = _module.AddInstruction(
SpirvOp.AtomicLoad,
_uintType,
pointer,
UInt(scope),
UInt(semantics));
_module.AddStatement(SpirvOp.Branch, header);
_module.AddLabel(header);
var observed = _module.AddInstruction(
SpirvOp.Phi,
_uintType,
initial,
preheader,
exchanged,
continueLabel);
var observedFloat = Bitcast(_floatType, observed);
var valueFloat = Bitcast(_floatType, value);
var replace = _module.AddInstruction(
maxValue ? SpirvOp.FOrdGreaterThan : SpirvOp.FOrdLessThan,
_boolType,
valueFloat,
observedFloat);
var next = _module.AddInstruction(SpirvOp.Select, _uintType, replace, value, observed);
_module.AddStatement(
SpirvOp.AtomicCompareExchange,
_uintType,
exchanged,
pointer,
UInt(scope),
UInt(semantics),
UInt((semantics & ~0x8u) | 0x2u),
next,
observed);
var success = _module.AddInstruction(SpirvOp.IEqual, _boolType, exchanged, observed);
_module.AddStatement(SpirvOp.LoopMerge, mergeLabel, continueLabel, 0);
_module.AddStatement(SpirvOp.BranchConditional, success, mergeLabel, continueLabel);
_module.AddLabel(continueLabel);
_module.AddStatement(SpirvOp.Branch, header);
_module.AddLabel(mergeLabel);
return observed;
}
// Maps the AMD atomic-op name suffix shared by buffer/image atomics to a SPIR-V opcode.
// Inc/Dec approximate the AMD wrap-clamp semantics (MEM = tmp >= DATA ? 0 : tmp + 1),
// which is exact for the common 0xFFFFFFFF clamp operand.
@ -2145,7 +2228,70 @@ public static partial class Gen5SpirvTranslator
if (instruction.Opcode.StartsWith("BufferAtomic", StringComparison.Ordinal))
{
if (!TryGetAtomicOp(instruction.Opcode["BufferAtomic".Length..], out var atomicOp))
var atomicSuffix = instruction.Opcode["BufferAtomic".Length..];
if (atomicSuffix == "OrX2")
{
EmitExecConditional(() =>
{
var secondAddress = IAdd(dwordAddress, UInt(1));
var inRange = _module.AddInstruction(
SpirvOp.LogicalAnd,
_boolType,
IsBufferWordInRange(bindingIndex, dwordAddress),
IsBufferWordInRange(bindingIndex, secondAddress));
EmitConditional(inRange, () =>
{
var originalLow = EmitAtomic(
SpirvOp.AtomicOr,
_uintType,
BufferWordPointer(bindingIndex, dwordAddress),
scope: 1,
semantics: 0x48,
value: () => LoadV(control.VectorData),
comparator: () => UInt(0));
var originalHigh = EmitAtomic(
SpirvOp.AtomicOr,
_uintType,
BufferWordPointer(bindingIndex, secondAddress),
scope: 1,
semantics: 0x48,
value: () => LoadV(control.VectorData + 1),
comparator: () => UInt(0));
if (control.Glc)
{
StoreV(control.VectorData, originalLow);
StoreV(control.VectorData + 1, originalHigh);
}
});
});
return true;
}
if (atomicSuffix is "Fmin" or "Fmax")
{
EmitExecConditional(() =>
{
var inRange = IsBufferWordInRange(bindingIndex, dwordAddress);
EmitConditional(inRange, () =>
{
var original = EmitBufferFloatAtomic(
BufferWordPointer(bindingIndex, dwordAddress),
LoadV(control.VectorData),
maxValue: atomicSuffix == "Fmax",
scope: 1,
semantics: 0x48);
if (control.Glc)
{
StoreV(control.VectorData, original);
}
});
});
return true;
}
if (!TryGetAtomicOp(atomicSuffix, out var atomicOp))
{
error = $"unsupported buffer opcode {instruction.Opcode}";
return false;

View File

@ -1216,6 +1216,7 @@ public static partial class Gen5ShaderTranslator
0x36 => "DsReadB32",
0x37 => "DsRead2B32",
0x38 => "DsRead2St64B32",
0x39 => "DsReadI8",
0x3D => "DsConsume",
0x3E => "DsAppend",
0x4D => "DsWriteB64",
@ -1342,6 +1343,9 @@ public static partial class Gen5ShaderTranslator
0x3B => "BufferAtomicXor",
0x3C => "BufferAtomicInc",
0x3D => "BufferAtomicDec",
0x3F => "BufferAtomicFmin",
0x40 => "BufferAtomicFmax",
0x5A => "BufferAtomicOrX2",
_ => $"MubufRaw{opcode:X2}",
};
sizeDwords = (extra >> 24) == 0xFF ? 3u : 2u;
@ -2181,7 +2185,7 @@ public static partial class Gen5ShaderTranslator
"DsAppend" or "DsConsume" => [
Gen5Operand.Vector(vectorDestination),
],
"DsReadB32" or "DsReadAddtidB32" or "DsSwizzleB32" => [
"DsReadB32" or "DsReadI8" or "DsReadAddtidB32" or "DsSwizzleB32" => [
Gen5Operand.Vector(vectorDestination),
],
"DsReadB64" or "DsRead2B32" or "DsRead2St64B32" => [
@ -2339,7 +2343,7 @@ public static partial class Gen5ShaderTranslator
"BufferStoreDwordx2" => 2u,
"BufferStoreDwordx3" => 3u,
"BufferStoreDwordx4" => 4u,
"BufferAtomicCmpswap" => 2u,
"BufferAtomicCmpswap" or "BufferAtomicOrX2" => 2u,
_ when opcode.StartsWith("BufferAtomic", StringComparison.Ordinal) => 1u,
_ => 0u,
};