mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
(Vulkan) Cleanups
This commit is contained in:
parent
a378ce0aec
commit
eaabfefcb0
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user