Pica: Create 'State' structure and move state memory there.
This commit is contained in:
parent
4c207798b4
commit
1b42d55a9d
15 changed files with 461 additions and 438 deletions
|
@ -26,55 +26,8 @@ namespace Pica {
|
|||
|
||||
namespace VertexShader {
|
||||
|
||||
static struct {
|
||||
Math::Vec4<float24> f[96];
|
||||
|
||||
std::array<bool,16> b;
|
||||
|
||||
std::array<Math::Vec4<u8>,4> i;
|
||||
} shader_uniforms;
|
||||
|
||||
static Math::Vec4<float24> vs_default_attributes[16];
|
||||
|
||||
// TODO: Not sure where the shader binary and swizzle patterns are supposed to be loaded to!
|
||||
// For now, we just keep these local arrays around.
|
||||
static std::array<u32, 1024> shader_memory;
|
||||
static std::array<u32, 1024> swizzle_data;
|
||||
|
||||
void SubmitShaderMemoryChange(u32 addr, u32 value) {
|
||||
shader_memory[addr] = value;
|
||||
}
|
||||
|
||||
void SubmitSwizzleDataChange(u32 addr, u32 value) {
|
||||
swizzle_data[addr] = value;
|
||||
}
|
||||
|
||||
Math::Vec4<float24>& GetFloatUniform(u32 index) {
|
||||
return shader_uniforms.f[index];
|
||||
}
|
||||
|
||||
bool& GetBoolUniform(u32 index) {
|
||||
return shader_uniforms.b[index];
|
||||
}
|
||||
|
||||
Math::Vec4<u8>& GetIntUniform(u32 index) {
|
||||
return shader_uniforms.i[index];
|
||||
}
|
||||
|
||||
Math::Vec4<float24>& GetDefaultAttribute(u32 index) {
|
||||
return vs_default_attributes[index];
|
||||
}
|
||||
|
||||
const std::array<u32, 1024>& GetShaderBinary() {
|
||||
return shader_memory;
|
||||
}
|
||||
|
||||
const std::array<u32, 1024>& GetSwizzlePatterns() {
|
||||
return swizzle_data;
|
||||
}
|
||||
|
||||
struct VertexShaderState {
|
||||
u32* program_counter;
|
||||
const u32* program_counter;
|
||||
|
||||
const float24* input_register_table[16];
|
||||
Math::Vec4<float24> output_registers[16];
|
||||
|
@ -109,6 +62,9 @@ struct VertexShaderState {
|
|||
};
|
||||
|
||||
static void ProcessShaderCode(VertexShaderState& state) {
|
||||
const auto& uniforms = g_state.vs.uniforms;
|
||||
const auto& swizzle_data = g_state.vs.swizzle_data;
|
||||
const auto& program_code = g_state.vs.program_code;
|
||||
|
||||
// Placeholder for invalid inputs
|
||||
static float24 dummy_vec4_float24[4];
|
||||
|
@ -116,14 +72,14 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
while (true) {
|
||||
if (!state.call_stack.empty()) {
|
||||
auto& top = state.call_stack.top();
|
||||
if (state.program_counter - shader_memory.data() == top.final_address) {
|
||||
if (state.program_counter - program_code.data() == top.final_address) {
|
||||
state.address_registers[2] += top.loop_increment;
|
||||
|
||||
if (top.repeat_counter-- == 0) {
|
||||
state.program_counter = &shader_memory[top.return_address];
|
||||
state.program_counter = &program_code[top.return_address];
|
||||
state.call_stack.pop();
|
||||
} else {
|
||||
state.program_counter = &shader_memory[top.loop_address];
|
||||
state.program_counter = &program_code[top.loop_address];
|
||||
}
|
||||
|
||||
// TODO: Is "trying again" accurate to hardware?
|
||||
|
@ -135,12 +91,12 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
const Instruction& instr = *(const Instruction*)state.program_counter;
|
||||
const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id];
|
||||
|
||||
static auto call = [](VertexShaderState& state, u32 offset, u32 num_instructions,
|
||||
static auto call = [&program_code](VertexShaderState& state, u32 offset, u32 num_instructions,
|
||||
u32 return_offset, u8 repeat_count, u8 loop_increment) {
|
||||
state.program_counter = &shader_memory[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset
|
||||
state.program_counter = &program_code[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset
|
||||
state.call_stack.push({ offset + num_instructions, return_offset, repeat_count, loop_increment, offset });
|
||||
};
|
||||
u32 binary_offset = state.program_counter - shader_memory.data();
|
||||
u32 binary_offset = state.program_counter - program_code.data();
|
||||
|
||||
state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset);
|
||||
|
||||
|
@ -153,7 +109,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
return &state.temporary_registers[source_reg.GetIndex()].x;
|
||||
|
||||
case RegisterType::FloatUniform:
|
||||
return &shader_uniforms.f[source_reg.GetIndex()].x;
|
||||
return &uniforms.f[source_reg.GetIndex()].x;
|
||||
|
||||
default:
|
||||
return dummy_vec4_float24;
|
||||
|
@ -471,13 +427,13 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
|
||||
case OpCode::Id::JMPC:
|
||||
if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) {
|
||||
state.program_counter = &shader_memory[instr.flow_control.dest_offset] - 1;
|
||||
state.program_counter = &program_code[instr.flow_control.dest_offset] - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OpCode::Id::JMPU:
|
||||
if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
state.program_counter = &shader_memory[instr.flow_control.dest_offset] - 1;
|
||||
if (uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
state.program_counter = &program_code[instr.flow_control.dest_offset] - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -489,7 +445,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
break;
|
||||
|
||||
case OpCode::Id::CALLU:
|
||||
if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
if (uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
call(state,
|
||||
instr.flow_control.dest_offset,
|
||||
instr.flow_control.num_instructions,
|
||||
|
@ -510,7 +466,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
break;
|
||||
|
||||
case OpCode::Id::IFU:
|
||||
if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
if (uniforms.b[instr.flow_control.bool_uniform_id]) {
|
||||
call(state,
|
||||
binary_offset + 1,
|
||||
instr.flow_control.dest_offset - binary_offset - 1,
|
||||
|
@ -545,14 +501,14 @@ static void ProcessShaderCode(VertexShaderState& state) {
|
|||
|
||||
case OpCode::Id::LOOP:
|
||||
{
|
||||
state.address_registers[2] = shader_uniforms.i[instr.flow_control.int_uniform_id].y;
|
||||
state.address_registers[2] = uniforms.i[instr.flow_control.int_uniform_id].y;
|
||||
|
||||
call(state,
|
||||
binary_offset + 1,
|
||||
instr.flow_control.dest_offset - binary_offset + 1,
|
||||
instr.flow_control.dest_offset + 1,
|
||||
shader_uniforms.i[instr.flow_control.int_uniform_id].x,
|
||||
shader_uniforms.i[instr.flow_control.int_uniform_id].z);
|
||||
uniforms.i[instr.flow_control.int_uniform_id].x,
|
||||
uniforms.i[instr.flow_control.int_uniform_id].z);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -578,15 +534,17 @@ static Common::Profiling::TimingCategory shader_category("Vertex Shader");
|
|||
OutputVertex RunShader(const InputVertex& input, int num_attributes) {
|
||||
Common::Profiling::ScopeTimer timer(shader_category);
|
||||
|
||||
const auto& regs = g_state.regs;
|
||||
const auto& vs = g_state.vs;
|
||||
VertexShaderState state;
|
||||
|
||||
const u32* main = &shader_memory[registers.vs_main_offset];
|
||||
const u32* main = &vs.program_code[regs.vs_main_offset];
|
||||
state.program_counter = (u32*)main;
|
||||
state.debug.max_offset = 0;
|
||||
state.debug.max_opdesc_id = 0;
|
||||
|
||||
// Setup input register table
|
||||
const auto& attribute_register_map = registers.vs_input_register_map;
|
||||
const auto& attribute_register_map = regs.vs_input_register_map;
|
||||
float24 dummy_register;
|
||||
boost::fill(state.input_register_table, &dummy_register);
|
||||
|
||||
|
@ -611,16 +569,16 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes) {
|
|||
state.conditional_code[1] = false;
|
||||
|
||||
ProcessShaderCode(state);
|
||||
DebugUtils::DumpShader(shader_memory.data(), state.debug.max_offset, swizzle_data.data(),
|
||||
state.debug.max_opdesc_id, registers.vs_main_offset,
|
||||
registers.vs_output_attributes);
|
||||
DebugUtils::DumpShader(vs.program_code.data(), state.debug.max_offset, vs.swizzle_data.data(),
|
||||
state.debug.max_opdesc_id, regs.vs_main_offset,
|
||||
regs.vs_output_attributes);
|
||||
|
||||
// Setup output data
|
||||
OutputVertex ret;
|
||||
// TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to
|
||||
// figure out what those circumstances are and enable the remaining outputs then.
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
const auto& output_register_map = registers.vs_output_attributes[i];
|
||||
const auto& output_register_map = regs.vs_output_attributes[i];
|
||||
|
||||
u32 semantics[4] = {
|
||||
output_register_map.map_x, output_register_map.map_y,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue