rsx: Support indexed immediate draw via ArrayElement method

This commit is contained in:
kd-11 2017-03-28 13:41:45 +03:00
parent 632287afe7
commit 909f3e9b3e
10 changed files with 92 additions and 22 deletions

View File

@ -395,7 +395,10 @@ namespace
get_index_count(rsx::method_registers.current_draw_clause.primitive,
::narrow<int>(get_vertex_count(command.ranges_to_fetch_in_index_buffer)));
rsx::index_array_type indexed_type = rsx::method_registers.index_type();
rsx::index_array_type indexed_type = rsx::method_registers.current_draw_clause.is_immediate_draw?
rsx::index_array_type::u32:
rsx::method_registers.index_type();
size_t index_size = get_index_type_size(indexed_type);
// Alloc

View File

@ -291,7 +291,10 @@ void D3D12GSRender::load_program()
if (rsx::method_registers.restart_index_enabled())
{
rsx::index_array_type index_type = rsx::method_registers.index_type();
rsx::index_array_type index_type = rsx::method_registers.current_draw_clause.is_immediate_draw?
rsx::index_array_type::u32:
rsx::method_registers.index_type();
if (index_type == rsx::index_array_type::u32)
{
prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;

View File

@ -332,7 +332,10 @@ namespace
{
u32 min_index = 0, max_index = 0;
rsx::index_array_type type = rsx::method_registers.index_type();
rsx::index_array_type type = rsx::method_registers.current_draw_clause.is_immediate_draw?
rsx::index_array_type::u32:
rsx::method_registers.index_type();
u32 type_size = ::narrow<u32>(get_index_type_size(type));
u32 vertex_count = rsx::method_registers.current_draw_clause.get_elements_count();

View File

@ -338,7 +338,7 @@ namespace rsx
vertex_push_buffers[attribute].append_vertex_data(subreg_index, type, value);
}
u32 thread::get_push_buffer_vertex_count()
u32 thread::get_push_buffer_vertex_count() const
{
//There's no restriction on which attrib shall hold vertex data, so we check them all
u32 max_vertex_count = 0;
@ -350,6 +350,18 @@ namespace rsx
return max_vertex_count;
}
void thread::append_array_element(u32 index)
{
//Endianness is swapped because common upload code expects input in BE
//TODO: Implement fast upload path for LE inputs and do away with this
element_push_buffer.push_back(se_storage<u32>::swap(index));
}
u32 thread::get_push_buffer_index_count() const
{
return element_push_buffer.size();
}
void thread::end()
{
rsx::method_registers.transform_constants.clear();
@ -363,6 +375,8 @@ namespace rsx
vertex_push_buffers[index].clear();
}
element_push_buffer.resize(0);
if (capture_current_frame)
{
u32 element_count = rsx::method_registers.current_draw_clause.get_elements_count();
@ -651,6 +665,12 @@ namespace rsx
gsl::span<const gsl::byte> thread::get_raw_index_array(const std::vector<std::pair<u32, u32> >& draw_indexed_clause) const
{
if (element_push_buffer.size())
{
//Indices provided via immediate mode
return{(const gsl::byte*)element_push_buffer.data(), ::narrow<u32>(element_push_buffer.size() * sizeof(u32))};
}
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();

View File

@ -169,6 +169,7 @@ namespace rsx
protected:
std::stack<u32> m_call_stack;
std::array<push_buffer_vertex_info, 16> vertex_push_buffers;
std::vector<u32> element_push_buffer;
public:
old_shaders_cache::shaders_cache shaders_cache;
@ -278,7 +279,10 @@ namespace rsx
* Appends a value to the push buffer (currently only supports 32-wide types)
*/
void append_to_push_buffer(u32 attribute, u32 size, u32 subreg_index, vertex_base_type type, u32 value);
u32 get_push_buffer_vertex_count();
u32 get_push_buffer_vertex_count() const;
void append_array_element(u32 index);
u32 get_push_buffer_index_count() const;
private:
std::mutex m_mtx_task;

View File

@ -397,7 +397,10 @@ namespace
VkPrimitiveTopology prims = vk::get_appropriate_topology(
rsx::method_registers.current_draw_clause.primitive, primitives_emulated);
rsx::index_array_type index_type = rsx::method_registers.index_type();
rsx::index_array_type index_type = rsx::method_registers.current_draw_clause.is_immediate_draw ?
rsx::index_array_type::u32 :
rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(index_type));
u32 index_count = rsx::method_registers.current_draw_clause.get_elements_count();

View File

@ -1000,12 +1000,11 @@ enum
NV3089_IMAGE_IN_OFFSET = 0x0000C408 >> 2,
NV3089_IMAGE_IN = 0x0000C40C >> 2,
GCM_FLIP_HEAD0 = 0X0000E920 >> 2,
GCM_FLIP_HEAD1 = 0X0000E924 >> 2,
GCM_PREPARE_DISPLAY_BUFFER_HEAD0 = 0X0000E940 >> 2, //0X940 + [HEAD << 2]
GCM_PREPARE_DISPLAY_BUFFER_HEAD1 = 0X0000E944 >> 2,
GCM_SET_USER_COMMAND = 0x0000EB00 >> 2,
GCM_SET_USER_COMMAND2 = 0x0000EB04 >> 2,
//lv1 hypervisor commands
GCM_SET_DRIVER_OBJECT = 0x0000E0000 >> 2,
GCM_FLIP_HEAD = 0X0000E920 >> 2, //0xE920:0xE924: Flip head 0 or 1
GCM_DRIVER_QUEUE = 0X0000E940 >> 2, //0XE940:0xE95C: First two indices prepare display buffers, rest unknown
GCM_SET_USER_COMMAND = 0x0000EB00 >> 2, //0xEB00:0xEB04: User interrupt
GCM_FLIP_COMMAND = 0x0000FEAC >> 2
};

View File

@ -203,6 +203,21 @@ namespace rsx
}
};
void set_array_element16(thread* rsx, u32, u32 arg)
{
if (rsx->in_begin_end)
{
rsx->append_array_element(arg & 0xFFFF);
rsx->append_array_element(arg >> 16);
}
}
void set_array_element32(thread* rsx, u32, u32 arg)
{
if (rsx->in_begin_end)
rsx->append_array_element(arg);
}
void draw_arrays(thread* rsx, u32 _reg, u32 arg)
{
rsx::method_registers.current_draw_clause.command = rsx::draw_command::array;
@ -262,12 +277,27 @@ namespace rsx
}
//Check if we have immediate mode vertex data in a driver-local buffer
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::none)
{
const u32 push_buffer_vertices_count = rsxthr->get_push_buffer_vertex_count();
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::none && push_buffer_vertices_count)
const u32 push_buffer_index_count = rsxthr->get_push_buffer_index_count();
//Need to set this flag since it overrides some register contents
rsx::method_registers.current_draw_clause.is_immediate_draw = true;
if (push_buffer_index_count)
{
rsx::method_registers.current_draw_clause.command = rsx::draw_command::indexed;
rsx::method_registers.current_draw_clause.first_count_commands.push_back(std::make_pair(0, push_buffer_index_count));
}
else if (push_buffer_vertices_count)
{
rsx::method_registers.current_draw_clause.command = rsx::draw_command::array;
rsx::method_registers.current_draw_clause.first_count_commands.push_back(std::make_pair(0, push_buffer_vertices_count));
}
}
else
rsx::method_registers.current_draw_clause.is_immediate_draw = false;
if (!(rsx::method_registers.current_draw_clause.first_count_commands.empty() &&
rsx::method_registers.current_draw_clause.inline_vertex_array.empty()))
@ -1245,8 +1275,10 @@ namespace rsx
methods[NV3089_IMAGE_IN] = nullptr;
//Some custom GCM methods
methods[GCM_PREPARE_DISPLAY_BUFFER_HEAD0] = nullptr;
methods[GCM_PREPARE_DISPLAY_BUFFER_HEAD1] = nullptr;
methods[GCM_SET_DRIVER_OBJECT] = nullptr;
bind_array<GCM_FLIP_HEAD, 1, 2, nullptr>();
bind_array<GCM_DRIVER_QUEUE, 1, 8, nullptr>();
bind_array<NV4097_SET_ANISO_SPREAD, 1, 16, nullptr>();
bind_array<NV4097_SET_VERTEX_TEXTURE_OFFSET, 1, 8 * 4, nullptr>();
@ -1290,6 +1322,8 @@ namespace rsx
bind<NV4097_DRAW_ARRAYS, nv4097::draw_arrays>();
bind<NV4097_DRAW_INDEX_ARRAY, nv4097::draw_index_array>();
bind<NV4097_INLINE_ARRAY, nv4097::draw_inline_array>();
bind<NV4097_ARRAY_ELEMENT16, nv4097::set_array_element16>();
bind<NV4097_ARRAY_ELEMENT32, nv4097::set_array_element32>();
bind_range<NV4097_SET_VERTEX_DATA_SCALED4S_M, 1, 32, nv4097::set_vertex_data_scaled4s_m>();
bind_range<NV4097_SET_VERTEX_DATA4UB_M, 1, 16, nv4097::set_vertex_data4ub_m>();
bind_range<NV4097_SET_VERTEX_DATA1F_M, 1, 16, nv4097::set_vertex_data1f_m>();
@ -1338,10 +1372,7 @@ namespace rsx
// custom methods
bind<GCM_FLIP_COMMAND, flip_command>();
bind<GCM_FLIP_HEAD0, flip_command>();
bind<GCM_FLIP_HEAD1, flip_command>();
bind<GCM_SET_USER_COMMAND, user_command>();
bind<GCM_SET_USER_COMMAND2, user_command>();
bind_array<GCM_SET_USER_COMMAND, 1, 2, user_command>();
return true;
}();

View File

@ -28,6 +28,8 @@ namespace rsx
primitive_type primitive;
draw_command command;
bool is_immediate_draw;
std::vector<u32> inline_vertex_array;
/**

View File

@ -110,6 +110,8 @@ struct push_buffer_vertex_info
void* dst = data.data() + ((vertex_count - 1) * vertex_size) + sub_index;
//NOTE: Endianness on wide types is converted to BE here because unified upload code assumes input in BE
//TODO: Implement fast LE source inputs and remove the byteswap
switch (type)
{
case vertex_base_type::f: