mirror of https://github.com/RPCS3/rpcs3.git
rsx/vk: Workaround for polaris primitive restart bug
This commit is contained in:
parent
5146f3ec47
commit
3d05e61f7e
|
@ -1211,7 +1211,8 @@ void VKGSRender::end()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::tuple<VkDeviceSize, VkIndexType> > index_info = std::get<4>(upload_info);
|
std::optional<std::tuple<VkDeviceSize, VkIndexType> > index_info = std::get<4>(upload_info);
|
||||||
bool single_draw = rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive;
|
const bool is_emulated_restart = (index_info && rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart() && rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed);
|
||||||
|
const bool single_draw = !is_emulated_restart && (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive);
|
||||||
|
|
||||||
if (!index_info)
|
if (!index_info)
|
||||||
{
|
{
|
||||||
|
@ -1244,12 +1245,23 @@ void VKGSRender::end()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 first_vertex = 0;
|
if (!is_emulated_restart)
|
||||||
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
|
|
||||||
{
|
{
|
||||||
const auto verts = get_index_count(rsx::method_registers.current_draw_clause.primitive, range.second);
|
u32 first_vertex = 0;
|
||||||
vkCmdDrawIndexed(*m_current_command_buffer, verts, 1, 0, first_vertex, 0);
|
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
|
||||||
first_vertex += verts;
|
{
|
||||||
|
const auto verts = get_index_count(rsx::method_registers.current_draw_clause.primitive, range.second);
|
||||||
|
vkCmdDrawIndexed(*m_current_command_buffer, verts, 1, first_vertex, 0, 0);
|
||||||
|
first_vertex += verts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto &range : rsx::method_registers.current_draw_clause.alternate_first_count_commands)
|
||||||
|
{
|
||||||
|
//Primitive restart splitting happens after the primitive type expansion step
|
||||||
|
vkCmdDrawIndexed(*m_current_command_buffer, range.second, 1, range.first, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1839,7 +1851,7 @@ bool VKGSRender::check_program_status()
|
||||||
properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
properties.ia.topology = vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, 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.current_draw_clause.command == rsx::draw_command::indexed && rsx::method_registers.restart_index_enabled() && !vk::emulate_primitive_restart())
|
||||||
properties.ia.primitiveRestartEnable = VK_TRUE;
|
properties.ia.primitiveRestartEnable = VK_TRUE;
|
||||||
else
|
else
|
||||||
properties.ia.primitiveRestartEnable = VK_FALSE;
|
properties.ia.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace vk
|
||||||
VkSampler g_null_sampler = nullptr;
|
VkSampler g_null_sampler = nullptr;
|
||||||
|
|
||||||
bool g_cb_no_interrupt_flag = false;
|
bool g_cb_no_interrupt_flag = false;
|
||||||
|
bool g_drv_no_primitive_restart_flag = false;
|
||||||
|
|
||||||
u64 g_num_processed_frames = 0;
|
u64 g_num_processed_frames = 0;
|
||||||
u64 g_num_total_frames = 0;
|
u64 g_num_total_frames = 0;
|
||||||
|
@ -257,6 +258,34 @@ namespace vk
|
||||||
void set_current_renderer(const vk::render_device &device)
|
void set_current_renderer(const vk::render_device &device)
|
||||||
{
|
{
|
||||||
g_current_renderer = device;
|
g_current_renderer = device;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const std::array<std::string, 6> black_listed =
|
||||||
|
{
|
||||||
|
// Black list all polaris unless its proven they dont have a problem with primitive restart
|
||||||
|
"RX 580",
|
||||||
|
"RX 570",
|
||||||
|
"RX 560",
|
||||||
|
"RX 480",
|
||||||
|
"RX 470",
|
||||||
|
"RX 460",
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto gpu_name = g_current_renderer.gpu().name();
|
||||||
|
for (const auto& test : black_listed)
|
||||||
|
{
|
||||||
|
if (gpu_name.find(test) != std::string::npos)
|
||||||
|
{
|
||||||
|
g_drv_no_primitive_restart_flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emulate_primitive_restart()
|
||||||
|
{
|
||||||
|
return g_drv_no_primitive_restart_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
|
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
|
||||||
|
|
|
@ -66,6 +66,8 @@ namespace vk
|
||||||
vk::render_device *get_current_renderer();
|
vk::render_device *get_current_renderer();
|
||||||
void set_current_renderer(const vk::render_device &device);
|
void set_current_renderer(const vk::render_device &device);
|
||||||
|
|
||||||
|
bool emulate_primitive_restart();
|
||||||
|
|
||||||
VkComponentMapping default_component_map();
|
VkComponentMapping default_component_map();
|
||||||
VkImageSubresource default_image_subresource();
|
VkImageSubresource default_image_subresource();
|
||||||
VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect);
|
VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect);
|
||||||
|
|
|
@ -141,18 +141,43 @@ namespace
|
||||||
VkDeviceSize offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_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);
|
void* buf = m_index_buffer_ring_info.map(offset_in_index_buffer, upload_size);
|
||||||
|
|
||||||
|
gsl::span<gsl::byte> dst;
|
||||||
|
std::vector<gsl::byte> tmp;
|
||||||
|
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
||||||
|
{
|
||||||
|
tmp.resize(upload_size);
|
||||||
|
dst = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst = gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), upload_size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload index (and expands it if primitive type is not natively supported).
|
* Upload index (and expands it if primitive type is not natively supported).
|
||||||
*/
|
*/
|
||||||
u32 min_index, max_index;
|
u32 min_index, max_index;
|
||||||
std::tie(min_index, max_index) = write_index_array_data_to_buffer(
|
std::tie(min_index, max_index) = write_index_array_data_to_buffer(
|
||||||
gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), index_count * type_size),
|
dst,
|
||||||
command.raw_index_buffer, index_type,
|
command.raw_index_buffer, index_type,
|
||||||
rsx::method_registers.current_draw_clause.primitive,
|
rsx::method_registers.current_draw_clause.primitive,
|
||||||
rsx::method_registers.restart_index_enabled(),
|
rsx::method_registers.restart_index_enabled(),
|
||||||
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
|
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
|
||||||
[](auto prim) { return !vk::is_primitive_native(prim); });
|
[](auto prim) { return !vk::is_primitive_native(prim); });
|
||||||
|
|
||||||
|
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
||||||
|
{
|
||||||
|
//Emulate primitive restart by breaking up the draw calls
|
||||||
|
rsx::method_registers.current_draw_clause.alternate_first_count_commands.resize(0);
|
||||||
|
|
||||||
|
if (index_type == rsx::index_array_type::u16)
|
||||||
|
rsx::split_index_list(reinterpret_cast<u16*>(tmp.data()), index_count, UINT16_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
|
||||||
|
else
|
||||||
|
rsx::split_index_list(reinterpret_cast<u32*>(tmp.data()), index_count, UINT32_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
|
||||||
|
|
||||||
|
memcpy(buf, tmp.data(), tmp.size());
|
||||||
|
}
|
||||||
|
|
||||||
m_index_buffer_ring_info.unmap();
|
m_index_buffer_ring_info.unmap();
|
||||||
|
|
||||||
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
|
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
|
||||||
|
|
|
@ -38,6 +38,11 @@ namespace rsx
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<u32, u32> > first_count_commands;
|
std::vector<std::pair<u32, u32> > first_count_commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionally split first-count pairs for disjoint range rendering. Valid when emulating primitive restart
|
||||||
|
*/
|
||||||
|
std::vector<std::pair<u32, u32> > alternate_first_count_commands;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns how many vertex or index will be consumed by the draw clause.
|
* Returns how many vertex or index will be consumed by the draw clause.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -251,4 +251,33 @@ namespace rsx
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void split_index_list(T* indices, int index_count, T restart_index, std::vector<std::pair<u32, u32>>& out)
|
||||||
|
{
|
||||||
|
int last_valid_index = -1;
|
||||||
|
int last_start = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < index_count; ++i)
|
||||||
|
{
|
||||||
|
if (indices[i] == UINT16_MAX)
|
||||||
|
{
|
||||||
|
if (last_start >= 0)
|
||||||
|
{
|
||||||
|
out.push_back(std::make_pair(last_start, i - last_start));
|
||||||
|
last_start = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_start < 0)
|
||||||
|
last_start = i;
|
||||||
|
|
||||||
|
last_valid_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_start >= 0)
|
||||||
|
out.push_back(std::make_pair(last_start, last_valid_index - last_start + 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue