diff options
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 8 | ||||
| -rw-r--r-- | src/video_core/shader/decode/conversion.cpp | 22 | 
2 files changed, 23 insertions, 7 deletions
| diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index ba28ff51c..c3678b9ea 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1020,7 +1020,6 @@ union Instruction {      } iset;      union { -        BitField<41, 2, u64> selector; // i2i and i2f only          BitField<45, 1, u64> negate_a;          BitField<49, 1, u64> abs_a;          BitField<10, 2, Register::Size> src_size; @@ -1046,6 +1045,13 @@ union Instruction {              }          } f2f; +        union { +            BitField<41, 2, u64> selector; +        } int_src; + +        union { +            BitField<41, 1, u64> selector; +        } float_src;      } conversion;      union { diff --git a/src/video_core/shader/decode/conversion.cpp b/src/video_core/shader/decode/conversion.cpp index 8973fbefa..32facd6ba 100644 --- a/src/video_core/shader/decode/conversion.cpp +++ b/src/video_core/shader/decode/conversion.cpp @@ -14,6 +14,12 @@ using Tegra::Shader::Instruction;  using Tegra::Shader::OpCode;  using Tegra::Shader::Register; +namespace { +constexpr OperationCode GetFloatSelector(u64 selector) { +    return selector == 0 ? OperationCode::FCastHalf0 : OperationCode::FCastHalf1; +} +} // Anonymous namespace +  u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {      const Instruction instr = {program_code[pc]};      const auto opcode = OpCode::Decode(instr); @@ -22,7 +28,7 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {      case OpCode::Id::I2I_R:      case OpCode::Id::I2I_C:      case OpCode::Id::I2I_IMM: { -        UNIMPLEMENTED_IF(instr.conversion.selector); +        UNIMPLEMENTED_IF(instr.conversion.int_src.selector != 0);          UNIMPLEMENTED_IF(instr.conversion.dst_size != Register::Size::Word);          UNIMPLEMENTED_IF(instr.alu.saturate_d); @@ -57,8 +63,8 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {      case OpCode::Id::I2F_R:      case OpCode::Id::I2F_C:      case OpCode::Id::I2F_IMM: { +        UNIMPLEMENTED_IF(instr.conversion.int_src.selector != 0);          UNIMPLEMENTED_IF(instr.conversion.dst_size == Register::Size::Long); -        UNIMPLEMENTED_IF(instr.conversion.selector);          UNIMPLEMENTED_IF_MSG(instr.generates_cc,                               "Condition codes generation in I2F is not implemented"); @@ -113,8 +119,10 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {          }();          if (instr.conversion.src_size == Register::Size::Short) { -            // TODO: figure where extract is sey in the encoding -            value = Operation(OperationCode::FCastHalf0, PRECISE, value); +            value = Operation(GetFloatSelector(instr.conversion.float_src.selector), NO_PRECISE, +                              std::move(value)); +        } else { +            ASSERT(instr.conversion.float_src.selector == 0);          }          value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); @@ -169,8 +177,10 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {          }();          if (instr.conversion.src_size == Register::Size::Short) { -            // TODO: figure where extract is sey in the encoding -            value = Operation(OperationCode::FCastHalf0, PRECISE, value); +            value = Operation(GetFloatSelector(instr.conversion.float_src.selector), NO_PRECISE, +                              std::move(value)); +        } else { +            ASSERT(instr.conversion.float_src.selector == 0);          }          value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); | 
