[SpirvTranslator] Decode one selected component per destination for runtime buffer formats
This commit is contained in:
parent
fb5b9c014e
commit
b61ef8ede6
|
|
@ -169,6 +169,7 @@ public static partial class Gen5SpirvTranslator
|
|||
private readonly Dictionary<(uint Register, uint Lane), uint> _laneSpillSlots = new();
|
||||
private uint _globalBuffers;
|
||||
private uint _gfx10BufferFormatTable;
|
||||
private uint _gfx10BufferLayoutTable;
|
||||
private uint _storageBlockPointer;
|
||||
private uint _storageUintPointer;
|
||||
private uint _lds;
|
||||
|
|
@ -3902,6 +3903,11 @@ public static partial class Gen5SpirvTranslator
|
|||
ShiftRightLogical(descriptorWord3, UInt(12)),
|
||||
UInt(0x7F));
|
||||
var (dataFormat, numberFormat) = DecodeGfx10BufferFormat(unifiedFormat);
|
||||
if (!_module.TryGetConstantValue(descriptorWord3, out _))
|
||||
{
|
||||
EmitSelectedBufferFormatLoad(bindingIndex, byteAddress, descriptorWord3, dataFormat, numberFormat, vectorData, componentCount);
|
||||
return;
|
||||
}
|
||||
|
||||
var canonical = new uint[4];
|
||||
var componentBounds = new uint[4];
|
||||
|
|
@ -3952,6 +3958,86 @@ public static partial class Gen5SpirvTranslator
|
|||
}
|
||||
}
|
||||
|
||||
private void EmitSelectedBufferFormatLoad(
|
||||
int bindingIndex,
|
||||
uint byteAddress,
|
||||
uint descriptorWord3,
|
||||
uint dataFormat,
|
||||
uint numberFormat,
|
||||
uint vectorData,
|
||||
uint componentCount)
|
||||
{
|
||||
var one = Gfx10FormatOne(numberFormat);
|
||||
var values = new uint[componentCount];
|
||||
var constants = new uint[componentCount];
|
||||
var inBounds = _module.ConstantBool(true);
|
||||
for (uint destination = 0; destination < componentCount; destination++)
|
||||
{
|
||||
var selector = BitwiseAnd(
|
||||
ShiftRightLogical(descriptorWord3, UInt(destination * 3)), UInt(7));
|
||||
var fromMemory = _module.AddInstruction(SpirvOp.UGreaterThanEqual, _boolType, selector, UInt(4));
|
||||
var loaded = LoadGfx10BufferFormatSelectedComponent(
|
||||
bindingIndex,
|
||||
byteAddress,
|
||||
dataFormat,
|
||||
numberFormat,
|
||||
BitwiseAnd(selector, UInt(3)),
|
||||
one,
|
||||
out var componentInBounds);
|
||||
inBounds = _module.AddInstruction(
|
||||
SpirvOp.LogicalAnd, _boolType, inBounds,
|
||||
_module.AddInstruction(SpirvOp.Select, _boolType, fromMemory, componentInBounds, _module.ConstantBool(true)));
|
||||
constants[destination] = SelectUInt(selector, 1, one, UInt(0));
|
||||
values[destination] = _module.AddInstruction(SpirvOp.Select, _uintType, fromMemory, loaded, constants[destination]);
|
||||
}
|
||||
|
||||
for (uint destination = 0; destination < componentCount; destination++)
|
||||
{
|
||||
StoreV(
|
||||
vectorData + destination,
|
||||
_module.AddInstruction(SpirvOp.Select, _uintType, inBounds, values[destination], constants[destination]));
|
||||
}
|
||||
}
|
||||
|
||||
private uint LoadGfx10BufferFormatSelectedComponent(
|
||||
int bindingIndex,
|
||||
uint elementAddress,
|
||||
uint dataFormat,
|
||||
uint numberFormat,
|
||||
uint component,
|
||||
uint one,
|
||||
out uint componentInBounds)
|
||||
{
|
||||
if (_gfx10BufferLayoutTable == 0)
|
||||
{
|
||||
const uint layoutCount = 64;
|
||||
var entries = new uint[layoutCount];
|
||||
Array.Fill(entries, UInt(0));
|
||||
foreach (var layout in Gfx10UnifiedFormat.ComponentLayouts)
|
||||
{
|
||||
entries[(layout.DataFormat & 15) * 4 + layout.Component] =
|
||||
UInt(layout.ByteOffset | (layout.BitOffset << 8) | (layout.BitCount << 16));
|
||||
}
|
||||
|
||||
var tableType = _module.TypeArray(_uintType, layoutCount);
|
||||
_gfx10BufferLayoutTable = _module.AddGlobalVariable(
|
||||
_module.TypePointer(SpirvStorageClass.Private, tableType),
|
||||
SpirvStorageClass.Private,
|
||||
_module.ConstantComposite(tableType, entries));
|
||||
_module.AddName(_gfx10BufferLayoutTable, "gfx10BufferLayouts");
|
||||
_interfaces.Add(_gfx10BufferLayoutTable);
|
||||
}
|
||||
|
||||
var index = IAdd(ShiftLeftLogical(BitwiseAnd(dataFormat, UInt(15)), UInt(2)), component);
|
||||
var entry = Load(_uintType, _module.AddInstruction(SpirvOp.AccessChain, _privateUintPointer, _gfx10BufferLayoutTable, index));
|
||||
var byteOffset = BitwiseAnd(entry, UInt(0xFF));
|
||||
var bitOffset = BitwiseAnd(ShiftRightLogical(entry, UInt(8)), UInt(0xFF));
|
||||
var bitCount = BitwiseAnd(ShiftRightLogical(entry, UInt(16)), UInt(0xFF));
|
||||
return ExtractGfx10BufferFormatComponent(
|
||||
bindingIndex, elementAddress, byteOffset, bitOffset, bitCount, numberFormat, dataFormat,
|
||||
() => SelectUInt(component, 3, one, UInt(0)), out componentInBounds);
|
||||
}
|
||||
|
||||
// Check the first and last dwords of the required range together.
|
||||
private uint IsBufferElementInRange(int bindingIndex, uint byteAddress, uint lastByteOffset)
|
||||
{
|
||||
|
|
@ -4345,6 +4431,22 @@ public static partial class Gen5SpirvTranslator
|
|||
}
|
||||
}
|
||||
|
||||
return ExtractGfx10BufferFormatComponent(
|
||||
bindingIndex, elementAddress, byteOffset, bitOffset, bitCount, numberFormat, dataFormat,
|
||||
() => component == 3 ? Gfx10FormatOne(numberFormat) : UInt(0), out componentInBounds);
|
||||
}
|
||||
|
||||
private uint ExtractGfx10BufferFormatComponent(
|
||||
int bindingIndex,
|
||||
uint elementAddress,
|
||||
uint byteOffset,
|
||||
uint bitOffset,
|
||||
uint bitCount,
|
||||
uint numberFormat,
|
||||
uint dataFormat,
|
||||
Func<uint> missing,
|
||||
out uint componentInBounds)
|
||||
{
|
||||
var packed = LoadUnalignedBufferWord(
|
||||
bindingIndex,
|
||||
IAdd(elementAddress, byteOffset));
|
||||
|
|
@ -4375,7 +4477,7 @@ public static partial class Gen5SpirvTranslator
|
|||
_uintType,
|
||||
valid,
|
||||
converted,
|
||||
component == 3 ? Gfx10FormatOne(numberFormat) : UInt(0));
|
||||
missing());
|
||||
}
|
||||
|
||||
private uint ConvertGfx10BufferComponent(
|
||||
|
|
|
|||
Loading…
Reference in New Issue