mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00:00
vulkan: Only submit command buffer at flip and avoid extra sync.
This commit is contained in:
parent
7a988c73a6
commit
aa3c97f918
@ -381,15 +381,7 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
//create command buffer...
|
||||
m_command_buffer_pool.create((*m_device));
|
||||
m_command_buffer.create(m_command_buffer_pool);
|
||||
|
||||
VkCommandBufferInheritanceInfo inheritance_info = {};
|
||||
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
|
||||
|
||||
VkCommandBufferBeginInfo begin_infos = {};
|
||||
begin_infos.pInheritanceInfo = &inheritance_info;
|
||||
begin_infos.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
||||
CHECK_RESULT(vkBeginCommandBuffer(m_command_buffer, &begin_infos));
|
||||
open_command_buffer();
|
||||
|
||||
for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i)
|
||||
{
|
||||
@ -405,9 +397,6 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
}
|
||||
|
||||
CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
|
||||
execute_command_buffer(false);
|
||||
|
||||
|
||||
#define RING_BUFFER_SIZE 16 * 1024 * 1024
|
||||
@ -433,16 +422,21 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
|
||||
null_buffer = std::make_unique<vk::buffer>(*m_device, 32, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0);
|
||||
null_buffer_view = std::make_unique<vk::buffer_view>(*m_device, null_buffer->value, VK_FORMAT_R32_SFLOAT, 0, 32);
|
||||
|
||||
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;
|
||||
|
||||
vkCreateSemaphore((*m_device), &semaphore_info, nullptr, &m_present_semaphore);
|
||||
}
|
||||
|
||||
VKGSRender::~VKGSRender()
|
||||
{
|
||||
if (m_submit_fence)
|
||||
{
|
||||
vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, 1000000L);
|
||||
vkDestroyFence((*m_device), m_submit_fence, nullptr);
|
||||
m_submit_fence = nullptr;
|
||||
}
|
||||
CHECK_RESULT(vkQueueWaitIdle(m_swap_chain->get_present_queue()));
|
||||
|
||||
if (m_present_semaphore)
|
||||
{
|
||||
@ -500,8 +494,6 @@ void VKGSRender::begin()
|
||||
//TODO: Fence sync, ring-buffers, etc
|
||||
//CHECK_RESULT(vkDeviceWaitIdle((*m_device)));
|
||||
|
||||
if (!recording)
|
||||
begin_command_buffer_recording();
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.descriptorPool = descriptor_pool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
@ -616,9 +608,6 @@ void VKGSRender::end()
|
||||
vkCmdEndRenderPass(m_command_buffer);
|
||||
|
||||
|
||||
end_command_buffer_recording();
|
||||
execute_command_buffer(false);
|
||||
|
||||
rsx::thread::end();
|
||||
}
|
||||
|
||||
@ -680,11 +669,6 @@ void VKGSRender::clear_surface(u32 mask)
|
||||
|
||||
if (m_current_present_image== 0xFFFF) return;
|
||||
|
||||
bool was_recording = recording;
|
||||
|
||||
if (!was_recording)
|
||||
begin_command_buffer_recording();
|
||||
|
||||
init_buffers();
|
||||
|
||||
float depth_clear = 1.f;
|
||||
@ -756,13 +740,16 @@ void VKGSRender::clear_surface(u32 mask)
|
||||
change_image_layout(m_command_buffer, depth_stencil_image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, range);
|
||||
}
|
||||
|
||||
if (!was_recording)
|
||||
{
|
||||
end_command_buffer_recording();
|
||||
execute_command_buffer(false);
|
||||
}
|
||||
}
|
||||
|
||||
recording = was_recording;
|
||||
void VKGSRender::sync_at_semaphore_release()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
bool VKGSRender::do_method(u32 cmd, u32 arg)
|
||||
@ -772,6 +759,10 @@ bool VKGSRender::do_method(u32 cmd, u32 arg)
|
||||
case NV4097_CLEAR_SURFACE:
|
||||
clear_surface(arg);
|
||||
return true;
|
||||
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
|
||||
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
|
||||
sync_at_semaphore_release();
|
||||
return false; //call rsx::thread method implementation
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -978,20 +969,6 @@ static const u32 mr_color_pitch[rsx::limits::color_buffers_count] =
|
||||
|
||||
void VKGSRender::init_buffers(bool skip_reading)
|
||||
{
|
||||
if (dirty_frame)
|
||||
{
|
||||
//Prepare surface for new frame
|
||||
VkSemaphoreCreateInfo semaphore_info = {};
|
||||
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
vkCreateSemaphore((*m_device), &semaphore_info, nullptr, &m_present_semaphore);
|
||||
|
||||
VkFence nullFence = VK_NULL_HANDLE;
|
||||
CHECK_RESULT(vkAcquireNextImageKHR((*m_device), (*m_swap_chain), 0, m_present_semaphore, nullFence, &m_current_present_image));
|
||||
|
||||
dirty_frame = false;
|
||||
}
|
||||
|
||||
prepare_rtts();
|
||||
|
||||
if (!skip_reading)
|
||||
@ -1010,7 +987,25 @@ void VKGSRender::write_buffers()
|
||||
{
|
||||
}
|
||||
|
||||
void VKGSRender::begin_command_buffer_recording()
|
||||
void VKGSRender::close_and_submit_command_buffer(const std::vector<VkSemaphore> &semaphores, VkFence fence)
|
||||
{
|
||||
CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
|
||||
|
||||
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkCommandBuffer cmd = m_command_buffer;
|
||||
|
||||
VkSubmitInfo infos = {};
|
||||
infos.commandBufferCount = 1;
|
||||
infos.pCommandBuffers = &cmd;
|
||||
infos.pWaitDstStageMask = &pipe_stage_flags;
|
||||
infos.pWaitSemaphores = semaphores.data();
|
||||
infos.waitSemaphoreCount = semaphores.size();
|
||||
infos.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
CHECK_RESULT(vkQueueSubmit(m_swap_chain->get_present_queue(), 1, &infos, fence));
|
||||
}
|
||||
|
||||
void VKGSRender::open_command_buffer()
|
||||
{
|
||||
VkCommandBufferInheritanceInfo inheritance_info = {};
|
||||
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
|
||||
@ -1018,25 +1013,10 @@ void VKGSRender::begin_command_buffer_recording()
|
||||
VkCommandBufferBeginInfo begin_infos = {};
|
||||
begin_infos.pInheritanceInfo = &inheritance_info;
|
||||
begin_infos.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
||||
if (m_submit_fence)
|
||||
{
|
||||
vkWaitForFences(*m_device, 1, &m_submit_fence, VK_TRUE, ~0ULL);
|
||||
vkDestroyFence(*m_device, m_submit_fence, nullptr);
|
||||
m_submit_fence = nullptr;
|
||||
|
||||
CHECK_RESULT(vkResetCommandBuffer(m_command_buffer, 0));
|
||||
}
|
||||
|
||||
begin_infos.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
CHECK_RESULT(vkBeginCommandBuffer(m_command_buffer, &begin_infos));
|
||||
recording = true;
|
||||
}
|
||||
|
||||
void VKGSRender::end_command_buffer_recording()
|
||||
{
|
||||
recording = false;
|
||||
CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
|
||||
}
|
||||
|
||||
void VKGSRender::prepare_rtts()
|
||||
{
|
||||
@ -1110,31 +1090,6 @@ void VKGSRender::prepare_rtts()
|
||||
m_framebuffer_to_clean.push_back(std::make_unique<vk::framebuffer>(*m_device, current_render_pass, clip_width, clip_height, std::move(fbo_images)));
|
||||
}
|
||||
|
||||
void VKGSRender::execute_command_buffer(bool wait)
|
||||
{
|
||||
if (recording)
|
||||
throw EXCEPTION("execute_command_buffer called before end_command_buffer_recording()!");
|
||||
|
||||
if (m_submit_fence)
|
||||
throw EXCEPTION("Synchronization deadlock!");
|
||||
|
||||
VkFenceCreateInfo fence_info = {};
|
||||
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateFence(*m_device, &fence_info, nullptr, &m_submit_fence));
|
||||
|
||||
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkCommandBuffer cmd = m_command_buffer;
|
||||
|
||||
VkSubmitInfo infos = {};
|
||||
infos.commandBufferCount = 1;
|
||||
infos.pCommandBuffers = &cmd;
|
||||
infos.pWaitDstStageMask = &pipe_stage_flags;
|
||||
infos.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
CHECK_RESULT(vkQueueSubmit(m_swap_chain->get_present_queue(), 1, &infos, m_submit_fence));
|
||||
CHECK_RESULT(vkQueueWaitIdle(m_swap_chain->get_present_queue()));
|
||||
}
|
||||
|
||||
void VKGSRender::flip(int buffer)
|
||||
{
|
||||
@ -1178,28 +1133,21 @@ void VKGSRender::flip(int buffer)
|
||||
VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
|
||||
uint32_t next_image_temp = 0;
|
||||
|
||||
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;
|
||||
present.pWaitSemaphores = &m_present_semaphore;
|
||||
present.waitSemaphoreCount = 1;
|
||||
//Prepare surface for new frame
|
||||
CHECK_RESULT(vkAcquireNextImageKHR((*m_device), (*m_swap_chain), 0, m_present_semaphore, VK_NULL_HANDLE, &m_current_present_image));
|
||||
|
||||
begin_command_buffer_recording();
|
||||
|
||||
if (m_present_semaphore)
|
||||
//Blit contents to screen..
|
||||
VkImage image_to_flip = nullptr;
|
||||
|
||||
if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
|
||||
image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0])->value;
|
||||
else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
|
||||
image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1])->value;
|
||||
|
||||
VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_present_image);
|
||||
if (image_to_flip)
|
||||
{
|
||||
//Blit contents to screen..
|
||||
VkImage image_to_flip = nullptr;
|
||||
|
||||
if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
|
||||
image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0])->value;
|
||||
else
|
||||
image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1])->value;
|
||||
|
||||
VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_present_image);
|
||||
vk::copy_scaled_image(m_command_buffer, image_to_flip, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
buffer_width, buffer_height, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
@ -1212,37 +1160,27 @@ void VKGSRender::flip(int buffer)
|
||||
VkImageSubresourceRange range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
VkClearColorValue clear_black = { 0 };
|
||||
vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(next_image_temp), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, &clear_black, 1, &range);
|
||||
|
||||
present.pImageIndices = &next_image_temp;
|
||||
present.waitSemaphoreCount = 0;
|
||||
}
|
||||
|
||||
end_command_buffer_recording();
|
||||
execute_command_buffer(false);
|
||||
|
||||
//Check if anything is waiting in queue and wait for it if possible..
|
||||
if (m_submit_fence)
|
||||
{
|
||||
CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
|
||||
|
||||
vkDestroyFence((*m_device), m_submit_fence, nullptr);
|
||||
m_submit_fence = nullptr;
|
||||
|
||||
CHECK_RESULT(vkResetCommandBuffer(m_command_buffer, 0));
|
||||
}
|
||||
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));
|
||||
CHECK_RESULT(vkQueueWaitIdle(m_swap_chain->get_present_queue()));
|
||||
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &m_submit_fence));
|
||||
CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
|
||||
open_command_buffer();
|
||||
|
||||
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();
|
||||
m_texture_upload_buffer_ring_info.m_get_pos = m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one();
|
||||
if (m_present_semaphore)
|
||||
{
|
||||
vkDestroySemaphore((*m_device), m_present_semaphore, nullptr);
|
||||
m_present_semaphore = nullptr;
|
||||
}
|
||||
|
||||
//Feed back damaged resources to the main texture cache for management...
|
||||
// m_texture_cache.merge_dirty_textures(m_rtts.invalidated_resources);
|
||||
|
@ -61,7 +61,6 @@ private:
|
||||
|
||||
vk::command_pool m_command_buffer_pool;
|
||||
vk::command_buffer m_command_buffer;
|
||||
bool recording = false;
|
||||
bool dirty_frame = true;
|
||||
|
||||
|
||||
@ -85,10 +84,9 @@ public:
|
||||
|
||||
private:
|
||||
void clear_surface(u32 mask);
|
||||
void execute_command_buffer(bool wait);
|
||||
void begin_command_buffer_recording();
|
||||
void end_command_buffer_recording();
|
||||
|
||||
void close_and_submit_command_buffer(const std::vector<VkSemaphore> &semaphores, VkFence fence);
|
||||
void open_command_buffer();
|
||||
void sync_at_semaphore_release();
|
||||
void prepare_rtts();
|
||||
/// returns primitive topology, is_indexed, index_count, offset in index buffer, index type
|
||||
std::tuple<VkPrimitiveTopology, bool, u32, VkDeviceSize, VkIndexType> upload_vertex_data();
|
||||
|
@ -899,7 +899,7 @@ namespace vk
|
||||
{
|
||||
owner = &dev;
|
||||
VkCommandPoolCreateInfo infos = {};
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
|
||||
infos.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateCommandPool(dev, &infos, nullptr, &pool));
|
||||
|
Loading…
Reference in New Issue
Block a user