(Vulkan) Cleanups

This commit is contained in:
libretroadmin 2022-05-19 15:28:26 +02:00
parent a378ce0aec
commit eaabfefcb0

View File

@ -67,12 +67,11 @@ static void vulkan_render_overlay(vk_t *vk, unsigned width, unsigned height);
#endif
static void vulkan_viewport_info(void *data, struct video_viewport *vp);
static const gfx_ctx_driver_t *vulkan_get_context(vk_t *vk)
static const gfx_ctx_driver_t *vulkan_get_context(vk_t *vk, settings_t *settings)
{
void *ctx_data = NULL;
unsigned major = 1;
unsigned minor = 0;
settings_t *settings = config_get_ptr();
enum gfx_ctx_api api = GFX_CTX_VULKAN_API;
const gfx_ctx_driver_t *gfx_ctx = video_context_driver_init_first(
vk, settings->arrays.video_context_driver,
@ -87,13 +86,12 @@ static const gfx_ctx_driver_t *vulkan_get_context(vk_t *vk)
static void vulkan_init_render_pass(
vk_t *vk)
{
VkRenderPassCreateInfo rp_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
VkAttachmentReference color_ref = { 0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
VkAttachmentDescription attachment = {0};
VkSubpassDescription subpass = {0};
VkRenderPassCreateInfo rp_info;
VkAttachmentReference color_ref;
VkAttachmentDescription attachment;
VkSubpassDescription subpass;
attachment.flags = 0;
/* Backbuffer format. */
attachment.format = vk->context->swapchain_format;
/* Not multisampled. */
@ -111,17 +109,34 @@ static void vulkan_init_render_pass(
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
/* Color attachment reference */
color_ref.attachment = 0;
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
/* We have one subpass.
* This subpass has 1 color attachment. */
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = NULL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
subpass.pResolveAttachments = NULL;
subpass.pDepthStencilAttachment = NULL;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = NULL;
/* Finally, create the renderpass. */
rp_info.sType =
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rp_info.pNext = NULL;
rp_info.flags = 0;
rp_info.attachmentCount = 1;
rp_info.pAttachments = &attachment;
rp_info.subpassCount = 1;
rp_info.pSubpasses = &subpass;
rp_info.dependencyCount = 0;
rp_info.pDependencies = NULL;
vkCreateRenderPass(vk->context->device,
&rp_info, NULL, &vk->render_pass);
@ -132,8 +147,6 @@ static void vulkan_init_framebuffers(
{
unsigned i;
vulkan_init_render_pass(vk);
for (i = 0; i < vk->num_swapchain_images; i++)
{
VkImageViewCreateInfo view =
@ -562,39 +575,13 @@ static void vulkan_init_pipelines(vk_t *vk)
}
}
static void vulkan_init_command_buffers(vk_t *vk)
{
/* RESET_COMMAND_BUFFER_BIT allows command buffer to be reset. */
unsigned i;
for (i = 0; i < vk->num_swapchain_images; i++)
{
VkCommandPoolCreateInfo pool_info = {
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
VkCommandBufferAllocateInfo info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
pool_info.queueFamilyIndex = vk->context->graphics_queue_index;
pool_info.flags =
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(vk->context->device,
&pool_info, NULL, &vk->swapchain[i].cmd_pool);
info.commandPool = vk->swapchain[i].cmd_pool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
vkAllocateCommandBuffers(vk->context->device,
&info, &vk->swapchain[i].cmd);
}
}
static void vulkan_init_samplers(vk_t *vk)
{
VkSamplerCreateInfo info =
{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
VkSamplerCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.pNext = NULL;
info.flags = 0;
info.magFilter = VK_FILTER_NEAREST;
info.minFilter = VK_FILTER_NEAREST;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
@ -602,56 +589,35 @@ static void vulkan_init_samplers(vk_t *vk)
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.mipLodBias = 0.0f;
info.anisotropyEnable = false;
info.maxAnisotropy = 1.0f;
info.compareEnable = false;
info.minLod = 0.0f;
info.maxLod = 0.0f;
info.unnormalizedCoordinates = false;
info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
info.unnormalizedCoordinates = false;
vkCreateSampler(vk->context->device,
&info, NULL, &vk->samplers.nearest);
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
vkCreateSampler(vk->context->device,
&info, NULL, &vk->samplers.linear);
info.maxLod = VK_LOD_CLAMP_NONE;
info.magFilter = VK_FILTER_NEAREST;
info.minFilter = VK_FILTER_NEAREST;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
info.maxLod = VK_LOD_CLAMP_NONE;
info.magFilter = VK_FILTER_NEAREST;
info.minFilter = VK_FILTER_NEAREST;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
vkCreateSampler(vk->context->device,
&info, NULL, &vk->samplers.mipmap_nearest);
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
vkCreateSampler(vk->context->device,
&info, NULL, &vk->samplers.mipmap_linear);
}
static void vulkan_deinit_samplers(vk_t *vk)
{
vkDestroySampler(vk->context->device, vk->samplers.nearest, NULL);
vkDestroySampler(vk->context->device, vk->samplers.linear, NULL);
vkDestroySampler(vk->context->device, vk->samplers.mipmap_nearest, NULL);
vkDestroySampler(vk->context->device, vk->samplers.mipmap_linear, NULL);
}
static void vulkan_init_buffers(vk_t *vk)
{
unsigned i;
for (i = 0; i < vk->num_swapchain_images; i++)
{
vk->swapchain[i].vbo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vk->swapchain[i].ubo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE,
vk->context->gpu_properties.limits.minUniformBufferOffsetAlignment,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
}
static void vulkan_deinit_buffers(vk_t *vk)
{
unsigned i;
@ -692,16 +658,15 @@ static void vulkan_deinit_descriptor_pool(vk_t *vk)
static void vulkan_init_textures(vk_t *vk)
{
unsigned i;
const uint32_t zero = 0;
vulkan_init_samplers(vk);
if (!vk->hw.enable)
{
unsigned i;
for (i = 0; i < vk->num_swapchain_images; i++)
{
vk->swapchain[i].texture = vulkan_create_texture(vk, NULL,
vk->tex_w, vk->tex_h, vk->tex_fmt,
vk->swapchain[i].texture = vulkan_create_texture(
vk, NULL, vk->tex_w, vk->tex_h, vk->tex_fmt,
NULL, NULL, VULKAN_TEXTURE_STREAMED);
{
@ -710,8 +675,8 @@ static void vulkan_init_textures(vk_t *vk)
}
if (vk->swapchain[i].texture.type == VULKAN_TEXTURE_STAGING)
vk->swapchain[i].texture_optimal = vulkan_create_texture(vk, NULL,
vk->tex_w, vk->tex_h, vk->tex_fmt,
vk->swapchain[i].texture_optimal = vulkan_create_texture(
vk, NULL, vk->tex_w, vk->tex_h, vk->tex_fmt,
NULL, NULL, VULKAN_TEXTURE_DYNAMIC);
}
}
@ -724,14 +689,17 @@ static void vulkan_init_textures(vk_t *vk)
static void vulkan_deinit_textures(vk_t *vk)
{
unsigned i;
const void* cached_frame;
/* Avoid memcpying from a destroyed/unmapped texture later on. */
const void* cached_frame;
video_driver_cached_frame_get(&cached_frame, NULL, NULL, NULL);
if (vulkan_is_mapped_swapchain_texture_ptr(vk, cached_frame))
video_driver_set_cached_frame_ptr(NULL);
vulkan_deinit_samplers(vk);
vkDestroySampler(vk->context->device, vk->samplers.nearest, NULL);
vkDestroySampler(vk->context->device, vk->samplers.linear, NULL);
vkDestroySampler(vk->context->device, vk->samplers.mipmap_nearest, NULL);
vkDestroySampler(vk->context->device, vk->samplers.mipmap_linear, NULL);
for (i = 0; i < vk->num_swapchain_images; i++)
{
@ -762,19 +730,14 @@ static void vulkan_deinit_command_buffers(vk_t *vk)
}
}
static void vulkan_deinit_pipeline_layout(vk_t *vk)
{
vkDestroyPipelineLayout(vk->context->device,
vk->pipelines.layout, NULL);
vkDestroyDescriptorSetLayout(vk->context->device,
vk->pipelines.set_layout, NULL);
}
static void vulkan_deinit_pipelines(vk_t *vk)
{
unsigned i;
vulkan_deinit_pipeline_layout(vk);
vkDestroyPipelineLayout(vk->context->device,
vk->pipelines.layout, NULL);
vkDestroyDescriptorSetLayout(vk->context->device,
vk->pipelines.set_layout, NULL);
vkDestroyPipeline(vk->context->device,
vk->pipelines.alpha_blend, NULL);
vkDestroyPipeline(vk->context->device,
@ -795,16 +758,12 @@ static void vulkan_deinit_framebuffers(vk_t *vk)
for (i = 0; i < vk->num_swapchain_images; i++)
{
if (vk->backbuffers[i].framebuffer)
{
vkDestroyFramebuffer(vk->context->device,
vk->backbuffers[i].framebuffer, NULL);
}
if (vk->backbuffers[i].view)
{
vkDestroyImageView(vk->context->device,
vk->backbuffers[i].view, NULL);
}
}
vkDestroyRenderPass(vk->context->device, vk->render_pass, NULL);
@ -1020,21 +979,6 @@ static bool vulkan_init_filter_chain(vk_t *vk)
return true;
}
static void vulkan_init_resources(vk_t *vk)
{
if (!vk->context)
return;
vk->num_swapchain_images = vk->context->num_swapchain_images;
vulkan_init_framebuffers(vk);
vulkan_init_pipelines(vk);
vulkan_init_descriptor_pool(vk);
vulkan_init_textures(vk);
vulkan_init_buffers(vk);
vulkan_init_command_buffers(vk);
}
static void vulkan_init_static_resources(vk_t *vk)
{
unsigned i;
@ -1089,16 +1033,6 @@ static void vulkan_deinit_static_resources(vk_t *vk)
&vk->readback.staging[i]);
}
static void vulkan_deinit_resources(vk_t *vk)
{
vulkan_deinit_pipelines(vk);
vulkan_deinit_framebuffers(vk);
vulkan_deinit_descriptor_pool(vk);
vulkan_deinit_textures(vk);
vulkan_deinit_buffers(vk);
vulkan_deinit_command_buffers(vk);
}
static void vulkan_deinit_menu(vk_t *vk)
{
unsigned i;
@ -1128,7 +1062,12 @@ static void vulkan_free(void *data)
#ifdef HAVE_THREADS
slock_unlock(vk->context->queue_lock);
#endif
vulkan_deinit_resources(vk);
vulkan_deinit_pipelines(vk);
vulkan_deinit_framebuffers(vk);
vulkan_deinit_descriptor_pool(vk);
vulkan_deinit_textures(vk);
vulkan_deinit_buffers(vk);
vulkan_deinit_command_buffers(vk);
/* No need to init this since textures are create on-demand. */
vulkan_deinit_menu(vk);
@ -1293,14 +1232,13 @@ static void vulkan_init_hw_render(vk_t *vk)
iface->get_instance_proc_addr = vulkan_symbol_wrapper_instance_proc_addr();
}
static void vulkan_init_readback(vk_t *vk)
static void vulkan_init_readback(vk_t *vk, settings_t *settings)
{
/* Only bother with this if we're doing GPU recording.
* Check recording_st->enable and not
* driver.recording_data, because recording is
* not initialized yet.
*/
settings_t *settings = config_get_ptr();
recording_state_t
*recording_st = recording_state_get_ptr();
bool recording_enabled = recording_st->enable;
@ -1359,7 +1297,7 @@ static void *vulkan_init(const video_info_t *video,
vk_t *vk = (vk_t*)calloc(1, sizeof(*vk));
if (!vk)
return NULL;
ctx_driver = vulkan_get_context(vk);
ctx_driver = vulkan_get_context(vk, settings);
if (!ctx_driver)
{
RARCH_ERR("[Vulkan]: Failed to get Vulkan context.\n");
@ -1470,7 +1408,53 @@ static void *vulkan_init(const video_info_t *video,
vulkan_init_hw_render(vk);
vulkan_init_static_resources(vk);
vulkan_init_resources(vk);
if (vk->context)
{
unsigned i;
vk->num_swapchain_images = vk->context->num_swapchain_images;
vulkan_init_render_pass(vk);
vulkan_init_framebuffers(vk);
vulkan_init_pipelines(vk);
vulkan_init_descriptor_pool(vk);
vulkan_init_samplers(vk);
vulkan_init_textures(vk);
for (i = 0; i < vk->num_swapchain_images; i++)
{
VkCommandPoolCreateInfo pool_info;
VkCommandBufferAllocateInfo info;
vk->swapchain[i].vbo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE, 16,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vk->swapchain[i].ubo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE,
vk->context->gpu_properties.limits.minUniformBufferOffsetAlignment,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
pool_info.sType =
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.pNext = NULL;
/* RESET_COMMAND_BUFFER_BIT allows command buffer to be reset. */
pool_info.flags =
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_info.queueFamilyIndex = vk->context->graphics_queue_index;
vkCreateCommandPool(vk->context->device,
&pool_info, NULL, &vk->swapchain[i].cmd_pool);
info.sType =
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.pNext = NULL;
info.commandPool = vk->swapchain[i].cmd_pool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
vkAllocateCommandBuffers(vk->context->device,
&info, &vk->swapchain[i].cmd);
}
}
if (!vulkan_init_filter_chain(vk))
{
@ -1493,7 +1477,7 @@ static void *vulkan_init(const video_info_t *video,
video->is_threaded,
FONT_DRIVER_RENDER_VULKAN_API);
vulkan_init_readback(vk);
vulkan_init_readback(vk, settings);
return vk;
error:
@ -1501,54 +1485,98 @@ error:
return NULL;
}
static void vulkan_update_filter_chain(vk_t *vk)
{
struct vulkan_filter_chain_swapchain_info info;
info.viewport = vk->vk_vp;
info.format = vk->context->swapchain_format;
info.render_pass = vk->render_pass;
info.num_indices = vk->context->num_swapchain_images;
if (!vulkan_filter_chain_update_swapchain_info((vulkan_filter_chain_t*)vk->filter_chain, &info))
RARCH_ERR("Failed to update filter chain info. This will probably lead to a crash ...\n");
}
static void vulkan_check_swapchain(vk_t *vk)
{
if (vk->context->invalid_swapchain)
struct vulkan_filter_chain_swapchain_info filter_info;
#ifdef HAVE_THREADS
slock_lock(vk->context->queue_lock);
#endif
vkQueueWaitIdle(vk->context->queue);
#ifdef HAVE_THREADS
slock_unlock(vk->context->queue_lock);
#endif
vulkan_deinit_pipelines(vk);
vulkan_deinit_framebuffers(vk);
vulkan_deinit_descriptor_pool(vk);
vulkan_deinit_textures(vk);
vulkan_deinit_buffers(vk);
vulkan_deinit_command_buffers(vk);
if (vk->context)
{
#ifdef HAVE_THREADS
slock_lock(vk->context->queue_lock);
#endif
vkQueueWaitIdle(vk->context->queue);
#ifdef HAVE_THREADS
slock_unlock(vk->context->queue_lock);
#endif
unsigned i;
vk->num_swapchain_images = vk->context->num_swapchain_images;
vulkan_deinit_resources(vk);
vulkan_init_resources(vk);
vk->context->invalid_swapchain = false;
vulkan_init_render_pass(vk);
vulkan_init_framebuffers(vk);
vulkan_init_pipelines(vk);
vulkan_init_descriptor_pool(vk);
vulkan_init_samplers(vk);
vulkan_init_textures(vk);
for (i = 0; i < vk->num_swapchain_images; i++)
{
VkCommandPoolCreateInfo pool_info;
VkCommandBufferAllocateInfo info;
vulkan_update_filter_chain(vk);
vk->swapchain[i].vbo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE,
16,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vk->swapchain[i].ubo = vulkan_buffer_chain_init(
VULKAN_BUFFER_BLOCK_SIZE,
vk->context->gpu_properties.limits.minUniformBufferOffsetAlignment,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
pool_info.sType =
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.pNext = NULL;
/* RESET_COMMAND_BUFFER_BIT allows command buffer to be reset. */
pool_info.flags =
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_info.queueFamilyIndex = vk->context->graphics_queue_index;
vkCreateCommandPool(vk->context->device,
&pool_info, NULL, &vk->swapchain[i].cmd_pool);
info.sType =
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.pNext = NULL;
info.commandPool = vk->swapchain[i].cmd_pool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
vkAllocateCommandBuffers(vk->context->device,
&info, &vk->swapchain[i].cmd);
}
}
vk->context->invalid_swapchain = false;
filter_info.viewport = vk->vk_vp;
filter_info.format = vk->context->swapchain_format;
filter_info.render_pass = vk->render_pass;
filter_info.num_indices = vk->context->num_swapchain_images;
if (
!vulkan_filter_chain_update_swapchain_info(
(vulkan_filter_chain_t*)vk->filter_chain,
&filter_info)
)
RARCH_ERR("Failed to update filter chain info. This will probably lead to a crash ...\n");
}
static void vulkan_set_nonblock_state(void *data, bool state,
bool adaptive_vsync_enabled,
unsigned swap_interval)
{
int interval = 0;
vk_t *vk = (vk_t*)data;
if (!vk)
return;
if (!state)
interval = swap_interval;
if (vk->ctx_driver->swap_interval)
{
int interval = 0;
if (!state)
interval = swap_interval;
if (adaptive_vsync_enabled && interval == 1)
interval = -1;
vk->ctx_driver->swap_interval(vk->ctx_data, interval);
@ -1556,7 +1584,8 @@ static void vulkan_set_nonblock_state(void *data, bool state,
/* Changing vsync might require recreating the swapchain,
* which means new VkImages to render into. */
vulkan_check_swapchain(vk);
if (vk->context->invalid_swapchain)
vulkan_check_swapchain(vk);
}
static bool vulkan_alive(void *data)
@ -1832,9 +1861,7 @@ static void vulkan_readback(vk_t *vk)
1, &barrier, 0, NULL, 0, NULL);
}
static void vulkan_inject_black_frame(
vk_t *vk, video_frame_info_t *video_info,
void *context_data)
static void vulkan_inject_black_frame(vk_t *vk, video_frame_info_t *video_info)
{
VkCommandBufferBeginInfo begin_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
@ -1870,28 +1897,29 @@ static void vulkan_inject_black_frame(
vkEndCommandBuffer(vk->cmd);
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &vk->cmd;
if (vk->context->has_acquired_swapchain &&
vk->context->swapchain_semaphores[swapchain_index] != VK_NULL_HANDLE)
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &vk->cmd;
if (
vk->context->has_acquired_swapchain
&& vk->context->swapchain_semaphores[swapchain_index] != VK_NULL_HANDLE)
{
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &vk->context->swapchain_semaphores[swapchain_index];
submit_info.pSignalSemaphores = &vk->context->swapchain_semaphores[swapchain_index];
}
if (vk->context->has_acquired_swapchain &&
vk->context->swapchain_acquire_semaphore != VK_NULL_HANDLE)
if ( vk->context->has_acquired_swapchain
&& vk->context->swapchain_acquire_semaphore != VK_NULL_HANDLE)
{
static const VkPipelineStageFlags wait_stage =
static const VkPipelineStageFlags wait_stage =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
assert(!vk->context->swapchain_wait_semaphores[frame_index]);
vk->context->swapchain_wait_semaphores[frame_index] =
vk->context->swapchain_acquire_semaphore;
vk->context->swapchain_acquire_semaphore = VK_NULL_HANDLE;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &vk->context->swapchain_wait_semaphores[frame_index];
submit_info.pWaitDstStageMask = &wait_stage;
vk->context->swapchain_acquire_semaphore = VK_NULL_HANDLE;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &vk->context->swapchain_wait_semaphores[frame_index];
submit_info.pWaitDstStageMask = &wait_stage;
}
#ifdef HAVE_THREADS
@ -1903,9 +1931,6 @@ static void vulkan_inject_black_frame(
#ifdef HAVE_THREADS
slock_unlock(vk->context->queue_lock);
#endif
if (vk->ctx_driver->swap_buffers)
vk->ctx_driver->swap_buffers(context_data);
}
static bool vulkan_frame(void *data, const void *frame,
@ -2187,9 +2212,7 @@ static bool vulkan_frame(void *data, const void *frame,
#ifdef VULKAN_HDR_SWAPCHAIN
if(vk->context->hdr_enable && use_main_buffer)
{
backbuffer = &vk->main_buffer;
}
#endif /* VULKAN_HDR_SWAPCHAIN */
/* Render to backbuffer. */
@ -2234,20 +2257,20 @@ static bool vulkan_frame(void *data, const void *frame,
#if defined(HAVE_MENU)
if (vk->menu.enable)
{
settings_t *settings = config_get_ptr();
bool menu_linear_filter = settings->bools.menu_linear_filter;
menu_driver_frame(menu_is_alive, video_info);
if (vk->menu.textures[vk->menu.last_index].image != VK_NULL_HANDLE ||
if (vk->menu.textures[vk->menu.last_index].image != VK_NULL_HANDLE ||
vk->menu.textures[vk->menu.last_index].buffer != VK_NULL_HANDLE)
{
struct vk_draw_quad quad;
struct vk_texture *optimal = &vk->menu.textures_optimal[vk->menu.last_index];
settings_t *settings = config_get_ptr();
bool menu_linear_filter = settings->bools.menu_linear_filter;
vulkan_set_viewport(vk, width, height, vk->menu.full_screen, false);
quad.pipeline = vk->pipelines.alpha_blend;
quad.texture = &vk->menu.textures[vk->menu.last_index];
quad.pipeline = vk->pipelines.alpha_blend;
quad.texture = &vk->menu.textures[vk->menu.last_index];
if (optimal->memory != VK_NULL_HANDLE)
quad.texture = optimal;
@ -2393,24 +2416,19 @@ static bool vulkan_frame(void *data, const void *frame,
{
VkViewport viewport;
VkRect2D sci;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = vk->context->swapchain_width;
viewport.height = vk->context->swapchain_height;
const VkRect2D scissor = {
{
(int32_t)viewport.x,
(int32_t)viewport.y
},
{
(uint32_t)viewport.width,
(uint32_t)viewport.height
},
};
sci.offset.x = (int32_t)viewport.x;
sci.offset.y = (int32_t)viewport.y;
sci.extent.width = (uint32_t)viewport.width;
sci.extent.height = (uint32_t)viewport.height;
vkCmdSetViewport(vk->cmd, 0, 1, &viewport);
vkCmdSetScissor(vk->cmd, 0, 1, &scissor);
vkCmdSetScissor(vk->cmd, 0, 1, &sci);
}
/* Upload VBO */
@ -2521,13 +2539,6 @@ static bool vulkan_frame(void *data, const void *frame,
/* Submit command buffers to GPU. */
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = NULL;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = NULL;
submit_info.pWaitDstStageMask = NULL;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &vk->cmd;
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = NULL;
if (vk->hw.num_cmd)
{
@ -2539,6 +2550,11 @@ static bool vulkan_frame(void *data, const void *frame,
vk->hw.num_cmd = 0;
}
else
{
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &vk->cmd;
}
if (waits_for_semaphores)
{
@ -2575,16 +2591,22 @@ static bool vulkan_frame(void *data, const void *frame,
vk->context->swapchain_acquire_semaphore = VK_NULL_HANDLE;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &vk->context->swapchain_wait_semaphores[frame_index];
submit_info.pWaitDstStageMask = &wait_stage;
submit_info.pWaitSemaphores = &vk->context->swapchain_wait_semaphores[frame_index];
submit_info.pWaitDstStageMask = &wait_stage;
}
else
{
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = NULL;
submit_info.pWaitDstStageMask = NULL;
}
submit_info.signalSemaphoreCount = 0;
if (vk->context->swapchain_semaphores[swapchain_index]
!= VK_NULL_HANDLE &&
vk->context->has_acquired_swapchain)
{
signal_semaphores[submit_info.signalSemaphoreCount++] = vk->context->swapchain_semaphores[swapchain_index];
}
if (vk->hw.signal_semaphore != VK_NULL_HANDLE)
{
@ -2740,12 +2762,13 @@ static bool vulkan_frame(void *data, const void *frame,
vk->should_resize = false;
}
vulkan_check_swapchain(vk);
if (vk->context->invalid_swapchain)
vulkan_check_swapchain(vk);
/* Disable BFI during fast forward, slow-motion,
* and pause to prevent flicker. */
if (
backbuffer->image != VK_NULL_HANDLE
backbuffer->image != VK_NULL_HANDLE
&& vk->context->has_acquired_swapchain
&& black_frame_insertion
&& !input_driver_nonblock_state
@ -2754,8 +2777,19 @@ static bool vulkan_frame(void *data, const void *frame,
&& !vk->menu.enable)
{
unsigned n;
for (n = 0; n < black_frame_insertion; ++n)
vulkan_inject_black_frame(vk, video_info, vk->ctx_data);
if (vk->ctx_driver->swap_buffers)
{
for (n = 0; n < black_frame_insertion; ++n)
vulkan_inject_black_frame(vk, video_info);
}
else
{
for (n = 0; n < black_frame_insertion; ++n)
{
vulkan_inject_black_frame(vk, video_info);
vk->ctx_driver->swap_buffers(vk->ctx_data);
}
}
}
/* Vulkan doesn't directly support swap_interval > 1,
@ -2809,10 +2843,9 @@ static void vulkan_show_mouse(void *data, bool state)
static struct video_shader *vulkan_get_current_shader(void *data)
{
vk_t *vk = (vk_t*)data;
if (!vk || !vk->filter_chain)
return NULL;
return vulkan_filter_chain_get_preset((vulkan_filter_chain_t*)vk->filter_chain);
if (vk && vk->filter_chain)
return vulkan_filter_chain_get_preset((vulkan_filter_chain_t*)vk->filter_chain);
return NULL;
}
static bool vulkan_get_current_sw_framebuffer(void *data,