feat(shader): implement VOPC I16/U16 cmpx compares

This commit is contained in:
asimplestray 2026-09-30 16:41:27 +00:00
parent a67b644ff6
commit 889af1d542
6 changed files with 110 additions and 0 deletions

View File

@ -203,6 +203,14 @@ if(BUILD_TESTING)
set_tests_properties(ray_tracing_miss PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_executable(vector_compare_i16_u16_tests tests/VectorCompareI16U16.cpp)
target_link_libraries(vector_compare_i16_u16_tests PRIVATE shader_recompiler_agc_driver libc)
configure_windows_unwind(vector_compare_i16_u16_tests)
add_test(NAME vector_compare_i16_u16 COMMAND vector_compare_i16_u16_tests)
if(WIN32)
set_tests_properties(vector_compare_i16_u16 PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
target_include_directories(guest_indexed_draw_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_indexed_draw_tests PRIVATE libSceAgc libSceAgcDriver libc)
configure_windows_unwind(guest_indexed_draw_tests)

View File

@ -0,0 +1,32 @@
#include "Translation/TranslationContext.hpp"
#include "RdnaDecoder/RdnaVectorOpDecoder.hpp"
#include <array>
#include <stdexcept>
using namespace ShaderRecompiler;
static void Require(bool value) { if (!value) throw std::runtime_error("vector compare regression"); }
static void Check(std::uint32_t encoding, RdnaOpcode opcode) {
const std::array<std::uint32_t, 1> code{(encoding << 17u) | (1u << 9u) | 100u};
const RdnaInstruction instruction = DecodeRdnaVopc(0u, code, 0u);
Require(instruction.op == opcode);
Require(instruction.family == RdnaInstructionFamily::VOPC);
Require(IsVectorAluOpcode(instruction.op));
Require(instruction.destination.kind == RdnaOperandKind::ExecLo);
IrProgram program;
auto& block = program.CreateBlock();
program.SetEntryBlock(block);
TranslationContext context(program, block, 256);
context.TranslateInstruction(instruction);
}
int main() {
Check(0x99u, RdnaOpcode::VCmpxLtI16);
Check(0x9au, RdnaOpcode::VCmpxEqI16);
Check(0x9bu, RdnaOpcode::VCmpxLeI16);
Check(0x9cu, RdnaOpcode::VCmpxGtI16);
Check(0x9du, RdnaOpcode::VCmpxNeI16);
Check(0x9eu, RdnaOpcode::VCmpxGeI16);
Check(0xbau, RdnaOpcode::VCmpxEqU16);
Check(0xbbu, RdnaOpcode::VCmpxLeU16);
Check(0xbdu, RdnaOpcode::VCmpxNeU16);
Check(0xbeu, RdnaOpcode::VCmpxGeU16);
}

View File

@ -394,6 +394,12 @@ enum class RdnaOpcode : std::uint16_t {
VCmpGtI16,
VCmpNeI16,
VCmpGeI16,
VCmpxLtI16,
VCmpxEqI16,
VCmpxLeI16,
VCmpxGtI16,
VCmpxNeI16,
VCmpxGeI16,
VCmpLtF16,
VCmpEqF16,
VCmpLeF16,
@ -420,7 +426,11 @@ enum class RdnaOpcode : std::uint16_t {
VCmpLeU16,
VCmpGtU16,
VCmpxLtU16,
VCmpxEqU16,
VCmpxLeU16,
VCmpxGtU16,
VCmpxNeU16,
VCmpxGeU16,
VCmpNeU16,
VCmpGeU16,
VCmpFU32,

View File

@ -367,6 +367,12 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) {
case RdnaOpcode::VCmpGtI16:
case RdnaOpcode::VCmpNeI16:
case RdnaOpcode::VCmpGeI16:
case RdnaOpcode::VCmpxLtI16:
case RdnaOpcode::VCmpxEqI16:
case RdnaOpcode::VCmpxLeI16:
case RdnaOpcode::VCmpxGtI16:
case RdnaOpcode::VCmpxNeI16:
case RdnaOpcode::VCmpxGeI16:
case RdnaOpcode::VCmpLtF16:
case RdnaOpcode::VCmpEqF16:
case RdnaOpcode::VCmpLeF16:
@ -393,7 +399,11 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) {
case RdnaOpcode::VCmpLeU16:
case RdnaOpcode::VCmpGtU16:
case RdnaOpcode::VCmpxLtU16:
case RdnaOpcode::VCmpxEqU16:
case RdnaOpcode::VCmpxLeU16:
case RdnaOpcode::VCmpxGtU16:
case RdnaOpcode::VCmpxNeU16:
case RdnaOpcode::VCmpxGeU16:
case RdnaOpcode::VCmpNeU16:
case RdnaOpcode::VCmpGeU16:
case RdnaOpcode::VCmpFU32:

View File

@ -258,6 +258,12 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = {
{0x95u, RdnaOpcode::VCmpxNeI32},
{0x96u, RdnaOpcode::VCmpxGeI32},
{0x98u, RdnaOpcode::VCmpxClassF32},
{0x99u, RdnaOpcode::VCmpxLtI16},
{0x9au, RdnaOpcode::VCmpxEqI16},
{0x9bu, RdnaOpcode::VCmpxLeI16},
{0x9cu, RdnaOpcode::VCmpxGtI16},
{0x9du, RdnaOpcode::VCmpxNeI16},
{0x9eu, RdnaOpcode::VCmpxGeI16},
{0xa9u, RdnaOpcode::VCmpLtU16},
{0xaau, RdnaOpcode::VCmpEqU16},
{0xabu, RdnaOpcode::VCmpLeU16},
@ -265,7 +271,11 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = {
{0xadu, RdnaOpcode::VCmpNeU16},
{0xaeu, RdnaOpcode::VCmpGeU16},
{0xb9u, RdnaOpcode::VCmpxLtU16, false},
{0xbau, RdnaOpcode::VCmpxEqU16},
{0xbbu, RdnaOpcode::VCmpxLeU16},
{0xbcu, RdnaOpcode::VCmpxGtU16},
{0xbdu, RdnaOpcode::VCmpxNeU16},
{0xbeu, RdnaOpcode::VCmpxGeU16},
{0xc0u, RdnaOpcode::VCmpFU32},
{0xc1u, RdnaOpcode::VCmpLtU32},
{0xc2u, RdnaOpcode::VCmpEqU32},
@ -1124,8 +1134,18 @@ bool isVopcCompareExec(RdnaOpcode opcode) {
case RdnaOpcode::VCmpxGeU32:
case RdnaOpcode::VCmpxNeI64:
case RdnaOpcode::VCmpxNeU64:
case RdnaOpcode::VCmpxLtI16:
case RdnaOpcode::VCmpxEqI16:
case RdnaOpcode::VCmpxLeI16:
case RdnaOpcode::VCmpxGtI16:
case RdnaOpcode::VCmpxNeI16:
case RdnaOpcode::VCmpxGeI16:
case RdnaOpcode::VCmpxLtU16:
case RdnaOpcode::VCmpxEqU16:
case RdnaOpcode::VCmpxLeU16:
case RdnaOpcode::VCmpxGtU16:
case RdnaOpcode::VCmpxNeU16:
case RdnaOpcode::VCmpxGeU16:
case RdnaOpcode::VCmpxLtF16:
case RdnaOpcode::VCmpxEqF16:
case RdnaOpcode::VCmpxLeF16:

View File

@ -148,15 +148,27 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
case RdnaOpcode::VCmpEqU16:
emitInteger16Compare(inst, IrOpcode::IEqual32, false, false);
return true;
case RdnaOpcode::VCmpxEqU16:
emitInteger16Compare(inst, IrOpcode::IEqual32, false, true);
return true;
case RdnaOpcode::VCmpEqI16:
emitInteger16Compare(inst, IrOpcode::IEqual32, true, false);
return true;
case RdnaOpcode::VCmpxEqI16:
emitInteger16Compare(inst, IrOpcode::IEqual32, true, true);
return true;
case RdnaOpcode::VCmpNeU16:
emitInteger16Compare(inst, IrOpcode::INotEqual32, false, false);
return true;
case RdnaOpcode::VCmpxNeU16:
emitInteger16Compare(inst, IrOpcode::INotEqual32, false, true);
return true;
case RdnaOpcode::VCmpNeI16:
emitInteger16Compare(inst, IrOpcode::INotEqual32, true, false);
return true;
case RdnaOpcode::VCmpxNeI16:
emitInteger16Compare(inst, IrOpcode::INotEqual32, true, true);
return true;
case RdnaOpcode::VCmpGtU16:
emitInteger16Compare(inst, IrOpcode::UGreaterThan32, false, false);
return true;
@ -166,6 +178,9 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
case RdnaOpcode::VCmpGeU16:
emitInteger16Compare(inst, IrOpcode::UGreaterThanEqual32, false, false);
return true;
case RdnaOpcode::VCmpxGeU16:
emitInteger16Compare(inst, IrOpcode::UGreaterThanEqual32, false, true);
return true;
case RdnaOpcode::VCmpLtU16:
emitInteger16Compare(inst, IrOpcode::ULessThan32, false, false);
return true;
@ -175,18 +190,33 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
case RdnaOpcode::VCmpLeU16:
emitInteger16Compare(inst, IrOpcode::ULessThanEqual32, false, false);
return true;
case RdnaOpcode::VCmpxLeU16:
emitInteger16Compare(inst, IrOpcode::ULessThanEqual32, false, true);
return true;
case RdnaOpcode::VCmpGtI16:
emitInteger16Compare(inst, IrOpcode::SGreaterThan32, true, false);
return true;
case RdnaOpcode::VCmpxGtI16:
emitInteger16Compare(inst, IrOpcode::SGreaterThan32, true, true);
return true;
case RdnaOpcode::VCmpGeI16:
emitInteger16Compare(inst, IrOpcode::SGreaterThanEqual32, true, false);
return true;
case RdnaOpcode::VCmpxGeI16:
emitInteger16Compare(inst, IrOpcode::SGreaterThanEqual32, true, true);
return true;
case RdnaOpcode::VCmpLtI16:
emitInteger16Compare(inst, IrOpcode::SLessThan32, true, false);
return true;
case RdnaOpcode::VCmpxLtI16:
emitInteger16Compare(inst, IrOpcode::SLessThan32, true, true);
return true;
case RdnaOpcode::VCmpLeI16:
emitInteger16Compare(inst, IrOpcode::SLessThanEqual32, true, false);
return true;
case RdnaOpcode::VCmpxLeI16:
emitInteger16Compare(inst, IrOpcode::SLessThanEqual32, true, true);
return true;
case RdnaOpcode::VCmpEqF32:
emitFloatCompare(inst, IrOpcode::FPOrdEqual32, false, false);
return true;