diff --git a/src/xenia/gpu/gl4/draw_batcher.cc b/src/xenia/gpu/gl4/draw_batcher.cc index b86ed1ba3..d69ac7dad 100644 --- a/src/xenia/gpu/gl4/draw_batcher.cc +++ b/src/xenia/gpu/gl4/draw_batcher.cc @@ -195,6 +195,7 @@ bool DrawBatcher::BeginDraw() { auto state_host_ptr = reinterpret_cast(active_draw_.state_allocation.host_ptr); active_draw_.header = reinterpret_cast(state_host_ptr); + active_draw_.header->ps_param_gen = -1; // active_draw_.float_consts = // reinterpret_cast(state_host_ptr + // batch_state_.float_consts_offset); diff --git a/src/xenia/gpu/gl4/draw_batcher.h b/src/xenia/gpu/gl4/draw_batcher.h index 5c83d73e1..c62542194 100644 --- a/src/xenia/gpu/gl4/draw_batcher.h +++ b/src/xenia/gpu/gl4/draw_batcher.h @@ -75,6 +75,9 @@ class DrawBatcher { active_draw_.header->alpha_test.y = static_cast(func); active_draw_.header->alpha_test.z = ref; } + void set_ps_param_gen(int register_index) { + active_draw_.header->ps_param_gen = register_index; + } void set_texture_sampler(int index, GLuint64 handle) { active_draw_.header->texture_samplers[index] = handle; } @@ -132,6 +135,8 @@ class DrawBatcher { float4 window_scale; // sx,sy, ?, ? float4 vtx_fmt; // float4 alpha_test; // alpha test enable, func, ref, ? + int ps_param_gen; + int padding[3]; // TODO(benvanik): pack tightly GLuint64 texture_samplers[32]; diff --git a/src/xenia/gpu/gl4/gl4_command_processor.cc b/src/xenia/gpu/gl4/gl4_command_processor.cc index e71753642..a2c1d7a13 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.cc +++ b/src/xenia/gpu/gl4/gl4_command_processor.cc @@ -623,6 +623,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders( dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, XE_GPU_REG_PA_SU_SC_MODE_CNTL); dirty |= SetShadowRegister(®s.sq_program_cntl, XE_GPU_REG_SQ_PROGRAM_CNTL); + dirty |= SetShadowRegister(®s.sq_context_misc, XE_GPU_REG_SQ_CONTEXT_MISC); dirty |= regs.vertex_shader != active_vertex_shader_; dirty |= regs.pixel_shader != active_pixel_shader_; dirty |= regs.prim_type != prim_type; @@ -640,6 +641,10 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders( xe_gpu_program_cntl_t program_cntl; program_cntl.dword_0 = regs.sq_program_cntl; + // Populate a register in the pixel shader with frag coord. + int ps_param_gen = (regs.sq_context_misc >> 8) & 0xFF; + draw_batcher_.set_ps_param_gen(program_cntl.param_gen ? ps_param_gen : -1); + // Normal vertex shaders only, for now. // TODO(benvanik): transform feedback/memexport. // 0 = normal diff --git a/src/xenia/gpu/gl4/gl4_command_processor.h b/src/xenia/gpu/gl4/gl4_command_processor.h index f113d8673..c92a1dc66 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.h +++ b/src/xenia/gpu/gl4/gl4_command_processor.h @@ -213,6 +213,7 @@ class GL4CommandProcessor : public CommandProcessor { PrimitiveType prim_type; uint32_t pa_su_sc_mode_cntl; uint32_t sq_program_cntl; + uint32_t sq_context_misc; GL4Shader* vertex_shader; GL4Shader* pixel_shader; diff --git a/src/xenia/gpu/glsl_shader_translator.cc b/src/xenia/gpu/glsl_shader_translator.cc index 8394db959..3f20b8b20 100644 --- a/src/xenia/gpu/glsl_shader_translator.cc +++ b/src/xenia/gpu/glsl_shader_translator.cc @@ -111,6 +111,8 @@ struct StateData { vec4 window_scale; vec4 vtx_fmt; vec4 alpha_test; + int ps_param_gen; + int padding[3]; // TODO(benvanik): variable length. uvec2 texture_samplers[32]; vec4 float_consts[512]; @@ -270,17 +272,8 @@ void main() { // Enter the main function, where all of our shader lives. if (is_vertex_shader()) { EmitSource("void processVertex(const in StateData state) {\n"); - - // Temporary registers. - EmitSource(" vec4 r[64];\n"); } else { EmitSource("void processFragment(const in StateData state) {\n"); - - // Bring interpolators from vertex shader into temporary registers. - EmitSource(" vec4 r[64];\n"); - for (int i = 0; i < kMaxInterpolators; ++i) { - EmitSource(" r[%d] = vtx.o[%d];\n", i, i); - } } // Previous Vector result (used as a scratch). @@ -301,6 +294,22 @@ void main() { EmitSource(" vec4 src1;\n"); EmitSource(" vec4 src2;\n"); + // Temporary registers. + if (is_vertex_shader()) { + EmitSource(" vec4 r[64];\n"); + } else { + // Bring interpolators from vertex shader into temporary registers. + EmitSource(" vec4 r[64];\n"); + for (int i = 0; i < kMaxInterpolators; ++i) { + EmitSource(" r[%d] = vtx.o[%d];\n", i, i); + } + EmitSource(" if (state.ps_param_gen != -1) {\n"); + EmitSource(" pv = vec4(gl_FragCoord.xy, gl_PointCoord.xy);\n"); + EmitSource(" pv.x *= (gl_FrontFacing ? 1.0 : -1.0);\n"); + EmitSource(" r[state.ps_param_gen] = pv;\n"); + EmitSource(" }\n"); + } + // Master loop and switch for flow control. EmitSourceDepth("int pc = 0;\n"); EmitSourceDepth("while (pc != 0xFFFF) {\n");