diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 0081c8eb6..5c4c04408 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -358,6 +358,8 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { break; } + VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id); + if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast(&id)); } diff --git a/src/video_core/hwrasterizer_base.h b/src/video_core/hwrasterizer_base.h index 08e77562b..8a16db5b6 100644 --- a/src/video_core/hwrasterizer_base.h +++ b/src/video_core/hwrasterizer_base.h @@ -23,9 +23,12 @@ public: /// Draw the current batch of triangles virtual void DrawTriangles() = 0; + /// Notify rasterizer that the specified PICA register has been changed + virtual void NotifyPicaRegisterChanged(u32 id) = 0; + /// Notify rasterizer that the specified 3DS memory region will be read from after this notification - virtual void NotifyPreRead(u32 paddr, u32 size) = 0; + virtual void NotifyPreRead(PAddr addr, u32 size) = 0; /// Notify rasterizer that a 3DS memory region has been changed - virtual void NotifyFlush(u32 addr, u32 size) = 0; + virtual void NotifyFlush(PAddr addr, u32 size) = 0; }; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 0f5102a35..fc7023c95 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -17,6 +17,17 @@ #include +static bool IsNotPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) { + return (stage.color_op != Pica::Regs::TevStageConfig::Operation::Replace || + stage.alpha_op != Pica::Regs::TevStageConfig::Operation::Replace || + stage.color_source1 != Pica::Regs::TevStageConfig::Source::Previous || + stage.alpha_source1 != Pica::Regs::TevStageConfig::Source::Previous || + stage.color_modifier1 != Pica::Regs::TevStageConfig::ColorModifier::SourceColor || + stage.alpha_modifier1 != Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha || + stage.GetColorMultiplier() != 1 || + stage.GetAlphaMultiplier() != 1); +} + RasterizerOpenGL::RasterizerOpenGL() : last_fb_color_addr(0), last_fb_depth_addr(0) { } @@ -32,6 +43,7 @@ void RasterizerOpenGL::InitObjects() { attrib_color = glGetAttribLocation(shader.GetHandle(), "vert_color"); attrib_texcoords = glGetAttribLocation(shader.GetHandle(), "vert_texcoords"); + uniform_alphatest_enabled = glGetUniformLocation(shader.GetHandle(), "alphatest_enabled"); uniform_alphatest_func = glGetUniformLocation(shader.GetHandle(), "alphatest_func"); uniform_alphatest_ref = glGetUniformLocation(shader.GetHandle(), "alphatest_ref"); @@ -54,8 +66,6 @@ void RasterizerOpenGL::InitObjects() { uniform_tev.updates_combiner_buffer_color_alpha = glGetUniformLocation(shader.GetHandle(), (tev_ref_str + ".updates_combiner_buffer_color_alpha").c_str()); } - uniform_out_maps = glGetUniformLocation(shader.GetHandle(), "out_maps"); - // Generate VBO and VAO vertex_buffer.Create(); vertex_array.Create(); @@ -132,8 +142,6 @@ void RasterizerOpenGL::AddTriangle(const Pica::VertexShader::OutputVertex& v0, } void RasterizerOpenGL::DrawTriangles() { - state.Apply(); - SyncFramebuffer(); SyncDrawState(); @@ -143,11 +151,224 @@ void RasterizerOpenGL::DrawTriangles() { vertex_batch.clear(); } -void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) { +void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { if (!Settings::values.use_hw_renderer) return; - state.Apply(); + switch(id) { + // Culling + case PICA_REG_INDEX(cull_mode): + { + switch (Pica::registers.cull_mode) { + case Pica::Regs::CullMode::KeepAll: + state.cull.enabled = false; + break; + + case Pica::Regs::CullMode::KeepClockWise: + state.cull.enabled = true; + state.cull.mode = GL_BACK; + break; + + case Pica::Regs::CullMode::KeepCounterClockWise: + state.cull.enabled = true; + state.cull.mode = GL_FRONT; + break; + + default: + LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", Pica::registers.cull_mode.Value()); + UNIMPLEMENTED(); + break; + } + break; + } + + // Blending + case PICA_REG_INDEX(output_merger.alphablend_enable): + { + state.blend.enabled = Pica::registers.output_merger.alphablend_enable; + break; + } + case PICA_REG_INDEX(output_merger.alpha_blending): + { + state.blend.src_rgb_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_source_rgb); + state.blend.dst_rgb_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_dest_rgb); + state.blend.src_a_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_source_a); + state.blend.dst_a_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_dest_a); + break; + } + case PICA_REG_INDEX(output_merger.blend_const): + { + state.blend.color.red = (GLclampf)Pica::registers.output_merger.blend_const.r / 255.0f; + state.blend.color.green = (GLclampf)Pica::registers.output_merger.blend_const.g / 255.0f; + state.blend.color.blue = (GLclampf)Pica::registers.output_merger.blend_const.b / 255.0f; + state.blend.color.alpha = (GLclampf)Pica::registers.output_merger.blend_const.a / 255.0f; + break; + } + + // Alpha test + case PICA_REG_INDEX(output_merger.alpha_test): + { + glUniform1i(uniform_alphatest_enabled, Pica::registers.output_merger.alpha_test.enable); + glUniform1i(uniform_alphatest_func, Pica::registers.output_merger.alpha_test.func); + glUniform1f(uniform_alphatest_ref, Pica::registers.output_merger.alpha_test.ref / 255.0f); + break; + } + + // Stencil test + case PICA_REG_INDEX(output_merger.stencil_test): + { + // TODO: Implement stencil test, mask, and op + break; + } + + // Depth test + case PICA_REG_INDEX(output_merger.depth_test_enable): + { + state.depth.test_enabled = Pica::registers.output_merger.depth_test_enable; + state.depth.test_func = PicaToGL::CompareFunc(Pica::registers.output_merger.depth_test_func); + + if (Pica::registers.output_merger.depth_write_enable) { + state.depth.write_mask = GL_TRUE; + } else { + state.depth.write_mask = GL_FALSE; + } + + break; + } + + // TEV stage 0 + case PICA_REG_INDEX(tev_stage0.color_source1): + SyncTevSources(0, Pica::registers.tev_stage0); + break; + case PICA_REG_INDEX(tev_stage0.color_modifier1): + SyncTevModifiers(0, Pica::registers.tev_stage0); + break; + case PICA_REG_INDEX(tev_stage0.color_op): + SyncTevOps(0, Pica::registers.tev_stage0); + break; + case PICA_REG_INDEX(tev_stage0.const_r): + SyncTevColor(0, Pica::registers.tev_stage0); + break; + case PICA_REG_INDEX(tev_stage0.color_scale): + SyncTevMultipliers(0, Pica::registers.tev_stage0); + break; + + // TEV stage 1 + case PICA_REG_INDEX(tev_stage1.color_source1): + SyncTevSources(1, Pica::registers.tev_stage1); + break; + case PICA_REG_INDEX(tev_stage1.color_modifier1): + SyncTevModifiers(1, Pica::registers.tev_stage1); + break; + case PICA_REG_INDEX(tev_stage1.color_op): + SyncTevOps(1, Pica::registers.tev_stage1); + break; + case PICA_REG_INDEX(tev_stage1.const_r): + SyncTevColor(1, Pica::registers.tev_stage1); + break; + case PICA_REG_INDEX(tev_stage1.color_scale): + SyncTevMultipliers(1, Pica::registers.tev_stage1); + break; + + // TEV stage 2 + case PICA_REG_INDEX(tev_stage2.color_source1): + SyncTevSources(2, Pica::registers.tev_stage2); + break; + case PICA_REG_INDEX(tev_stage2.color_modifier1): + SyncTevModifiers(2, Pica::registers.tev_stage2); + break; + case PICA_REG_INDEX(tev_stage2.color_op): + SyncTevOps(2, Pica::registers.tev_stage2); + break; + case PICA_REG_INDEX(tev_stage2.const_r): + SyncTevColor(2, Pica::registers.tev_stage2); + break; + case PICA_REG_INDEX(tev_stage2.color_scale): + SyncTevMultipliers(2, Pica::registers.tev_stage2); + break; + + // TEV stage 3 + case PICA_REG_INDEX(tev_stage3.color_source1): + SyncTevSources(3, Pica::registers.tev_stage3); + break; + case PICA_REG_INDEX(tev_stage3.color_modifier1): + SyncTevModifiers(3, Pica::registers.tev_stage3); + break; + case PICA_REG_INDEX(tev_stage3.color_op): + SyncTevOps(3, Pica::registers.tev_stage3); + break; + case PICA_REG_INDEX(tev_stage3.const_r): + SyncTevColor(3, Pica::registers.tev_stage3); + break; + case PICA_REG_INDEX(tev_stage3.color_scale): + SyncTevMultipliers(3, Pica::registers.tev_stage3); + break; + + // TEV stage 4 + case PICA_REG_INDEX(tev_stage4.color_source1): + SyncTevSources(4, Pica::registers.tev_stage4); + break; + case PICA_REG_INDEX(tev_stage4.color_modifier1): + SyncTevModifiers(4, Pica::registers.tev_stage4); + break; + case PICA_REG_INDEX(tev_stage4.color_op): + SyncTevOps(4, Pica::registers.tev_stage4); + break; + case PICA_REG_INDEX(tev_stage4.const_r): + SyncTevColor(4, Pica::registers.tev_stage4); + break; + case PICA_REG_INDEX(tev_stage4.color_scale): + SyncTevMultipliers(4, Pica::registers.tev_stage4); + break; + + // TEV stage 5 + case PICA_REG_INDEX(tev_stage5.color_source1): + SyncTevSources(5, Pica::registers.tev_stage5); + break; + case PICA_REG_INDEX(tev_stage5.color_modifier1): + SyncTevModifiers(5, Pica::registers.tev_stage5); + break; + case PICA_REG_INDEX(tev_stage5.color_op): + SyncTevOps(5, Pica::registers.tev_stage5); + break; + case PICA_REG_INDEX(tev_stage5.const_r): + SyncTevColor(5, Pica::registers.tev_stage5); + break; + case PICA_REG_INDEX(tev_stage5.color_scale): + SyncTevMultipliers(5, Pica::registers.tev_stage5); + break; + + // TEV combiner buffer color + case PICA_REG_INDEX(tev_combiner_buffer_color): + { + GLfloat combiner_color[4] = { Pica::registers.tev_combiner_buffer_color.r / 255.0f, + Pica::registers.tev_combiner_buffer_color.g / 255.0f, + Pica::registers.tev_combiner_buffer_color.b / 255.0f, + Pica::registers.tev_combiner_buffer_color.a / 255.0f }; + + glUniform4fv(uniform_tev_combiner_buffer_color, 1, combiner_color); + break; + } + + // TEV combiner buffer write flags + case PICA_REG_INDEX(tev_combiner_buffer_input): + { + for (int tev_stage_idx = 0; tev_stage_idx < 6; ++tev_stage_idx) { + glUniform2i(uniform_tev_cfgs[tev_stage_idx].updates_combiner_buffer_color_alpha, + Pica::registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(tev_stage_idx), + Pica::registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(tev_stage_idx)); + } + break; + } + + default: + break; + } +} + +void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) { + if (!Settings::values.use_hw_renderer) + return; PAddr cur_fb_color_addr = Pica::registers.framebuffer.GetColorBufferPhysicalAddress(); u32 cur_fb_color_size = Pica::registers.framebuffer.BytesPerColorPixel(Pica::registers.framebuffer.color_format) @@ -177,8 +398,6 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) { if (!Settings::values.use_hw_renderer) return; - state.Apply(); - PAddr cur_fb_color_addr = Pica::registers.framebuffer.GetColorBufferPhysicalAddress(); u32 cur_fb_color_size = Pica::registers.framebuffer.BytesPerColorPixel(Pica::registers.framebuffer.color_format) * Pica::registers.framebuffer.GetWidth() * Pica::registers.framebuffer.GetHeight(); @@ -361,6 +580,47 @@ void RasterizerOpenGL::SyncFramebuffer() { } } +void RasterizerOpenGL::SyncTevSources(int stage_index, const Pica::Regs::TevStageConfig& config) { + GLint color_srcs[3] = { (GLint)config.color_source1.Value(), + (GLint)config.color_source2.Value(), + (GLint)config.color_source3.Value() }; + GLint alpha_srcs[3] = { (GLint)config.alpha_source1.Value(), + (GLint)config.alpha_source2.Value(), + (GLint)config.alpha_source3.Value() }; + + glUniform3iv(uniform_tev_cfgs[stage_index].color_sources, 1, color_srcs); + glUniform3iv(uniform_tev_cfgs[stage_index].alpha_sources, 1, alpha_srcs); +} + +void RasterizerOpenGL::SyncTevModifiers(int stage_index, const Pica::Regs::TevStageConfig& config) { + GLint color_mods[3] = { (GLint)config.color_modifier1.Value(), + (GLint)config.color_modifier2.Value(), + (GLint)config.color_modifier3.Value() }; + GLint alpha_mods[3] = { (GLint)config.alpha_modifier1.Value(), + (GLint)config.alpha_modifier2.Value(), + (GLint)config.alpha_modifier3.Value() }; + + glUniform3iv(uniform_tev_cfgs[stage_index].color_modifiers, 1, color_mods); + glUniform3iv(uniform_tev_cfgs[stage_index].alpha_modifiers, 1, alpha_mods); +} + +void RasterizerOpenGL::SyncTevOps(int stage_index, const Pica::Regs::TevStageConfig& config) { + glUniform2i(uniform_tev_cfgs[stage_index].color_alpha_op, (GLint)config.color_op.Value(), (GLint)config.alpha_op.Value()); +} + +void RasterizerOpenGL::SyncTevColor(int stage_index, const Pica::Regs::TevStageConfig& config) { + GLfloat const_color[4] = { config.const_r / 255.0f, + config.const_g / 255.0f, + config.const_b / 255.0f, + config.const_a / 255.0f }; + + glUniform4fv(uniform_tev_cfgs[stage_index].const_color, 1, const_color); +} + +void RasterizerOpenGL::SyncTevMultipliers(int stage_index, const Pica::Regs::TevStageConfig& config) { + glUniform2i(uniform_tev_cfgs[stage_index].color_alpha_multiplier, config.GetColorMultiplier(), config.GetAlphaMultiplier()); +} + void RasterizerOpenGL::SyncDrawState() { // Sync the viewport GLsizei viewport_width = (GLsizei)Pica::float24::FromRawFloat24(Pica::registers.viewport_size_x).ToFloat32() * 2; @@ -373,63 +633,7 @@ void RasterizerOpenGL::SyncDrawState() { + Pica::registers.framebuffer.GetHeight() - viewport_height, viewport_width, viewport_height); - // Sync the cull mode - switch (Pica::registers.cull_mode) { - case Pica::Regs::CullMode::KeepAll: - state.cull.enabled = false; - break; - - case Pica::Regs::CullMode::KeepClockWise: - state.cull.enabled = true; - state.cull.mode = GL_BACK; - break; - - case Pica::Regs::CullMode::KeepCounterClockWise: - state.cull.enabled = true; - state.cull.mode = GL_FRONT; - break; - - default: - LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", Pica::registers.cull_mode.Value()); - UNIMPLEMENTED(); - break; - } - - // Sync depth test - if (Pica::registers.output_merger.depth_test_enable) { - state.depth.test_enabled = true; - state.depth.test_func = PicaToGL::CompareFunc(Pica::registers.output_merger.depth_test_func); - } else { - state.depth.test_enabled = false; - } - - // Sync depth writing - if (Pica::registers.output_merger.depth_write_enable) { - state.depth.write_mask = GL_TRUE; - } else { - state.depth.write_mask = GL_FALSE; - } - - // TODO: Implement stencil test, mask, and op via: state.stencil.* = Pica::registers.output_merger.stencil_test.* - - // Sync blend state - if (Pica::registers.output_merger.alphablend_enable) { - state.blend.enabled = true; - - state.blend.color.red = (GLclampf)Pica::registers.output_merger.blend_const.r / 255.0f; - state.blend.color.green = (GLclampf)Pica::registers.output_merger.blend_const.g / 255.0f; - state.blend.color.blue = (GLclampf)Pica::registers.output_merger.blend_const.b / 255.0f; - state.blend.color.alpha = (GLclampf)Pica::registers.output_merger.blend_const.a / 255.0f; - - state.blend.src_rgb_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_source_rgb); - state.blend.dst_rgb_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_dest_rgb); - state.blend.src_a_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_source_a); - state.blend.dst_a_func = PicaToGL::BlendFunc(Pica::registers.output_merger.alpha_blending.factor_dest_a); - } else { - state.blend.enabled = false; - } - - // Sync bound texture(s), upload if uncached + // Sync bound texture(s), upload if not cached const auto pica_textures = Pica::registers.GetTextures(); for (int i = 0; i < 3; ++i) { @@ -443,84 +647,13 @@ void RasterizerOpenGL::SyncDrawState() { } } - state.Apply(); - - // Sync shader output register mapping to hw shader - 7 vectors with 4 components - for (int i = 0; i < 7 * 4; ++i) { - glUniform1i(uniform_out_maps + i, 0); - } - - for (int i = 0; i < 7; ++i) { - const auto& output_register_map = Pica::registers.vs_output_attributes[i]; - - u32 semantics[4] = { - output_register_map.map_x, output_register_map.map_y, - output_register_map.map_z, output_register_map.map_w - }; - - // TODO: Might only need to do this once per shader? Not sure when/if out maps are modified. - for (int comp = 0; comp < 4; ++comp) { - if (semantics[comp] != Pica::Regs::VSOutputAttributes::INVALID) { - glUniform1i(uniform_out_maps + semantics[comp], 4 * i + comp); - } - } - } - - // Sync intial combiner buffer color - GLfloat initial_combiner_color[4] = { Pica::registers.tev_combiner_buffer_color.r / 255.0f, - Pica::registers.tev_combiner_buffer_color.g / 255.0f, - Pica::registers.tev_combiner_buffer_color.b / 255.0f, - Pica::registers.tev_combiner_buffer_color.a / 255.0f }; - - glUniform4fv(uniform_tev_combiner_buffer_color, 1, initial_combiner_color); - - // Sync texture environment configurations to hw shader + // Skip processing TEV stages that simply pass the previous stage results through const auto tev_stages = Pica::registers.GetTevStages(); for (unsigned tev_stage_idx = 0; tev_stage_idx < tev_stages.size(); ++tev_stage_idx) { - const auto& stage = tev_stages[tev_stage_idx]; - const auto& uniform_tev_cfg = uniform_tev_cfgs[tev_stage_idx]; - - // No need to process the tev stage if it simply passes the previous stage results through - if (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace && - stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace && - stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous && - stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous && - stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor && - stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha && - stage.GetColorMultiplier() == 1 && - stage.GetAlphaMultiplier() == 1) { - glUniform1i(uniform_tev_cfg.enabled, 0); - } else { - GLint color_srcs[3] = { (GLint)stage.color_source1.Value(), (GLint)stage.color_source2.Value(), (GLint)stage.color_source3.Value() }; - GLint alpha_srcs[3] = { (GLint)stage.alpha_source1.Value(), (GLint)stage.alpha_source2.Value(), (GLint)stage.alpha_source3.Value() }; - GLint color_mods[3] = { (GLint)stage.color_modifier1.Value(), (GLint)stage.color_modifier2.Value(), (GLint)stage.color_modifier3.Value() }; - GLint alpha_mods[3] = { (GLint)stage.alpha_modifier1.Value(), (GLint)stage.alpha_modifier2.Value(), (GLint)stage.alpha_modifier3.Value() }; - GLfloat const_color[4] = { stage.const_r / 255.0f, - stage.const_g / 255.0f, - stage.const_b / 255.0f, - stage.const_a / 255.0f }; - - glUniform1i(uniform_tev_cfg.enabled, 1); - glUniform3iv(uniform_tev_cfg.color_sources, 1, color_srcs); - glUniform3iv(uniform_tev_cfg.alpha_sources, 1, alpha_srcs); - glUniform3iv(uniform_tev_cfg.color_modifiers, 1, color_mods); - glUniform3iv(uniform_tev_cfg.alpha_modifiers, 1, alpha_mods); - glUniform2i(uniform_tev_cfg.color_alpha_op, (GLint)stage.color_op.Value(), (GLint)stage.alpha_op.Value()); - glUniform2i(uniform_tev_cfg.color_alpha_multiplier, stage.GetColorMultiplier(), stage.GetAlphaMultiplier()); - glUniform4fv(uniform_tev_cfg.const_color, 1, const_color); - glUniform2i(uniform_tev_cfg.updates_combiner_buffer_color_alpha, - Pica::registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(tev_stage_idx), - Pica::registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(tev_stage_idx)); - } + glUniform1i(uniform_tev_cfgs[tev_stage_idx].enabled, IsNotPassThroughTevStage(tev_stages[tev_stage_idx])); } - // Sync alpha testing to hw shader - if (Pica::registers.output_merger.alpha_test.enable) { - glUniform1i(uniform_alphatest_func, Pica::registers.output_merger.alpha_test.func); - glUniform1f(uniform_alphatest_ref, Pica::registers.output_merger.alpha_test.ref / 255.0f); - } else { - glUniform1i(uniform_alphatest_func, Pica::registers.output_merger.Always); - } + state.Apply(); } void RasterizerOpenGL::ReloadColorBuffer() { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 4cf8dc0fc..60cc1f265 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -26,6 +26,9 @@ public: /// Draw the current batch of triangles void DrawTriangles() override; + /// Notify rasterizer that the specified PICA register has been changed + void NotifyPicaRegisterChanged(u32 id) override; + /// Notify rasterizer that the specified 3DS memory region will be read from after this notification void NotifyPreRead(PAddr addr, u32 size) override; @@ -101,7 +104,22 @@ private: /// Syncs the state and contents of the OpenGL framebuffer to match the current PICA framebuffer void SyncFramebuffer(); - /// Syncs the OpenGL drawing state to match the current PICA state + /// Syncs the specified TEV stage's color and alpha sources to match the PICA register + void SyncTevSources(int stage_index, const Pica::Regs::TevStageConfig& config); + + /// Syncs the specified TEV stage's color and alpha modifiers to match the PICA register + void SyncTevModifiers(int stage_index, const Pica::Regs::TevStageConfig& config); + + /// Syncs the specified TEV stage's color and alpha combiner operations to match the PICA register + void SyncTevOps(int stage_index, const Pica::Regs::TevStageConfig& config); + + /// Syncs the specified TEV stage's constant color to match the PICA register + void SyncTevColor(int stage_index, const Pica::Regs::TevStageConfig& config); + + /// Syncs the specified TEV stage's color and alpha multipliers to match the PICA register + void SyncTevMultipliers(int stage_index, const Pica::Regs::TevStageConfig& config); + + /// Syncs the remaining OpenGL drawing state to match the current PICA state void SyncDrawState(); /// Copies the 3ds color framebuffer into the OpenGL color framebuffer texture @@ -147,11 +165,10 @@ private: GLuint attrib_texcoords; // Hardware fragment shader + GLuint uniform_alphatest_enabled; GLuint uniform_alphatest_func; GLuint uniform_alphatest_ref; GLuint uniform_tex; GLuint uniform_tev_combiner_buffer_color; TEVConfigUniforms uniform_tev_cfgs[6]; - GLuint uniform_out_maps; - GLuint uniform_tex_envs; }; diff --git a/src/video_core/renderer_opengl/gl_shaders.h b/src/video_core/renderer_opengl/gl_shaders.h index 3527f8601..8f0941230 100644 --- a/src/video_core/renderer_opengl/gl_shaders.h +++ b/src/video_core/renderer_opengl/gl_shaders.h @@ -53,25 +53,10 @@ in vec2 vert_texcoords[3]; out vec4 o[NUM_VTX_ATTR]; -uniform int out_maps[NUM_VTX_ATTR * 4]; - -void SetVal(int map_idx, float val) { - o[out_maps[map_idx] / 4][out_maps[map_idx] % 4] = val; -} - void main() { - SetVal(8, vert_color.x); - SetVal(9, vert_color.y); - SetVal(10, vert_color.z); - SetVal(11, vert_color.w); - SetVal(12, vert_texcoords[0].x); - SetVal(13, vert_texcoords[0].y); - - // TODO: These seem like the wrong map indices - SetVal(14, vert_texcoords[1].x); - SetVal(15, vert_texcoords[1].y); - SetVal(16, vert_texcoords[2].x); - SetVal(17, vert_texcoords[2].y); + o[2] = vert_color; + o[3] = vec4(vert_texcoords[0].xy, vert_texcoords[1].xy); + o[5] = vec4(0.0, 0.0, vert_texcoords[2].xy); gl_Position = vec4(vert_position.x, -vert_position.y, -vert_position.z, vert_position.w); } @@ -81,8 +66,8 @@ void main() { const char g_fragment_shader_hw[] = R"( #version 150 core -#define NUM_TEV_STAGES 6 #define NUM_VTX_ATTR 7 +#define NUM_TEV_STAGES 6 #define SOURCE_PRIMARYCOLOR 0x0 #define SOURCE_PRIMARYFRAGMENTCOLOR 0x1 @@ -135,6 +120,7 @@ const char g_fragment_shader_hw[] = R"( in vec4 o[NUM_VTX_ATTR]; out vec4 color; +uniform bool alphatest_enabled; uniform int alphatest_func; uniform float alphatest_ref; @@ -157,31 +143,23 @@ struct TEVConfig uniform TEVConfig tev_cfgs[NUM_TEV_STAGES]; -uniform int out_maps[NUM_VTX_ATTR * 4]; - vec4 g_combiner_buffer; vec4 g_last_tex_env_out; vec4 g_const_color; -float GetVal(int map_idx) { - return o[out_maps[map_idx] / 4][out_maps[map_idx] % 4]; -} - vec4 GetSource(int source) { if (source == SOURCE_PRIMARYCOLOR) { - // HACK: Should use values 8/9/10/11 but hurts framerate - // Hack assumes 9/10/11 follow directly after 8's map - return o[out_maps[8] >> 2]; + return o[2]; } else if (source == SOURCE_PRIMARYFRAGMENTCOLOR) { // HACK: Uses color value, but should really use fragment lighting output - return o[out_maps[8] >> 2]; + return o[2]; } else if (source == SOURCE_TEXTURE0) { - return texture(tex[0], vec2(GetVal(12), GetVal(13))); + return texture(tex[0], o[3].xy); } else if (source == SOURCE_TEXTURE1) { - return texture(tex[1], vec2(GetVal(14), GetVal(15))); + return texture(tex[1], o[3].zw); } else if (source == SOURCE_TEXTURE2) { // TODO: Unverified - return texture(tex[2], vec2(GetVal(16), GetVal(17))); + return texture(tex[2], o[5].zw); } else if (source == SOURCE_TEXTURE3) { // TODO: no 4th texture? } else if (source == SOURCE_PREVIOUSBUFFER) { @@ -316,33 +294,35 @@ void main(void) { } } - if (alphatest_func == COMPAREFUNC_NEVER) { - discard; - } else if (alphatest_func == COMPAREFUNC_ALWAYS) { + if (alphatest_enabled) { + if (alphatest_func == COMPAREFUNC_NEVER) { + discard; + } else if (alphatest_func == COMPAREFUNC_ALWAYS) { - } else if (alphatest_func == COMPAREFUNC_EQUAL) { - if (g_last_tex_env_out.a != alphatest_ref) { - discard; - } - } else if (alphatest_func == COMPAREFUNC_NOTEQUAL) { - if (g_last_tex_env_out.a == alphatest_ref) { - discard; - } - } else if (alphatest_func == COMPAREFUNC_LESSTHAN) { - if (g_last_tex_env_out.a >= alphatest_ref) { - discard; - } - } else if (alphatest_func == COMPAREFUNC_LESSTHANOREQUAL) { - if (g_last_tex_env_out.a > alphatest_ref) { - discard; - } - } else if (alphatest_func == COMPAREFUNC_GREATERTHAN) { - if (g_last_tex_env_out.a <= alphatest_ref) { - discard; - } - } else if (alphatest_func == COMPAREFUNC_GREATERTHANOREQUAL) { - if (g_last_tex_env_out.a < alphatest_ref) { - discard; + } else if (alphatest_func == COMPAREFUNC_EQUAL) { + if (g_last_tex_env_out.a != alphatest_ref) { + discard; + } + } else if (alphatest_func == COMPAREFUNC_NOTEQUAL) { + if (g_last_tex_env_out.a == alphatest_ref) { + discard; + } + } else if (alphatest_func == COMPAREFUNC_LESSTHAN) { + if (g_last_tex_env_out.a >= alphatest_ref) { + discard; + } + } else if (alphatest_func == COMPAREFUNC_LESSTHANOREQUAL) { + if (g_last_tex_env_out.a > alphatest_ref) { + discard; + } + } else if (alphatest_func == COMPAREFUNC_GREATERTHAN) { + if (g_last_tex_env_out.a <= alphatest_ref) { + discard; + } + } else if (alphatest_func == COMPAREFUNC_GREATERTHANOREQUAL) { + if (g_last_tex_env_out.a < alphatest_ref) { + discard; + } } } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8b48f80d9..1258e81cf 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -67,6 +67,7 @@ RendererOpenGL::~RendererOpenGL() { void RendererOpenGL::SwapBuffers() { render_window->MakeCurrent(); + OpenGLState prev_state = OpenGLState::GetCurState(); state.Apply(); for(int i : {0, 1}) { @@ -114,6 +115,8 @@ void RendererOpenGL::SwapBuffers() { render_window->PollEvents(); render_window->SwapBuffers(); + prev_state.Apply(); + profiler.BeginFrame(); }