diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 5f9dc8ac6c..887420a7af 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -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,