feat: Create the swapchain
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Ubuntu Cross to Win64 / Cross Compile with ming64 (1.4.0, ubuntu-latest) (push) Failing after 1m50s
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Ubuntu Cross to Win64 / Cross Compile with ming64 (1.4.0, ubuntu-latest) (push) Failing after 1m50s
				
			This commit is contained in:
		
							parent
							
								
									e0904e84c4
								
							
						
					
					
						commit
						3a7bca385c
					
				@ -1,12 +1,12 @@
 | 
				
			|||||||
#ifndef RT_RENCOM_RENDERER_API_H
 | 
					#ifndef RT_RENCOM_RENDERER_API_H
 | 
				
			||||||
#define RT_RENCOM_RENDERER_API_H
 | 
					#define RT_RENCOM_RENDERER_API_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "runtime/runtime.h"
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
#include "renderer.h"
 | 
					#include "renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct rt_physical_resource_manager_i rt_physical_resource_manager_i;
 | 
					typedef struct rt_physical_resource_manager_i rt_physical_resource_manager_i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef rt_physical_resource_manager_i *rt_render_device_get_physical_resource_manager_fn(void *o);
 | 
					typedef rt_physical_resource_manager_i rt_render_device_get_physical_resource_manager_fn(void *o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Interface for the render device.
 | 
					/* Interface for the render device.
 | 
				
			||||||
 * The device is responsible for executing command lists. */
 | 
					 * The device is responsible for executing command lists. */
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <runtime/runtime.h>
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
#include <runtime/config.h>
 | 
					#include <runtime/config.h>
 | 
				
			||||||
 | 
					#include <runtime/timing.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "device.h"
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -439,6 +440,7 @@ static rt_result CreateDevice(rt_vk_device *dev) {
 | 
				
			|||||||
    queue_info[0].queueCount       = 1;
 | 
					    queue_info[0].queueCount       = 1;
 | 
				
			||||||
    queue_info[0].queueFamilyIndex = queue_indices.graphics;
 | 
					    queue_info[0].queueFamilyIndex = queue_indices.graphics;
 | 
				
			||||||
    queue_info[0].pQueuePriorities = &priority;
 | 
					    queue_info[0].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					    dev->unique_families[0] = queue_indices.graphics;
 | 
				
			||||||
    if (queue_indices.compute != queue_indices.graphics) {
 | 
					    if (queue_indices.compute != queue_indices.graphics) {
 | 
				
			||||||
        queue_info[1].sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
					        queue_info[1].sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
        queue_info[1].pNext            = NULL;
 | 
					        queue_info[1].pNext            = NULL;
 | 
				
			||||||
@ -446,6 +448,7 @@ static rt_result CreateDevice(rt_vk_device *dev) {
 | 
				
			|||||||
        queue_info[1].queueCount       = 1;
 | 
					        queue_info[1].queueCount       = 1;
 | 
				
			||||||
        queue_info[1].queueFamilyIndex = queue_indices.compute;
 | 
					        queue_info[1].queueFamilyIndex = queue_indices.compute;
 | 
				
			||||||
        queue_info[1].pQueuePriorities = &priority;
 | 
					        queue_info[1].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        dev->unique_families[distinct_queue_count] = queue_indices.compute;
 | 
				
			||||||
        ++distinct_queue_count;
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (queue_indices.present != queue_indices.graphics &&
 | 
					    if (queue_indices.present != queue_indices.graphics &&
 | 
				
			||||||
@ -456,18 +459,23 @@ static rt_result CreateDevice(rt_vk_device *dev) {
 | 
				
			|||||||
        queue_info[distinct_queue_count].queueCount = 1;
 | 
					        queue_info[distinct_queue_count].queueCount = 1;
 | 
				
			||||||
        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.present;
 | 
					        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.present;
 | 
				
			||||||
        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
					        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        dev->unique_families[distinct_queue_count] = queue_indices.present;
 | 
				
			||||||
        ++distinct_queue_count;
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (queue_indices.transfer != queue_indices.graphics &&
 | 
					    if (queue_indices.transfer != queue_indices.graphics &&
 | 
				
			||||||
        queue_indices.transfer != queue_indices.compute) {
 | 
					        queue_indices.transfer != queue_indices.compute &&
 | 
				
			||||||
 | 
					        queue_indices.transfer != queue_indices.present) {
 | 
				
			||||||
        queue_info[distinct_queue_count].sType      = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
					        queue_info[distinct_queue_count].sType      = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
        queue_info[distinct_queue_count].pNext      = NULL;
 | 
					        queue_info[distinct_queue_count].pNext      = NULL;
 | 
				
			||||||
        queue_info[distinct_queue_count].flags      = 0;
 | 
					        queue_info[distinct_queue_count].flags      = 0;
 | 
				
			||||||
        queue_info[distinct_queue_count].queueCount = 1;
 | 
					        queue_info[distinct_queue_count].queueCount = 1;
 | 
				
			||||||
        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.transfer;
 | 
					        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.transfer;
 | 
				
			||||||
        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
					        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        dev->unique_families[distinct_queue_count] = queue_indices.transfer;
 | 
				
			||||||
        ++distinct_queue_count;
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    dev->unique_family_count = distinct_queue_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore_features = {
 | 
					    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore_features = {
 | 
				
			||||||
        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
 | 
					        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@ -619,9 +627,15 @@ void DestroyPerFrameObjects(rt_vk_device *dev) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info) {
 | 
					 | 
				
			||||||
    rtLog("vk", "Init");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern rt_result CreateSwapchain(rt_vk_device *dev);
 | 
				
			||||||
 | 
					extern rt_result RecreateSwapchain(rt_vk_device *dev);
 | 
				
			||||||
 | 
					extern void DestroySwapchain(rt_vk_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info) {
 | 
				
			||||||
 | 
					    rtLog("VK", "Init");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_timestamp initBegin = rtTimeNow();
 | 
				
			||||||
    rt_vk_device dev;
 | 
					    rt_vk_device dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _tracking_alloc_cbs.pUserData       = NULL;
 | 
					    _tracking_alloc_cbs.pUserData       = NULL;
 | 
				
			||||||
@ -635,6 +649,13 @@ rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info)
 | 
				
			|||||||
        dev.alloc_cb = NULL;
 | 
					        dev.alloc_cb = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dev.max_frames_in_flight = RT_RESTRICT_VALUE_TO_BOUNDS(r_VkMaxFramesInFlight.i, 2, 3);
 | 
				
			||||||
 | 
					    rtLog("VK", "Max frames in flight: %u", dev.max_frames_in_flight);
 | 
				
			||||||
 | 
					    if ((int)dev.max_frames_in_flight != r_VkMaxFramesInFlight.i) {
 | 
				
			||||||
 | 
					        r_VkMaxFramesInFlight.i = (int)dev.max_frames_in_flight;
 | 
				
			||||||
 | 
					        rtNotifyCVARChange(&r_VkMaxFramesInFlight);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_result res;
 | 
					    rt_result res;
 | 
				
			||||||
    if ((res = CreateInstance(&dev)) != RT_SUCCESS)
 | 
					    if ((res = CreateInstance(&dev)) != RT_SUCCESS)
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
@ -646,6 +667,11 @@ rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info)
 | 
				
			|||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    if ((res = CreatePerFrameObjects(&dev)) != RT_SUCCESS)
 | 
					    if ((res = CreatePerFrameObjects(&dev)) != RT_SUCCESS)
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
 | 
					    if ((res = CreateSwapchain(&dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_time_delta initTime = rtTimeBetween(initBegin, rtTimeNow());
 | 
				
			||||||
 | 
					    rtLog("VK", "Init complete. Took %lf seconds.", initTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    return (rt_create_vk_device_result) {.result = res, .device = dev};
 | 
					    return (rt_create_vk_device_result) {.result = res, .device = dev};
 | 
				
			||||||
@ -654,6 +680,7 @@ out:
 | 
				
			|||||||
void rtDestroyVkDevice(rt_vk_device *dev) {
 | 
					void rtDestroyVkDevice(rt_vk_device *dev) {
 | 
				
			||||||
    rtLog("VK", "Shutdown");
 | 
					    rtLog("VK", "Shutdown");
 | 
				
			||||||
    vkDeviceWaitIdle(dev->device);
 | 
					    vkDeviceWaitIdle(dev->device);
 | 
				
			||||||
 | 
					    DestroySwapchain(dev);
 | 
				
			||||||
    DestroyPerFrameObjects(dev);
 | 
					    DestroyPerFrameObjects(dev);
 | 
				
			||||||
    // DestroyAllocator();
 | 
					    // DestroyAllocator();
 | 
				
			||||||
    vkDestroyDevice(dev->device, dev->alloc_cb);
 | 
					    vkDestroyDevice(dev->device, dev->alloc_cb);
 | 
				
			||||||
@ -663,3 +690,9 @@ void rtDestroyVkDevice(rt_vk_device *dev) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    vkDestroyInstance(dev->instance, dev->alloc_cb);
 | 
					    vkDestroyInstance(dev->instance, dev->alloc_cb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* rt_render_device_i functions */
 | 
				
			||||||
 | 
					rt_physical_resource_manager_i rtVkDevGetPhysicalResourceManager(void *o) {
 | 
				
			||||||
 | 
					    rt_physical_resource_manager_i iface = {};
 | 
				
			||||||
 | 
					    return iface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
#include <volk/volk.h>
 | 
					#include <volk/volk.h>
 | 
				
			||||||
#include <runtime/runtime.h>
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
#include <renderer/renderer.h>
 | 
					#include <renderer/renderer.h>
 | 
				
			||||||
 | 
					#include <renderer/backend_api.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
struct HINSTANCE__;
 | 
					struct HINSTANCE__;
 | 
				
			||||||
@ -29,7 +30,7 @@ typedef struct {
 | 
				
			|||||||
    VkSemaphore swapchain_transitioned;
 | 
					    VkSemaphore swapchain_transitioned;
 | 
				
			||||||
} rt_vk_frame_data;
 | 
					} rt_vk_frame_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct rt_vk_device {
 | 
				
			||||||
    /* *** Vulkan objects *** */
 | 
					    /* *** Vulkan objects *** */
 | 
				
			||||||
    VkInstance instance;
 | 
					    VkInstance instance;
 | 
				
			||||||
    VkDevice device;
 | 
					    VkDevice device;
 | 
				
			||||||
@ -42,11 +43,14 @@ typedef struct {
 | 
				
			|||||||
    uint32_t compute_family;
 | 
					    uint32_t compute_family;
 | 
				
			||||||
    uint32_t transfer_family;
 | 
					    uint32_t transfer_family;
 | 
				
			||||||
    uint32_t present_family;
 | 
					    uint32_t present_family;
 | 
				
			||||||
 | 
					    uint32_t unique_families[4];
 | 
				
			||||||
 | 
					    uint32_t unique_family_count;
 | 
				
			||||||
    VkQueue graphics_queue;
 | 
					    VkQueue graphics_queue;
 | 
				
			||||||
    VkQueue compute_queue;
 | 
					    VkQueue compute_queue;
 | 
				
			||||||
    VkQueue transfer_queue;
 | 
					    VkQueue transfer_queue;
 | 
				
			||||||
    VkQueue present_queue;
 | 
					    VkQueue present_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* *** Properties and features *** */
 | 
					    /* *** Properties and features *** */
 | 
				
			||||||
    VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props;
 | 
					    VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props;
 | 
				
			||||||
    VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features;
 | 
					    VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features;
 | 
				
			||||||
@ -59,6 +63,10 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* *** Windowing system *** */
 | 
					    /* *** Windowing system *** */
 | 
				
			||||||
    rt_vk_native_window native_window;
 | 
					    rt_vk_native_window native_window;
 | 
				
			||||||
 | 
					    VkSwapchainKHR swapchain;
 | 
				
			||||||
 | 
					    VkImage swapchain_images[4];
 | 
				
			||||||
 | 
					    VkImageView swapchain_image_views[4];
 | 
				
			||||||
 | 
					    uint32_t swapchain_image_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* *** Debug utils *** */
 | 
					    /* *** Debug utils *** */
 | 
				
			||||||
#ifdef RT_DEBUG
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
@ -75,5 +83,7 @@ rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void rtDestroyVkDevice(rt_vk_device *dev);
 | 
					void rtDestroyVkDevice(rt_vk_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					/* rt_render_device_i functions */
 | 
				
			||||||
 | 
					rt_physical_resource_manager_i rtVkDevGetPhysicalResourceManager(void *o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -7,11 +7,7 @@
 | 
				
			|||||||
extern rt_cvar r_VkEnableAPIAllocTracking;
 | 
					extern rt_cvar r_VkEnableAPIAllocTracking;
 | 
				
			||||||
extern rt_cvar r_VkPhysDeviceName;
 | 
					extern rt_cvar r_VkPhysDeviceName;
 | 
				
			||||||
extern rt_cvar r_VkMaxFramesInFlight;
 | 
					extern rt_cvar r_VkMaxFramesInFlight;
 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
extern rt_cvar r_VkPreferredSwapchainImages;
 | 
					 | 
				
			||||||
extern rt_cvar r_VkPreferMailboxMode;
 | 
					extern rt_cvar r_VkPreferMailboxMode;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void VkRegisterCVARs(void) {
 | 
					void VkRegisterCVARs(void) {
 | 
				
			||||||
    rtRegisterCVAR(&r_VkEnableAPIAllocTracking);
 | 
					    rtRegisterCVAR(&r_VkEnableAPIAllocTracking);
 | 
				
			||||||
@ -37,7 +33,7 @@ rt_render_backend_init_result VkInit(const rt_renderer_window_info *info) {
 | 
				
			|||||||
    _device = device_result.device;
 | 
					    _device = device_result.device;
 | 
				
			||||||
    rt_render_device_i device_i = {
 | 
					    rt_render_device_i device_i = {
 | 
				
			||||||
        .o =  &_device,
 | 
					        .o =  &_device,
 | 
				
			||||||
        .GetPhysicalResourceManager =  NULL
 | 
					        .GetPhysicalResourceManager = rtVkDevGetPhysicalResourceManager,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    res.device = device_i;
 | 
					    res.device = device_i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,12 @@ if get_option('build_vk')
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  vk_renderer_lib = library('rtvk',
 | 
					  vk_renderer_lib = library('rtvk',
 | 
				
			||||||
    'device.h',
 | 
					    'device.h',
 | 
				
			||||||
 | 
					    'physical_resource_manager.h',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    'device.c',
 | 
					    'device.c',
 | 
				
			||||||
    'init.c',
 | 
					    'init.c',
 | 
				
			||||||
    
 | 
					    'physical_resource_manager.c',
 | 
				
			||||||
 | 
					    'swapchain.c',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    '../../../contrib/volk/volk.c',
 | 
					    '../../../contrib/volk/volk.c',
 | 
				
			||||||
    '../../../contrib/volk/volk.h',
 | 
					    '../../../contrib/volk/volk.h',
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								src/renderer/vk/physical_resource_manager.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/renderer/vk/physical_resource_manager.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include "physical_resource_manager.h"
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/renderer/vk/physical_resource_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/renderer/vk/physical_resource_manager.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					#ifndef RT_VK_PHYSICAL_RESOURCE_MANAGER_H
 | 
				
			||||||
 | 
					#define RT_VK_PHYSICAL_RESOURCE_MANAGER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rt_vk_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    struct rt_vk_device *dev;
 | 
				
			||||||
 | 
					} rt_vk_physical_resource_manager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										176
									
								
								src/renderer/vk/swapchain.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								src/renderer/vk/swapchain.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,176 @@
 | 
				
			|||||||
 | 
					#include <runtime/mem_arena.h>
 | 
				
			||||||
 | 
					#include <runtime/config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RT_CVAR_I(r_VkPreferMailboxMode, "Prefer the mailbox present mode. [0/1] (Default: 1)", 1);
 | 
				
			||||||
 | 
					RT_CVAR_I(r_VkPreferRelaxedMode, "Prefer the relaxed FIFO present mode. [0/1] (Default: 0)", 0);
 | 
				
			||||||
 | 
					RT_CVAR_I(r_VkEnableVSync, "Enable VSync. [0/1] (Default: 0)", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rt_result CreateSwapchain(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
 | 
				
			||||||
 | 
					    uint32_t format_count = 0;
 | 
				
			||||||
 | 
					    if (vkGetPhysicalDeviceSurfaceFormatsKHR(dev->phys_device, dev->surface, &format_count, NULL) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReturnTemporaryArena(temp);
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VkSurfaceFormatKHR *formats = RT_ARENA_PUSH_ARRAY(temp.arena, VkSurfaceFormatKHR, format_count);
 | 
				
			||||||
 | 
					    if (vkGetPhysicalDeviceSurfaceFormatsKHR(dev->phys_device, dev->surface, &format_count, formats) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReturnTemporaryArena(temp);
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Pick a format */
 | 
				
			||||||
 | 
					    VkFormat surface_format = formats[0].format;
 | 
				
			||||||
 | 
					    VkColorSpaceKHR color_space = formats[0].colorSpace;
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < format_count; ++i) {
 | 
				
			||||||
 | 
					        if (formats[i].format == VK_FORMAT_B8G8R8A8_SRGB && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
 | 
				
			||||||
 | 
					            surface_format = formats[i].format;
 | 
				
			||||||
 | 
					            color_space = formats[i].colorSpace;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Determine the number of images to create */
 | 
				
			||||||
 | 
					    uint32_t num_images = dev->max_frames_in_flight + 1;
 | 
				
			||||||
 | 
					    VkSurfaceCapabilitiesKHR surface_capabilities;
 | 
				
			||||||
 | 
					    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev->phys_device, dev->surface, &surface_capabilities);
 | 
				
			||||||
 | 
					    if (surface_capabilities.maxImageCount > 0 && surface_capabilities.maxImageCount < dev->max_frames_in_flight) {
 | 
				
			||||||
 | 
					        dev->max_frames_in_flight = surface_capabilities.maxImageCount;
 | 
				
			||||||
 | 
					        num_images = dev->max_frames_in_flight;
 | 
				
			||||||
 | 
					        rtLog("VK", "Limiting number of frames in flight to maximum number of swapchain images %u.", dev->max_frames_in_flight);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (surface_capabilities.maxImageCount > 0 && num_images > surface_capabilities.maxImageCount) {
 | 
				
			||||||
 | 
					        num_images = surface_capabilities.maxImageCount;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Determine the extent */
 | 
				
			||||||
 | 
					    VkExtent2D extent = surface_capabilities.currentExtent;
 | 
				
			||||||
 | 
					    if (surface_capabilities.currentExtent.width == UINT32_MAX && surface_capabilities.currentExtent.height == UINT32_MAX) {
 | 
				
			||||||
 | 
					        extent = surface_capabilities.maxImageExtent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Determine the present mode */
 | 
				
			||||||
 | 
					    uint32_t present_mode_count = 0;
 | 
				
			||||||
 | 
					    if (vkGetPhysicalDeviceSurfacePresentModesKHR(dev->phys_device, dev->surface, &present_mode_count, NULL) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReturnTemporaryArena(temp);
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VkPresentModeKHR *present_modes = RT_ARENA_PUSH_ARRAY(temp.arena, VkPresentModeKHR, present_mode_count);
 | 
				
			||||||
 | 
					    if (vkGetPhysicalDeviceSurfacePresentModesKHR(dev->phys_device, dev->surface, &present_mode_count, present_modes) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReturnTemporaryArena(temp);
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VkPresentModeKHR present_mode = present_modes[0];
 | 
				
			||||||
 | 
					    if (!r_VkEnableVSync.i) {
 | 
				
			||||||
 | 
					        if (r_VkPreferMailboxMode.i) {
 | 
				
			||||||
 | 
					            rtLog("VK", "r_VkPreferMailboxMode has no effect, if VSync is disabled.");
 | 
				
			||||||
 | 
					            r_VkPreferMailboxMode.i = 0;
 | 
				
			||||||
 | 
					            rtNotifyCVARChange(&r_VkPreferMailboxMode);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (r_VkPreferRelaxedMode.i) {
 | 
				
			||||||
 | 
					            rtLog("VK", "r_VkPreferRelaxedMode has no effect, if VSync is disabled.");
 | 
				
			||||||
 | 
					            r_VkPreferRelaxedMode.i = 0;
 | 
				
			||||||
 | 
					            rtNotifyCVARChange(&r_VkPreferRelaxedMode);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (uint32_t i = 0; i < present_mode_count; ++i) {
 | 
				
			||||||
 | 
					            if (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
 | 
				
			||||||
 | 
					                present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (present_mode != VK_PRESENT_MODE_IMMEDIATE_KHR) {
 | 
				
			||||||
 | 
					            rtLog("VK", "VSync was disabled, but the physical device/surface combination does not support VK_PRESENT_MODE_IMMEDIATE_KHR");
 | 
				
			||||||
 | 
					            r_VkEnableVSync.i = 1;
 | 
				
			||||||
 | 
					            rtNotifyCVARChange(&r_VkEnableVSync);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* NOT an else if, because we fall back to this if disabled vsync is not supported. */
 | 
				
			||||||
 | 
					    if (r_VkEnableVSync.i) {
 | 
				
			||||||
 | 
					        /* Required to be supported */
 | 
				
			||||||
 | 
					        present_mode = VK_PRESENT_MODE_FIFO_KHR;
 | 
				
			||||||
 | 
					        if (r_VkPreferMailboxMode.i || r_VkPreferRelaxedMode.i) {
 | 
				
			||||||
 | 
					            for (uint32_t i = 0; i < present_mode_count; ++i) {
 | 
				
			||||||
 | 
					                if (present_modes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR && r_VkPreferRelaxedMode.i) {
 | 
				
			||||||
 | 
					                    present_mode = present_modes[i];
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR && r_VkPreferMailboxMode.i) {
 | 
				
			||||||
 | 
					                    present_mode = present_modes[i];
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VkSwapchainCreateInfoKHR swapchain_info = {
 | 
				
			||||||
 | 
					        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
 | 
				
			||||||
 | 
					        .pNext = NULL,
 | 
				
			||||||
 | 
					        .flags = 0,
 | 
				
			||||||
 | 
					        .surface = dev->surface,
 | 
				
			||||||
 | 
					        .minImageCount =  num_images,
 | 
				
			||||||
 | 
					        .imageFormat = surface_format,
 | 
				
			||||||
 | 
					        .imageColorSpace = color_space,
 | 
				
			||||||
 | 
					        .imageExtent = extent,
 | 
				
			||||||
 | 
					        .imageArrayLayers = 1,
 | 
				
			||||||
 | 
					        .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
 | 
				
			||||||
 | 
					        .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
 | 
				
			||||||
 | 
					        .pQueueFamilyIndices = NULL,
 | 
				
			||||||
 | 
					        .queueFamilyIndexCount = 0,
 | 
				
			||||||
 | 
					        .preTransform =  surface_capabilities.currentTransform,
 | 
				
			||||||
 | 
					        .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
 | 
				
			||||||
 | 
					        .presentMode = present_mode,
 | 
				
			||||||
 | 
					        .clipped = VK_TRUE,
 | 
				
			||||||
 | 
					        .oldSwapchain = VK_NULL_HANDLE,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev->graphics_family != dev->present_family) {
 | 
				
			||||||
 | 
					        uint32_t queue_families[2];
 | 
				
			||||||
 | 
					        queue_families[0] = dev->graphics_family;
 | 
				
			||||||
 | 
					        queue_families[1] = dev->present_family;
 | 
				
			||||||
 | 
					        swapchain_info.pQueueFamilyIndices = &queue_families[0];
 | 
				
			||||||
 | 
					        swapchain_info.queueFamilyIndexCount = 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (vkCreateSwapchainKHR(dev->device, &swapchain_info, dev->alloc_cb, &dev->swapchain) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReturnTemporaryArena(temp);
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vkGetSwapchainImagesKHR(dev->device, dev->swapchain, &dev->swapchain_image_count, NULL);
 | 
				
			||||||
 | 
					    RT_ASSERT(dev->swapchain_image_count <= RT_ARRAY_COUNT(dev->swapchain_images), "Unexpectedly high number of swapchain images.");
 | 
				
			||||||
 | 
					    vkGetSwapchainImagesKHR(dev->device, dev->swapchain, &dev->swapchain_image_count, &dev->swapchain_images[0]);
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < dev->swapchain_image_count; ++i) {
 | 
				
			||||||
 | 
					        VkImageViewCreateInfo view_info = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
 | 
				
			||||||
 | 
					            .image = dev->swapchain_images[i],
 | 
				
			||||||
 | 
					            .viewType = VK_IMAGE_VIEW_TYPE_2D,
 | 
				
			||||||
 | 
					            .format = surface_format,
 | 
				
			||||||
 | 
					            .components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
 | 
				
			||||||
 | 
					                VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
 | 
				
			||||||
 | 
					            .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
 | 
				
			||||||
 | 
					                .baseArrayLayer =  0,.baseMipLevel = 0,
 | 
				
			||||||
 | 
					                .layerCount = 1, .levelCount = 1},
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        vkCreateImageView(dev->device, &view_info, dev->alloc_cb, &dev->swapchain_image_views[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return RT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void DestroySwapchain(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    vkDestroySwapchainKHR(dev->device, dev->swapchain, dev->alloc_cb);
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < dev->swapchain_image_count; ++i) {
 | 
				
			||||||
 | 
					        vkDestroyImageView(dev->device, dev->swapchain_image_views[i], dev->alloc_cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rt_result RecreateSwapchain(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    /* TODO(Kevin): Do this in a more perfomant way involving oldSwapchain */
 | 
				
			||||||
 | 
					    vkDeviceWaitIdle(dev->device);
 | 
				
			||||||
 | 
					    DestroySwapchain(dev);
 | 
				
			||||||
 | 
					    return CreateSwapchain(dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,7 +16,7 @@ khronos_validation.validate_sync = true
 | 
				
			|||||||
khronos_validation.thread_safety = true
 | 
					khronos_validation.thread_safety = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Specifies what action is to be taken when a layer reports information
 | 
					# Specifies what action is to be taken when a layer reports information
 | 
				
			||||||
khronos_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG
 | 
					#khronos_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Comma-delineated list of options specifying the types of messages to be reported
 | 
					# Comma-delineated list of options specifying the types of messages to be reported
 | 
				
			||||||
khronos_validation.report_flags = debug,error,perf,info,warn
 | 
					khronos_validation.report_flags = debug,error,perf,info,warn
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user