mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
vulkan: Use non-blocking list of lists (WIP)
whitespace fix only facepalm
This commit is contained in:
parent
b78c6f7127
commit
c7db322873
@ -492,7 +492,14 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
|
||||
//create command buffer...
|
||||
m_command_buffer_pool.create((*m_device));
|
||||
m_command_buffer.create(m_command_buffer_pool);
|
||||
|
||||
for (auto &cb : m_primary_cb_list)
|
||||
{
|
||||
cb.create(m_command_buffer_pool);
|
||||
cb.init_fence(*m_device);
|
||||
}
|
||||
|
||||
m_current_command_buffer = &m_primary_cb_list[0];
|
||||
|
||||
//Create secondar command_buffer for parallel operations
|
||||
m_secondary_command_buffer_pool.create((*m_device));
|
||||
@ -502,14 +509,14 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
|
||||
for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i)
|
||||
{
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
|
||||
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
VkClearColorValue clear_color{};
|
||||
auto range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
@ -544,8 +551,6 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
VkFenceCreateInfo fence_info = {};
|
||||
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateFence(*m_device, &fence_info, nullptr, &m_submit_fence));
|
||||
|
||||
VkSemaphoreCreateInfo semaphore_info = {};
|
||||
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
@ -577,12 +582,6 @@ VKGSRender::~VKGSRender()
|
||||
m_present_semaphore = nullptr;
|
||||
}
|
||||
|
||||
if (m_submit_fence)
|
||||
{
|
||||
vkDestroyFence(*m_device, m_submit_fence, nullptr);
|
||||
m_submit_fence = nullptr;
|
||||
}
|
||||
|
||||
//Shaders
|
||||
m_prog_buffer.clear();
|
||||
|
||||
@ -622,7 +621,9 @@ VKGSRender::~VKGSRender()
|
||||
descriptor_pool.destroy();
|
||||
|
||||
//Command buffer
|
||||
m_command_buffer.destroy();
|
||||
for (auto &cb : m_primary_cb_list)
|
||||
cb.destroy();
|
||||
|
||||
m_command_buffer_pool.destroy();
|
||||
|
||||
m_secondary_command_buffer.destroy();
|
||||
@ -644,6 +645,12 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
if (!m_texture_cache.address_is_flushable(address))
|
||||
return false;
|
||||
|
||||
if (m_last_flushable_cb >= 0)
|
||||
{
|
||||
if (m_primary_cb_list[m_last_flushable_cb].pending)
|
||||
m_primary_cb_list[m_last_flushable_cb].wait();
|
||||
}
|
||||
|
||||
if (std::this_thread::get_id() != rsx_thread)
|
||||
{
|
||||
//TODO: Guard this when the renderer is flushing the command queue, might deadlock otherwise
|
||||
@ -676,15 +683,11 @@ void VKGSRender::begin()
|
||||
{
|
||||
std::chrono::time_point<steady_clock> submit_start = steady_clock::now();
|
||||
|
||||
close_and_submit_command_buffer({}, m_submit_fence);
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
|
||||
|
||||
vkResetDescriptorPool(*m_device, descriptor_pool, 0);
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &m_submit_fence));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
open_command_buffer();
|
||||
flush_command_queue(true);
|
||||
|
||||
CHECK_RESULT(vkResetDescriptorPool(*m_device, descriptor_pool, 0));
|
||||
m_used_descriptors = 0;
|
||||
|
||||
m_uniform_buffer_ring_info.m_get_pos = m_uniform_buffer_ring_info.get_current_put_pos_minus_one();
|
||||
m_index_buffer_ring_info.m_get_pos = m_index_buffer_ring_info.get_current_put_pos_minus_one();
|
||||
m_attrib_ring_info.m_get_pos = m_attrib_ring_info.get_current_put_pos_minus_one();
|
||||
@ -711,7 +714,7 @@ void VKGSRender::begin()
|
||||
|
||||
float actual_line_width = rsx::method_registers.line_width();
|
||||
|
||||
vkCmdSetLineWidth(m_command_buffer, actual_line_width);
|
||||
vkCmdSetLineWidth(*m_current_command_buffer, actual_line_width);
|
||||
|
||||
//TODO: Set up other render-state parameters into the program pipeline
|
||||
|
||||
@ -750,7 +753,7 @@ void VKGSRender::end()
|
||||
continue;
|
||||
}
|
||||
|
||||
vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, rsx::method_registers.fragment_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
|
||||
vk::image_view *texture0 = m_texture_cache.upload_texture(*m_current_command_buffer, rsx::method_registers.fragment_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
|
||||
|
||||
if (!texture0)
|
||||
{
|
||||
@ -799,7 +802,7 @@ void VKGSRender::end()
|
||||
continue;
|
||||
}
|
||||
|
||||
vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, rsx::method_registers.vertex_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
|
||||
vk::image_view *texture0 = m_texture_cache.upload_texture(*m_current_command_buffer, rsx::method_registers.vertex_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
|
||||
|
||||
if (!texture0)
|
||||
{
|
||||
@ -832,20 +835,20 @@ void VKGSRender::end()
|
||||
rp_begin.renderArea.extent.width = m_framebuffer_to_clean.back()->width();
|
||||
rp_begin.renderArea.extent.height = m_framebuffer_to_clean.back()->height();
|
||||
|
||||
vkCmdBeginRenderPass(m_command_buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBeginRenderPass(*m_current_command_buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
auto upload_info = upload_vertex_data();
|
||||
|
||||
std::chrono::time_point<steady_clock> vertex_end = steady_clock::now();
|
||||
m_vertex_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(vertex_end - textures_end).count();
|
||||
|
||||
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);
|
||||
vkCmdBindPipeline(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline);
|
||||
vkCmdBindDescriptorSets(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_sets, 0, nullptr);
|
||||
|
||||
std::optional<std::tuple<VkDeviceSize, VkIndexType> > index_info = std::get<2>(upload_info);
|
||||
|
||||
if (!index_info)
|
||||
vkCmdDraw(m_command_buffer, std::get<1>(upload_info), 1, 0, 0);
|
||||
vkCmdDraw(*m_current_command_buffer, std::get<1>(upload_info), 1, 0, 0);
|
||||
else
|
||||
{
|
||||
VkIndexType index_type;
|
||||
@ -854,11 +857,11 @@ void VKGSRender::end()
|
||||
|
||||
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);
|
||||
vkCmdBindIndexBuffer(*m_current_command_buffer, m_index_buffer_ring_info.heap->value, offset, index_type);
|
||||
vkCmdDrawIndexed(*m_current_command_buffer, index_count, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(m_command_buffer);
|
||||
vkCmdEndRenderPass(*m_current_command_buffer);
|
||||
|
||||
std::chrono::time_point<steady_clock> draw_end = steady_clock::now();
|
||||
m_draw_time += std::chrono::duration_cast<std::chrono::microseconds>(draw_end - vertex_end).count();
|
||||
@ -884,7 +887,7 @@ void VKGSRender::set_viewport()
|
||||
viewport.minDepth = 0.f;
|
||||
viewport.maxDepth = 1.f;
|
||||
|
||||
vkCmdSetViewport(m_command_buffer, 0, 1, &viewport);
|
||||
vkCmdSetViewport(*m_current_command_buffer, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.height = scissor_h;
|
||||
@ -892,7 +895,7 @@ void VKGSRender::set_viewport()
|
||||
scissor.offset.x = scissor_x;
|
||||
scissor.offset.y = scissor_y;
|
||||
|
||||
vkCmdSetScissor(m_command_buffer, 0, 1, &scissor);
|
||||
vkCmdSetScissor(*m_current_command_buffer, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
void VKGSRender::on_init_thread()
|
||||
@ -1010,11 +1013,11 @@ void VKGSRender::clear_surface(u32 mask)
|
||||
rp_begin.renderArea.extent.width = m_framebuffer_to_clean.back()->width();
|
||||
rp_begin.renderArea.extent.height = m_framebuffer_to_clean.back()->height();
|
||||
|
||||
vkCmdBeginRenderPass(m_command_buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBeginRenderPass(*m_current_command_buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
vkCmdClearAttachments(m_command_buffer, clear_descriptors.size(), clear_descriptors.data(), clear_regions.size(), clear_regions.data());
|
||||
vkCmdClearAttachments(*m_current_command_buffer, clear_descriptors.size(), clear_descriptors.data(), clear_regions.size(), clear_regions.data());
|
||||
|
||||
vkCmdEndRenderPass(m_command_buffer);
|
||||
vkCmdEndRenderPass(*m_current_command_buffer);
|
||||
}
|
||||
|
||||
void VKGSRender::sync_at_semaphore_release()
|
||||
@ -1042,7 +1045,7 @@ void VKGSRender::copy_render_targets_to_dma_location()
|
||||
continue;
|
||||
|
||||
m_texture_cache.flush_memory_to_cache(m_surface_info[index].address, m_surface_info[index].pitch * m_surface_info[index].height,
|
||||
m_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
|
||||
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1051,30 +1054,122 @@ void VKGSRender::copy_render_targets_to_dma_location()
|
||||
if (m_depth_surface_info.pitch)
|
||||
{
|
||||
m_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height,
|
||||
m_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
|
||||
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue());
|
||||
}
|
||||
}
|
||||
|
||||
close_and_submit_command_buffer({}, m_submit_fence);
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
|
||||
m_last_flushable_cb = m_current_cb_index;
|
||||
flush_command_queue();
|
||||
|
||||
m_flush_draw_buffers = false;
|
||||
}
|
||||
|
||||
void VKGSRender::flush_command_queue(bool hard_sync)
|
||||
{
|
||||
close_and_submit_command_buffer({}, m_current_command_buffer->submit_fence);
|
||||
|
||||
if (hard_sync)
|
||||
{
|
||||
m_current_command_buffer->pending = true;
|
||||
m_current_command_buffer->wait();
|
||||
|
||||
//swap handler checks the pending flag, so call it here
|
||||
process_swap_request();
|
||||
|
||||
//Clear all command buffer statuses
|
||||
for (auto &cb : m_primary_cb_list)
|
||||
cb.poke();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Mark this queue as pending
|
||||
m_current_command_buffer->pending = true;
|
||||
|
||||
//Grab next cb in line and make it usable
|
||||
m_current_cb_index = (m_current_cb_index + 1) % VK_MAX_ASYNC_CB_COUNT;
|
||||
m_current_command_buffer = &m_primary_cb_list[m_current_cb_index];
|
||||
m_current_command_buffer->reset();
|
||||
}
|
||||
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &m_submit_fence));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
open_command_buffer();
|
||||
}
|
||||
|
||||
void VKGSRender::queue_swap_request()
|
||||
{
|
||||
//buffer the swap request and return
|
||||
if (m_swap_command_buffer && m_swap_command_buffer->pending)
|
||||
{
|
||||
//Its probable that no actual drawing took place
|
||||
process_swap_request();
|
||||
}
|
||||
|
||||
m_swap_command_buffer = m_current_command_buffer;
|
||||
close_and_submit_command_buffer({ m_present_semaphore }, m_current_command_buffer->submit_fence);
|
||||
|
||||
//Grab next cb in line and make it usable
|
||||
m_current_cb_index = (m_current_cb_index + 1) % VK_MAX_ASYNC_CB_COUNT;
|
||||
m_current_command_buffer = &m_primary_cb_list[m_current_cb_index];
|
||||
m_current_command_buffer->reset();
|
||||
|
||||
m_swap_command_buffer->pending = true;
|
||||
open_command_buffer();
|
||||
}
|
||||
|
||||
void VKGSRender::process_swap_request()
|
||||
{
|
||||
if (!m_swap_command_buffer)
|
||||
return;
|
||||
|
||||
if (m_swap_command_buffer->pending)
|
||||
{
|
||||
//Perform hard swap here
|
||||
m_swap_command_buffer->wait();
|
||||
|
||||
VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
|
||||
|
||||
VkPresentInfoKHR present = {};
|
||||
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
present.pNext = nullptr;
|
||||
present.swapchainCount = 1;
|
||||
present.pSwapchains = &swap_chain;
|
||||
present.pImageIndices = &m_current_present_image;
|
||||
CHECK_RESULT(m_swap_chain->queuePresentKHR(m_swap_chain->get_present_queue(), &present));
|
||||
}
|
||||
else
|
||||
fmt::throw_exception("How can a process be set without a pending flag?");
|
||||
|
||||
//Clean up all the resources from the last frame
|
||||
|
||||
//Feed back damaged resources to the main texture cache for management...
|
||||
//m_texture_cache.merge_dirty_textures(m_rtts.invalidated_resources);
|
||||
|
||||
m_rtts.invalidated_resources.clear();
|
||||
m_texture_cache.flush();
|
||||
|
||||
m_buffer_view_to_clean.clear();
|
||||
m_sampler_to_clean.clear();
|
||||
m_framebuffer_to_clean.clear();
|
||||
|
||||
if (g_cfg_rsx_overlay)
|
||||
{
|
||||
m_text_writer->reset_descriptors();
|
||||
}
|
||||
|
||||
m_swap_command_buffer = nullptr;
|
||||
}
|
||||
|
||||
void VKGSRender::do_local_task()
|
||||
{
|
||||
if (m_flush_commands)
|
||||
{
|
||||
close_and_submit_command_buffer({}, m_submit_fence);
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
|
||||
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &m_submit_fence));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
open_command_buffer();
|
||||
//WARNING: This is a hard sync, expect horrendous performance
|
||||
//Need to process this a little better!
|
||||
//TODO: Link cb with draw buffer and wait for that specific cb based on address
|
||||
LOG_ERROR(RSX, "Hard sync point is to be processed. Performance warning");
|
||||
flush_command_queue(true);
|
||||
|
||||
m_flush_commands = false;
|
||||
m_flush_draw_buffers = false;
|
||||
while (m_queued_threads);
|
||||
}
|
||||
}
|
||||
@ -1329,6 +1424,9 @@ static const u32 mr_color_pitch[rsx::limits::color_buffers_count] =
|
||||
|
||||
void VKGSRender::init_buffers(bool skip_reading)
|
||||
{
|
||||
//Clear any pending swap requests
|
||||
process_swap_request();
|
||||
|
||||
prepare_rtts();
|
||||
|
||||
if (!skip_reading)
|
||||
@ -1349,9 +1447,9 @@ void VKGSRender::write_buffers()
|
||||
|
||||
void VKGSRender::close_and_submit_command_buffer(const std::vector<VkSemaphore> &semaphores, VkFence fence, VkPipelineStageFlags pipeline_stage_flags)
|
||||
{
|
||||
CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
|
||||
CHECK_RESULT(vkEndCommandBuffer(*m_current_command_buffer));
|
||||
|
||||
VkCommandBuffer cmd = m_command_buffer;
|
||||
VkCommandBuffer cmd = *m_current_command_buffer;
|
||||
|
||||
VkSubmitInfo infos = {};
|
||||
infos.commandBufferCount = 1;
|
||||
@ -1373,7 +1471,7 @@ void VKGSRender::open_command_buffer()
|
||||
begin_infos.pInheritanceInfo = &inheritance_info;
|
||||
begin_infos.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_infos.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
CHECK_RESULT(vkBeginCommandBuffer(m_command_buffer, &begin_infos));
|
||||
CHECK_RESULT(vkBeginCommandBuffer(*m_current_command_buffer, &begin_infos));
|
||||
}
|
||||
|
||||
|
||||
@ -1397,12 +1495,12 @@ void VKGSRender::prepare_rtts()
|
||||
const u32 surface_pitchs[] = { rsx::method_registers.surface_a_pitch(), rsx::method_registers.surface_b_pitch(),
|
||||
rsx::method_registers.surface_c_pitch(), rsx::method_registers.surface_d_pitch() };
|
||||
|
||||
m_rtts.prepare_render_target(&m_command_buffer,
|
||||
m_rtts.prepare_render_target(&*m_current_command_buffer,
|
||||
rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(),
|
||||
clip_width, clip_height,
|
||||
rsx::method_registers.surface_color_target(),
|
||||
surface_addresses, zeta_address,
|
||||
(*m_device), &m_command_buffer, m_optimal_tiling_supported_formats, m_memory_type_mapping);
|
||||
(*m_device), &*m_current_command_buffer, m_optimal_tiling_supported_formats, m_memory_type_mapping);
|
||||
|
||||
//Reset framebuffer information
|
||||
for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||
@ -1513,6 +1611,8 @@ void VKGSRender::flip(int buffer)
|
||||
|
||||
std::chrono::time_point<steady_clock> flip_start = steady_clock::now();
|
||||
|
||||
process_swap_request();
|
||||
|
||||
if (!resize_screen)
|
||||
{
|
||||
u32 buffer_width = gcm_buffers[buffer].width;
|
||||
@ -1545,8 +1645,6 @@ void VKGSRender::flip(int buffer)
|
||||
|
||||
aspect_ratio.size = new_size;
|
||||
|
||||
VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
|
||||
|
||||
//Prepare surface for new frame
|
||||
CHECK_RESULT(vkAcquireNextImageKHR((*m_device), (*m_swap_chain), 0, m_present_semaphore, VK_NULL_HANDLE, &m_current_present_image));
|
||||
|
||||
@ -1561,7 +1659,7 @@ void VKGSRender::flip(int buffer)
|
||||
VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_present_image);
|
||||
if (image_to_flip)
|
||||
{
|
||||
vk::copy_scaled_image(m_command_buffer, image_to_flip, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
vk::copy_scaled_image(*m_current_command_buffer, image_to_flip, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
0, 0, buffer_width, buffer_height, aspect_ratio.x, aspect_ratio.y, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
else
|
||||
@ -1569,9 +1667,9 @@ void VKGSRender::flip(int buffer)
|
||||
//No draw call was issued!
|
||||
VkImageSubresourceRange range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
VkClearColorValue clear_black = { 0 };
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, range);
|
||||
vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range);
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range);
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, range);
|
||||
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range);
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range);
|
||||
}
|
||||
|
||||
std::unique_ptr<vk::framebuffer> direct_fbo;
|
||||
@ -1591,7 +1689,7 @@ void VKGSRender::flip(int buffer)
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.subresourceRange = subres;
|
||||
|
||||
vkCmdPipelineBarrier(m_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
vkCmdPipelineBarrier(*m_current_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
|
||||
size_t idx = vk::get_render_pass_location(m_swap_chain->get_surface_format(), VK_FORMAT_UNDEFINED, 1);
|
||||
VkRenderPass single_target_pass = m_render_passes[idx];
|
||||
@ -1599,26 +1697,17 @@ void VKGSRender::flip(int buffer)
|
||||
swap_image_view.push_back(std::make_unique<vk::image_view>(*m_device, target_image, VK_IMAGE_VIEW_TYPE_2D, m_swap_chain->get_surface_format(), vk::default_component_map(), subres));
|
||||
direct_fbo.reset(new vk::framebuffer(*m_device, single_target_pass, m_client_width, m_client_height, std::move(swap_image_view)));
|
||||
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 0, direct_fbo->width(), direct_fbo->height(), "draw calls: " + std::to_string(m_draw_calls));
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), "draw call setup: " + std::to_string(m_setup_time) + "us");
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), "texture upload time: " + std::to_string(m_textures_upload_time) + "us");
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
||||
m_text_writer->print_text(m_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), "submit and flip: " + std::to_string(m_flip_time) + "us");
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 0, direct_fbo->width(), direct_fbo->height(), "draw calls: " + std::to_string(m_draw_calls));
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 18, direct_fbo->width(), direct_fbo->height(), "draw call setup: " + std::to_string(m_setup_time) + "us");
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 36, direct_fbo->width(), direct_fbo->height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 54, direct_fbo->width(), direct_fbo->height(), "texture upload time: " + std::to_string(m_textures_upload_time) + "us");
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 72, direct_fbo->width(), direct_fbo->height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
||||
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 90, direct_fbo->width(), direct_fbo->height(), "submit and flip: " + std::to_string(m_flip_time) + "us");
|
||||
|
||||
vk::change_image_layout(m_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, subres);
|
||||
vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, subres);
|
||||
}
|
||||
|
||||
close_and_submit_command_buffer({ m_present_semaphore }, m_submit_fence);
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
|
||||
|
||||
VkPresentInfoKHR present = {};
|
||||
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
present.pNext = nullptr;
|
||||
present.swapchainCount = 1;
|
||||
present.pSwapchains = &swap_chain;
|
||||
present.pImageIndices = &m_current_present_image;
|
||||
CHECK_RESULT(m_swap_chain->queuePresentKHR(m_swap_chain->get_present_queue(), &present));
|
||||
queue_swap_request();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1628,7 +1717,8 @@ void VKGSRender::flip(int buffer)
|
||||
* and there are no explicit methods to ensure that the presentation engine is not using the images at all.
|
||||
*/
|
||||
|
||||
CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
|
||||
//NOTE: This operation will create a hard sync point
|
||||
CHECK_RESULT(vkEndCommandBuffer(*m_current_command_buffer));
|
||||
|
||||
//Will have to block until rendering is completed
|
||||
VkFence resize_fence = VK_NULL_HANDLE;
|
||||
@ -1662,19 +1752,19 @@ void VKGSRender::flip(int buffer)
|
||||
m_swap_chain->init_swapchain(m_client_width, m_client_height);
|
||||
|
||||
//Prepare new swapchain images for use
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
m_current_command_buffer->reset();
|
||||
open_command_buffer();
|
||||
|
||||
for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i)
|
||||
{
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
|
||||
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
VkClearColorValue clear_color{};
|
||||
auto range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
|
||||
vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
|
||||
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i),
|
||||
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
}
|
||||
@ -1683,6 +1773,13 @@ void VKGSRender::flip(int buffer)
|
||||
close_and_submit_command_buffer({}, resize_fence);
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &resize_fence, VK_TRUE, UINT64_MAX));
|
||||
vkDestroyFence((*m_device), resize_fence, nullptr);
|
||||
|
||||
m_current_command_buffer->reset();
|
||||
open_command_buffer();
|
||||
|
||||
//Do cleanup
|
||||
m_swap_command_buffer = m_current_command_buffer;
|
||||
process_swap_request();
|
||||
}
|
||||
|
||||
std::chrono::time_point<steady_clock> flip_end = steady_clock::now();
|
||||
@ -1693,30 +1790,12 @@ void VKGSRender::flip(int buffer)
|
||||
m_attrib_ring_info.m_get_pos = m_attrib_ring_info.get_current_put_pos_minus_one();
|
||||
m_texture_upload_buffer_ring_info.m_get_pos = m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one();
|
||||
|
||||
//Feed back damaged resources to the main texture cache for management...
|
||||
// m_texture_cache.merge_dirty_textures(m_rtts.invalidated_resources);
|
||||
m_rtts.invalidated_resources.clear();
|
||||
m_texture_cache.flush();
|
||||
|
||||
m_buffer_view_to_clean.clear();
|
||||
m_sampler_to_clean.clear();
|
||||
m_framebuffer_to_clean.clear();
|
||||
|
||||
if (g_cfg_rsx_overlay)
|
||||
{
|
||||
m_text_writer->reset_descriptors();
|
||||
}
|
||||
|
||||
vkResetDescriptorPool(*m_device, descriptor_pool, 0);
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &m_submit_fence));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
open_command_buffer();
|
||||
//Resource destruction is handled within the real swap handler
|
||||
|
||||
m_draw_calls = 0;
|
||||
m_draw_time = 0;
|
||||
m_setup_time = 0;
|
||||
m_vertex_upload_time = 0;
|
||||
m_textures_upload_time = 0;
|
||||
m_used_descriptors = 0;
|
||||
m_frame->flip(m_context);
|
||||
}
|
||||
|
@ -15,6 +15,74 @@
|
||||
|
||||
#pragma comment(lib, "VKstatic.1.lib")
|
||||
|
||||
#define VK_MAX_ASYNC_CB_COUNT 64
|
||||
|
||||
struct command_buffer_chunk: public vk::command_buffer
|
||||
{
|
||||
VkFence submit_fence = VK_NULL_HANDLE;
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
|
||||
bool pending = false;
|
||||
|
||||
command_buffer_chunk()
|
||||
{}
|
||||
|
||||
void init_fence(VkDevice dev)
|
||||
{
|
||||
m_device = dev;
|
||||
|
||||
VkFenceCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
vkCreateFence(m_device, &info, nullptr, &submit_fence);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
vk::command_buffer::destroy();
|
||||
|
||||
if (submit_fence != VK_NULL_HANDLE)
|
||||
vkDestroyFence(m_device, submit_fence, nullptr);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (pending)
|
||||
poke();
|
||||
|
||||
if (pending)
|
||||
wait();
|
||||
|
||||
vkResetCommandBuffer(commands, 0);
|
||||
}
|
||||
|
||||
void poke()
|
||||
{
|
||||
if (vkGetFenceStatus(m_device, submit_fence) == VK_SUCCESS)
|
||||
{
|
||||
vkResetFences(m_device, 1, &submit_fence);
|
||||
pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
if (!pending)
|
||||
return;
|
||||
|
||||
switch(vkGetFenceStatus(m_device, submit_fence))
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
break;
|
||||
case VK_NOT_READY:
|
||||
vkWaitForFences(m_device, 1, &submit_fence, VK_TRUE, UINT64_MAX);
|
||||
break;
|
||||
}
|
||||
|
||||
vkResetFences(m_device, 1, &submit_fence);
|
||||
pending = false;
|
||||
}
|
||||
};
|
||||
|
||||
class VKGSRender : public GSRender
|
||||
{
|
||||
private:
|
||||
@ -55,11 +123,13 @@ private:
|
||||
u32 m_current_present_image = 0xFFFF;
|
||||
VkSemaphore m_present_semaphore = nullptr;
|
||||
|
||||
u32 m_current_sync_buffer_index = 0;
|
||||
VkFence m_submit_fence = nullptr;
|
||||
|
||||
vk::command_pool m_command_buffer_pool;
|
||||
vk::command_buffer m_command_buffer;
|
||||
std::array<command_buffer_chunk, VK_MAX_ASYNC_CB_COUNT> m_primary_cb_list;
|
||||
|
||||
command_buffer_chunk* m_current_command_buffer = nullptr;
|
||||
command_buffer_chunk* m_swap_command_buffer = nullptr;
|
||||
|
||||
u32 m_current_cb_index = 0;
|
||||
|
||||
std::mutex m_secondary_cb_guard;
|
||||
vk::command_pool m_secondary_command_buffer_pool;
|
||||
@ -92,6 +162,7 @@ private:
|
||||
rsx::gcm_framebuffer_info m_depth_surface_info;
|
||||
|
||||
bool m_flush_draw_buffers = false;
|
||||
s32 m_last_flushable_cb = -1;
|
||||
|
||||
std::atomic<bool> m_flush_commands = false;
|
||||
std::atomic<int> m_queued_threads = 0;
|
||||
@ -109,6 +180,11 @@ private:
|
||||
void sync_at_semaphore_release();
|
||||
void prepare_rtts();
|
||||
void copy_render_targets_to_dma_location();
|
||||
|
||||
void flush_command_queue(bool hard_sync = false);
|
||||
void queue_swap_request();
|
||||
void process_swap_request();
|
||||
|
||||
/// returns primitive topology, is_indexed, index_count, offset in index buffer, index type
|
||||
std::tuple<VkPrimitiveTopology, u32, std::optional<std::tuple<VkDeviceSize, VkIndexType> > > upload_vertex_data();
|
||||
public:
|
||||
|
@ -941,7 +941,7 @@ namespace vk
|
||||
{
|
||||
owner = &dev;
|
||||
VkCommandPoolCreateInfo infos = {};
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
infos.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateCommandPool(dev, &infos, nullptr, &pool));
|
||||
@ -969,6 +969,7 @@ namespace vk
|
||||
|
||||
class command_buffer
|
||||
{
|
||||
protected:
|
||||
vk::command_pool *pool = nullptr;
|
||||
VkCommandBuffer commands = nullptr;
|
||||
|
||||
|
@ -189,7 +189,7 @@ namespace vk
|
||||
|
||||
//Now we need to restart the command-buffer to restore it to the way it was before...
|
||||
CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, cmd.get_command_pool(), 0));
|
||||
CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user