diff --git a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp index bdebdbce8..3d58f2b4c 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp @@ -483,10 +483,11 @@ void Translator::S_BITCMP_B64(const Decoder::Instruction& inst, bool expected) { WriteCompareResult(inst.dst, ir.IEqual(bit, IR::U32(IR::Value(expected ? 1u : 0u)))); } -void Translator::V_ALIGNBIT_B32(const Decoder::Instruction& inst) { - const auto hi = ReadU32(inst.src0); - const auto lo = ReadU32(inst.src1); - const auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); +void Translator::V_ALIGN_B32(const Decoder::Instruction& inst, bool byte_offset) { + const auto hi = ReadU32(inst.src0); + const auto lo = ReadU32(inst.src1); + auto shift = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(byte_offset ? 3u : 31u))); + if (byte_offset) shift = ir.ShiftLeftLogical(shift, IR::U32(IR::Value(3u))); const auto lo_part = ir.ShiftRightLogical(lo, shift); const auto inverse = ir.BitwiseAnd(ir.ISub(IR::U32(IR::Value(32u)), shift), IR::U32(IR::Value(31u))); @@ -496,21 +497,6 @@ void Translator::V_ALIGNBIT_B32(const Decoder::Instruction& inst) { WriteOperand(DestinationOperand(inst), ir.BitwiseOr(lo_part, hi_part)); } -void Translator::V_ALIGNBYTE_B32(const Decoder::Instruction& inst) { - const auto hi = ReadU32(inst.src0); - const auto lo = ReadU32(inst.src1); - const auto byte_offset = ir.BitwiseAnd(ReadU32(inst.src2), IR::U32(IR::Value(31u))); - const auto bit_offset = ir.ShiftLeftLogical(byte_offset, IR::U32(IR::Value(3u))); - const auto concatenated = ir.ConstructU64(lo, hi); - const auto shifted = - IR::U64(ir.Emit(IR::ValueOpcode::ShiftRightLogical64, - {concatenated, ir.BitwiseAnd(bit_offset, IR::U32(IR::Value(63u)))})); - const auto in_range = - IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {byte_offset, IR::Value(8u)})); - WriteOperand(DestinationOperand(inst), - ir.Select(in_range, ExtractU64(shifted)[0], IR::U32(IR::Value(0u)))); -} - void Translator::V_LSHL_ADD_U32(const Decoder::Instruction& inst) { const auto shift = ir.BitwiseAnd(ReadU32(inst.src1), IR::U32(IR::Value(31u))); const auto result = ir.IAdd(ir.ShiftLeftLogical(ReadU32(inst.src0), shift), ReadU32(inst.src2)); diff --git a/src/graphics/shader/recompiler/frontend/translate/Translator.h b/src/graphics/shader/recompiler/frontend/translate/Translator.h index 298c4c287..e98219634 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translator.h +++ b/src/graphics/shader/recompiler/frontend/translate/Translator.h @@ -208,8 +208,7 @@ private: void V_BFI_B32(const Decoder::Instruction& inst); void S_BITCMP_B32(const Decoder::Instruction& inst, bool expected); void S_BITCMP_B64(const Decoder::Instruction& inst, bool expected); - void V_ALIGNBIT_B32(const Decoder::Instruction& inst); - void V_ALIGNBYTE_B32(const Decoder::Instruction& inst); + void V_ALIGN_B32(const Decoder::Instruction& inst, bool byte_offset); void V_LSHL_ADD_U32(const Decoder::Instruction& inst); void V_ADD_LSHL_U32(const Decoder::Instruction& inst); void V_XAD_U32(const Decoder::Instruction& inst); diff --git a/src/graphics/shader/recompiler/frontend/translate/Vector.cpp b/src/graphics/shader/recompiler/frontend/translate/Vector.cpp index 5669663fc..cd76f1b79 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Vector.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Vector.cpp @@ -592,8 +592,8 @@ void Translator::EmitVector(const Decoder::Instruction& inst) { case O::V_BFE_U32: return V_BFE_U32(inst, false); case O::V_BFE_I32: return V_BFE_U32(inst, true); case O::V_BFI_B32: return V_BFI_B32(inst); - case O::V_ALIGNBIT_B32: return V_ALIGNBIT_B32(inst); - case O::V_ALIGNBYTE_B32: return V_ALIGNBYTE_B32(inst); + case O::V_ALIGNBIT_B32: return V_ALIGN_B32(inst, false); + case O::V_ALIGNBYTE_B32: return V_ALIGN_B32(inst, true); case O::V_LSHL_ADD_U32: return V_LSHL_ADD_U32(inst); case O::V_ADD_LSHL_U32: return V_ADD_LSHL_U32(inst); case O::V_XAD_U32: return V_XAD_U32(inst); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 25016a751..d995fb415 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -21243,27 +21243,32 @@ TestCase VectorBfeI32SignExtendsField() { return test; } -TestCase VectorAlignByteUsesFiveBitByteOffset() { +TestCase VectorAlignByteUsesTwoBitByteOffset() { using O = ShaderOpcode; std::vector code; AppendVMovLiteral(&code, 0, 0x11223344u); AppendVMovLiteral(&code, 1, 0x55667788u); - constexpr u32 offsets[] = {0, 1, 3, 4, 5, 7, 8, 31}; + const std::vector offsets = {0, 1, 2, 3, 4, 5, 7, 8, 31, 32, 0xffffffffu}; for (u32 i = 0; i < static_cast(std::size(offsets)); i++) { - AppendVMovU32(&code, 2, offsets[i]); + AppendVMovU32(&code, 2, i * sizeof(u32)); + AppendBufferLoadDword(&code, 2, 2); AppendVop3(&code, 0x14f, 10u + i, Vgpr(0), Vgpr(1), Vgpr(2)); AppendStoreVgpr(&code, 10u + i, i); } AppendEnd(&code); - return { - "VectorAlignByteUsesFiveBitByteOffset", + TestCase test{ + "VectorAlignByteUsesTwoBitByteOffset", code, - {}, - {0x55667788u, 0x44556677u, 0x22334455u, 0x11223344u, 0x00112233u, - 0x00000011u, 0u, 0u}, - {O::V_MOV_B32, O::V_ALIGNBYTE_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; + offsets, + {0x55667788u, 0x44556677u, 0x33445566u, 0x22334455u, 0x55667788u, + 0x44556677u, 0x22334455u, 0x55667788u, 0x22334455u, 0x55667788u, + 0x22334455u}, + {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_ALIGNBYTE_B32, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; + test.forbidden_spirv = {"OpTypeInt 64"}; + return test; } TestCase VectorCarryAndBitCountOps() { @@ -32485,7 +32490,7 @@ std::vector MakeCases() { AddCase(VectorVop3LshlrevB64Captured); AddCase(VectorVop3IntegerOps); AddCase(VectorBfeI32SignExtendsField); - AddCase(VectorAlignByteUsesFiveBitByteOffset); + AddCase(VectorAlignByteUsesTwoBitByteOffset); AddCase(VectorCarryAndBitCountOps); AddCase(VectorMbcntUsesThreadMask); AddCase(VectorAddcWritesPerLaneCarryOut); @@ -37926,7 +37931,8 @@ int main(int argc, char **argv) { } if (argc == 2 && std::strcmp(argv[1], "--alignbyte-only") == 0) { VulkanHarness vulkan; - RunCase(&vulkan, VectorAlignByteUsesFiveBitByteOffset()); + RunCase(&vulkan, VectorAlignByteUsesTwoBitByteOffset()); + RunCase(&vulkan, VectorVop3IntegerOps()); return 0; } if (argc == 2 && std::strcmp(argv[1], "--zero-shift-only") == 0) {