mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-05 06:39:52 +00:00
rsx: Support indexed immediate draw via ArrayElement method
This commit is contained in:
parent
632287afe7
commit
909f3e9b3e
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
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)
|
||||
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::none)
|
||||
{
|
||||
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));
|
||||
const u32 push_buffer_vertices_count = rsxthr->get_push_buffer_vertex_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;
|
||||
}();
|
||||
|
@ -28,6 +28,8 @@ namespace rsx
|
||||
primitive_type primitive;
|
||||
draw_command command;
|
||||
|
||||
bool is_immediate_draw;
|
||||
|
||||
std::vector<u32> inline_vertex_array;
|
||||
|
||||
/**
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user