Merge pull request #2021 from vlj/rsx-refactor

rsx: Move index pointer generation in rsx::thread
This commit is contained in:
vlj 2016-08-05 18:08:03 +02:00 committed by GitHub
commit 98f09e4f27
7 changed files with 119 additions and 212 deletions

View File

@ -243,11 +243,11 @@ bool is_primitive_native(rsx::primitive_type draw_mode)
{
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
return true;
case rsx::primitive_type::line_loop:
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::quads:
@ -270,6 +270,8 @@ size_t get_index_count(rsx::primitive_type draw_mode, unsigned initial_index_cou
switch (draw_mode)
{
case rsx::primitive_type::line_loop:
return initial_index_count + 1;
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return (initial_index_count - 2) * 3;
@ -297,6 +299,11 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
unsigned short *typedDst = (unsigned short *)(dst);
switch (draw_mode)
{
case rsx::primitive_type::line_loop:
for (unsigned i = 0; i < count; ++i)
dst[i] = i;
dst[count] = 0;
return;
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::polygon:
for (unsigned i = 0; i < (count - 2); i++)
@ -334,7 +341,6 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
return;
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
@ -342,111 +348,68 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
}
}
// TODO: Unify indexed and non indexed primitive expansion ?
// FIXME: these functions shouldn't access rsx::method_registers (global)
template<typename T>
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
namespace
{
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
EXPECTS(rsx::method_registers.vertex_data_base_index() == 0);
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u32 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
/**
* Get first index and index count from a draw indexed clause.
*/
std::tuple<u32, u32> get_first_count_from_draw_indexed_clause(const std::vector<std::pair<u32, u32>>& first_count_arguments)
{
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const T>(address + first * type_size);
switch (draw_mode)
{
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::quad_strip:
return upload_untouched<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return expand_indexed_triangle_fan<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
case rsx::primitive_type::quads:
return expand_indexed_quads<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
return std::make_tuple(first, count);
}
throw EXCEPTION("Unknown draw mode");
// TODO: Unify indexed and non indexed primitive expansion ?
template<typename T>
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
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,
std::function<bool(rsx::primitive_type)> 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<T>(src.subspan(first), dst, restart_index_enabled, restart_index);
switch (draw_mode)
{
case rsx::primitive_type::line_loop:
{
const auto &returnvalue = upload_untouched<T>(src.subspan(first), dst, restart_index_enabled, restart_index);
dst[count] = src[first];
return returnvalue;
}
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return expand_indexed_triangle_fan<T>(src.subspan(first), dst, restart_index_enabled, restart_index);
case rsx::primitive_type::quads:
return expand_indexed_quads<T>(src.subspan(first), dst, restart_index_enabled, restart_index);
}
throw EXCEPTION("Don't know how to expand draw mode");
}
}
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, rsx::index_array_type type, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
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,
std::function<bool(rsx::primitive_type)> expands)
{
switch (type)
{
case rsx::index_array_type::u16:
return write_index_array_data_to_buffer_impl<u16>(as_span_workaround<u16>(dst), draw_mode, first_count_arguments);
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);
case rsx::index_array_type::u32:
return write_index_array_data_to_buffer_impl<u32>(as_span_workaround<u32>(dst), draw_mode, first_count_arguments);
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);
}
throw EXCEPTION("Unknown index type");
}
std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u32 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
{
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const u32>(address + first * type_size);
return upload_untouched<u32>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
}
std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u16 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
{
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const u16>(address + first * type_size);
return upload_untouched<u16>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
}
void stream_vector(void *dst, u32 x, u32 y, u32 z, u32 w)
{
__m128i vector = _mm_set_epi32(w, z, y, x);

View File

@ -30,16 +30,11 @@ size_t get_index_type_size(rsx::index_array_type type);
/**
* Write count indexes using (first, first + count) ranges.
* Returns min/max index found during the process.
* The function expands index buffer for non native primitive type.
* The function expands index buffer for non native primitive type if expands(draw_mode) return true.
*/
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, rsx::index_array_type, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments);
/**
* Doesn't expand index
*/
std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments);
std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments);
std::tuple<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,
std::function<bool(rsx::primitive_type)> expands);
/**
* Write index data needed to emulate non indexed non native primitive mode.

View File

@ -380,7 +380,9 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
u32 min_index, max_index;
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(mapped_buffer), gsl::narrow<u32>(buffer_size) };
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, indexed_type, draw_mode, first_count_commands);
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, get_raw_index_array(first_count_commands),
indexed_type, draw_mode, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands,
[](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 = {

View File

@ -154,28 +154,19 @@ namespace
return std::make_tuple(vertex_draw_count, mapping.second);
}
std::tuple<u32, u32, u32> upload_index_buffer(void *ptr, rsx::index_array_type type, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32>> first_count_commands, u32 initial_vertex_count)
std::tuple<u32, u32, u32> upload_index_buffer(gsl::span<const gsl::byte> raw_index_buffer, void *ptr, rsx::index_array_type type, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32>> first_count_commands, u32 initial_vertex_count)
{
u32 min_index, max_index, vertex_draw_count = initial_vertex_count;
if (gl::is_primitive_native(draw_mode))
{
if (type == rsx::index_array_type::u16)
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u16>{(u16*)ptr, vertex_draw_count}, first_count_commands);
else
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u32>{(u32*)ptr, vertex_draw_count}, first_count_commands);
vertex_draw_count = (u32)get_index_count(draw_mode, gsl::narrow<int>(vertex_draw_count));
}
else
{
vertex_draw_count = (u32)get_index_count(draw_mode, gsl::narrow<int>(vertex_draw_count));
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
u32 block_sz = vertex_draw_count * type_size;
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), gsl::narrow<u32>(block_sz) };
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, type, draw_mode, first_count_commands);
}
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
u32 block_sz = vertex_draw_count * type_size;
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), gsl::narrow<u32>(block_sz) };
std::tie(min_index, max_index) = 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 !is_primitive_native(prim); });
return std::make_tuple(min_index, max_index, vertex_draw_count);
}
@ -223,7 +214,7 @@ u32 GLGSRender::set_vertex_buffer()
void *ptr = mapping.first;
offset_in_index_buffer = mapping.second;
std::tie(min_index, max_index, vertex_draw_count) = upload_index_buffer(ptr, type, draw_mode, first_count_commands, vertex_draw_count);
std::tie(min_index, max_index, vertex_draw_count) = upload_index_buffer(get_raw_index_array(first_count_commands), ptr, type, draw_mode, first_count_commands, vertex_draw_count);
m_index_ring_buffer.unmap();
}

View File

@ -318,17 +318,9 @@ namespace rsx
{
draw_state.vertex_count += range.second;
}
if (draw_state.state.index_type() == rsx::index_array_type::u16)
{
draw_state.index.resize(2 * draw_state.vertex_count);
}
if (draw_state.state.index_type() == rsx::index_array_type::u32)
{
draw_state.index.resize(4 * draw_state.vertex_count);
}
gsl::span<gsl::byte> dst = { (gsl::byte*)draw_state.index.data(), gsl::narrow<int>(draw_state.index.size()) };
write_index_array_data_to_buffer(dst, draw_state.state.index_type(), draw_mode, first_count_commands);
auto index_raw_data_ptr = get_raw_index_array(first_count_commands);
draw_state.index.resize(index_raw_data_ptr.size_bytes());
std::copy(index_raw_data_ptr.begin(), index_raw_data_ptr.end(), draw_state.index.begin());
}
draw_state.programs = get_programs();
@ -580,6 +572,28 @@ namespace rsx
return get_system_time() * 1000;
}
gsl::span<const gsl::byte> thread::get_raw_index_array(const std::vector<std::pair<u32, u32> >& draw_indexed_clause) const
{
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u32 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < draw_indexed_clause.size() - 1; i++)
{
const std::tuple<u32, u32> &range = draw_indexed_clause[i];
const std::tuple<u32, u32> &next_range = draw_indexed_clause[i + 1];
EXPECTS(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(draw_indexed_clause.front());
u32 count = std::get<0>(draw_indexed_clause.back()) + std::get<1>(draw_indexed_clause.back()) - first;
const gsl::byte* ptr = static_cast<const gsl::byte*>(vm::base(address));
return{ ptr, count * type_size };
}
void thread::do_internal_task()
{
if (m_internal_tasks.empty())

View File

@ -11,6 +11,7 @@
#include "RSXFragmentProgram.h"
#include "rsx_methods.h"
#include "rsx_trace.h"
#include <Utilities/GSL.h>
#include "Utilities/Thread.h"
#include "Utilities/Timer.h"
@ -252,6 +253,8 @@ namespace rsx
virtual u64 timestamp() const;
virtual bool on_access_violation(u32 address, bool is_writing) { return false; }
gsl::span<const gsl::byte> get_raw_index_array(const std::vector<std::pair<u32, u32> >& draw_indexed_clause) const;
private:
std::mutex m_mtx_task;

View File

@ -85,19 +85,6 @@ namespace vk
}
}
/**
* Expand line loop array to line strip array; simply loop back the last vertex to the first..
*/
void expand_line_loop_array_to_strip(u32 vertex_draw_count, u16* indices)
{
u32 i = 0;
for (; i < vertex_draw_count; ++i)
indices[i] = i;
indices[i] = 0;
}
template <typename T, u32 padding>
void copy_inlined_data_to_buffer(void *src_data, void *dst_data, u32 vertex_count, rsx::vertex_base_type type, u8 src_channels, u8 dst_channels, u16 element_size, u16 stride)
{
@ -206,84 +193,36 @@ namespace vk
}
}
u32 get_emulated_index_array_size(rsx::primitive_type type, u32 vertex_count)
VkIndexType get_index_type(rsx::index_array_type type)
{
switch (type)
{
case rsx::primitive_type::line_loop:
return vertex_count + 1;
default:
return static_cast<u32>(get_index_count(type, vertex_count));
case rsx::index_array_type::u32:
return VK_INDEX_TYPE_UINT32;
case rsx::index_array_type::u16:
return VK_INDEX_TYPE_UINT16;
}
throw;
}
std::tuple<u32, u32, VkIndexType> upload_index_buffer(rsx::primitive_type type, rsx::index_array_type index_type, void *dst_ptr, bool indexed_draw, u32 vertex_count, u32 index_count, std::vector<std::pair<u32, u32>> first_count_commands)
std::tuple<u32, u32, VkIndexType> upload_index_buffer(gsl::span<const gsl::byte> raw_index_buffer, rsx::primitive_type type, rsx::index_array_type index_type, void *dst_ptr, bool indexed_draw, u32 vertex_count, u32 index_count, std::vector<std::pair<u32, u32>> first_count_commands)
{
bool emulated = false;
get_appropriate_topology(type, emulated);
u32 min_index, max_index;
if (!emulated)
if (indexed_draw)
{
switch (index_type)
{
case rsx::index_array_type::u32:
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u32>((u32*)dst_ptr, vertex_count), first_count_commands);
return std::make_tuple(min_index, max_index, VK_INDEX_TYPE_UINT32);
case rsx::index_array_type::u16:
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u16>((u16*)dst_ptr, vertex_count), first_count_commands);
return std::make_tuple(min_index, max_index, VK_INDEX_TYPE_UINT16);
}
u32 min_index, max_index;
size_t index_size = (index_type == rsx::index_array_type::u32) ? 4 : 2;
std::tie(min_index, max_index) = write_index_array_data_to_buffer(gsl::span<gsl::byte>(static_cast<gsl::byte*>(dst_ptr), vertex_count * index_size), raw_index_buffer,
index_type, type, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands,
[](auto prim) { return !is_primitive_native(prim); });
return std::make_tuple(min_index, max_index, get_index_type(index_type));
}
switch (type)
{
case rsx::primitive_type::line_loop:
{
if (!indexed_draw)
{
expand_line_loop_array_to_strip(vertex_count, static_cast<u16*>(dst_ptr));
return std::make_tuple(0, vertex_count-1, VK_INDEX_TYPE_UINT16);
}
VkIndexType vk_index_type = VK_INDEX_TYPE_UINT16;
switch (index_type)
{
case rsx::index_array_type::u32:
{
u32 *idx_ptr = static_cast<u32*>(dst_ptr);
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u32>(idx_ptr, vertex_count), first_count_commands);
idx_ptr[vertex_count] = idx_ptr[0];
vk_index_type = VK_INDEX_TYPE_UINT32;
break;
}
case rsx::index_array_type::u16:
{
u16 *idx_ptr = static_cast<u16*>(dst_ptr);
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u16>(idx_ptr, vertex_count), first_count_commands);
idx_ptr[vertex_count] = idx_ptr[0];
break;
}
}
return std::make_tuple(min_index, max_index, vk_index_type);
}
default:
{
if (indexed_draw)
{
std::tie(min_index, max_index) = write_index_array_data_to_buffer(gsl::span<gsl::byte>(static_cast<gsl::byte*>(dst_ptr), index_count * 2), rsx::index_array_type::u16, type, first_count_commands);
return std::make_tuple(min_index, max_index, VK_INDEX_TYPE_UINT16);
}
else
{
write_index_array_for_non_indexed_non_native_primitive_to_buffer(reinterpret_cast<char*>(dst_ptr), type, 0, vertex_count);
return std::make_tuple(0, vertex_count-1, VK_INDEX_TYPE_UINT16);
}
}
}
write_index_array_for_non_indexed_non_native_primitive_to_buffer(reinterpret_cast<char*>(dst_ptr), type, 0, vertex_count);
return std::make_tuple(0, vertex_count-1, VK_INDEX_TYPE_UINT16);
}
}
@ -342,7 +281,7 @@ VKGSRender::upload_vertex_data()
if (primitives_emulated)
{
index_count = vk::get_emulated_index_array_size(draw_mode, vertex_draw_count);
index_count = get_index_count(draw_mode, vertex_draw_count);
upload_size = index_count * sizeof(u16);
if (is_indexed_draw)
@ -355,7 +294,7 @@ VKGSRender::upload_vertex_data()
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer_ring_info.map(offset_in_index_buffer, upload_size);
std::tie(min_index, max_index, index_format) = vk::upload_index_buffer(draw_mode, type, buf, is_indexed_draw, vertex_draw_count, index_count, ranges);
std::tie(min_index, max_index, index_format) = vk::upload_index_buffer(get_raw_index_array(ranges), draw_mode, type, buf, is_indexed_draw, vertex_draw_count, index_count, ranges);
m_index_buffer_ring_info.unmap();
is_indexed_draw = true;