mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02: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,
|
||||
const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t data) {
|
||||
uint32_t component, uint32_t data, uint32_t data_bits) {
|
||||
auto& state = ctx.state;
|
||||
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 ||
|
||||
info.type == Format::ComponentType::Snorm;
|
||||
const bool scaled = info.type == Format::ComponentType::Uscaled ||
|
||||
@@ -779,7 +788,7 @@ void StoreFormattedPrepared(ValueEmitContext& ctx, const IR::Inst& inst,
|
||||
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];
|
||||
if (info.packed_bitfield) {
|
||||
packed = EmitBitFieldInsert(
|
||||
|
||||
@@ -63,6 +63,7 @@ constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = {
|
||||
{0x50u, Opcode::BUFFER_ATOMIC_SWAP_X2, 2, 32},
|
||||
{0x59u, Opcode::BUFFER_ATOMIC_AND_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[] = {
|
||||
|
||||
@@ -622,6 +622,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::BUFFER_STORE_FORMAT_XY:
|
||||
case Opcode::BUFFER_STORE_FORMAT_XYZ:
|
||||
case Opcode::BUFFER_STORE_FORMAT_XYZW:
|
||||
case Opcode::BUFFER_STORE_FORMAT_D16_X:
|
||||
case Opcode::BUFFER_LOAD_UBYTE:
|
||||
case Opcode::BUFFER_LOAD_USHORT:
|
||||
case Opcode::BUFFER_LOAD_DWORD:
|
||||
|
||||
@@ -509,6 +509,7 @@ enum class Opcode {
|
||||
BUFFER_STORE_FORMAT_XY,
|
||||
BUFFER_STORE_FORMAT_XYZ,
|
||||
BUFFER_STORE_FORMAT_XYZW,
|
||||
BUFFER_STORE_FORMAT_D16_X,
|
||||
BUFFER_LOAD_UBYTE,
|
||||
BUFFER_LOAD_SBYTE,
|
||||
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) {
|
||||
const bool store_or_atomic =
|
||||
(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_DWORDX4) ||
|
||||
(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);
|
||||
IR::ValueOpcode opcode;
|
||||
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:
|
||||
opcode = IR::ValueOpcode::StoreBufferU8;
|
||||
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_XYZ:
|
||||
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_XY:
|
||||
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,
|
||||
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) |
|
||||
(glc ? (1u << 14u) : 0u) | (offset & 0xfffu);
|
||||
}
|
||||
@@ -28716,6 +28716,44 @@ TestCase BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords() {
|
||||
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() {
|
||||
using F = Prospero::BufferFormat;
|
||||
using O = ShaderOpcode;
|
||||
@@ -35547,6 +35585,9 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(BufferStoreFormatXyzwFloat16ConvertsComponents);
|
||||
AddCase(BufferStoreFormatXyzwSnorm16CapturedSkinningVectors);
|
||||
AddCase(BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords);
|
||||
for (auto &test : BufferStoreFormatD16XCases()) {
|
||||
cases.push_back(std::move(test));
|
||||
}
|
||||
for (auto &test : FormattedStoreConversionCases()) {
|
||||
cases.push_back(std::move(test));
|
||||
}
|
||||
@@ -40809,6 +40850,9 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, BufferStoreFormatXyzwFloat16ConvertsComponents());
|
||||
RunCase(&vulkan, BufferStoreFormatXyzwSnorm16CapturedSkinningVectors());
|
||||
RunCase(&vulkan, BufferStoreFormatXSnorm16ClampsRoundsAndPreservesHalfwords());
|
||||
for (const auto &test : BufferStoreFormatD16XCases()) {
|
||||
RunCase(&vulkan, test);
|
||||
}
|
||||
for (const auto &test : FormattedStoreConversionCases()) {
|
||||
RunCase(&vulkan, test);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user