yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #501 from Subv/shader_bra

GPU: Partially implemented the bra shader instruction
This commit is contained in:
bunnei 2018-06-04 18:31:07 -04:00 committed by GitHub
commit cdd92dc692
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View File

@ -288,6 +288,19 @@ union Instruction {
} }
} texs; } texs;
union {
BitField<20, 5, u64> target;
BitField<5, 1, u64> constant_buffer;
s32 GetBranchTarget() const {
// Sign extend the branch target offset
u32 mask = 1U << (5 - 1);
u32 value = static_cast<u32>(target);
// The branch offset is relative to the next instruction, so add 1 to it.
return static_cast<s32>((value ^ mask) - mask) + 1;
}
} bra;
BitField<61, 1, u64> is_b_imm; BitField<61, 1, u64> is_b_imm;
BitField<60, 1, u64> is_b_gpr; BitField<60, 1, u64> is_b_gpr;
BitField<59, 1, u64> is_c_gpr; BitField<59, 1, u64> is_c_gpr;
@ -306,6 +319,7 @@ class OpCode {
public: public:
enum class Id { enum class Id {
KIL, KIL,
BRA,
LD_A, LD_A,
ST_A, ST_A,
TEX, TEX,
@ -470,6 +484,7 @@ private:
std::vector<Matcher> table = { std::vector<Matcher> table = {
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
INST("111000110011----", Id::KIL, Type::Flow, "KIL"), INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
INST("1100000000111---", Id::TEX, Type::Memory, "TEX"), INST("1100000000111---", Id::TEX, Type::Memory, "TEX"),

View File

@ -88,6 +88,20 @@ private:
return *subroutines.insert(std::move(subroutine)).first; return *subroutines.insert(std::move(subroutine)).first;
} }
/// Merges exit method of two parallel branches.
static ExitMethod ParallelExit(ExitMethod a, ExitMethod b) {
if (a == ExitMethod::Undetermined) {
return b;
}
if (b == ExitMethod::Undetermined) {
return a;
}
if (a == b) {
return a;
}
return ExitMethod::Conditional;
}
/// Scans a range of code for labels and determines the exit method. /// Scans a range of code for labels and determines the exit method.
ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) { ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) {
auto [iter, inserted] = auto [iter, inserted] =
@ -97,11 +111,19 @@ private:
return exit_method; return exit_method;
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) { for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
if (const auto opcode = OpCode::Decode({program_code[offset]})) { const Instruction instr = {program_code[offset]};
if (const auto opcode = OpCode::Decode(instr)) {
switch (opcode->GetId()) { switch (opcode->GetId()) {
case OpCode::Id::EXIT: { case OpCode::Id::EXIT: {
return exit_method = ExitMethod::AlwaysEnd; return exit_method = ExitMethod::AlwaysEnd;
} }
case OpCode::Id::BRA: {
u32 target = offset + instr.bra.GetBranchTarget();
labels.insert(target);
ExitMethod no_jmp = Scan(offset + 1, end, labels);
ExitMethod jmp = Scan(target, end, labels);
return exit_method = ParallelExit(no_jmp, jmp);
}
} }
} }
} }
@ -1081,6 +1103,13 @@ private:
shader.AddLine("discard;"); shader.AddLine("discard;");
break; break;
} }
case OpCode::Id::BRA: {
ASSERT_MSG(instr.bra.constant_buffer == 0,
"BRA with constant buffers are not implemented");
u32 target = offset + instr.bra.GetBranchTarget();
shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
break;
}
case OpCode::Id::IPA: { case OpCode::Id::IPA: {
const auto& attribute = instr.attribute.fmt28; const auto& attribute = instr.attribute.fmt28;
regs.SetRegisterToInputAttibute(instr.gpr0, attribute.element, attribute.index); regs.SetRegisterToInputAttibute(instr.gpr0, attribute.element, attribute.index);