diff options
Diffstat (limited to 'src/video_core/vertex_shader.cpp')
-rw-r--r-- | src/video_core/vertex_shader.cpp | 96 |
1 files changed, 27 insertions, 69 deletions
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index 981d1a356..7d68998f1 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp @@ -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, |