mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-17 19:21:30 +12:00
[PICA] Implement loops
This commit is contained in:
parent
a5c6fb858f
commit
3706c7ee0c
2 changed files with 44 additions and 3 deletions
|
@ -17,7 +17,8 @@ namespace ShaderOpcodes {
|
||||||
MUL = 0x08,
|
MUL = 0x08,
|
||||||
MOVA = 0x12,
|
MOVA = 0x12,
|
||||||
MOV = 0x13,
|
MOV = 0x13,
|
||||||
END = 0x22
|
END = 0x22,
|
||||||
|
LOOP = 0x29
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +26,13 @@ class PICAShader {
|
||||||
using f24 = Floats::f24;
|
using f24 = Floats::f24;
|
||||||
using vec4f = OpenGL::Vector<f24, 4>;
|
using vec4f = OpenGL::Vector<f24, 4>;
|
||||||
|
|
||||||
|
struct Loop {
|
||||||
|
u32 startingPC; // PC at the start of the loop
|
||||||
|
u32 endingPC; // PC at the end of the loop
|
||||||
|
u32 iterations; // How many iterations of the loop to run
|
||||||
|
u32 increment; // How much to increment the loop counter after each iteration
|
||||||
|
};
|
||||||
|
|
||||||
int bufferIndex; // Index of the next instruction to overwrite for shader uploads
|
int bufferIndex; // Index of the next instruction to overwrite for shader uploads
|
||||||
int opDescriptorIndex; // Index of the next operand descriptor we'll overwrite
|
int opDescriptorIndex; // Index of the next operand descriptor we'll overwrite
|
||||||
u32 floatUniformIndex = 0; // Which float uniform are we writing to? ([0, 95] range)
|
u32 floatUniformIndex = 0; // Which float uniform are we writing to? ([0, 95] range)
|
||||||
|
@ -35,9 +43,12 @@ class PICAShader {
|
||||||
std::array<u32, 128> operandDescriptors;
|
std::array<u32, 128> operandDescriptors;
|
||||||
std::array<vec4f, 16> tempRegisters; // General purpose registers the shader can use for temp values
|
std::array<vec4f, 16> tempRegisters; // General purpose registers the shader can use for temp values
|
||||||
OpenGL::Vector<s32, 2> addrRegister; // Address register
|
OpenGL::Vector<s32, 2> addrRegister; // Address register
|
||||||
u32 pc = 0; // Program counter: Index of the next instruction we're going to execute
|
|
||||||
|
|
||||||
u32 loopCounter;
|
u32 loopCounter;
|
||||||
|
|
||||||
|
u32 pc = 0; // Program counter: Index of the next instruction we're going to execute
|
||||||
|
u32 loopIndex = 0; // The index of our loop stack (0 = empty, 4 = full)
|
||||||
|
std::array<Loop, 4> loopInfo;
|
||||||
|
|
||||||
ShaderType type;
|
ShaderType type;
|
||||||
|
|
||||||
vec4f getSource(u32 source);
|
vec4f getSource(u32 source);
|
||||||
|
@ -46,6 +57,7 @@ class PICAShader {
|
||||||
// Shader opcodes
|
// Shader opcodes
|
||||||
void add(u32 instruction);
|
void add(u32 instruction);
|
||||||
void dp4(u32 instruction);
|
void dp4(u32 instruction);
|
||||||
|
void loop(u32 instruction);
|
||||||
void mov(u32 instruction);
|
void mov(u32 instruction);
|
||||||
void mova(u32 instruction);
|
void mova(u32 instruction);
|
||||||
void mul(u32 instruction);
|
void mul(u32 instruction);
|
||||||
|
|
|
@ -11,11 +11,25 @@ void PICAShader::run() {
|
||||||
case ShaderOpcodes::ADD: add(instruction); break;
|
case ShaderOpcodes::ADD: add(instruction); break;
|
||||||
case ShaderOpcodes::DP4: dp4(instruction); break;
|
case ShaderOpcodes::DP4: dp4(instruction); break;
|
||||||
case ShaderOpcodes::END: return; // Stop running shader
|
case ShaderOpcodes::END: return; // Stop running shader
|
||||||
|
case ShaderOpcodes::LOOP: loop(instruction); break;
|
||||||
case ShaderOpcodes::MOV: mov(instruction); break;
|
case ShaderOpcodes::MOV: mov(instruction); break;
|
||||||
case ShaderOpcodes::MOVA: mova(instruction); break;
|
case ShaderOpcodes::MOVA: mova(instruction); break;
|
||||||
case ShaderOpcodes::MUL: mul(instruction); break;
|
case ShaderOpcodes::MUL: mul(instruction); break;
|
||||||
default:Helpers::panic("Unimplemented PICA instruction %08X (Opcode = %02X)", instruction, opcode);
|
default:Helpers::panic("Unimplemented PICA instruction %08X (Opcode = %02X)", instruction, opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle loop
|
||||||
|
if (loopIndex != 0) {
|
||||||
|
auto& loop = loopInfo[loopIndex - 1];
|
||||||
|
if (pc == loop.endingPC) { // Check if the loop needs to start over
|
||||||
|
loop.iterations -= 1;
|
||||||
|
if (loop.iterations == 0) // If the loop ended, go one level down on the loop stack
|
||||||
|
loopIndex -= 1;
|
||||||
|
|
||||||
|
loopCounter += loop.increment;
|
||||||
|
pc = loop.startingPC;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,3 +168,18 @@ void PICAShader::dp4(u32 instruction) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PICAShader::loop(u32 instruction) {
|
||||||
|
if (loopIndex >= 4) [[unlikely]]
|
||||||
|
Helpers::panic("[PICA] Overflowed loop stack");
|
||||||
|
|
||||||
|
u32 dest = (instruction >> 10) & 0xfff;
|
||||||
|
auto& uniform = intUniforms[(instruction >> 22) & 3]; // The uniform we'll get loop info from
|
||||||
|
loopCounter = uniform.y();
|
||||||
|
auto& loop = loopInfo[loopIndex++];
|
||||||
|
|
||||||
|
loop.startingPC = pc;
|
||||||
|
loop.endingPC = dest + 1; // Loop is inclusive so we need + 1 here
|
||||||
|
loop.iterations = uniform.x() + 1;
|
||||||
|
loop.increment = uniform.z();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue