diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 0443337e35..388e889611 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -673,14 +673,17 @@ void VKGSRender::end() vkCmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline); vkCmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_sets, 0, nullptr); - if (!std::get<1>(upload_info)) - vkCmdDraw(m_command_buffer, vertex_draw_count, 1, 0, 0); + std::optional > index_info = std::get<2>(upload_info); + + if (!index_info) + vkCmdDraw(m_command_buffer, std::get<1>(upload_info), 1, 0, 0); else { VkIndexType index_type; - u32 index_count; + u32 index_count = std::get<1>(upload_info); VkDeviceSize offset; - std::tie(std::ignore, std::ignore, index_count, offset, index_type) = upload_info; + + std::tie(offset, index_type) = index_info.value(); vkCmdBindIndexBuffer(m_command_buffer, m_index_buffer_ring_info.heap->value, offset, index_type); vkCmdDrawIndexed(m_command_buffer, index_count, 1, 0, 0, 0); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 4d334710d6..368fc6f9f0 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -4,6 +4,7 @@ #include "VKTextureCache.h" #include "VKRenderTargets.h" #include "VKFormats.h" +#include #define RSX_DEBUG 1 @@ -85,7 +86,24 @@ private: void sync_at_semaphore_release(); void prepare_rtts(); /// returns primitive topology, is_indexed, index_count, offset in index buffer, index type - std::tuple upload_vertex_data(); + std::tuple > > upload_vertex_data(); + + void upload_vertex_buffers(u32 input_mask, u32 vertex_max_index); + + /// returns number of vertex drawn + u32 upload_inlined_array(); + + /** + * Upload index (and expands it if primitive type is not natively supported). + * Returns min index, max index, index_count, and (offset_in_index_buffer, index_type) + */ + std::tuple> upload_index_buffer(const rsx::draw_clause &clause); + + /** + * Creates and fills an index buffer emulating unsupported primitive type. + * Returns index_count and (offset_in_index_buffer, index_type) + */ + std::tuple > generate_emulating_index_buffer(const rsx::draw_clause &clause); public: bool load_program(); diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index 3b3634efda..8d967c41dc 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -204,33 +204,11 @@ namespace vk } throw; } - - std::tuple upload_index_buffer(gsl::span 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> first_count_commands) - { - bool emulated = false; - get_appropriate_topology(type, emulated); - - if (indexed_draw) - { - 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(static_cast(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)); - } - - write_index_array_for_non_indexed_non_native_primitive_to_buffer(reinterpret_cast(dst_ptr), type, 0, vertex_count); - return std::make_tuple(0, vertex_count-1, VK_INDEX_TYPE_UINT16); - } } -std::tuple -VKGSRender::upload_vertex_data() +namespace { - //initialize vertex attributes - const std::string reg_table[] = + static constexpr std::array s_reg_table = { "in_pos_buffer", "in_weight_buffer", "in_normal_buffer", "in_diff_color_buffer", "in_spec_color_buffer", @@ -239,266 +217,279 @@ VKGSRender::upload_vertex_data() "in_tc0_buffer", "in_tc1_buffer", "in_tc2_buffer", "in_tc3_buffer", "in_tc4_buffer", "in_tc5_buffer", "in_tc6_buffer", "in_tc7_buffer" }; +} +std::tuple > > +VKGSRender::upload_vertex_data() +{ u32 input_mask = rsx::method_registers.vertex_attrib_input_mask(); - - size_t offset_in_index_buffer = -1; - vertex_draw_count = 0; u32 min_index, max_index; bool is_indexed_draw = (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed); - bool primitives_emulated = false; - u32 index_count = 0; + u32 index_count = 0; - VkIndexType index_format = VK_INDEX_TYPE_UINT16; + std::optional > index_info; + + if (is_indexed_draw) + { + std::tie(min_index, max_index, index_count, index_info) = upload_index_buffer(rsx::method_registers.current_draw_clause); + } + + bool primitives_emulated = false; VkPrimitiveTopology prims = vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitives_emulated); if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array) { - vertex_draw_count += rsx::method_registers.current_draw_clause.get_elements_count(); - } - - 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 = ::narrow(get_index_type_size(type)); - - if (is_indexed_draw) //Could be emulated or not, emulated array vertex count already computed above - { - 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 = rsx::method_registers.current_draw_clause.first_count_commands; - if (primitives_emulated) { - 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) - { - ranges.resize(0); - ranges.push_back(std::pair(0, vertex_draw_count)); - } + std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause); + } + else + { + index_count = rsx::method_registers.current_draw_clause.get_elements_count(); } - - 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), 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; + min_index = 0; + max_index = rsx::method_registers.current_draw_clause.get_elements_count() - 1; } if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array) { - u32 stride = 0; - u32 offsets[rsx::limits::vertex_count] = { 0 }; - - for (u32 i = 0; i < rsx::limits::vertex_count; ++i) - { - const auto &info = rsx::method_registers.vertex_arrays_info[i]; - if (!info.size) continue; - - offsets[i] = stride; - stride += rsx::get_vertex_type_size_on_host(info.type, info.size); - } - - vertex_draw_count = (u32)(inline_vertex_array.size() * sizeof(u32)) / stride; - - for (int index = 0; index < rsx::limits::vertex_count; ++index) - { - auto &vertex_info = rsx::method_registers.vertex_arrays_info[index]; - - if (!m_program->has_uniform(reg_table[index])) - continue; - - if (!vertex_info.size) // disabled - { - continue; - } - - const u32 element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); - const u32 data_size = element_size * vertex_draw_count; - const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); - - u32 offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); - u8 *src = reinterpret_cast(inline_vertex_array.data()); - u8 *dst = static_cast(m_attrib_ring_info.map(offset_in_attrib_buffer, data_size)); - - src += offsets[index]; - u8 opt_size = vertex_info.size; - - if (vertex_info.size == 3) - opt_size = 4; - - //TODO: properly handle cmp type - if (vertex_info.type == rsx::vertex_base_type::cmp) - LOG_ERROR(RSX, "Compressed vertex attributes not supported for inlined arrays yet"); - - switch (vertex_info.type) - { - case rsx::vertex_base_type::f: - vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); - break; - case rsx::vertex_base_type::sf: - vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); - break; - case rsx::vertex_base_type::s1: - case rsx::vertex_base_type::ub: - case rsx::vertex_base_type::ub256: - vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); - break; - case rsx::vertex_base_type::s32k: - case rsx::vertex_base_type::cmp: - vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); - break; - default: - fmt::throw_exception("Unknown base type %d" HERE, (u32)vertex_info.type); - } - - m_attrib_ring_info.unmap(); - m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size)); - m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); - } + index_count = upload_inlined_array(); } 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) - { - bool enabled = !!(input_mask & (1 << index)); - - if (!m_program->has_uniform(reg_table[index])) - continue; - - if (!enabled) - { - continue; - } - - if (rsx::method_registers.vertex_arrays_info[index].size > 0) - { - auto &vertex_info = rsx::method_registers.vertex_arrays_info[index]; - - // Fill vertex_array - u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); - u32 real_element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); - - u32 upload_size = real_element_size * vertex_draw_count; - u32 offset_in_attrib_buffer = 0; - bool requires_expansion = vk::requires_component_expansion(vertex_info.type, vertex_info.size); - - // Get source pointer - u32 base_offset = rsx::method_registers.vertex_data_base_offset(); - u32 offset = rsx::method_registers.vertex_arrays_info[index].offset(); - u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31); - const gsl::byte *src_ptr = gsl::narrow_cast(vm::base(address)); - - u32 num_stored_verts = vertex_draw_count; - - 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); - void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, upload_size); - vk::prepare_buffer_for_writing(dst, vertex_info.type, vertex_info.size, vertex_draw_count); - - gsl::span dest_span(static_cast(dst), upload_size); - - 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; - } - - m_attrib_ring_info.unmap(); - } - - 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; - offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(upload_size); - void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, upload_size); - - gsl::span dest_span(static_cast(dst), upload_size); - vk::prepare_buffer_for_writing(dst, vertex_info.type, vertex_info.size, num_stored_verts); - - write_vertex_array_data_to_buffer(dest_span, src_ptr, 0, max_index + 1, vertex_info.type, vertex_info.size, vertex_info.stride, real_element_size); - m_attrib_ring_info.unmap(); - } - - const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); - - m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, upload_size)); - m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); - } - else if (rsx::method_registers.register_vertex_info[index].size > 0) - { - //Untested! - auto &vertex_info = rsx::method_registers.register_vertex_info[index]; - - switch (vertex_info.type) - { - case rsx::vertex_base_type::f: - { - size_t data_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); - const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); - - u32 offset_in_attrib_buffer = 0; - void *data_ptr = vertex_info.data.data(); - - if (vk::requires_component_expansion(vertex_info.type, vertex_info.size)) - { - const u32 num_stored_verts = static_cast(data_size / (sizeof(float) * vertex_info.size)); - const u32 real_element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); - - data_size = real_element_size * num_stored_verts; - offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); - void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); - - vk::expand_array_components(reinterpret_cast(vertex_info.data.data()), dst, num_stored_verts); - m_attrib_ring_info.unmap(); - } - else - { - offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); - void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); - memcpy(dst, vertex_info.data.data(), data_size); - m_attrib_ring_info.unmap(); - } - - m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size)); - m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); - break; - } - default: - LOG_ERROR(RSX, "bad non array vertex data format (type=%d, size=%d)", (u32)vertex_info.type, vertex_info.size); - break; - } - } - else - { - //This section should theoretically be unreachable (data stream without available data) - //Variable is defined in the shaders but no data is available - //Bind a buffer view to keep the driver from crashing if access is attempted. - - u32 offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(32); - void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, 32); - memset(dst, 0, 32); - m_attrib_ring_info.unmap(); - - m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, VK_FORMAT_R32_SFLOAT, offset_in_attrib_buffer, 32)); - m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); - } - } + upload_vertex_buffers(input_mask, max_index); } - return std::make_tuple(prims, is_indexed_draw, index_count, offset_in_index_buffer, index_format); + return std::make_tuple(prims, index_count, index_info); } +void VKGSRender::upload_vertex_buffers(u32 input_mask, u32 vertex_max_index) +{ + for (int index = 0; index < rsx::limits::vertex_count; ++index) + { + bool enabled = !!(input_mask & (1 << index)); + + if (!m_program->has_uniform(s_reg_table[index])) + continue; + + if (!enabled) + { + continue; + } + + if (rsx::method_registers.vertex_arrays_info[index].size > 0) + { + auto &vertex_info = rsx::method_registers.vertex_arrays_info[index]; + + // Fill vertex_array + u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); + u32 real_element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); + + u32 upload_size = real_element_size * (vertex_max_index + 1); + bool requires_expansion = vk::requires_component_expansion(vertex_info.type, vertex_info.size); + + // Get source pointer + u32 base_offset = rsx::method_registers.vertex_data_base_offset(); + u32 offset = rsx::method_registers.vertex_arrays_info[index].offset(); + u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31); + const gsl::byte *src_ptr = gsl::narrow_cast(vm::base(address)); + + u32 num_stored_verts = vertex_max_index + 1; + VkDeviceSize offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(upload_size); + void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, upload_size); + vk::prepare_buffer_for_writing(dst, vertex_info.type, vertex_info.size, vertex_max_index + 1); + gsl::span dest_span(static_cast(dst), upload_size); + + if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array) + { + VkDeviceSize offset = 0; + 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; + } + } + else if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed) + { + write_vertex_array_data_to_buffer(dest_span, src_ptr, 0, vertex_max_index + 1, vertex_info.type, vertex_info.size, vertex_info.stride, real_element_size); + } + + m_attrib_ring_info.unmap(); + const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); + + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, upload_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets); + } + else if (rsx::method_registers.register_vertex_info[index].size > 0) + { + //Untested! + auto &vertex_info = rsx::method_registers.register_vertex_info[index]; + + switch (vertex_info.type) + { + case rsx::vertex_base_type::f: + { + size_t data_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); + const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); + + u32 offset_in_attrib_buffer = 0; + void *data_ptr = vertex_info.data.data(); + + if (vk::requires_component_expansion(vertex_info.type, vertex_info.size)) + { + const u32 num_stored_verts = static_cast(data_size / (sizeof(float) * vertex_info.size)); + const u32 real_element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); + + data_size = real_element_size * num_stored_verts; + offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); + void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); + + vk::expand_array_components(reinterpret_cast(vertex_info.data.data()), dst, num_stored_verts); + m_attrib_ring_info.unmap(); + } + else + { + offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); + void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); + memcpy(dst, vertex_info.data.data(), data_size); + m_attrib_ring_info.unmap(); + } + + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets); + break; + } + default: + fmt::throw_exception("Unknown base type %d" HERE, (u32)vertex_info.type); + } + } + else + { + //This section should theoretically be unreachable (data stream without available data) + //Variable is defined in the shaders but no data is available + //Bind a buffer view to keep the driver from crashing if access is attempted. + + u32 offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(32); + void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, 32); + memset(dst, 0, 32); + m_attrib_ring_info.unmap(); + + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, VK_FORMAT_R32_SFLOAT, offset_in_attrib_buffer, 32)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets); + } + } +} + +u32 VKGSRender::upload_inlined_array() +{ + u32 stride = 0; + u32 offsets[rsx::limits::vertex_count] = { 0 }; + + for (u32 i = 0; i < rsx::limits::vertex_count; ++i) + { + const auto &info = rsx::method_registers.vertex_arrays_info[i]; + if (!info.size) continue; + + offsets[i] = stride; + stride += rsx::get_vertex_type_size_on_host(info.type, info.size); + } + + u32 vertex_draw_count = (u32)(inline_vertex_array.size() * sizeof(u32)) / stride; + + for (int index = 0; index < rsx::limits::vertex_count; ++index) + { + auto &vertex_info = rsx::method_registers.vertex_arrays_info[index]; + + if (!m_program->has_uniform(s_reg_table[index])) + continue; + + if (!vertex_info.size) // disabled + { + continue; + } + + const u32 element_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size); + const u32 data_size = element_size * vertex_draw_count; + const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); + + u32 offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); + u8 *src = reinterpret_cast(inline_vertex_array.data()); + u8 *dst = static_cast(m_attrib_ring_info.map(offset_in_attrib_buffer, data_size)); + + src += offsets[index]; + u8 opt_size = vertex_info.size; + + if (vertex_info.size == 3) + opt_size = 4; + + //TODO: properly handle cmp type + if (vertex_info.type == rsx::vertex_base_type::cmp) + LOG_ERROR(RSX, "Compressed vertex attributes not supported for inlined arrays yet"); + + switch (vertex_info.type) + { + case rsx::vertex_base_type::f: + vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); + break; + case rsx::vertex_base_type::sf: + vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); + break; + case rsx::vertex_base_type::s1: + case rsx::vertex_base_type::ub: + case rsx::vertex_base_type::ub256: + vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); + break; + case rsx::vertex_base_type::s32k: + case rsx::vertex_base_type::cmp: + vk::copy_inlined_data_to_buffer(src, dst, vertex_draw_count, vertex_info.type, vertex_info.size, opt_size, element_size, stride); + break; + default: + fmt::throw_exception("Unknown base type %d" HERE, (u32)vertex_info.type); + } + + m_attrib_ring_info.unmap(); + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets); + } + return vertex_draw_count; +} + +std::tuple> VKGSRender::upload_index_buffer(const rsx::draw_clause &clause) +{ + rsx::index_array_type index_type = rsx::method_registers.index_type(); + u32 type_size = gsl::narrow(get_index_type_size(index_type)); + + u32 index_count = get_index_count(clause.primitive, clause.get_elements_count()); + u32 upload_size = index_count * type_size; + + VkDeviceSize 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); + + u32 min_index, max_index; + std::tie(min_index, max_index) = write_index_array_data_to_buffer(gsl::span(static_cast(buf), index_count * type_size), get_raw_index_array(clause.first_count_commands), + index_type, clause.primitive, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), clause.first_count_commands, + [](auto prim) { return !is_primitive_native(prim); }); + + m_index_buffer_ring_info.unmap(); + return std::make_tuple(min_index, max_index, index_count, std::make_tuple(offset_in_index_buffer, vk::get_index_type(index_type))); +} + + +std::tuple > VKGSRender::generate_emulating_index_buffer(const rsx::draw_clause &clause) +{ + u32 vertex_count = clause.get_elements_count(); + + u32 index_count = get_index_count(clause.primitive, vertex_count); + u32 upload_size = index_count * sizeof(u16); + + VkDeviceSize 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); + + write_index_array_for_non_indexed_non_native_primitive_to_buffer(reinterpret_cast(buf), clause.primitive, 0, vertex_count); + + m_index_buffer_ring_info.unmap(); + return std::make_tuple(index_count, std::make_tuple(offset_in_index_buffer, VK_INDEX_TYPE_UINT16)); +}