Merge pull request #2033 from vlj/rsx-refactor

rsx: Use a "draw clause" object in rsx_state.
This commit is contained in:
vlj 2016-08-05 23:48:48 +02:00 committed by GitHub
commit 247c776a1b
11 changed files with 102 additions and 106 deletions

View file

@ -303,7 +303,7 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
{ {
size_t index_count = 0; size_t index_count = 0;
for (const auto &pair : vertex_ranges) for (const auto &pair : vertex_ranges)
index_count += get_index_count(draw_mode, pair.second); index_count += get_index_count(rsx::method_registers.current_draw_clause.primitive, pair.second);
// Alloc // Alloc
size_t buffer_size = align(index_count * sizeof(u16), 64); size_t buffer_size = align(index_count * sizeof(u16), 64);
@ -313,8 +313,8 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
size_t first = 0; size_t first = 0;
for (const auto &pair : vertex_ranges) for (const auto &pair : vertex_ranges)
{ {
size_t element_count = get_index_count(draw_mode, pair.second); size_t element_count = get_index_count(rsx::method_registers.current_draw_clause.primitive, pair.second);
write_index_array_for_non_indexed_non_native_primitive_to_buffer((char*)mapped_buffer, draw_mode, (u32)first, (u32)pair.second); write_index_array_for_non_indexed_non_native_primitive_to_buffer((char*)mapped_buffer, rsx::method_registers.current_draw_clause.primitive, (u32)first, (u32)pair.second);
mapped_buffer = (char*)mapped_buffer + element_count * sizeof(u16); mapped_buffer = (char*)mapped_buffer + element_count * sizeof(u16);
first += pair.second; first += pair.second;
} }
@ -330,7 +330,7 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list) std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list)
{ {
if (draw_command == rsx::draw_command::inlined_array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array)
{ {
size_t vertex_count; size_t vertex_count;
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_view; std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_view;
@ -339,7 +339,7 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
{ (const gsl::byte*) inline_vertex_array.data(), gsl::narrow<int>(inline_vertex_array.size() * sizeof(uint)) }, { (const gsl::byte*) inline_vertex_array.data(), gsl::narrow<int>(inline_vertex_array.size() * sizeof(uint)) },
m_buffer_data, m_vertex_buffer_data.Get(), command_list); m_buffer_data, m_vertex_buffer_data.Get(), command_list);
if (is_primitive_native(draw_mode)) if (is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
return std::make_tuple(false, vertex_count, vertex_buffer_view); return std::make_tuple(false, vertex_count, vertex_buffer_view);
D3D12_INDEX_BUFFER_VIEW index_buffer_view; D3D12_INDEX_BUFFER_VIEW index_buffer_view;
@ -349,25 +349,25 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
return std::make_tuple(true, index_count, vertex_buffer_view); return std::make_tuple(true, index_count, vertex_buffer_view);
} }
if (draw_command == rsx::draw_command::array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array)
{ {
if (is_primitive_native(draw_mode)) if (is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
{ {
size_t vertex_count = get_vertex_count(first_count_commands); size_t vertex_count = get_vertex_count(rsx::method_registers.current_draw_clause.first_count_commands);
return std::make_tuple(false, vertex_count, upload_vertex_attributes(first_count_commands, command_list)); return std::make_tuple(false, vertex_count, upload_vertex_attributes(rsx::method_registers.current_draw_clause.first_count_commands, command_list));
} }
D3D12_INDEX_BUFFER_VIEW index_buffer_view; D3D12_INDEX_BUFFER_VIEW index_buffer_view;
size_t index_count; size_t index_count;
std::tie(index_buffer_view, index_count) = generate_index_buffer_for_emulated_primitives_array(first_count_commands); std::tie(index_buffer_view, index_count) = generate_index_buffer_for_emulated_primitives_array(rsx::method_registers.current_draw_clause.first_count_commands);
command_list->IASetIndexBuffer(&index_buffer_view); command_list->IASetIndexBuffer(&index_buffer_view);
return std::make_tuple(true, index_count, upload_vertex_attributes(first_count_commands, command_list)); return std::make_tuple(true, index_count, upload_vertex_attributes(rsx::method_registers.current_draw_clause.first_count_commands, command_list));
} }
EXPECTS(draw_command == rsx::draw_command::indexed); EXPECTS(rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed);
// Index count // Index count
size_t index_count = get_index_count(draw_mode, gsl::narrow<int>(get_vertex_count(first_count_commands))); size_t index_count = get_index_count(rsx::method_registers.current_draw_clause.primitive, gsl::narrow<int>(get_vertex_count(rsx::method_registers.current_draw_clause.first_count_commands)));
rsx::index_array_type indexed_type = rsx::method_registers.index_type(); rsx::index_array_type indexed_type = rsx::method_registers.index_type();
size_t index_size = get_index_type_size(indexed_type); size_t index_size = get_index_type_size(indexed_type);
@ -380,8 +380,8 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
u32 min_index, max_index; u32 min_index, max_index;
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(mapped_buffer), gsl::narrow<u32>(buffer_size) }; 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, get_raw_index_array(first_count_commands), std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, get_raw_index_array(rsx::method_registers.current_draw_clause.first_count_commands),
indexed_type, draw_mode, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands, indexed_type, rsx::method_registers.current_draw_clause.primitive, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), rsx::method_registers.current_draw_clause.first_count_commands,
[](auto prim) { return !is_primitive_native(prim); }); [](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));

View file

@ -442,7 +442,7 @@ void D3D12GSRender::end()
get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(),
rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height())); rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(draw_mode)); get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(rsx::method_registers.current_draw_clause.primitive));
if (indexed_draw) if (indexed_draw)
get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0); get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0);

View file

@ -44,7 +44,7 @@ void D3D12GSRender::load_program()
m_fragment_program = get_current_fragment_program(); m_fragment_program = get_current_fragment_program();
D3D12PipelineProperties prop = {}; D3D12PipelineProperties prop = {};
prop.Topology = get_primitive_topology_type(draw_mode); prop.Topology = get_primitive_topology_type(rsx::method_registers.current_draw_clause.primitive);
static D3D12_BLEND_DESC CD3D12_BLEND_DESC = static D3D12_BLEND_DESC CD3D12_BLEND_DESC =
{ {

View file

@ -497,30 +497,30 @@ void GLGSRender::end()
m_program->validate(); m_program->validate();
} }
if (draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
rsx::index_array_type indexed_type = rsx::method_registers.index_type(); rsx::index_array_type indexed_type = rsx::method_registers.index_type();
if (indexed_type == rsx::index_array_type::u32) if (indexed_type == rsx::index_array_type::u32)
{ {
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_INT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer); __glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, GL_UNSIGNED_INT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
} }
else if (indexed_type == rsx::index_array_type::u16) else if (indexed_type == rsx::index_array_type::u16)
{ {
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer); __glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
} }
else else
{ {
throw std::logic_error("bad index array type"); throw std::logic_error("bad index array type");
} }
} }
else if (!gl::is_primitive_native(draw_mode)) else if (!gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
{ {
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer); __glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
} }
else else
{ {
draw_fbo.draw_arrays(draw_mode, vertex_draw_count); draw_fbo.draw_arrays(rsx::method_registers.current_draw_clause.primitive, vertex_draw_count);
} }
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

View file

@ -199,27 +199,24 @@ u32 GLGSRender::set_vertex_buffer()
} }
} }
if (draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
rsx::index_array_type type = rsx::method_registers.index_type(); rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type)); u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
for (const auto& first_count : first_count_commands) vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count();
{
vertex_draw_count += first_count.second;
}
u32 max_size = get_index_count(draw_mode, vertex_draw_count) * type_size; u32 max_size = get_index_count(rsx::method_registers.current_draw_clause.primitive, vertex_draw_count) * type_size;
auto mapping = m_index_ring_buffer.alloc_and_map(max_size); auto mapping = m_index_ring_buffer.alloc_and_map(max_size);
void *ptr = mapping.first; void *ptr = mapping.first;
offset_in_index_buffer = mapping.second; offset_in_index_buffer = mapping.second;
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); std::tie(min_index, max_index, vertex_draw_count) = upload_index_buffer(get_raw_index_array(rsx::method_registers.current_draw_clause.first_count_commands), ptr, type, rsx::method_registers.current_draw_clause.primitive, rsx::method_registers.current_draw_clause.first_count_commands, vertex_draw_count);
m_index_ring_buffer.unmap(); m_index_ring_buffer.unmap();
} }
if (draw_command == rsx::draw_command::inlined_array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array)
{ {
u32 stride = 0; u32 stride = 0;
u32 offsets[rsx::limits::vertex_count] = { 0 }; u32 offsets[rsx::limits::vertex_count] = { 0 };
@ -287,22 +284,19 @@ u32 GLGSRender::set_vertex_buffer()
//Link texture to uniform //Link texture to uniform
m_program->uniforms.texture(location, index + texture_index_offset, texture); m_program->uniforms.texture(location, index + texture_index_offset, texture);
if (!gl::is_primitive_native(draw_mode)) if (!gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
{ {
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, draw_mode, m_index_ring_buffer); std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, rsx::method_registers.current_draw_clause.primitive, m_index_ring_buffer);
} }
} }
} }
if (draw_command == rsx::draw_command::array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array)
{ {
for (const auto &first_count : first_count_commands) vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count();
{
vertex_draw_count += first_count.second;
}
} }
if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array || rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
u32 verts_allocated = std::max(vertex_draw_count, max_index + 1); u32 verts_allocated = std::max(vertex_draw_count, max_index + 1);
__glcheck m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size); __glcheck m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size);
@ -342,7 +336,7 @@ u32 GLGSRender::set_vertex_buffer()
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31); u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address)); const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
if (draw_command == rsx::draw_command::array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array)
{ {
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment); auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
gsl::byte *dst = static_cast<gsl::byte*>(mapping.first); gsl::byte *dst = static_cast<gsl::byte*>(mapping.first);
@ -352,14 +346,14 @@ u32 GLGSRender::set_vertex_buffer()
gsl::span<gsl::byte> dest_span(dst, data_size); gsl::span<gsl::byte> dest_span(dst, data_size);
prepare_buffer_for_writing(dst, vertex_info.type, vertex_info.size, vertex_draw_count); prepare_buffer_for_writing(dst, vertex_info.type, vertex_info.size, vertex_draw_count);
for (const auto &first_count : first_count_commands) for (const auto &first_count : rsx::method_registers.current_draw_clause.first_count_commands)
{ {
write_vertex_array_data_to_buffer(dest_span.subspan(offset), src_ptr, first_count.first, first_count.second, vertex_info.type, vertex_info.size, vertex_info.stride, rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size)); write_vertex_array_data_to_buffer(dest_span.subspan(offset), src_ptr, first_count.first, first_count.second, vertex_info.type, vertex_info.size, vertex_info.stride, rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size));
offset += first_count.second * element_size; offset += first_count.second * element_size;
} }
} }
if (draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
data_size = (max_index + 1) * element_size; data_size = (max_index + 1) * element_size;
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment); auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
@ -415,9 +409,9 @@ u32 GLGSRender::set_vertex_buffer()
} }
} }
if (draw_command == rsx::draw_command::array && !gl::is_primitive_native(draw_mode)) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array && !gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
{ {
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw(first_count_commands, draw_mode, m_index_ring_buffer); std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw(rsx::method_registers.current_draw_clause.first_count_commands, rsx::method_registers.current_draw_clause.primitive, m_index_ring_buffer);
} }
} }

View file

@ -311,14 +311,11 @@ namespace rsx
draw_state.color_buffer = std::move(copy_render_targets_to_memory()); draw_state.color_buffer = std::move(copy_render_targets_to_memory());
draw_state.depth_stencil = std::move(copy_depth_stencil_buffer_to_memory()); draw_state.depth_stencil = std::move(copy_depth_stencil_buffer_to_memory());
if (draw_command == rsx::draw_command::indexed) if (draw_state.state.current_draw_clause.command == rsx::draw_command::indexed)
{ {
draw_state.vertex_count = 0; draw_state.vertex_count = 0;
for (const auto &range : first_count_commands) draw_state.vertex_count = draw_state.state.current_draw_clause.get_elements_count();
{ auto index_raw_data_ptr = get_raw_index_array(draw_state.state.current_draw_clause.first_count_commands);
draw_state.vertex_count += range.second;
}
auto index_raw_data_ptr = get_raw_index_array(first_count_commands);
draw_state.index.resize(index_raw_data_ptr.size_bytes()); 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()); std::copy(index_raw_data_ptr.begin(), index_raw_data_ptr.end(), draw_state.index.begin());
} }
@ -332,9 +329,6 @@ namespace rsx
{ {
draw_inline_vertex_array = false; draw_inline_vertex_array = false;
inline_vertex_array.clear(); inline_vertex_array.clear();
first_count_commands.clear();
draw_command = rsx::draw_command::none;
draw_mode = method_registers.primitive_mode();
} }
void thread::end() void thread::end()
@ -349,13 +343,8 @@ namespace rsx
if (capture_current_frame) if (capture_current_frame)
{ {
for (const auto &first_count : first_count_commands) u32 element_count = rsx::method_registers.current_draw_clause.get_elements_count();
{ capture_frame("Draw " + rsx::to_string(rsx::method_registers.current_draw_clause.primitive) + std::to_string(element_count));
vertex_draw_count += first_count.second;
}
capture_frame("Draw " + std::to_string(vertex_draw_count));
vertex_draw_count = 0;
} }
} }

View file

@ -143,14 +143,6 @@ namespace rsx
} }
}; };
enum class draw_command
{
none,
array,
inlined_array,
indexed,
};
class thread : public named_thread class thread : public named_thread
{ {
std::shared_ptr<thread_ctrl> m_vblank_thread; std::shared_ptr<thread_ctrl> m_vblank_thread;
@ -171,11 +163,6 @@ namespace rsx
u32 vertex_draw_count = 0; u32 vertex_draw_count = 0;
/**
* Stores the first and count argument from draw/draw indexed parameters between begin/end clauses.
*/
std::vector<std::pair<u32, u32> > first_count_commands;
// Constant stored for whole frame // Constant stored for whole frame
std::unordered_map<u32, color4f> local_transform_constants; std::unordered_map<u32, color4f> local_transform_constants;
@ -198,8 +185,6 @@ namespace rsx
u32 gcm_current_buffer; u32 gcm_current_buffer;
u32 ctxt_addr; u32 ctxt_addr;
u32 label_addr; u32 label_addr;
rsx::draw_command draw_command;
primitive_type draw_mode;
u32 local_mem_addr, main_mem_addr; u32 local_mem_addr, main_mem_addr;
bool strict_ordering[0x1000]; bool strict_ordering[0x1000];

View file

@ -854,7 +854,7 @@ bool VKGSRender::load_program()
properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
bool unused; bool unused;
properties.ia.topology = vk::get_appropriate_topology(draw_mode, unused); properties.ia.topology = vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, unused);
if (rsx::method_registers.restart_index_enabled()) if (rsx::method_registers.restart_index_enabled())
{ {

View file

@ -246,42 +246,36 @@ VKGSRender::upload_vertex_data()
vertex_draw_count = 0; vertex_draw_count = 0;
u32 min_index, max_index; u32 min_index, max_index;
bool is_indexed_draw = (draw_command == rsx::draw_command::indexed); bool is_indexed_draw = (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed);
bool primitives_emulated = false; bool primitives_emulated = false;
u32 index_count = 0; u32 index_count = 0;
VkIndexType index_format = VK_INDEX_TYPE_UINT16; VkIndexType index_format = VK_INDEX_TYPE_UINT16;
VkPrimitiveTopology prims = vk::get_appropriate_topology(draw_mode, primitives_emulated); VkPrimitiveTopology prims = vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitives_emulated);
if (draw_command == rsx::draw_command::array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array)
{ {
for (const auto &first_count : first_count_commands) vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count();
{
vertex_draw_count += first_count.second;
}
} }
if (draw_command == rsx::draw_command::indexed || primitives_emulated) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed || primitives_emulated)
{ {
rsx::index_array_type type = rsx::method_registers.index_type(); rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type)); u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
if (is_indexed_draw) //Could be emulated or not, emulated array vertex count already computed above if (is_indexed_draw) //Could be emulated or not, emulated array vertex count already computed above
{ {
for (const auto& first_count : first_count_commands) vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count();
{
vertex_draw_count += first_count.second;
}
} }
index_count = vertex_draw_count; index_count = vertex_draw_count;
u32 upload_size = vertex_draw_count * type_size; u32 upload_size = vertex_draw_count * type_size;
std::vector<std::pair<u32, u32>> ranges = first_count_commands; std::vector<std::pair<u32, u32>> ranges = rsx::method_registers.current_draw_clause.first_count_commands;
if (primitives_emulated) if (primitives_emulated)
{ {
index_count = get_index_count(draw_mode, vertex_draw_count); index_count = get_index_count(rsx::method_registers.current_draw_clause.primitive, vertex_draw_count);
upload_size = index_count * sizeof(u16); upload_size = index_count * sizeof(u16);
if (is_indexed_draw) if (is_indexed_draw)
@ -294,13 +288,13 @@ VKGSRender::upload_vertex_data()
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); 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); 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(get_raw_index_array(ranges), 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), rsx::method_registers.current_draw_clause.primitive, type, buf, is_indexed_draw, vertex_draw_count, index_count, ranges);
m_index_buffer_ring_info.unmap(); m_index_buffer_ring_info.unmap();
is_indexed_draw = true; is_indexed_draw = true;
} }
if (draw_command == rsx::draw_command::inlined_array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array)
{ {
u32 stride = 0; u32 stride = 0;
u32 offsets[rsx::limits::vertex_count] = { 0 }; u32 offsets[rsx::limits::vertex_count] = { 0 };
@ -373,7 +367,7 @@ VKGSRender::upload_vertex_data()
} }
} }
if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array || rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
for (int index = 0; index < rsx::limits::vertex_count; ++index) for (int index = 0; index < rsx::limits::vertex_count; ++index)
{ {
@ -407,7 +401,7 @@ VKGSRender::upload_vertex_data()
u32 num_stored_verts = vertex_draw_count; u32 num_stored_verts = vertex_draw_count;
if (draw_command == rsx::draw_command::array) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array)
{ {
size_t offset = 0; size_t offset = 0;
offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(upload_size); offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(upload_size);
@ -416,7 +410,7 @@ VKGSRender::upload_vertex_data()
gsl::span<gsl::byte> dest_span(static_cast<gsl::byte*>(dst), upload_size); gsl::span<gsl::byte> dest_span(static_cast<gsl::byte*>(dst), upload_size);
for (const auto &first_count : first_count_commands) for (const auto &first_count : rsx::method_registers.current_draw_clause.first_count_commands)
{ {
write_vertex_array_data_to_buffer(dest_span.subspan(offset), src_ptr, first_count.first, first_count.second, vertex_info.type, vertex_info.size, vertex_info.stride, real_element_size); write_vertex_array_data_to_buffer(dest_span.subspan(offset), src_ptr, first_count.first, first_count.second, vertex_info.type, vertex_info.size, vertex_info.stride, real_element_size);
offset += first_count.second * real_element_size; offset += first_count.second * real_element_size;
@ -425,7 +419,7 @@ VKGSRender::upload_vertex_data()
m_attrib_ring_info.unmap(); m_attrib_ring_info.unmap();
} }
if (draw_command == rsx::draw_command::indexed) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
{ {
num_stored_verts = (max_index + 1); num_stored_verts = (max_index + 1);
upload_size = real_element_size * num_stored_verts; upload_size = real_element_size * num_stored_verts;

View file

@ -200,25 +200,25 @@ namespace rsx
void draw_arrays(thread* rsx, u32 _reg, u32 arg) void draw_arrays(thread* rsx, u32 _reg, u32 arg)
{ {
rsx->draw_command = rsx::draw_command::array; rsx::method_registers.current_draw_clause.command = rsx::draw_command::array;
u32 first = arg & 0xffffff; u32 first = arg & 0xffffff;
u32 count = (arg >> 24) + 1; u32 count = (arg >> 24) + 1;
rsx->first_count_commands.emplace_back(std::make_pair(first, count)); rsx::method_registers.current_draw_clause.first_count_commands.emplace_back(std::make_pair(first, count));
} }
void draw_index_array(thread* rsx, u32 _reg, u32 arg) void draw_index_array(thread* rsx, u32 _reg, u32 arg)
{ {
rsx->draw_command = rsx::draw_command::indexed; rsx::method_registers.current_draw_clause.command = rsx::draw_command::indexed;
u32 first = arg & 0xffffff; u32 first = arg & 0xffffff;
u32 count = (arg >> 24) + 1; u32 count = (arg >> 24) + 1;
rsx->first_count_commands.emplace_back(std::make_pair(first, count)); rsx::method_registers.current_draw_clause.first_count_commands.emplace_back(std::make_pair(first, count));
} }
void draw_inline_array(thread* rsx, u32 _reg, u32 arg) void draw_inline_array(thread* rsx, u32 _reg, u32 arg)
{ {
rsx->draw_command = rsx::draw_command::inlined_array; rsx::method_registers.current_draw_clause.command = rsx::draw_command::inlined_array;
rsx->draw_inline_vertex_array = true; rsx->draw_inline_vertex_array = true;
rsx->inline_vertex_array.push_back(arg); rsx->inline_vertex_array.push_back(arg);
} }
@ -250,6 +250,9 @@ namespace rsx
{ {
if (arg) if (arg)
{ {
rsx::method_registers.current_draw_clause.first_count_commands.clear();
rsx::method_registers.current_draw_clause.command = draw_command::none;
rsx::method_registers.current_draw_clause.primitive = rsx::method_registers.primitive_mode();
rsxthr->begin(); rsxthr->begin();
return; return;
} }
@ -267,20 +270,20 @@ namespace rsx
vertex_info.frequency = element_count; vertex_info.frequency = element_count;
if (rsxthr->draw_command == rsx::draw_command::none) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::none)
{ {
max_vertex_count = std::max<u32>(max_vertex_count, element_count); max_vertex_count = std::max<u32>(max_vertex_count, element_count);
} }
} }
} }
if (rsxthr->draw_command == rsx::draw_command::none && max_vertex_count) if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::none && max_vertex_count)
{ {
rsxthr->draw_command = rsx::draw_command::array; rsx::method_registers.current_draw_clause.command = rsx::draw_command::array;
rsxthr->first_count_commands.push_back(std::make_pair(0, max_vertex_count)); rsx::method_registers.current_draw_clause.first_count_commands.push_back(std::make_pair(0, max_vertex_count));
} }
if (!(rsxthr->first_count_commands.empty() && rsxthr->inline_vertex_array.empty())) if (!(rsx::method_registers.current_draw_clause.first_count_commands.empty() && rsxthr->inline_vertex_array.empty()))
{ {
rsxthr->end(); rsxthr->end();
} }

View file

@ -2,6 +2,7 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include <numeric>
#include "GCM.h" #include "GCM.h"
#include "rsx_decode.h" #include "rsx_decode.h"
@ -14,6 +15,34 @@
namespace rsx namespace rsx
{ {
enum class draw_command
{
none,
array,
inlined_array,
indexed,
};
struct draw_clause
{
primitive_type primitive;
draw_command command;
/**
* Stores the first and count argument from draw/draw indexed parameters between begin/end clauses.
*/
std::vector<std::pair<u32, u32> > first_count_commands;
/**
* Returns how many vertex or index will be consumed by the draw clause.
*/
u32 get_elements_count() const
{
return std::accumulate(first_count_commands.begin(), first_count_commands.end(), 0,
[](u32 acc, auto b) { return acc + b.second; });
}
};
using rsx_method_t = void(*)(class thread*, u32 reg, u32 arg); using rsx_method_t = void(*)(class thread*, u32 reg, u32 arg);
//TODO //TODO
@ -125,6 +154,8 @@ namespace rsx
std::array<u32, 512 * 4> transform_program; std::array<u32, 512 * 4> transform_program;
std::unordered_map<u32, color4_base<f32>> transform_constants; std::unordered_map<u32, color4_base<f32>> transform_constants;
draw_clause current_draw_clause;
/** /**
* RSX can sources vertex attributes from 2 places: * RSX can sources vertex attributes from 2 places:
* - Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write. * - Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write.