From 6d6d6fa82783a3699fd99ba57b1ff119dbd5a4d5 Mon Sep 17 00:00:00 2001 From: Jake Date: Thu, 29 Mar 2018 00:42:44 -0500 Subject: [PATCH] dx12/vk/gl: implement use of vertex_data_base_index when calculating index --- rpcs3/Emu/RSX/Common/BufferUtils.cpp | 32 ++++++++++++++++------------ rpcs3/Emu/RSX/Common/BufferUtils.h | 2 +- rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp | 3 +-- rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 7 ------ rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp | 2 +- rpcs3/Emu/RSX/rsx_utils.h | 15 +++++++++++++ 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/BufferUtils.cpp b/rpcs3/Emu/RSX/Common/BufferUtils.cpp index 707134fa65..36854d6dbb 100644 --- a/rpcs3/Emu/RSX/Common/BufferUtils.cpp +++ b/rpcs3/Emu/RSX/Common/BufferUtils.cpp @@ -525,7 +525,7 @@ void write_vertex_array_data_to_buffer(gsl::span raw_dst_span, gsl::s namespace { template -std::tuple upload_untouched(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index) +std::tuple upload_untouched(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index) { T min_index = -1; T max_index = 0; @@ -545,6 +545,7 @@ std::tuple upload_untouched(gsl::span> src, gsl::spa } else { + index = rsx::get_index_from_base(index, base_index); max_index = std::max(max_index, index); min_index = std::min(min_index, index); } @@ -555,7 +556,7 @@ std::tuple upload_untouched(gsl::span> src, gsl::spa } template -std::tuple expand_indexed_triangle_fan(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index) +std::tuple expand_indexed_triangle_fan(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index) { const T invalid_index = (T)-1; @@ -573,12 +574,15 @@ std::tuple expand_indexed_triangle_fan(gsl::span> sr for (size_t src_idx = 0; src_idx < src.size(); ++src_idx) { + T index = src[src_idx]; + index = rsx::get_index_from_base(index, base_index); + if (needs_anchor) { if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index) continue; - anchor = src[src_idx]; + anchor = index; needs_anchor = false; continue; } @@ -590,7 +594,6 @@ std::tuple expand_indexed_triangle_fan(gsl::span> sr continue; } - T index = src[src_idx]; max_index = std::max(max_index, index); min_index = std::min(min_index, index); @@ -612,7 +615,7 @@ std::tuple expand_indexed_triangle_fan(gsl::span> sr } template -std::tuple expand_indexed_quads(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index) +std::tuple expand_indexed_quads(gsl::span> src, gsl::span dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index) { T min_index = -1; T max_index = 0; @@ -626,7 +629,8 @@ std::tuple expand_indexed_quads(gsl::span> src, gsl: for (int src_idx = 0; src_idx < src.size(); ++src_idx) { T index = src[src_idx]; - if (is_primitive_restart_enabled && index == primitive_restart_index) + index = rsx::get_index_from_base(index, base_index); + if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index) { //empty temp buffer set_size = 0; @@ -780,27 +784,27 @@ namespace std::tuple write_index_array_data_to_buffer_impl(gsl::span dst, gsl::span> src, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector > &first_count_arguments, - std::function expands) + u32 base_index, std::function expands) { u32 first; u32 count; std::tie(first, count) = get_first_count_from_draw_indexed_clause(first_count_arguments); - if (!expands(draw_mode)) return upload_untouched(src, dst, restart_index_enabled, restart_index); + if (!expands(draw_mode)) return upload_untouched(src, dst, restart_index_enabled, restart_index, base_index); switch (draw_mode) { case rsx::primitive_type::line_loop: { - const auto &returnvalue = upload_untouched(src, dst, restart_index_enabled, restart_index); + const auto &returnvalue = upload_untouched(src, dst, restart_index_enabled, restart_index, base_index); dst[count] = src[0]; return returnvalue; } case rsx::primitive_type::polygon: case rsx::primitive_type::triangle_fan: - return expand_indexed_triangle_fan(src, dst, restart_index_enabled, restart_index); + return expand_indexed_triangle_fan(src, dst, restart_index_enabled, restart_index, base_index); case rsx::primitive_type::quads: - return expand_indexed_quads(src, dst, restart_index_enabled, restart_index); + return expand_indexed_quads(src, dst, restart_index_enabled, restart_index, base_index); default: fmt::throw_exception("Unknown draw mode (0x%x)" HERE, (u32)draw_mode); } @@ -810,16 +814,16 @@ namespace std::tuple write_index_array_data_to_buffer(gsl::span dst, gsl::span src, rsx::index_array_type type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector > &first_count_arguments, - std::function expands) + u32 base_index, std::function expands) { switch (type) { case rsx::index_array_type::u16: return write_index_array_data_to_buffer_impl(as_span_workaround(dst), - gsl::as_span>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, expands); + gsl::as_span>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, base_index, expands); case rsx::index_array_type::u32: return write_index_array_data_to_buffer_impl(as_span_workaround(dst), - gsl::as_span>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, expands); + gsl::as_span>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, base_index, expands); } fmt::throw_exception("Unknown index type" HERE); } diff --git a/rpcs3/Emu/RSX/Common/BufferUtils.h b/rpcs3/Emu/RSX/Common/BufferUtils.h index 2cdc7b28d5..bdf231b935 100644 --- a/rpcs3/Emu/RSX/Common/BufferUtils.h +++ b/rpcs3/Emu/RSX/Common/BufferUtils.h @@ -34,7 +34,7 @@ u32 get_index_type_size(rsx::index_array_type type); */ std::tuple write_index_array_data_to_buffer(gsl::span dst, gsl::span src, rsx::index_array_type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector > &first_count_arguments, - std::function expands); + u32 base_index, std::function expands); /** * Write index data needed to emulate non indexed non native primitive mode. diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index e0b5b00d4c..b8b8111ce5 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -269,7 +269,6 @@ namespace D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_COPY_DEST)); u32 vertex_count = get_vertex_count(vertex_ranges); - verify(HERE), rsx::method_registers.vertex_data_base_index() == 0; vertex_buffer_visitor visitor( vertex_count, command_list, m_vertex_buffer_data, m_buffer_data); @@ -415,7 +414,7 @@ namespace rsx::method_registers.current_draw_clause.primitive, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer, - [](auto prim) { return !is_primitive_native(prim); }); + rsx::method_registers.vertex_data_base_index(), [](auto prim) { return !is_primitive_native(prim); }); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); D3D12_INDEX_BUFFER_VIEW index_buffer_view = { diff --git a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp index a61ebeeab2..23664a126c 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp @@ -53,7 +53,7 @@ namespace gsl::span dst{ reinterpret_cast(ptr), ::narrow(block_sz) }; std::tie(min_index, max_index, vertex_draw_count) = write_index_array_data_to_buffer(dst, raw_index_buffer, type, draw_mode, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands, - [](auto prim) { return !gl::is_primitive_native(prim); }); + rsx::method_registers.vertex_data_base_index(), [](auto prim) { return !gl::is_primitive_native(prim); }); return std::make_tuple(min_index, max_index, vertex_draw_count); } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 192064cb3d..b7842484ea 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -89,13 +89,6 @@ namespace rsx } } - // The rsx internally adds the 'data_base_offset' and the 'vert_offset' and masks it - // before actually attempting to translate to the internal address. Seen happening heavily in R&C games - u32 get_vertex_offset_from_base(u32 vert_data_base_offset, u32 vert_base_offset) - { - return ((u64)vert_data_base_offset + vert_base_offset) & 0xFFFFFFF; - } - u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size) { switch (type) diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index 277d3ffcad..a9be0b4b00 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -171,7 +171,7 @@ namespace rsx::method_registers.current_draw_clause.primitive, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer, - [](auto prim) { return !vk::is_primitive_native(prim); }); + rsx::method_registers.vertex_data_base_index(), [](auto prim) { return !vk::is_primitive_native(prim); }); if (min_index >= max_index) { diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 40478024d0..b1633abef5 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -344,4 +344,19 @@ namespace rsx if (last_start >= 0) out.push_back(std::make_pair(last_start, last_valid_index - last_start + 1)); } + + // The rsx internally adds the 'data_base_offset' and the 'vert_offset' and masks it + // before actually attempting to translate to the internal address. Seen happening heavily in R&C games + static inline u32 get_vertex_offset_from_base(u32 vert_data_base_offset, u32 vert_base_offset) + { + return ((u64)vert_data_base_offset + vert_base_offset) & 0xFFFFFFF; + } + + // Similar to vertex_offset_base calculation, the rsx internally adds and masks index + // before using + static inline u32 get_index_from_base(u32 index, u32 index_base) + { + return ((u64)index + index_base) & 0x000FFFFF; + } + }