diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index 97318010d2..9fe0c723c2 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -334,8 +334,11 @@ public: fmt::throw_exception("Trying to get unknown shader program" HERE); } + // Returns 2 booleans. + // First flag hints that there is more work to do (busy hint) + // Second flag is true if at least one program has been linked successfully (sync hint) template - bool async_update(u32 max_decompile_count, Args&& ...args) + std::pair async_update(u32 max_decompile_count, Args&& ...args) { // Decompile shaders and link one pipeline object per 'run' // NOTE: Linking is much slower than decompilation step, so always decompile at least 1 unit @@ -381,7 +384,7 @@ public: } else { - return busy; + return { busy, false }; } } @@ -392,7 +395,7 @@ public: m_storage[key] = std::move(pipeline); m_link_queue.erase(key); - return (busy || !m_link_queue.empty()); + return { (busy || !m_link_queue.empty()), true }; } template diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index cbf39fe4a7..8df37b8fea 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -402,13 +402,12 @@ void GLGSRender::end() //Bind textures and resolve external copy operations std::chrono::time_point textures_start = steady_clock::now(); - int unused_location; void *unused = nullptr; gl::texture_view* tmp_view; for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) { - if (m_program->uniforms.has_location(rsx::constants::fragment_texture_names[i], &unused_location)) + if (m_program->uniforms.has_location(rsx::constants::fragment_texture_names[i])) { auto sampler_state = static_cast(fs_sampler_state[i].get()); auto &tex = rsx::method_registers.fragment_textures[i]; @@ -444,7 +443,7 @@ void GLGSRender::end() for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) { - if (m_program->uniforms.has_location(rsx::constants::vertex_texture_names[i], &unused_location)) + if (m_program->uniforms.has_location(rsx::constants::vertex_texture_names[i])) { auto sampler_state = static_cast(vs_sampler_state[i].get()); glActiveTexture(GL_TEXTURE0 + rsx::limits::fragment_textures_count + i); @@ -1786,11 +1785,13 @@ void GLGSRender::on_decompiler_exit() bool GLGSRender::on_decompiler_task() { - bool ret = m_prog_buffer.async_update(8); + const auto result = m_prog_buffer.async_update(8); + if (result.second) + { + // TODO: Proper synchronization with renderer + // Finish works well enough for now but it is not a proper soulution + glFinish(); + } - // TODO: Proper synchronization with renderer - // Finish works well enough for now but it is not a proper soulution - glFinish(); - - return ret; + return result.first; } diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 81ff25f487..4ac36582fa 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -2435,35 +2435,51 @@ public: bool has_location(const std::string &name, int *location = nullptr) { - int result = glGetUniformLocation(m_program.id(), name.c_str()); + auto found = locations.find(name); + if (found != locations.end()) + { + if (location) + { + *location = found->second; + } - if (result < 0) - return false; + return (found->second >= 0); + } + auto result = glGetUniformLocation(m_program.id(), name.c_str()); locations[name] = result; if (location) + { *location = result; + } - return true; + return (result >= 0); } GLint location(const std::string &name) { - auto finded = locations.find(name); - - if (finded != locations.end()) + auto found = locations.find(name); + if (found != locations.end()) { - return finded->second; + if (found->second >= 0) + { + return found->second; + } + else + { + throw not_found_exception(name); + } } - int result = glGetUniformLocation(m_program.id(), name.c_str()); + auto result = glGetUniformLocation(m_program.id(), name.c_str()); if (result < 0) + { throw not_found_exception(name); + } locations[name] = result; - return result; } @@ -2476,28 +2492,6 @@ public: return active_texture; } - int texture(const std::string &name, int active_texture, const gl::texture_view& texture_) - { - return texture(location(name), active_texture, texture_); - } - - int texture(const std::string &name, const gl::texture_view& texture_) - { - int atex; - auto finded = locations.find(name); - - if (finded != locations.end()) - { - atex = finded->second; - } - else - { - atex = active_texture++; - } - - return texture(name, atex, texture_); - } - uniform_t operator[](GLint location) { return{ m_program, location }; @@ -2515,83 +2509,6 @@ public: } } uniforms{ this }; - class attribs_t - { - program& m_program; - std::unordered_map m_locations; - - public: - attribs_t(program* program) : m_program(*program) - { - } - - void clear() - { - m_locations.clear(); - } - - GLint location(const std::string &name) - { - auto finded = m_locations.find(name); - - if (finded != m_locations.end()) - { - if (finded->second < 0) - throw not_found_exception(name); - - return finded->second; - } - - int result = glGetAttribLocation(m_program.id(), name.c_str()); - - if (result < 0) - throw not_found_exception(name); - - m_locations[name] = result; - - return result; - } - - bool has_location(const std::string &name, int *location_ = nullptr) - { - auto finded = m_locations.find(name); - - if (finded != m_locations.end()) - { - if (finded->second < 0) - return false; - - *location_ = finded->second; - return true; - } - - int loc = glGetAttribLocation(m_program.id(), name.c_str()); - - m_locations[name] = loc; - - if (loc < 0) - return false; - - *location_ = loc; - return true; - } - - attrib_t operator[](GLint location) - { - return{ location }; - } - - attrib_t operator[](const std::string &name) - { - return{ location(name) }; - } - - void swap(attribs_t& attribs) - { - m_locations.swap(attribs.m_locations); - } - } attribs{ this }; - program& recreate() { if (created()) @@ -2686,7 +2603,6 @@ public: void set_id(uint id) { uniforms.clear(); - attribs.clear(); m_id = id; } @@ -2764,7 +2680,6 @@ public: set_id(program_.id()); program_.set_id(my_old_id); uniforms.swap(program_.uniforms); - attribs.swap(program_.attribs); } program& operator = (const program& rhs) = delete; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b8c71f737f..5e7b24ff2a 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -437,10 +437,6 @@ namespace rsx thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(thread_class::rsx)); } - // Weak cpus need all the help they can get, sleep instead of yield loop - // Lowers decompiler responsiveness but improves emulator performance - const bool prefer_sleep = (std::thread::hardware_concurrency() < 6); - while (!Emu.IsStopped() && !m_rsx_thread_exiting) { if (!on_decompiler_task()) @@ -449,13 +445,9 @@ namespace rsx { std::this_thread::sleep_for(1ms); } - else if (prefer_sleep) - { - std::this_thread::sleep_for(500us); - } else { - std::this_thread::yield(); + std::this_thread::sleep_for(500us); } } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 2be6fb8f43..3f3747f0ce 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -3442,5 +3442,5 @@ void VKGSRender::discard_occlusion_query(rsx::reports::occlusion_query_info* que bool VKGSRender::on_decompiler_task() { - return m_prog_buffer->async_update(8, *m_device, pipeline_layout); + return m_prog_buffer->async_update(8, *m_device, pipeline_layout).first; } \ No newline at end of file diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index f046ff3eec..aaffdd03a7 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -780,7 +780,6 @@ namespace vk const u16 section_depth = depth; const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap; VkFormat vk_format; - VkComponentMapping mapping; VkImageAspectFlags aspect_flags; VkImageType image_type; VkImageViewType image_view_type; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 0bc25f8824..b733e65f08 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -371,12 +371,18 @@ namespace rsx void set_transform_program_start(thread* rsx, u32, u32) { - rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty; + if (method_registers.register_change_flag) + { + rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty; + } } void set_vertex_attribute_output_mask(thread* rsx, u32, u32) { - rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty | rsx::pipeline_state::fragment_program_dirty; + if (method_registers.register_change_flag) + { + rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty | rsx::pipeline_state::fragment_program_dirty; + } } void set_begin_end(thread* rsxthr, u32 _reg, u32 arg) @@ -1310,7 +1316,16 @@ namespace rsx void rsx_state::decode(u32 reg, u32 value) { - registers[reg] = value; + auto& old_value = registers[reg]; + if (old_value != value) + { + register_change_flag = true; + old_value = value; + } + else + { + register_change_flag = false; + } } bool rsx_state::test(u32 reg, u32 value) const diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index baddd6cc02..e5be47e853 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -159,6 +159,8 @@ namespace rsx draw_clause current_draw_clause; + bool register_change_flag; + /** * RSX can sources vertex attributes from 2 places: * 1. Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write.