diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 6eba64a9d6..3a8e47f4a7 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -514,10 +514,19 @@ void GLGSRender::emit_geometry(u32 sub_index) // Rebase vertex bases instead of for (auto& info : m_vertex_layout.interleaved_blocks) { + info->vertex_range.second = 0; const auto vertex_base_offset = rsx::method_registers.vertex_data_base_offset(); info->real_offset_address = rsx::get_address(rsx::get_vertex_offset_from_base(vertex_base_offset, info->base_offset), info->memory_location); } } + else + { + // Discard cached results + for (auto& info : m_vertex_layout.interleaved_blocks) + { + info->vertex_range.second = 0; + } + } if (vertex_state && !m_vertex_layout.validate()) { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index eeef1124ac..8b1490b7fa 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -354,12 +354,12 @@ namespace rsx const u32 index_size = index_type == rsx::index_array_type::u32 ? 4 : 2; + const auto render = rsx::get_current_renderer(); + // If we can access a bit a more memory than required - do it // The alternative would be re-iterating again over all of them if (get_location(real_offset_address) == CELL_GCM_LOCATION_LOCAL) { - const auto render = rsx::get_current_renderer(); - if (utils::add_saturate(real_offset_address - rsx::constants::local_mem_base, (_max_index + 1) * attribute_stride) <= render->local_mem_size) { break; @@ -372,14 +372,18 @@ namespace rsx _max_index = 0; - // Force aligned indices as realhw - const u32 address = (0 - index_size) & get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location()); - - auto re_evaluate = [&](auto ptr) + auto re_evaluate = [&] (const std::byte* ptr, T) { + const u64 restart = rsx::method_registers.restart_index_enabled() ? rsx::method_registers.restart_index() : u64{umax}; + for (u32 _index = first; _index < first + count; _index++) { - const auto value = ptr[_index]; + const auto value = read_from_ptr>(ptr, _index * sizeof(T)); + + if (value == restart) + { + continue; + } for (u32 freq_it = 0; freq_it < freq_count; freq_it++) { @@ -387,7 +391,7 @@ namespace rsx if (res > _max_index) { - _max_index = value; + _max_index = res; } } } @@ -395,11 +399,29 @@ namespace rsx if (index_size == 4) { - re_evaluate(vm::get_super_ptr(address)); + if (!render->element_push_buffer.empty()) [[unlikely]] + { + // Indices provided via immediate mode + re_evaluate(reinterpret_cast(render->element_push_buffer.data()), u32{}); + } + else + { + const u32 address = (0 - index_size) & get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location()); + re_evaluate(vm::get_super_ptr(address), u32{}); + } } else { - re_evaluate(vm::get_super_ptr(address)); + if (!render->element_push_buffer.empty()) [[unlikely]] + { + // Indices provided via immediate mode + re_evaluate(reinterpret_cast(render->element_push_buffer.data()), u16{}); + } + else + { + const u32 address = (0 - index_size) & get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location()); + re_evaluate(vm::get_super_ptr(address), u16{}); + } } break; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 18306cc4cf..4f378939fd 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -159,7 +159,6 @@ namespace rsx protected: std::array vertex_push_buffers; - rsx::simple_array element_push_buffer; s32 m_skip_frame_ctr = 0; bool skip_current_frame = false; @@ -215,6 +214,7 @@ namespace rsx atomic_t external_interrupt_lock{ 0 }; atomic_t external_interrupt_ack{ false }; atomic_t is_initialized{0}; + rsx::simple_array element_push_buffer; bool is_fifo_idle() const; void flush_fifo(); diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 82498ba91a..164e62e300 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -718,10 +718,19 @@ void VKGSRender::emit_geometry(u32 sub_index) // Rebase vertex bases instead of for (auto& info : m_vertex_layout.interleaved_blocks) { + info->vertex_range.second = 0; const auto vertex_base_offset = rsx::method_registers.vertex_data_base_offset(); info->real_offset_address = rsx::get_address(rsx::get_vertex_offset_from_base(vertex_base_offset, info->base_offset), info->memory_location); } } + else + { + // Discard cached results + for (auto& info : m_vertex_layout.interleaved_blocks) + { + info->vertex_range.second = 0; + } + } if (vertex_state && !m_vertex_layout.validate()) {