Merge pull request #3578 from ReinUsesLisp/vmnmx

shader/video: Partially implement VMNMX
This commit is contained in:
Fernando Sahmkow
2020-04-12 10:44:03 -04:00
committed by GitHub
3 changed files with 117 additions and 1 deletions

View File

@ -10,16 +10,24 @@
namespace VideoCommon::Shader {
using std::move;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
using Tegra::Shader::VideoType;
using Tegra::Shader::VmadShr;
using Tegra::Shader::VmnmxOperation;
using Tegra::Shader::VmnmxType;
u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::VMNMX) {
DecodeVMNMX(bb, instr);
return pc;
}
const Node op_a =
GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a,
instr.video.type_a, instr.video.byte_height_a);
@ -109,4 +117,54 @@ Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed,
}
}
void ShaderIR::DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr) {
UNIMPLEMENTED_IF(!instr.vmnmx.is_op_b_register);
UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatA() != VmnmxType::Bits32);
UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatB() != VmnmxType::Bits32);
UNIMPLEMENTED_IF(instr.vmnmx.is_src_a_signed != instr.vmnmx.is_src_b_signed);
UNIMPLEMENTED_IF(instr.vmnmx.sat);
UNIMPLEMENTED_IF(instr.generates_cc);
Node op_a = GetRegister(instr.gpr8);
Node op_b = GetRegister(instr.gpr20);
Node op_c = GetRegister(instr.gpr39);
const bool is_oper1_signed = instr.vmnmx.is_src_a_signed; // Stubbed
const bool is_oper2_signed = instr.vmnmx.is_dest_signed;
const auto operation_a = instr.vmnmx.mx ? OperationCode::IMax : OperationCode::IMin;
Node value = SignedOperation(operation_a, is_oper1_signed, move(op_a), move(op_b));
switch (instr.vmnmx.operation) {
case VmnmxOperation::Mrg_16H:
value = BitfieldInsert(move(op_c), move(value), 16, 16);
break;
case VmnmxOperation::Mrg_16L:
value = BitfieldInsert(move(op_c), move(value), 0, 16);
break;
case VmnmxOperation::Mrg_8B0:
value = BitfieldInsert(move(op_c), move(value), 0, 8);
break;
case VmnmxOperation::Mrg_8B2:
value = BitfieldInsert(move(op_c), move(value), 16, 8);
break;
case VmnmxOperation::Acc:
value = Operation(OperationCode::IAdd, move(value), move(op_c));
break;
case VmnmxOperation::Min:
value = SignedOperation(OperationCode::IMin, is_oper2_signed, move(value), move(op_c));
break;
case VmnmxOperation::Max:
value = SignedOperation(OperationCode::IMax, is_oper2_signed, move(value), move(op_c));
break;
case VmnmxOperation::Nop:
break;
default:
UNREACHABLE();
break;
}
SetRegister(bb, instr.gpr0, move(value));
}
} // namespace VideoCommon::Shader

View File

@ -354,6 +354,9 @@ private:
/// Marks the usage of a input or output attribute.
void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element);
/// Decodes VMNMX instruction and inserts its code into the passed basic block.
void DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr);
void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
const Node4& components);