diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index fd202abf12..d72a7872a2 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -210,10 +210,34 @@ namespace vk } } + struct vertex_input_assembly_state + { + VkPrimitiveTopology primitive; + VkBool32 restart_index_enabled; + }; + + vertex_input_assembly_state decode_vertex_input_assembly_state() + { + vertex_input_assembly_state state{}; + const auto& current_draw = rsx::method_registers.current_draw_clause; + const auto [primitive, emulated_primitive] = vk::get_appropriate_topology(current_draw.primitive); + + if (rsx::method_registers.restart_index_enabled() && + !current_draw.is_disjoint_primitive && + current_draw.command == rsx::draw_command::indexed && + !emulated_primitive && + !vk::emulate_primitive_restart(current_draw.primitive)) + { + state.restart_index_enabled = VK_TRUE; + } + + state.primitive = primitive; + return state; + } + // TODO: This should be deprecated soon (kd) vk::pipeline_props decode_rsx_state( - VkPrimitiveTopology primitive, - bool emulated_primitive_type, + const vertex_input_assembly_state& vertex_input, vk::render_target* ds, const rsx::backend_configuration& backend_config, u8 num_draw_buffers, @@ -223,11 +247,8 @@ namespace vk vk::pipeline_props properties{}; // Input assembly - properties.state.set_primitive_type(primitive); - - const bool restarts_valid = rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed && !emulated_primitive_type && !rsx::method_registers.current_draw_clause.is_disjoint_primitive; - if (rsx::method_registers.restart_index_enabled() && !vk::emulate_primitive_restart(rsx::method_registers.current_draw_clause.primitive) && restarts_valid) - properties.state.enable_primitive_restart(); + properties.state.set_primitive_type(vertex_input.primitive); + properties.state.enable_primitive_restart(vertex_input.restart_index_enabled); // Rasterizer state properties.state.set_attachment_count(num_draw_buffers); @@ -1904,9 +1925,7 @@ bool VKGSRender::load_program() const auto shadermode = g_cfg.video.shadermode.get(); // TODO: EXT_dynamic_state should get rid of this sillyness soon (kd) - const auto [primitive_type, is_emulated_primitive] = rsx::method_registers.current_draw_clause.primitive == m_cached_draw_state.rsx_prim - ? std::make_pair(m_cached_draw_state.prim, m_cached_draw_state.is_emulated_prim) - : vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive); + const auto vertex_state = vk::decode_vertex_input_assembly_state(); if (m_graphics_state & rsx::pipeline_state::invalidate_pipeline_bits) { @@ -1918,8 +1937,9 @@ bool VKGSRender::load_program() m_graphics_state &= ~rsx::pipeline_state::invalidate_pipeline_bits; } else if (!(m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) && - m_cached_draw_state.prim == primitive_type && - m_program) + m_program && + m_pipeline_properties.state.ia.topology == vertex_state.primitive && + m_pipeline_properties.state.ia.primitiveRestartEnable == vertex_state.restart_index_enabled) { if (!m_shader_interpreter.is_interpreter(m_program)) [[ likely ]] { @@ -1936,15 +1956,10 @@ bool VKGSRender::load_program() auto &vertex_program = current_vertex_program; auto &fragment_program = current_fragment_program; - m_cached_draw_state.prim = primitive_type; - m_cached_draw_state.is_emulated_prim = is_emulated_primitive; - m_cached_draw_state.rsx_prim = rsx::method_registers.current_draw_clause.primitive; - if (m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) { vk::pipeline_props properties = vk::decode_rsx_state( - primitive_type, - is_emulated_primitive, + vertex_state, m_rtts.m_bound_depth_stencil.second, backend_config, static_cast(m_draw_buffers.size()), @@ -1967,8 +1982,10 @@ bool VKGSRender::load_program() } else { - // Update primitive type. Not needed with EXT_dynamic_state - m_pipeline_properties.state.set_primitive_type(primitive_type); + // Update primitive type and restart index. Note that this is not needed with EXT_dynamic_state + m_pipeline_properties.state.set_primitive_type(vertex_state.primitive); + m_pipeline_properties.state.enable_primitive_restart(vertex_state.restart_index_enabled); + m_pipeline_properties.renderpass_key = m_current_renderpass_key; } m_vertex_prog = nullptr; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 16b826d274..4af1d1d80f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -91,13 +91,6 @@ private: std::unique_ptr m_volatile_attribute_storage; std::unique_ptr m_vertex_layout_storage; - struct - { - rsx::primitive_type rsx_prim = rsx::primitive_type::points; - VkPrimitiveTopology prim = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - bool is_emulated_prim = false; - } m_cached_draw_state; - public: //vk::fbo draw_fbo; std::unique_ptr m_vertex_cache; diff --git a/rpcs3/Emu/RSX/VK/vkutils/graphics_pipeline_state.hpp b/rpcs3/Emu/RSX/VK/vkutils/graphics_pipeline_state.hpp index ceae859d2c..8d7fa0e407 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/graphics_pipeline_state.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/graphics_pipeline_state.hpp @@ -76,9 +76,9 @@ namespace vk ia.topology = type; } - void enable_primitive_restart(bool enable = true) + void enable_primitive_restart(VkBool32 enable = VK_TRUE) { - ia.primitiveRestartEnable = enable? VK_TRUE : VK_FALSE; + ia.primitiveRestartEnable = enable; } void set_color_mask(int index, bool r, bool g, bool b, bool a) diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index aa8a3f208f..863ce3a6c9 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -2501,6 +2501,7 @@ namespace rsx state_signals[NV4097_SET_DEPTH_BOUNDS_MIN] = rsx::depth_bounds_state_dirty; state_signals[NV4097_SET_DEPTH_BOUNDS_MAX] = rsx::depth_bounds_state_dirty; state_signals[NV4097_SET_FRONT_FACE] = rsx::pipeline_config_dirty; + state_signals[NV4097_SET_CULL_FACE_ENABLE] = rsx::pipeline_config_dirty; state_signals[NV4097_SET_ZMIN_MAX_CONTROL] = rsx::pipeline_config_dirty; state_signals[NV4097_SET_LOGIC_OP_ENABLE] = rsx::pipeline_config_dirty; state_signals[NV4097_SET_LOGIC_OP] = rsx::pipeline_config_dirty;