mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: add BUFFER_STORE_FORMAT_D16_X opcode
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user