shader: add BUFFER_STORE_FORMAT_D16_X opcode

This commit is contained in:
nmzik
2026-10-07 09:16:28 +04:00
parent 67d7db685a
commit 5af370c257
6 changed files with 63 additions and 5 deletions
@@ -725,9 +725,18 @@ uint32_t FormattedLoad(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Me
uint32_t EncodeFormattedStoreComponent(ValueEmitContext& ctx, uint32_t EncodeFormattedStoreComponent(ValueEmitContext& ctx,
const Format::BufferFormatInfo& info, const Format::BufferFormatInfo& info,
uint32_t component, uint32_t data) { uint32_t component, uint32_t data, uint32_t data_bits) {
auto& state = ctx.state; auto& state = ctx.state;
const auto bits = info.component_bits[component]; const auto bits = info.component_bits[component];
if (data_bits == 16u) {
if (info.type == Format::ComponentType::Uint) {
data = EmitBitFieldUExtract(state, data, ConstantU32(state, 0), ConstantU32(state, 16));
} else if (info.type == Format::ComponentType::Sint) {
data = EmitBitFieldSExtract(state, data, ConstantU32(state, 0), ConstantU32(state, 16));
} else {
data = EmitBitCastU32F32(state, EmitF16BitsToF32(state, data));
}
}
const bool normalized = info.type == Format::ComponentType::Unorm || const bool normalized = info.type == Format::ComponentType::Unorm ||
info.type == Format::ComponentType::Snorm; info.type == Format::ComponentType::Snorm;
const bool scaled = info.type == Format::ComponentType::Uscaled || const bool scaled = info.type == Format::ComponentType::Uscaled ||
@@ -779,7 +788,7 @@ void StoreFormattedPrepared(ValueEmitContext& ctx, const IR::Inst& inst,
value, data, component); value, data, component);
} }
} }
value = EncodeFormattedStoreComponent(ctx, info, component, value); value = EncodeFormattedStoreComponent(ctx, info, component, value, mem.data_bits);
const auto bits = info.component_bits[component]; const auto bits = info.component_bits[component];
if (info.packed_bitfield) { if (info.packed_bitfield) {
packed = EmitBitFieldInsert( packed = EmitBitFieldInsert(
@@ -63,6 +63,7 @@ constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = {
{0x50u, Opcode::BUFFER_ATOMIC_SWAP_X2, 2, 32}, {0x50u, Opcode::BUFFER_ATOMIC_SWAP_X2, 2, 32},
{0x59u, Opcode::BUFFER_ATOMIC_AND_X2, 2, 32}, {0x59u, Opcode::BUFFER_ATOMIC_AND_X2, 2, 32},
{0x5au, Opcode::BUFFER_ATOMIC_OR_X2, 2, 32}, {0x5au, Opcode::BUFFER_ATOMIC_OR_X2, 2, 32},
{0x84u, Opcode::BUFFER_STORE_FORMAT_D16_X, 1, 16, false, false, true},
}; };
constexpr MemoryOpcodeInfo MTBUF_OPCODE_LIST[] = { constexpr MemoryOpcodeInfo MTBUF_OPCODE_LIST[] = {
@@ -622,6 +622,7 @@ std::string InstructionToString(const Instruction& inst) {
case Opcode::BUFFER_STORE_FORMAT_XY: case Opcode::BUFFER_STORE_FORMAT_XY:
case Opcode::BUFFER_STORE_FORMAT_XYZ: case Opcode::BUFFER_STORE_FORMAT_XYZ:
case Opcode::BUFFER_STORE_FORMAT_XYZW: case Opcode::BUFFER_STORE_FORMAT_XYZW:
case Opcode::BUFFER_STORE_FORMAT_D16_X:
case Opcode::BUFFER_LOAD_UBYTE: case Opcode::BUFFER_LOAD_UBYTE:
case Opcode::BUFFER_LOAD_USHORT: case Opcode::BUFFER_LOAD_USHORT:
case Opcode::BUFFER_LOAD_DWORD: case Opcode::BUFFER_LOAD_DWORD:
@@ -509,6 +509,7 @@ enum class Opcode {
BUFFER_STORE_FORMAT_XY, BUFFER_STORE_FORMAT_XY,
BUFFER_STORE_FORMAT_XYZ, BUFFER_STORE_FORMAT_XYZ,
BUFFER_STORE_FORMAT_XYZW, BUFFER_STORE_FORMAT_XYZW,
BUFFER_STORE_FORMAT_D16_X,
BUFFER_LOAD_UBYTE, BUFFER_LOAD_UBYTE,
BUFFER_LOAD_SBYTE, BUFFER_LOAD_SBYTE,
BUFFER_LOAD_USHORT, BUFFER_LOAD_USHORT,
@@ -187,7 +187,7 @@ Decoder::Operand MemorySourceAt(const Decoder::Instruction& decoded, uint32_t in
if (decoded.family == Decoder::Family::MUBUF || decoded.family == Decoder::Family::MTBUF) { if (decoded.family == Decoder::Family::MUBUF || decoded.family == Decoder::Family::MTBUF) {
const bool store_or_atomic = const bool store_or_atomic =
(decoded.opcode >= Decoder::Opcode::BUFFER_STORE_FORMAT_X && (decoded.opcode >= Decoder::Opcode::BUFFER_STORE_FORMAT_X &&
decoded.opcode <= Decoder::Opcode::BUFFER_STORE_FORMAT_XYZW) || decoded.opcode <= Decoder::Opcode::BUFFER_STORE_FORMAT_D16_X) ||
(decoded.opcode >= Decoder::Opcode::BUFFER_STORE_BYTE && (decoded.opcode >= Decoder::Opcode::BUFFER_STORE_BYTE &&
decoded.opcode <= Decoder::Opcode::BUFFER_STORE_DWORDX4) || decoded.opcode <= Decoder::Opcode::BUFFER_STORE_DWORDX4) ||
(decoded.opcode >= Decoder::Opcode::TBUFFER_STORE_FORMAT_X && (decoded.opcode >= Decoder::Opcode::TBUFFER_STORE_FORMAT_X &&
@@ -473,7 +473,8 @@ void Translator::BUFFER_STORE(const Decoder::Instruction& inst) {
const auto data = ReadU32(data_src); const auto data = ReadU32(data_src);
IR::ValueOpcode opcode; IR::ValueOpcode opcode;
IR::Value value; IR::Value value;
switch (memory.data_bits) { // Formatted stores carry packed VGPR bits; the format determines their conversion.
switch (memory.formatted ? 32u : memory.data_bits) {
case 8u: case 8u:
opcode = IR::ValueOpcode::StoreBufferU8; opcode = IR::ValueOpcode::StoreBufferU8;
value = NarrowSubdword(data, 8u); value = NarrowSubdword(data, 8u);
@@ -995,6 +996,7 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
case Decoder::Opcode::BUFFER_STORE_FORMAT_XY: case Decoder::Opcode::BUFFER_STORE_FORMAT_XY:
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZ: case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZ:
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZW: case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZW:
case Decoder::Opcode::BUFFER_STORE_FORMAT_D16_X:
case Decoder::Opcode::TBUFFER_STORE_FORMAT_X: case Decoder::Opcode::TBUFFER_STORE_FORMAT_X:
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XY: case Decoder::Opcode::TBUFFER_STORE_FORMAT_XY:
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZ: case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZ:
+45 -1
View File
@@ -712,7 +712,7 @@ constexpr u32 EncodeVopcSdwa(u32 src0, u32 sdst = 0, u32 sd = 0,
constexpr u32 EncodeMubuf0(u32 opcode, u32 offset = 0, bool idxen = false, constexpr u32 EncodeMubuf0(u32 opcode, u32 offset = 0, bool idxen = false,
bool offen = true, bool glc = false) { bool offen = true, bool glc = false) {
return (0x38u << 26u) | ((opcode & 0x7fu) << 18u) | return (0x38u << 26u) | ((opcode & 0xffu) << 18u) |
(offen ? (1u << 12u) : 0u) | (idxen ? (1u << 13u) : 0u) | (offen ? (1u << 12u) : 0u) | (idxen ? (1u << 13u) : 0u) |
(glc ? (1u << 14u) : 0u) | (offset & 0xfffu); (glc ? (1u << 14u) : 0u) | (offset & 0xfffu);
} }
@@ -28716,6 +28716,44 @@ TestCase BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords() {
return test; return test;
} }
std::vector<TestCase> BufferStoreFormatD16XCases() {
using F = Prospero::BufferFormat;
using O = ShaderOpcode;
struct StoreCase {
const char *name;
F format;
u32 input;
u32 expected;
};
constexpr StoreCase inputs[] = {
{"BufferStoreFormatD16XFloat16", F::k16Float, 0x7e63c000u, 0xffffc000u},
{"BufferStoreFormatD16XFloat32", F::k32Float, 0x7e633800u, 0x3f000000u},
{"BufferStoreFormatD16XUint32", F::k32UInt, 0x7e63fffeu, 0x0000fffeu},
{"BufferStoreFormatD16XSint32", F::k32SInt, 0x7e63fffeu, 0xfffffffeu},
{"BufferStoreFormatD16XUnorm8", F::k8UNorm, 0x7e633800u, 0xffffff80u},
{"BufferStoreFormatD16XSnorm16", F::k16SNorm, 0x7e63b800u, 0xffffc000u},
{"BufferStoreFormatD16XZeroFill", F::k16_16Float, 0x7e633800u, 0x00003800u},
};
std::vector<TestCase> cases;
for (const auto &input : inputs) {
TestCase test;
test.name = input.name;
AppendVMovLiteral(&test.code, 66, input.input);
AppendVMovU32(&test.code, 65, 1);
// Match the captured CS824586f35db5c80d instruction at pc 0x484.
test.code.push_back(EncodeMubuf0(0x84u, 0, true, false));
test.code.push_back(EncodeMubuf1(66, 0, 65));
AppendEnd(&test.code);
test.initial = {0xdeadbeefu, 0xffffffffu, 0xcafef00du};
test.expected = {0xdeadbeefu, input.expected, 0xcafef00du};
test.user_data = MakeStructuredStorageBufferData(4, 3, false, BufferFormat(input.format));
test.has_user_data = true;
test.opcodes = {O::V_MOV_B32, O::BUFFER_STORE_FORMAT_D16_X, O::S_ENDPGM};
cases.push_back(std::move(test));
}
return cases;
}
std::vector<TestCase> FormattedStoreConversionCases() { std::vector<TestCase> FormattedStoreConversionCases() {
using F = Prospero::BufferFormat; using F = Prospero::BufferFormat;
using O = ShaderOpcode; using O = ShaderOpcode;
@@ -35547,6 +35585,9 @@ std::vector<TestCase> MakeCases() {
AddCase(BufferStoreFormatXyzwFloat16ConvertsComponents); AddCase(BufferStoreFormatXyzwFloat16ConvertsComponents);
AddCase(BufferStoreFormatXyzwSnorm16CapturedSkinningVectors); AddCase(BufferStoreFormatXyzwSnorm16CapturedSkinningVectors);
AddCase(BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords); AddCase(BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords);
for (auto &test : BufferStoreFormatD16XCases()) {
cases.push_back(std::move(test));
}
for (auto &test : FormattedStoreConversionCases()) { for (auto &test : FormattedStoreConversionCases()) {
cases.push_back(std::move(test)); cases.push_back(std::move(test));
} }
@@ -40809,6 +40850,9 @@ int main(int argc, char **argv) {
RunCase(&vulkan, BufferStoreFormatXyzwFloat16ConvertsComponents()); RunCase(&vulkan, BufferStoreFormatXyzwFloat16ConvertsComponents());
RunCase(&vulkan, BufferStoreFormatXyzwSnorm16CapturedSkinningVectors()); RunCase(&vulkan, BufferStoreFormatXyzwSnorm16CapturedSkinningVectors());
RunCase(&vulkan, BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords()); RunCase(&vulkan, BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords());
for (const auto &test : BufferStoreFormatD16XCases()) {
RunCase(&vulkan, test);
}
for (const auto &test : FormattedStoreConversionCases()) { for (const auto &test : FormattedStoreConversionCases()) {
RunCase(&vulkan, test); RunCase(&vulkan, test);
} }