Merge pull request #6010 from SachinVin/gunman

shader_jit: Fixes for Gunman clive
This commit is contained in:
BreadFish64 2022-07-06 23:45:44 -05:00 committed by GitHub
commit 353aaaf665
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 107 additions and 31 deletions

View file

@ -164,8 +164,10 @@ static void LogCritical(const char* msg) {
void JitShader::Compile_Assert(bool condition, const char* msg) {
if (!condition) {
ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0);
mov(ABI_PARAM1, reinterpret_cast<std::size_t>(msg));
CallFarFunction(*this, LogCritical);
ABI_PopRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0);
}
}
@ -595,11 +597,11 @@ void JitShader::Compile_END(Instruction instr) {
}
void JitShader::Compile_BREAKC(Instruction instr) {
Compile_Assert(looping, "BREAKC must be inside a LOOP");
if (looping) {
Compile_Assert(loop_depth, "BREAKC must be inside a LOOP");
if (loop_depth) {
Compile_EvaluateCondition(instr);
ASSERT(loop_break_label);
jnz(*loop_break_label);
ASSERT(!loop_break_labels.empty());
jnz(loop_break_labels.back(), T_NEAR);
}
}
@ -725,9 +727,11 @@ void JitShader::Compile_IF(Instruction instr) {
void JitShader::Compile_LOOP(Instruction instr) {
Compile_Assert(instr.flow_control.dest_offset >= program_counter,
"Backwards loops not supported");
Compile_Assert(!looping, "Nested loops not supported");
looping = true;
Compile_Assert(loop_depth < 1, "Nested loops may not be supported");
if (loop_depth++) {
const auto loop_save_regs = BuildRegSet({LOOPCOUNT_REG, LOOPINC, LOOPCOUNT});
ABI_PushRegistersAndAdjustStack(*this, loop_save_regs, 0);
}
// This decodes the fields from the integer uniform at index instr.flow_control.int_uniform_id.
// The Y (LOOPCOUNT_REG) and Z (LOOPINC) component are kept multiplied by 16 (Left shifted by
@ -746,16 +750,20 @@ void JitShader::Compile_LOOP(Instruction instr) {
Label l_loop_start;
L(l_loop_start);
loop_break_label = Xbyak::Label();
loop_break_labels.emplace_back(Xbyak::Label());
Compile_Block(instr.flow_control.dest_offset + 1);
add(LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component
sub(LOOPCOUNT, 1); // Increment loop count by 1
jnz(l_loop_start); // Loop if not equal
L(*loop_break_label);
loop_break_label.reset();
looping = false;
L(loop_break_labels.back());
loop_break_labels.pop_back();
if (--loop_depth) {
const auto loop_save_regs = BuildRegSet({LOOPCOUNT_REG, LOOPINC, LOOPCOUNT});
ABI_PopRegistersAndAdjustStack(*this, loop_save_regs, 0);
}
}
void JitShader::Compile_JMP(Instruction instr) {
@ -892,7 +900,7 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_
// Reset flow control state
program = (CompiledShader*)getCurr();
program_counter = 0;
looping = false;
loop_depth = 0;
instruction_labels.fill(Xbyak::Label());
// Find all `CALL` instructions and identify return locations

View file

@ -120,15 +120,15 @@ private:
/// Mapping of Pica VS instructions to pointers in the emitted code
std::array<Xbyak::Label, MAX_PROGRAM_CODE_LENGTH> instruction_labels;
/// Label pointing to the end of the current LOOP block. Used by the BREAKC instruction to break
/// out of the loop.
std::optional<Xbyak::Label> loop_break_label;
/// Labels pointing to the end of each nested LOOP block. Used by the BREAKC instruction to
/// break out of a loop.
std::vector<Xbyak::Label> loop_break_labels;
/// Offsets in code where a return needs to be inserted
std::vector<unsigned> return_offsets;
unsigned program_counter = 0; ///< Offset of the next instruction to decode
bool looping = false; ///< True if compiling a loop, used to check for nested loops
u8 loop_depth = 0; ///< Depth of the (nested) loops currently compiled
using CompiledShader = void(const void* setup, void* state, const u8* start_addr);
CompiledShader* program = nullptr;