diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 063648c228..c7207c6ae2 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -25,11 +25,12 @@ namespace vk using shader_cache = rsx::shaders_cache; } -//Heap allocation sizes in MB - each 'frame' owns a private heap, one of each kind +//Heap allocation sizes in MB +//NOTE: Texture uploads can be huge, upto 16MB for a single texture (4096x4096px) #define VK_ATTRIB_RING_BUFFER_SIZE_M 256 +#define VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M 256 #define VK_UBO_RING_BUFFER_SIZE_M 64 #define VK_INDEX_RING_BUFFER_SIZE_M 64 -#define VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M 128 #define VK_MAX_ASYNC_CB_COUNT 64 #define VK_MAX_ASYNC_FRAMES 2 diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 6a14d37ce9..d2bfe3d46e 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -15,6 +15,7 @@ namespace vk atomic_t g_cb_no_interrupt_flag { false }; atomic_t g_drv_no_primitive_restart_flag { false }; + atomic_t g_drv_force_32bit_indices{ false }; u64 g_num_processed_frames = 0; u64 g_num_total_frames = 0; @@ -280,8 +281,9 @@ namespace vk void set_current_renderer(const vk::render_device &device) { g_current_renderer = device; + const auto gpu_name = g_current_renderer.gpu().name(); - const std::array black_listed = +/* const std::array black_listed = { // Black list all polaris unless its proven they dont have a problem with primitive restart "RX 580", @@ -294,7 +296,6 @@ namespace vk "RX Vega", }; - const auto gpu_name = g_current_renderer.gpu().name(); for (const auto& test : black_listed) { if (gpu_name.find(test) != std::string::npos) @@ -302,6 +303,11 @@ namespace vk g_drv_no_primitive_restart_flag = !g_cfg.video.vk.force_primitive_restart; break; } + }*/ + + if (gpu_name.find("AMD") != std::string::npos) + { + g_drv_force_32bit_indices = true; } } @@ -310,6 +316,11 @@ namespace vk return g_drv_no_primitive_restart_flag; } + bool force_32bit_index_buffer() + { + return g_drv_force_32bit_indices; + } + void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range) { //Prepare an image to match the new layout.. diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index f40488c305..c707ed6b1b 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -65,7 +65,9 @@ namespace vk vk::render_device *get_current_renderer(); void set_current_renderer(const vk::render_device &device); + //Compatibility workarounds bool emulate_primitive_restart(); + bool force_32bit_index_buffer(); VkComponentMapping default_component_map(); VkImageSubresource default_image_subresource(); diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index 4614a54050..f1b0c73142 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -123,6 +123,10 @@ namespace vertex_input_state operator()(const rsx::draw_indexed_array_command& command) { + const bool primitive_restart_enabled = rsx::method_registers.restart_index_enabled(); + const bool emulate_primitive_restart = primitive_restart_enabled && vk::emulate_primitive_restart(); + const bool expand_indices_to_32bit = primitive_restart_enabled && !emulate_primitive_restart && vk::force_32bit_index_buffer(); + bool primitives_emulated = false; VkPrimitiveTopology prims = vk::get_appropriate_topology( rsx::method_registers.current_draw_clause.primitive, primitives_emulated); @@ -131,7 +135,8 @@ namespace rsx::index_array_type::u32 : rsx::method_registers.index_type(); - u32 type_size = gsl::narrow(get_index_type_size(index_type)); + rsx::index_array_type upload_type = expand_indices_to_32bit ? rsx::index_array_type::u32 : index_type; + u32 type_size = gsl::narrow(get_index_type_size(upload_type)); u32 index_count = rsx::method_registers.current_draw_clause.get_elements_count(); if (primitives_emulated) @@ -143,7 +148,7 @@ namespace gsl::span dst; std::vector tmp; - if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart()) + if (emulate_primitive_restart || (expand_indices_to_32bit && index_type == rsx::index_array_type::u16)) { tmp.resize(upload_size); dst = tmp; @@ -154,7 +159,7 @@ namespace } std::optional> index_info = - std::make_tuple(offset_in_index_buffer, vk::get_index_type(index_type)); + std::make_tuple(offset_in_index_buffer, vk::get_index_type(upload_type)); /** * Upload index (and expands it if primitive type is not natively supported). @@ -175,17 +180,36 @@ namespace return{ prims, 0, 0, 0, 0, index_info }; } - if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart()) + if (tmp.size() > 0) { - //Emulate primitive restart by breaking up the draw calls - rsx::method_registers.current_draw_clause.alternate_first_count_commands.resize(0); + if (emulate_primitive_restart) + { + //Emulate primitive restart by breaking up the draw calls + rsx::method_registers.current_draw_clause.alternate_first_count_commands.resize(0); + rsx::method_registers.current_draw_clause.alternate_first_count_commands.reserve(index_count / 3); - if (index_type == rsx::index_array_type::u16) - rsx::split_index_list(reinterpret_cast(tmp.data()), index_count, (u16)UINT16_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands); + if (index_type == rsx::index_array_type::u16) + rsx::split_index_list(reinterpret_cast(tmp.data()), index_count, (u16)UINT16_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands); + else + rsx::split_index_list(reinterpret_cast(tmp.data()), index_count, (u32)UINT32_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands); + + memcpy(buf, tmp.data(), tmp.size()); + } else - rsx::split_index_list(reinterpret_cast(tmp.data()), index_count, (u32)UINT32_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands); - - memcpy(buf, tmp.data(), tmp.size()); + { + //Force 32-bit indices + verify(HERE), index_type == rsx::index_array_type::u16; + u32* dst = reinterpret_cast(buf); + u16* src = reinterpret_cast(tmp.data()); + for (u32 n = 0; n < index_count; ++n) + { + const auto index = src[n]; + if (index == UINT16_MAX) + dst[n] = UINT32_MAX; + else + dst[n] = index; + } + } } m_index_buffer_ring_info.unmap();