dx12/vk/gl: implement use of vertex_data_base_index when calculating index

This commit is contained in:
Jake 2018-03-29 00:42:44 -05:00 committed by kd-11
parent 3e863f2189
commit 6d6d6fa827
7 changed files with 37 additions and 26 deletions

View file

@ -525,7 +525,7 @@ void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, gsl::s
namespace namespace
{ {
template<typename T> template<typename T>
std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index) std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index)
{ {
T min_index = -1; T min_index = -1;
T max_index = 0; T max_index = 0;
@ -545,6 +545,7 @@ std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::spa
} }
else else
{ {
index = rsx::get_index_from_base(index, base_index);
max_index = std::max(max_index, index); max_index = std::max(max_index, index);
min_index = std::min(min_index, index); min_index = std::min(min_index, index);
} }
@ -555,7 +556,7 @@ std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::spa
} }
template<typename T> template<typename T>
std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index) std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index)
{ {
const T invalid_index = (T)-1; const T invalid_index = (T)-1;
@ -573,12 +574,15 @@ std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> sr
for (size_t src_idx = 0; src_idx < src.size(); ++src_idx) 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 (needs_anchor)
{ {
if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index) if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index)
continue; continue;
anchor = src[src_idx]; anchor = index;
needs_anchor = false; needs_anchor = false;
continue; continue;
} }
@ -590,7 +594,6 @@ std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> sr
continue; continue;
} }
T index = src[src_idx];
max_index = std::max(max_index, index); max_index = std::max(max_index, index);
min_index = std::min(min_index, index); min_index = std::min(min_index, index);
@ -612,7 +615,7 @@ std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> sr
} }
template<typename T> template<typename T>
std::tuple<T, T, u32> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index) std::tuple<T, T, u32> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index, u32 base_index)
{ {
T min_index = -1; T min_index = -1;
T max_index = 0; T max_index = 0;
@ -626,7 +629,8 @@ std::tuple<T, T, u32> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl:
for (int src_idx = 0; src_idx < src.size(); ++src_idx) for (int src_idx = 0; src_idx < src.size(); ++src_idx)
{ {
T index = src[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 //empty temp buffer
set_size = 0; set_size = 0;
@ -780,27 +784,27 @@ namespace
std::tuple<T, T, u32> write_index_array_data_to_buffer_impl(gsl::span<T> dst, std::tuple<T, T, u32> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
gsl::span<const be_t<T>> src, gsl::span<const be_t<T>> src,
rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands) u32 base_index, std::function<bool(rsx::primitive_type)> expands)
{ {
u32 first; u32 first;
u32 count; u32 count;
std::tie(first, count) = get_first_count_from_draw_indexed_clause(first_count_arguments); std::tie(first, count) = get_first_count_from_draw_indexed_clause(first_count_arguments);
if (!expands(draw_mode)) return upload_untouched<T>(src, dst, restart_index_enabled, restart_index); if (!expands(draw_mode)) return upload_untouched<T>(src, dst, restart_index_enabled, restart_index, base_index);
switch (draw_mode) switch (draw_mode)
{ {
case rsx::primitive_type::line_loop: case rsx::primitive_type::line_loop:
{ {
const auto &returnvalue = upload_untouched<T>(src, dst, restart_index_enabled, restart_index); const auto &returnvalue = upload_untouched<T>(src, dst, restart_index_enabled, restart_index, base_index);
dst[count] = src[0]; dst[count] = src[0];
return returnvalue; return returnvalue;
} }
case rsx::primitive_type::polygon: case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan: case rsx::primitive_type::triangle_fan:
return expand_indexed_triangle_fan<T>(src, dst, restart_index_enabled, restart_index); return expand_indexed_triangle_fan<T>(src, dst, restart_index_enabled, restart_index, base_index);
case rsx::primitive_type::quads: case rsx::primitive_type::quads:
return expand_indexed_quads<T>(src, dst, restart_index_enabled, restart_index); return expand_indexed_quads<T>(src, dst, restart_index_enabled, restart_index, base_index);
default: default:
fmt::throw_exception("Unknown draw mode (0x%x)" HERE, (u32)draw_mode); fmt::throw_exception("Unknown draw mode (0x%x)" HERE, (u32)draw_mode);
} }
@ -810,16 +814,16 @@ namespace
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
gsl::span<const gsl::byte> src, gsl::span<const gsl::byte> src,
rsx::index_array_type type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments, rsx::index_array_type type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands) u32 base_index, std::function<bool(rsx::primitive_type)> expands)
{ {
switch (type) switch (type)
{ {
case rsx::index_array_type::u16: case rsx::index_array_type::u16:
return write_index_array_data_to_buffer_impl<u16>(as_span_workaround<u16>(dst), return write_index_array_data_to_buffer_impl<u16>(as_span_workaround<u16>(dst),
gsl::as_span<const be_t<u16>>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, expands); gsl::as_span<const be_t<u16>>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, base_index, expands);
case rsx::index_array_type::u32: case rsx::index_array_type::u32:
return write_index_array_data_to_buffer_impl<u32>(as_span_workaround<u32>(dst), return write_index_array_data_to_buffer_impl<u32>(as_span_workaround<u32>(dst),
gsl::as_span<const be_t<u32>>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, expands); gsl::as_span<const be_t<u32>>(src), draw_mode, restart_index_enabled, restart_index, first_count_arguments, base_index, expands);
} }
fmt::throw_exception("Unknown index type" HERE); fmt::throw_exception("Unknown index type" HERE);
} }

View file

@ -34,7 +34,7 @@ u32 get_index_type_size(rsx::index_array_type type);
*/ */
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src, std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src,
rsx::index_array_type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments, rsx::index_array_type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands); u32 base_index, std::function<bool(rsx::primitive_type)> expands);
/** /**
* Write index data needed to emulate non indexed non native primitive mode. * Write index data needed to emulate non indexed non native primitive mode.

View file

@ -269,7 +269,6 @@ namespace
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_COPY_DEST)); D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_COPY_DEST));
u32 vertex_count = get_vertex_count(vertex_ranges); u32 vertex_count = get_vertex_count(vertex_ranges);
verify(HERE), rsx::method_registers.vertex_data_base_index() == 0;
vertex_buffer_visitor visitor( vertex_buffer_visitor visitor(
vertex_count, command_list, m_vertex_buffer_data, m_buffer_data); 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.current_draw_clause.primitive,
rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index_enabled(),
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer, 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)); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_INDEX_BUFFER_VIEW index_buffer_view = { D3D12_INDEX_BUFFER_VIEW index_buffer_view = {

View file

@ -53,7 +53,7 @@ namespace
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), ::narrow<u32>(block_sz) }; gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), ::narrow<u32>(block_sz) };
std::tie(min_index, max_index, vertex_draw_count) = write_index_array_data_to_buffer(dst, raw_index_buffer, 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, 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); return std::make_tuple(min_index, max_index, vertex_draw_count);
} }

View file

@ -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) u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size)
{ {
switch (type) switch (type)

View file

@ -171,7 +171,7 @@ namespace
rsx::method_registers.current_draw_clause.primitive, rsx::method_registers.current_draw_clause.primitive,
rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index_enabled(),
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer, 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) if (min_index >= max_index)
{ {

View file

@ -344,4 +344,19 @@ namespace rsx
if (last_start >= 0) if (last_start >= 0)
out.push_back(std::make_pair(last_start, last_valid_index - last_start + 1)); 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;
}
} }