mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 06:16:55 +01:00
shader: support S_QUADMASK_B32
This commit is contained in:
@@ -694,6 +694,8 @@ if(BUILD_TESTING)
|
|||||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --float-min-max-only)
|
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --float-min-max-only)
|
||||||
add_test(NAME shader_recompiler_vop3_conversions
|
add_test(NAME shader_recompiler_vop3_conversions
|
||||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --vop3-conversions-only)
|
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --vop3-conversions-only)
|
||||||
|
add_test(NAME shader_recompiler_quadmask
|
||||||
|
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --quadmask-only)
|
||||||
add_test(NAME shader_recompiler_alignbyte
|
add_test(NAME shader_recompiler_alignbyte
|
||||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --alignbyte-only)
|
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --alignbyte-only)
|
||||||
add_test(NAME graphics_pipeline_rasterization
|
add_test(NAME graphics_pipeline_rasterization
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
|||||||
{0x21u, Opcode::S_SWAPPC_B64},
|
{0x21u, Opcode::S_SWAPPC_B64},
|
||||||
{0x24u, Opcode::S_AND_SAVEEXEC_B64},
|
{0x24u, Opcode::S_AND_SAVEEXEC_B64},
|
||||||
{0x28u, Opcode::S_ORN2_SAVEEXEC_B64},
|
{0x28u, Opcode::S_ORN2_SAVEEXEC_B64},
|
||||||
|
{0x2cu, Opcode::S_QUADMASK_B32},
|
||||||
{0x2du, Opcode::S_QUADMASK_B64},
|
{0x2du, Opcode::S_QUADMASK_B64},
|
||||||
{0x34u, Opcode::S_ABS_I32},
|
{0x34u, Opcode::S_ABS_I32},
|
||||||
{0x37u, Opcode::S_ANDN1_SAVEEXEC_B64},
|
{0x37u, Opcode::S_ANDN1_SAVEEXEC_B64},
|
||||||
|
|||||||
@@ -517,6 +517,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||||||
case Opcode::S_NOT_B64:
|
case Opcode::S_NOT_B64:
|
||||||
case Opcode::S_WQM_B32:
|
case Opcode::S_WQM_B32:
|
||||||
case Opcode::S_WQM_B64:
|
case Opcode::S_WQM_B64:
|
||||||
|
case Opcode::S_QUADMASK_B32:
|
||||||
case Opcode::S_QUADMASK_B64:
|
case Opcode::S_QUADMASK_B64:
|
||||||
case Opcode::S_AND_SAVEEXEC_B32:
|
case Opcode::S_AND_SAVEEXEC_B32:
|
||||||
case Opcode::S_ORN2_SAVEEXEC_B32:
|
case Opcode::S_ORN2_SAVEEXEC_B32:
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ enum class Opcode {
|
|||||||
S_FLBIT_I32,
|
S_FLBIT_I32,
|
||||||
S_FLBIT_I32_I64,
|
S_FLBIT_I32_I64,
|
||||||
S_BITREPLICATE_B64_B32,
|
S_BITREPLICATE_B64_B32,
|
||||||
|
S_QUADMASK_B32,
|
||||||
S_QUADMASK_B64,
|
S_QUADMASK_B64,
|
||||||
S_GETPC_B64,
|
S_GETPC_B64,
|
||||||
S_SETPC_B64,
|
S_SETPC_B64,
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ void Translator::S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst) {
|
|||||||
WriteOperand(DestinationOperand(inst), ir.ConstructU64(replicate(low), replicate(high)));
|
WriteOperand(DestinationOperand(inst), ir.ConstructU64(replicate(low), replicate(high)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::S_QUADMASK_B64(const Decoder::Instruction& inst) {
|
void Translator::S_QUADMASK(const Decoder::Instruction& inst, bool is64) {
|
||||||
const auto compact = [&](IR::U32 value) {
|
const auto compact = [&](IR::U32 value) {
|
||||||
auto bits = ir.BitwiseOr(value, ir.ShiftRightLogical(value, IR::U32(IR::Value(1u))));
|
auto bits = ir.BitwiseOr(value, ir.ShiftRightLogical(value, IR::U32(IR::Value(1u))));
|
||||||
bits = ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(2u))));
|
bits = ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(2u))));
|
||||||
@@ -388,12 +388,17 @@ void Translator::S_QUADMASK_B64(const Decoder::Instruction& inst) {
|
|||||||
ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(12u)))),
|
ir.BitwiseOr(bits, ir.ShiftRightLogical(bits, IR::U32(IR::Value(12u)))),
|
||||||
IR::U32(IR::Value(0xffu)));
|
IR::U32(IR::Value(0xffu)));
|
||||||
};
|
};
|
||||||
|
IR::U32 quads;
|
||||||
|
if (is64) {
|
||||||
const auto source = ReadU32Pair(inst.src0);
|
const auto source = ReadU32Pair(inst.src0);
|
||||||
const auto quads = ir.BitwiseOr(
|
quads = ir.BitwiseOr(
|
||||||
compact(source[0]), ir.ShiftLeftLogical(compact(source[1]), IR::U32(IR::Value(8u))));
|
compact(source[0]), ir.ShiftLeftLogical(compact(source[1]), IR::U32(IR::Value(8u))));
|
||||||
const auto result = ir.ConstructU64(quads, IR::U32(IR::Value(0u)));
|
WriteOperand(DestinationOperand(inst), ir.ConstructU64(quads, IR::U32(IR::Value(0u))));
|
||||||
WriteOperand(DestinationOperand(inst), result);
|
} else {
|
||||||
ir.SetScc(IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
|
quads = compact(ReadU32(inst.src0));
|
||||||
|
WriteOperand(DestinationOperand(inst), quads);
|
||||||
|
}
|
||||||
|
ir.SetScc(ir.INotEqual(quads, IR::U32(IR::Value(0u))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::BFM_B32(const Decoder::Instruction& inst) {
|
void Translator::BFM_B32(const Decoder::Instruction& inst) {
|
||||||
|
|||||||
@@ -248,7 +248,8 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
|
|||||||
case O::S_BITSET0_B64: return S_BITSET_B64(inst, false);
|
case O::S_BITSET0_B64: return S_BITSET_B64(inst, false);
|
||||||
case O::S_BITSET1_B64: return S_BITSET_B64(inst, true);
|
case O::S_BITSET1_B64: return S_BITSET_B64(inst, true);
|
||||||
case O::S_BITREPLICATE_B64_B32: return S_BITREPLICATE_B64_B32(inst);
|
case O::S_BITREPLICATE_B64_B32: return S_BITREPLICATE_B64_B32(inst);
|
||||||
case O::S_QUADMASK_B64: return S_QUADMASK_B64(inst);
|
case O::S_QUADMASK_B32: return S_QUADMASK(inst, false);
|
||||||
|
case O::S_QUADMASK_B64: return S_QUADMASK(inst, true);
|
||||||
case O::S_BFM_B32: return BFM_B32(inst);
|
case O::S_BFM_B32: return BFM_B32(inst);
|
||||||
case O::S_BFM_B64: return S_BFM_B64(inst);
|
case O::S_BFM_B64: return S_BFM_B64(inst);
|
||||||
case O::S_BFE_U32: return S_BFE_U32(inst, false);
|
case O::S_BFE_U32: return S_BFE_U32(inst, false);
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ private:
|
|||||||
void V_BCNT_U32_B32(const Decoder::Instruction& inst);
|
void V_BCNT_U32_B32(const Decoder::Instruction& inst);
|
||||||
void V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
|
void V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
|
||||||
void S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
|
void S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
|
||||||
void S_QUADMASK_B64(const Decoder::Instruction& inst);
|
void S_QUADMASK(const Decoder::Instruction& inst, bool is64);
|
||||||
void BFM_B32(const Decoder::Instruction& inst);
|
void BFM_B32(const Decoder::Instruction& inst);
|
||||||
IR::U32 RightMask32(IR::U32 count);
|
IR::U32 RightMask32(IR::U32 count);
|
||||||
void S_BFM_B64(const Decoder::Instruction& inst);
|
void S_BFM_B64(const Decoder::Instruction& inst);
|
||||||
|
|||||||
@@ -23748,6 +23748,46 @@ TestCase ScalarNotB64UpdatesScc() {
|
|||||||
O::S_ENDPGM}};
|
O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarQuadmaskB32(u32 wave_size) {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
TestCase test;
|
||||||
|
test.name = wave_size == 32 ? "ScalarQuadmaskB32Wave32" : "ScalarQuadmaskB32Wave64";
|
||||||
|
test.initial = {0, 0xffffffffu, 0x80000011u, 0x01010101u};
|
||||||
|
for (u32 bit = 0; bit < 32; ++bit) test.initial.push_back(1u << bit);
|
||||||
|
test.expected = test.initial;
|
||||||
|
auto &code = test.code;
|
||||||
|
for (u32 i = 0; i < test.initial.size(); ++i) {
|
||||||
|
u32 quads = 0;
|
||||||
|
for (u32 q = 0; q < 8; ++q) {
|
||||||
|
if ((test.initial[i] >> (4 * q)) & 15u) quads |= 1u << q;
|
||||||
|
}
|
||||||
|
AppendVMovU32(&code, 30, i * sizeof(u32));
|
||||||
|
AppendBufferLoadDword(&code, 2, 30);
|
||||||
|
for (u32 dst : {12u, 106u}) {
|
||||||
|
code.push_back(EncodeVop1(0x02, dst, Vgpr(2)));
|
||||||
|
AppendSMovLiteral(&code, dst + 1, 0xdeadbeefu);
|
||||||
|
code.push_back(EncodeSopc(0x06, InlineU32(quads == 0), InlineU32(1)));
|
||||||
|
code.push_back(EncodeSop1(0x2c, dst, dst));
|
||||||
|
code.push_back(EncodeSop2(0x0a, 14, InlineU32(1), InlineU32(0)));
|
||||||
|
AppendStoreSgpr(&code, dst, static_cast<u32>(test.expected.size()));
|
||||||
|
AppendStoreSgpr(&code, dst + 1, static_cast<u32>(test.expected.size()) + 1);
|
||||||
|
AppendStoreSgpr(&code, 14, static_cast<u32>(test.expected.size()) + 2);
|
||||||
|
test.expected.insert(test.expected.end(), {quads, 0xdeadbeefu, quads != 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code.push_back(EncodeSop1(0x2c, 12, 255));
|
||||||
|
code.push_back(0x000f000fu);
|
||||||
|
AppendStoreSgpr(&code, 12, static_cast<u32>(test.expected.size()));
|
||||||
|
test.expected.push_back(0x11u);
|
||||||
|
AppendEnd(&code);
|
||||||
|
test.opcodes = {O::S_QUADMASK_B32, O::S_CMP_EQ_U32, O::S_CSELECT_B32, O::S_MOV_B32,
|
||||||
|
O::V_READFIRSTLANE_B32, O::V_MOV_B32, O::BUFFER_LOAD_DWORD,
|
||||||
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.compute_info.wave_size = wave_size;
|
||||||
|
test.has_compute_info = true;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase ScalarQuadmaskB64() {
|
TestCase ScalarQuadmaskB64() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -46047,6 +46087,8 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarCompareOps);
|
AddCase(ScalarCompareOps);
|
||||||
AddCase(ScalarShiftAddAndMaskOps);
|
AddCase(ScalarShiftAddAndMaskOps);
|
||||||
AddCase(ScalarNotB64UpdatesScc);
|
AddCase(ScalarNotB64UpdatesScc);
|
||||||
|
cases.push_back(ScalarQuadmaskB32(32));
|
||||||
|
cases.push_back(ScalarQuadmaskB32(64));
|
||||||
AddCase(ScalarQuadmaskB64);
|
AddCase(ScalarQuadmaskB64);
|
||||||
AddCase(ScalarFlbitI32B64Gpu);
|
AddCase(ScalarFlbitI32B64Gpu);
|
||||||
AddCase(ScalarFlbitI32B32Gpu);
|
AddCase(ScalarFlbitI32B32Gpu);
|
||||||
@@ -52562,6 +52604,13 @@ int main(int argc, char **argv) {
|
|||||||
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
||||||
EnsureConfigInitialized();
|
EnsureConfigInitialized();
|
||||||
CheckLeastRecentlyUsedCacheOrdering();
|
CheckLeastRecentlyUsedCacheOrdering();
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--quadmask-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
RunCase(&vulkan, ScalarQuadmaskB32(32));
|
||||||
|
RunCase(&vulkan, ScalarQuadmaskB32(64));
|
||||||
|
RunCase(&vulkan, ScalarQuadmaskB64());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--vop3-conversions-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--vop3-conversions-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, Vop3FloatConversions(32));
|
RunCase(&vulkan, Vop3FloatConversions(32));
|
||||||
|
|||||||
Reference in New Issue
Block a user