From eb1d4811de22397250653526df3b60409ff28cbf Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Thu, 4 Aug 2016 19:59:50 +0200 Subject: [PATCH] rsx: Use a "draw clause" object in rsx_state. --- rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp | 30 +++++++++--------- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 2 +- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 12 ++++---- rpcs3/Emu/RSX/GL/vertex_buffer.cpp | 36 +++++++++------------- rpcs3/Emu/RSX/RSXThread.cpp | 21 +++---------- rpcs3/Emu/RSX/RSXThread.h | 15 --------- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 2 +- rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp | 34 +++++++++----------- rpcs3/Emu/RSX/rsx_methods.cpp | 23 ++++++++------ rpcs3/Emu/RSX/rsx_methods.h | 31 +++++++++++++++++++ 11 files changed, 102 insertions(+), 106 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 2fda5b8589..49fef0db29 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -303,7 +303,7 @@ std::tuple D3D12GSRender::generate_index_buffer { size_t index_count = 0; 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 size_t buffer_size = align(index_count * sizeof(u16), 64); @@ -313,8 +313,8 @@ std::tuple D3D12GSRender::generate_index_buffer size_t first = 0; for (const auto &pair : vertex_ranges) { - size_t element_count = get_index_count(draw_mode, pair.second); - write_index_array_for_non_indexed_non_native_primitive_to_buffer((char*)mapped_buffer, draw_mode, (u32)first, (u32)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, rsx::method_registers.current_draw_clause.primitive, (u32)first, (u32)pair.second); mapped_buffer = (char*)mapped_buffer + element_count * sizeof(u16); first += pair.second; } @@ -330,7 +330,7 @@ std::tuple D3D12GSRender::generate_index_buffer std::tuple> 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; std::vector vertex_buffer_view; @@ -339,7 +339,7 @@ std::tuple> D3D12GSRe { (const gsl::byte*) inline_vertex_array.data(), gsl::narrow(inline_vertex_array.size() * sizeof(uint)) }, 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); D3D12_INDEX_BUFFER_VIEW index_buffer_view; @@ -349,25 +349,25 @@ std::tuple> D3D12GSRe 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); - return std::make_tuple(false, vertex_count, upload_vertex_attributes(first_count_commands, command_list)); + 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(rsx::method_registers.current_draw_clause.first_count_commands, command_list)); } D3D12_INDEX_BUFFER_VIEW index_buffer_view; 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); - 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 - size_t index_count = get_index_count(draw_mode, gsl::narrow(get_vertex_count(first_count_commands))); + size_t index_count = get_index_count(rsx::method_registers.current_draw_clause.primitive, gsl::narrow(get_vertex_count(rsx::method_registers.current_draw_clause.first_count_commands))); rsx::index_array_type indexed_type = rsx::method_registers.index_type(); size_t index_size = get_index_type_size(indexed_type); @@ -380,8 +380,8 @@ std::tuple> D3D12GSRe u32 min_index, max_index; gsl::span dst{ reinterpret_cast(mapped_buffer), gsl::narrow(buffer_size) }; - 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, + 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, 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); }); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 0e14049564..ba6b24c398 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -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(), 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) get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index 56736d387d..fdd40afe1a 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -44,7 +44,7 @@ void D3D12GSRender::load_program() m_fragment_program = get_current_fragment_program(); 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 = { diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 877ecd95ea..eec0540b8e 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -497,30 +497,30 @@ void GLGSRender::end() 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(); 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) { - __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 { 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 { - 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 now = std::chrono::system_clock::now(); diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index c66dcc9c94..deb1fe45ab 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -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(); u32 type_size = gsl::narrow(get_index_type_size(type)); - for (const auto& first_count : first_count_commands) - { - vertex_draw_count += first_count.second; - } + vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count(); - 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); void *ptr = mapping.first; 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(); } - 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 offsets[rsx::limits::vertex_count] = { 0 }; @@ -287,22 +284,19 @@ u32 GLGSRender::set_vertex_buffer() //Link texture to uniform 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 += first_count.second; - } + vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count(); } - 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); __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); const gsl::byte *src_ptr = gsl::narrow_cast(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); gsl::byte *dst = static_cast(mapping.first); @@ -352,14 +346,14 @@ u32 GLGSRender::set_vertex_buffer() gsl::span dest_span(dst, data_size); 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)); 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; 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); } } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index c5b4fcfb70..3978011d72 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -311,14 +311,11 @@ namespace rsx draw_state.color_buffer = std::move(copy_render_targets_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; - for (const auto &range : first_count_commands) - { - draw_state.vertex_count += range.second; - } - auto index_raw_data_ptr = get_raw_index_array(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.index.resize(index_raw_data_ptr.size_bytes()); 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; inline_vertex_array.clear(); - first_count_commands.clear(); - draw_command = rsx::draw_command::none; - draw_mode = method_registers.primitive_mode(); } void thread::end() @@ -349,13 +343,8 @@ namespace rsx if (capture_current_frame) { - for (const auto &first_count : first_count_commands) - { - vertex_draw_count += first_count.second; - } - - capture_frame("Draw " + std::to_string(vertex_draw_count)); - vertex_draw_count = 0; + 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)); } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 50bef6a194..64f3fd2e03 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -143,14 +143,6 @@ namespace rsx } }; - enum class draw_command - { - none, - array, - inlined_array, - indexed, - }; - class thread : public named_thread { std::shared_ptr m_vblank_thread; @@ -171,11 +163,6 @@ namespace rsx u32 vertex_draw_count = 0; - /** - * Stores the first and count argument from draw/draw indexed parameters between begin/end clauses. - */ - std::vector > first_count_commands; - // Constant stored for whole frame std::unordered_map local_transform_constants; @@ -198,8 +185,6 @@ namespace rsx u32 gcm_current_buffer; u32 ctxt_addr; u32 label_addr; - rsx::draw_command draw_command; - primitive_type draw_mode; u32 local_mem_addr, main_mem_addr; bool strict_ordering[0x1000]; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index c7c3c4631e..f0ff23c387 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -854,7 +854,7 @@ bool VKGSRender::load_program() properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 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()) { diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index c257aeec6b..ca7e8850bf 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -246,42 +246,36 @@ VKGSRender::upload_vertex_data() vertex_draw_count = 0; 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; u32 index_count = 0; 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 += first_count.second; - } + vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count(); } - 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(); u32 type_size = gsl::narrow(get_index_type_size(type)); 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 += first_count.second; - } + vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count(); } index_count = vertex_draw_count; u32 upload_size = vertex_draw_count * type_size; - std::vector> ranges = first_count_commands; + std::vector> ranges = rsx::method_registers.current_draw_clause.first_count_commands; 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); 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); 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(); 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 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) { @@ -407,7 +401,7 @@ VKGSRender::upload_vertex_data() 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; offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(upload_size); @@ -416,7 +410,7 @@ VKGSRender::upload_vertex_data() gsl::span dest_span(static_cast(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); offset += first_count.second * real_element_size; @@ -425,7 +419,7 @@ VKGSRender::upload_vertex_data() 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); upload_size = real_element_size * num_stored_verts; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 68800e7aac..e22a9ebdc2 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -200,25 +200,25 @@ namespace rsx 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 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) { - rsx->draw_command = rsx::draw_command::indexed; + rsx::method_registers.current_draw_clause.command = rsx::draw_command::indexed; u32 first = arg & 0xffffff; 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) { - 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->inline_vertex_array.push_back(arg); } @@ -250,6 +250,9 @@ namespace rsx { 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(); return; } @@ -267,20 +270,20 @@ namespace rsx 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(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; - rsxthr->first_count_commands.push_back(std::make_pair(0, max_vertex_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, 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(); } diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index 16ebd772c6..7925aeb6e2 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -2,6 +2,7 @@ #include #include +#include #include "GCM.h" #include "rsx_decode.h" @@ -14,6 +15,34 @@ 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 > 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); //TODO @@ -125,6 +154,8 @@ namespace rsx std::array transform_program; std::unordered_map> transform_constants; + draw_clause current_draw_clause; + /** * RSX can sources vertex attributes from 2 places: * - Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write.