@ -12,6 +12,7 @@
# include <GLFW/glfw3.h>
# include <vulkan/vulkan.h>
// FIXME-VULKAN: Resizing with IMGUI_UNLIMITED_FRAME_RATE triggers errors from the validation layer.
# define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16
# define IMGUI_UNLIMITED_FRAME_RATE
# ifdef _DEBUG
@ -21,16 +22,15 @@
static VkAllocationCallbacks * g_Allocator = NULL ;
static VkInstance g_Instance = VK_NULL_HANDLE ;
static VkSurfaceKHR g_Surface = VK_NULL_HANDLE ;
static VkPhysicalDevice g_ Gpu = VK_NULL_HANDLE ;
static VkPhysicalDevice g_ PhysicalDevice = VK_NULL_HANDLE ;
static VkDevice g_Device = VK_NULL_HANDLE ;
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE ;
static VkRenderPass g_RenderPass = VK_NULL_HANDLE ;
static uint32_t g_QueueFamily = 0 ;
static uint32_t g_QueueFamily = ( uint32_t ) - 1 ;
static VkQueue g_Queue = VK_NULL_HANDLE ;
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE ;
static VkSurfaceFormatKHR g_SurfaceFormat ;
static VkImageSubresourceRange g_ImageRange = { VK_IMAGE_ASPECT_COLOR_BIT , 0 , 1 , 0 , 1 } ;
static VkPresentModeKHR g_PresentMode ;
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE ;
@ -67,17 +67,18 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
err = vkDeviceWaitIdle ( g_Device ) ;
check_vk_result ( err ) ;
// Destroy old Framebuffer :
// Destroy old Framebuffer
for ( uint32_t i = 0 ; i < g_BackBufferCount ; i + + )
{
if ( g_BackBufferView [ i ] )
vkDestroyImageView ( g_Device , g_BackBufferView [ i ] , g_Allocator ) ;
for ( uint32_t i = 0 ; i < g_BackBufferCount ; i + + )
if ( g_Framebuffer [ i ] )
vkDestroyFramebuffer ( g_Device , g_Framebuffer [ i ] , g_Allocator ) ;
}
if ( g_RenderPass )
vkDestroyRenderPass ( g_Device , g_RenderPass , g_Allocator ) ;
// Create Swapchain :
// Create Swapchain
{
VkSwapchainCreateInfoKHR info = { } ;
info . sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR ;
@ -85,15 +86,15 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
info . imageFormat = g_SurfaceFormat . format ;
info . imageColorSpace = g_SurfaceFormat . colorSpace ;
info . imageArrayLayers = 1 ;
info . imageUsage | = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ;
info . imageSharingMode = VK_SHARING_MODE_EXCLUSIVE ;
info . imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ;
info . imageSharingMode = VK_SHARING_MODE_EXCLUSIVE ; // Assume that graphics family == present family
info . preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ;
info . compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ;
info . presentMode = g_PresentMode ;
info . clipped = VK_TRUE ;
info . oldSwapchain = old_swapchain ;
VkSurfaceCapabilitiesKHR cap ;
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR ( g_ Gpu , g_Surface , & cap ) ;
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR ( g_ PhysicalDevice , g_Surface , & cap ) ;
check_vk_result ( err ) ;
if ( cap . maxImageCount > 0 )
info . minImageCount = ( cap . minImageCount + 2 < cap . maxImageCount ) ? ( cap . minImageCount + 2 ) : cap . maxImageCount ;
@ -102,17 +103,13 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
if ( cap . currentExtent . width = = 0xffffffff )
{
fb_width = w ;
fb_height = h ;
info . imageExtent . width = fb_width ;
info . imageExtent . height = fb_height ;
info . imageExtent . width = fb_width = w ;
info . imageExtent . height = fb_height = h ;
}
else
{
fb_width = cap . currentExtent . width ;
fb_height = cap . currentExtent . height ;
info . imageExtent . width = fb_width ;
info . imageExtent . height = fb_height ;
info . imageExtent . width = fb_width = cap . currentExtent . width ;
info . imageExtent . height = fb_height = cap . currentExtent . height ;
}
err = vkCreateSwapchainKHR ( g_Device , & info , g_Allocator , & g_Swapchain ) ;
check_vk_result ( err ) ;
@ -124,7 +121,7 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
if ( old_swapchain )
vkDestroySwapchainKHR ( g_Device , old_swapchain , g_Allocator ) ;
// Create the Render Pass :
// Create the Render Pass
{
VkAttachmentDescription attachment = { } ;
attachment . format = g_SurfaceFormat . format ;
@ -162,7 +159,8 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
info . components . g = VK_COMPONENT_SWIZZLE_G ;
info . components . b = VK_COMPONENT_SWIZZLE_B ;
info . components . a = VK_COMPONENT_SWIZZLE_A ;
info . subresourceRange = g_ImageRange ;
VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT , 0 , 1 , 0 , 1 } ;
info . subresourceRange = image_range ;
for ( uint32_t i = 0 ; i < g_BackBufferCount ; i + + )
{
info . image = g_BackBuffer [ i ] ;
@ -171,7 +169,7 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
}
}
// Create Framebuffer :
// Create Framebuffer
{
VkImageView attachment [ 1 ] ;
VkFramebufferCreateInfo info = { } ;
@ -252,7 +250,7 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
check_vk_result ( err ) ;
}
// Ge t GPU
// Selec t GPU
{
uint32_t gpu_count ;
err = vkEnumeratePhysicalDevices ( g_Instance , & gpu_count , NULL ) ;
@ -265,31 +263,30 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
// If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
// e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
// for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
g_ Gpu = gpus [ 0 ] ;
g_ PhysicalDevice = gpus [ 0 ] ;
free ( gpus ) ;
}
// Get queue
// Select graphics queue family
{
uint32_t count ;
vkGetPhysicalDeviceQueueFamilyProperties ( g_ Gpu , & count , NULL ) ;
vkGetPhysicalDeviceQueueFamilyProperties ( g_ PhysicalDevice , & count , NULL ) ;
VkQueueFamilyProperties * queues = ( VkQueueFamilyProperties * ) malloc ( sizeof ( VkQueueFamilyProperties ) * count ) ;
vkGetPhysicalDeviceQueueFamilyProperties ( g_ Gpu , & count , queues ) ;
vkGetPhysicalDeviceQueueFamilyProperties ( g_ PhysicalDevice , & count , queues ) ;
for ( uint32_t i = 0 ; i < count ; i + + )
{
if ( queues [ i ] . queueFlags & VK_QUEUE_GRAPHICS_BIT )
{
g_QueueFamily = i ;
break ;
}
}
free ( queues ) ;
IM_ASSERT ( g_QueueFamily ! = - 1 ) ;
}
// Check for WSI support
{
VkBool32 res ;
vkGetPhysicalDeviceSurfaceSupportKHR ( g_ Gpu , g_QueueFamily , g_Surface , & res ) ;
vkGetPhysicalDeviceSurfaceSupportKHR ( g_ PhysicalDevice , g_QueueFamily , g_Surface , & res ) ;
if ( res ! = VK_TRUE )
{
fprintf ( stderr , " Error no WSI support on physical device 0 \n " ) ;
@ -300,15 +297,15 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
// Get Surface Format
{
// Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
// Assuming that the default behavior is without setting this bit, there is no need for separate S pa wchain image and image view format
// a dditionally several new color spaces were introduced with Vulkan Spec v1.0.40
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used
// Assuming that the default behavior is without setting this bit, there is no need for separate S wap chain image and image view format
// A dditionally several new color spaces were introduced with Vulkan Spec v1.0.40,
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used .
uint32_t count ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( g_ Gpu , g_Surface , & count , NULL ) ;
VkSurfaceFormatKHR * formats = ( VkSurfaceFormatKHR * ) malloc ( sizeof ( VkSurfaceFormatKHR ) * count ) ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( g_ Gpu , g_Surface , & count , formats ) ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( g_ PhysicalDevice , g_Surface , & count , NULL ) ;
VkSurfaceFormatKHR * formats = ( VkSurfaceFormatKHR * ) malloc ( sizeof ( VkSurfaceFormatKHR ) * count ) ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( g_ PhysicalDevice , g_Surface , & count , formats ) ;
// f irst check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
// F irst check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
if ( count = = 1 )
{
if ( formats [ 0 ] . format = = VK_FORMAT_UNDEFINED )
@ -317,32 +314,27 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
g_SurfaceFormat . colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR ;
}
else
{ // no point in searching another format
{
// No point in searching another format
g_SurfaceFormat = formats [ 0 ] ;
}
}
else
{
// r equest several formats, the first found will be used
// R equest several formats, the first found will be used
VkFormat requestSurfaceImageFormat [ ] = { VK_FORMAT_B8G8R8A8_UNORM , VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_B8G8R8_UNORM , VK_FORMAT_R8G8B8_UNORM } ;
VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR ;
bool requestedFound = false ;
for ( size_t i = 0 ; i < sizeof ( requestSurfaceImageFormat ) / sizeof ( requestSurfaceImageFormat [ 0 ] ) ; i + + )
{
if ( requestedFound )
break ;
bool found = false ;
for ( size_t i = 0 ; found = = false & & i < sizeof ( requestSurfaceImageFormat ) / sizeof ( requestSurfaceImageFormat [ 0 ] ) ; i + + )
for ( uint32_t j = 0 ; j < count ; j + + )
{
if ( formats [ j ] . format = = requestSurfaceImageFormat [ i ] & & formats [ j ] . colorSpace = = requestSurfaceColorSpace )
{
g_SurfaceFormat = formats [ j ] ;
requestedF ound = true ;
f ound = true ;
}
}
}
// i f none of the requested image formats could be found, use the first available
if ( ! requestedF ound)
// If none of the requested image formats could be found, use the first available
if ( ! f ound)
g_SurfaceFormat = formats [ 0 ] ;
}
free ( formats ) ;
@ -351,41 +343,34 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
// Get Present Mode
{
// Requ st a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
// Requ e st a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
# ifdef IMGUI_UNLIMITED_FRAME_RATE
g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR ;
# else
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR ;
# endif
uint32_t count = 0 ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( g_ Gpu , g_Surface , & count , nullptr ) ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( g_ PhysicalDevice , g_Surface , & count , nullptr ) ;
VkPresentModeKHR * presentModes = ( VkPresentModeKHR * ) malloc ( sizeof ( VkQueueFamilyProperties ) * count ) ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( g_ Gpu , g_Surface , & count , presentModes ) ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( g_ PhysicalDevice , g_Surface , & count , presentModes ) ;
bool presentModeAvailable = false ;
for ( size_t i = 0 ; i < count ; i + + )
{
for ( size_t i = 0 ; i < count & & ! presentModeAvailable ; i + + )
if ( presentModes [ i ] = = g_PresentMode )
{
presentModeAvailable = true ;
break ;
}
}
if ( ! presentModeAvailable )
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR ; // a lways available
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR ; // Always available
}
// Create Logical Device
// Create Logical Device (with 1 queue)
{
int device_extension_count = 1 ;
const char * device_extensions [ ] = { " VK_KHR_swapchain " } ;
const uint32_t queue_index = 0 ;
const uint32_t queue_count = 1 ;
const float queue_priority [ ] = { 1.0f } ;
VkDeviceQueueCreateInfo queue_info [ 1 ] = { } ;
queue_info [ 0 ] . sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO ;
queue_info [ 0 ] . queueFamilyIndex = g_QueueFamily ;
queue_info [ 0 ] . queueCount = queue_count ;
queue_info [ 0 ] . queueCount = 1 ;
queue_info [ 0 ] . pQueuePriorities = queue_priority ;
VkDeviceCreateInfo create_info = { } ;
create_info . sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO ;
@ -393,11 +378,12 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
create_info . pQueueCreateInfos = queue_info ;
create_info . enabledExtensionCount = device_extension_count ;
create_info . ppEnabledExtensionNames = device_extensions ;
err = vkCreateDevice ( g_ Gpu , & create_info , g_Allocator , & g_Device ) ;
err = vkCreateDevice ( g_ PhysicalDevice , & create_info , g_Allocator , & g_Device ) ;
check_vk_result ( err ) ;
vkGetDeviceQueue ( g_Device , g_QueueFamily , queue_index , & g_Queue ) ;
vkGetDeviceQueue ( g_Device , g_QueueFamily , 0 , & g_Queue ) ;
}
// Create Framebuffers
{
int w , h ;
@ -406,6 +392,7 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
glfwSetFramebufferSizeCallback ( window , resize_vulkan ) ;
}
// Create Command Buffers
for ( int i = 0 ; i < IMGUI_VK_QUEUED_FRAMES ; i + + )
{
@ -614,18 +601,18 @@ int main(int, char**)
// Setup ImGui binding
ImGui : : CreateContext ( ) ;
ImGui_ImplVulkan_Init Data init_data = { } ;
init_ data. a llocator = g_Allocator ;
init_ data. gpu = g_Gpu ;
init_ data. d evice = g_Device ;
init_ data. render_p ass = g_RenderPass ;
init_ data. pipeline_c ache = g_PipelineCache ;
init_ data. descriptor_p ool = g_DescriptorPool ;
init_ data. check_vk_result = check_vk_result ;
ImGui_ImplVulkan_Init Info init_info = { } ;
init_ info. A llocator = g_Allocator ;
init_ info. PhysicalDevice = g_PhysicalDevice ;
init_ info. D evice = g_Device ;
init_ info. RenderP ass = g_RenderPass ;
init_ info. PipelineC ache = g_PipelineCache ;
init_ info. DescriptorP ool = g_DescriptorPool ;
init_ info. CheckVkResultFn = check_vk_result ;
ImGuiIO & io = ImGui : : GetIO ( ) ; ( void ) io ;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
ImGui_ImplVulkan_Init ( & init_ data ) ;
ImGui_ImplVulkan_Init ( & init_ info ) ;
ImGui_ImplGlfw_Init ( window , true ) ;
// Setup style