mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-14 05:29:02 +08:00
Merge branch 'examples_refactor' into viewport
# Conflicts: # examples/directx10_example/main.cpp # examples/directx11_example/main.cpp # examples/directx12_example/main.cpp # examples/opengl3_example/main.cpp # examples/sdl_opengl2_example/main.cpp # examples/sdl_opengl3_example/main.cpp # examples/sdl_vulkan_example/main.cpp # examples/vulkan_example/main.cpp # imgui.h
This commit is contained in:
commit
fc80f2b41a
@ -176,6 +176,7 @@ static void ImGui_ImplGlfw_UpdateMouse()
|
|||||||
io.MouseHoveredViewport = 0;
|
io.MouseHoveredViewport = 0;
|
||||||
|
|
||||||
// Update buttons
|
// Update buttons
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
||||||
{
|
{
|
||||||
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2018-XX-XX: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications).
|
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
|
||||||
|
// 2018-02-18: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications).
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
// 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy.
|
// 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy.
|
||||||
@ -23,13 +24,13 @@
|
|||||||
#include "imgui_impl_vulkan.h"
|
#include "imgui_impl_vulkan.h"
|
||||||
|
|
||||||
// Vulkan data
|
// Vulkan data
|
||||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
static const VkAllocationCallbacks* g_Allocator = NULL;
|
||||||
static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE;
|
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||||
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
||||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||||
static void (*g_CheckVkResult)(VkResult err) = NULL;
|
static void (*g_CheckVkResult)(VkResult err) = NULL;
|
||||||
|
|
||||||
static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE;
|
static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE;
|
||||||
static VkDeviceSize g_BufferMemoryAlignment = 256;
|
static VkDeviceSize g_BufferMemoryAlignment = 256;
|
||||||
@ -133,7 +134,7 @@ static uint32_t __glsl_shader_frag_spv[] =
|
|||||||
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
||||||
{
|
{
|
||||||
VkPhysicalDeviceMemoryProperties prop;
|
VkPhysicalDeviceMemoryProperties prop;
|
||||||
vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop);
|
vkGetPhysicalDeviceMemoryProperties(g_PhysicalDevice, &prop);
|
||||||
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
|
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
|
||||||
if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
|
if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
|
||||||
return i;
|
return i;
|
||||||
@ -688,15 +689,15 @@ void ImGui_ImplVulkan_InvalidateDeviceObjects()
|
|||||||
if (g_Pipeline) { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; }
|
if (g_Pipeline) { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitData *init_data)
|
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data)
|
||||||
{
|
{
|
||||||
g_Allocator = init_data->allocator;
|
g_Allocator = init_data->Allocator;
|
||||||
g_Gpu = init_data->gpu;
|
g_PhysicalDevice = init_data->PhysicalDevice;
|
||||||
g_Device = init_data->device;
|
g_Device = init_data->Device;
|
||||||
g_RenderPass = init_data->render_pass;
|
g_RenderPass = init_data->RenderPass;
|
||||||
g_PipelineCache = init_data->pipeline_cache;
|
g_PipelineCache = init_data->PipelineCache;
|
||||||
g_DescriptorPool = init_data->descriptor_pool;
|
g_DescriptorPool = init_data->DescriptorPool;
|
||||||
g_CheckVkResult = init_data->check_vk_result;
|
g_CheckVkResult = init_data->CheckVkResultFn;
|
||||||
|
|
||||||
ImGui_ImplVulkan_CreateDeviceObjects();
|
ImGui_ImplVulkan_CreateDeviceObjects();
|
||||||
return true;
|
return true;
|
||||||
@ -719,3 +720,73 @@ void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer)
|
|||||||
g_CommandBuffer = VK_NULL_HANDLE;
|
g_CommandBuffer = VK_NULL_HANDLE;
|
||||||
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Miscellaneous Vulkan Helpers
|
||||||
|
// (Those are currently not strictly needed by the binding, but will be once if we support multi-viewports)
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
|
||||||
|
{
|
||||||
|
IM_ASSERT(request_formats != NULL);
|
||||||
|
IM_ASSERT(request_formats_count > 0);
|
||||||
|
|
||||||
|
// 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 Swapchain image and image view format
|
||||||
|
// Additionally 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 avail_count;
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL);
|
||||||
|
ImVector<VkSurfaceFormatKHR> avail_format;
|
||||||
|
avail_format.resize((int)avail_count);
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);
|
||||||
|
|
||||||
|
// First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
|
||||||
|
if (avail_count == 1)
|
||||||
|
{
|
||||||
|
if (avail_format[0].format == VK_FORMAT_UNDEFINED)
|
||||||
|
{
|
||||||
|
VkSurfaceFormatKHR ret;
|
||||||
|
ret.format = request_formats[0];
|
||||||
|
ret.colorSpace = request_color_space;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No point in searching another format
|
||||||
|
return avail_format[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Request several formats, the first found will be used
|
||||||
|
for (int request_i = 0; request_i < request_formats_count; request_i++)
|
||||||
|
for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
|
||||||
|
if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space)
|
||||||
|
return avail_format[avail_i];
|
||||||
|
|
||||||
|
// If none of the requested image formats could be found, use the first available
|
||||||
|
return avail_format[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
|
||||||
|
{
|
||||||
|
IM_ASSERT(request_modes != NULL);
|
||||||
|
IM_ASSERT(request_modes_count > 0);
|
||||||
|
|
||||||
|
// Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
|
||||||
|
uint32_t avail_count = 0;
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL);
|
||||||
|
ImVector<VkPresentModeKHR> avail_modes;
|
||||||
|
avail_modes.resize((int)avail_count);
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);
|
||||||
|
for (int request_i = 0; request_i < request_modes_count; request_i++)
|
||||||
|
for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
|
||||||
|
if (request_modes[request_i] == avail_modes[avail_i])
|
||||||
|
return request_modes[request_i];
|
||||||
|
|
||||||
|
return VK_PRESENT_MODE_FIFO_KHR; // Always available
|
||||||
|
}
|
||||||
|
@ -13,18 +13,18 @@
|
|||||||
|
|
||||||
#define IMGUI_VK_QUEUED_FRAMES 2
|
#define IMGUI_VK_QUEUED_FRAMES 2
|
||||||
|
|
||||||
struct ImGui_ImplVulkan_InitData
|
struct ImGui_ImplVulkan_InitInfo
|
||||||
{
|
{
|
||||||
VkAllocationCallbacks* allocator;
|
const VkAllocationCallbacks* Allocator;
|
||||||
VkPhysicalDevice gpu;
|
VkPhysicalDevice PhysicalDevice;
|
||||||
VkDevice device;
|
VkDevice Device;
|
||||||
VkRenderPass render_pass;
|
VkRenderPass RenderPass;
|
||||||
VkPipelineCache pipeline_cache;
|
VkPipelineCache PipelineCache;
|
||||||
VkDescriptorPool descriptor_pool;
|
VkDescriptorPool DescriptorPool;
|
||||||
void (*check_vk_result)(VkResult err);
|
void (*CheckVkResultFn)(VkResult err);
|
||||||
};
|
};
|
||||||
|
|
||||||
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitData *init_data);
|
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data);
|
||||||
IMGUI_API void ImGui_ImplVulkan_Shutdown();
|
IMGUI_API void ImGui_ImplVulkan_Shutdown();
|
||||||
IMGUI_API void ImGui_ImplVulkan_NewFrame();
|
IMGUI_API void ImGui_ImplVulkan_NewFrame();
|
||||||
IMGUI_API void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer);
|
IMGUI_API void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer);
|
||||||
@ -34,3 +34,7 @@ IMGUI_API void ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
|||||||
IMGUI_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
|
IMGUI_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
|
||||||
IMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
IMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||||
IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects();
|
IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects();
|
||||||
|
|
||||||
|
// Miscellaneous Vulkan Helpers
|
||||||
|
IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
|
||||||
|
IMGUI_API VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
|
||||||
|
@ -38,6 +38,7 @@ int main(int, char**)
|
|||||||
io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
|
io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||||
|
|
||||||
ImGui_ImplGlfw_Init(window, true);
|
ImGui_ImplGlfw_Init(window, true);
|
||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
|
|
||||||
|
@ -9,25 +9,25 @@
|
|||||||
#include <SDL_vulkan.h>
|
#include <SDL_vulkan.h>
|
||||||
#include <vulkan/vulkan.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_MAX_POSSIBLE_BACK_BUFFERS 16
|
||||||
#define IMGUI_UNLIMITED_FRAME_RATE
|
#define IMGUI_UNLIMITED_FRAME_RATE
|
||||||
//#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
//#define IMGUI_VULKAN_DEBUG_REPORT
|
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||||
static VkSurfaceKHR g_Surface = 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 VkDevice g_Device = VK_NULL_HANDLE;
|
||||||
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
|
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
|
||||||
static VkRenderPass g_RenderPass = 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 VkQueue g_Queue = VK_NULL_HANDLE;
|
||||||
static VkDebugReportCallbackEXT g_Debug_Report = VK_NULL_HANDLE;
|
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||||
|
|
||||||
static VkSurfaceFormatKHR g_SurfaceFormat;
|
static VkSurfaceFormatKHR g_SurfaceFormat;
|
||||||
static VkImageSubresourceRange g_ImageRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
|
||||||
static VkPresentModeKHR g_PresentMode;
|
static VkPresentModeKHR g_PresentMode;
|
||||||
|
|
||||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||||
@ -57,24 +57,25 @@ static void check_vk_result(VkResult err)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resize_vulkan(SDL_Window*, int w, int h)
|
static void CreateOrResizeSwapChainAndFrameBuffer(int w, int h)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkSwapchainKHR old_swapchain = g_Swapchain;
|
VkSwapchainKHR old_swapchain = g_Swapchain;
|
||||||
err = vkDeviceWaitIdle(g_Device);
|
err = vkDeviceWaitIdle(g_Device);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
// Destroy old Framebuffer:
|
// Destroy old Framebuffer
|
||||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||||
|
{
|
||||||
if (g_BackBufferView[i])
|
if (g_BackBufferView[i])
|
||||||
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
||||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
|
||||||
if (g_Framebuffer[i])
|
if (g_Framebuffer[i])
|
||||||
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
||||||
|
}
|
||||||
if (g_RenderPass)
|
if (g_RenderPass)
|
||||||
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
||||||
|
|
||||||
// Create Swapchain:
|
// Create Swapchain
|
||||||
{
|
{
|
||||||
VkSwapchainCreateInfoKHR info = {};
|
VkSwapchainCreateInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
@ -82,15 +83,15 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
info.imageFormat = g_SurfaceFormat.format;
|
info.imageFormat = g_SurfaceFormat.format;
|
||||||
info.imageColorSpace = g_SurfaceFormat.colorSpace;
|
info.imageColorSpace = g_SurfaceFormat.colorSpace;
|
||||||
info.imageArrayLayers = 1;
|
info.imageArrayLayers = 1;
|
||||||
info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
|
||||||
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
info.presentMode = g_PresentMode;
|
info.presentMode = g_PresentMode;
|
||||||
info.clipped = VK_TRUE;
|
info.clipped = VK_TRUE;
|
||||||
info.oldSwapchain = old_swapchain;
|
info.oldSwapchain = old_swapchain;
|
||||||
VkSurfaceCapabilitiesKHR cap;
|
VkSurfaceCapabilitiesKHR cap;
|
||||||
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_Gpu, g_Surface, &cap);
|
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, g_Surface, &cap);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
if (cap.maxImageCount > 0)
|
if (cap.maxImageCount > 0)
|
||||||
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
|
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
|
||||||
@ -99,17 +100,13 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
|
|
||||||
if (cap.currentExtent.width == 0xffffffff)
|
if (cap.currentExtent.width == 0xffffffff)
|
||||||
{
|
{
|
||||||
fb_width = w;
|
info.imageExtent.width = fb_width = w;
|
||||||
fb_height = h;
|
info.imageExtent.height = fb_height = h;
|
||||||
info.imageExtent.width = fb_width;
|
|
||||||
info.imageExtent.height = fb_height;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fb_width = cap.currentExtent.width;
|
info.imageExtent.width = fb_width = cap.currentExtent.width;
|
||||||
fb_height = cap.currentExtent.height;
|
info.imageExtent.height = fb_height = cap.currentExtent.height;
|
||||||
info.imageExtent.width = fb_width;
|
|
||||||
info.imageExtent.height = fb_height;
|
|
||||||
}
|
}
|
||||||
err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain);
|
err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
@ -121,7 +118,7 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
if (old_swapchain)
|
if (old_swapchain)
|
||||||
vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
|
vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
|
||||||
|
|
||||||
// Create the Render Pass:
|
// Create the Render Pass
|
||||||
{
|
{
|
||||||
VkAttachmentDescription attachment = {};
|
VkAttachmentDescription attachment = {};
|
||||||
attachment.format = g_SurfaceFormat.format;
|
attachment.format = g_SurfaceFormat.format;
|
||||||
@ -159,7 +156,8 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
info.components.g = VK_COMPONENT_SWIZZLE_G;
|
info.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
info.components.b = VK_COMPONENT_SWIZZLE_B;
|
info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
info.components.a = VK_COMPONENT_SWIZZLE_A;
|
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++)
|
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||||
{
|
{
|
||||||
info.image = g_BackBuffer[i];
|
info.image = g_BackBuffer[i];
|
||||||
@ -168,7 +166,7 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Framebuffer:
|
// Create Framebuffer
|
||||||
{
|
{
|
||||||
VkImageView attachment[1];
|
VkImageView attachment[1];
|
||||||
VkFramebufferCreateInfo info = {};
|
VkFramebufferCreateInfo info = {};
|
||||||
@ -189,9 +187,9 @@ static void resize_vulkan(SDL_Window*, int w, int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||||
VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
|
||||||
{
|
{
|
||||||
|
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguemnts
|
||||||
printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
@ -209,38 +207,36 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e
|
|||||||
create_info.ppEnabledExtensionNames = extensions;
|
create_info.ppEnabledExtensionNames = extensions;
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
// enabling multiple validation layers grouped as lunarg standard validation
|
// Enabling multiple validation layers grouped as LunarG standard validation
|
||||||
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
||||||
create_info.enabledLayerCount = 1;
|
create_info.enabledLayerCount = 1;
|
||||||
create_info.ppEnabledLayerNames = layers;
|
create_info.ppEnabledLayerNames = layers;
|
||||||
|
|
||||||
// need additional storage for char pointer to debug report extension
|
// Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
|
||||||
const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
||||||
for (size_t i = 0; i < extensions_count; i++)
|
memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
|
||||||
extensions[i] = extensions[i];
|
extensions_ext[extensions_count] = "VK_EXT_debug_report";
|
||||||
extensions[extensions_count] = "VK_EXT_debug_report";
|
|
||||||
create_info.enabledExtensionCount = extensions_count + 1;
|
create_info.enabledExtensionCount = extensions_count + 1;
|
||||||
create_info.ppEnabledExtensionNames = extensions;
|
create_info.ppEnabledExtensionNames = extensions_ext;
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
free(extensions);
|
free(extensions_ext);
|
||||||
|
|
||||||
// create the debug report callback
|
// Get the function pointer (required for any extensions)
|
||||||
|
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||||
|
IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
|
||||||
|
|
||||||
|
// Setup the debug report callback
|
||||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||||
debug_report_ci.pfnCallback = debug_report;
|
debug_report_ci.pfnCallback = debug_report;
|
||||||
debug_report_ci.pUserData = NULL;
|
debug_report_ci.pUserData = NULL;
|
||||||
|
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||||
// get the proc address of the function pointer, required for used extensions
|
|
||||||
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT =
|
|
||||||
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
|
||||||
|
|
||||||
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report);
|
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
}
|
}
|
||||||
@ -255,7 +251,7 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get GPU
|
// Select GPU
|
||||||
{
|
{
|
||||||
uint32_t gpu_count;
|
uint32_t gpu_count;
|
||||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||||
@ -268,31 +264,30 @@ static void setup_vulkan(SDL_Window* 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
|
// 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.
|
// 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.
|
// 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);
|
free(gpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get queue
|
// Select graphics queue family
|
||||||
{
|
{
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL);
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
|
||||||
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
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++)
|
for (uint32_t i = 0; i < count; i++)
|
||||||
{
|
|
||||||
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
{
|
{
|
||||||
g_QueueFamily = i;
|
g_QueueFamily = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
free(queues);
|
free(queues);
|
||||||
|
IM_ASSERT(g_QueueFamily != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for WSI support
|
// Check for WSI support
|
||||||
{
|
{
|
||||||
VkBool32 res;
|
VkBool32 res;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res);
|
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, g_Surface, &res);
|
||||||
if (res != VK_TRUE)
|
if (res != VK_TRUE)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||||
@ -302,93 +297,32 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e
|
|||||||
|
|
||||||
// Get Surface Format
|
// 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
|
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||||
// Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format
|
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
// additionally several new color spaces were introduced with Vulkan Spec v1.0.40
|
g_SurfaceFormat = ImGui_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, g_Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// first 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)
|
|
||||||
{
|
|
||||||
g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // no point in searching another format
|
|
||||||
g_SurfaceFormat = formats[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// request 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;
|
|
||||||
for (uint32_t j = 0; j < count; j++)
|
|
||||||
{
|
|
||||||
if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace)
|
|
||||||
{
|
|
||||||
g_SurfaceFormat = formats[j];
|
|
||||||
requestedFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if none of the requested image formats could be found, use the first available
|
|
||||||
if (!requestedFound)
|
|
||||||
g_SurfaceFormat = formats[0];
|
|
||||||
}
|
|
||||||
free(formats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get Present Mode
|
// Get Present Mode
|
||||||
{
|
{
|
||||||
// Requst 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
|
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
||||||
g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
#else
|
#else
|
||||||
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
#endif
|
#endif
|
||||||
uint32_t count = 0;
|
g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1);
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, NULL);
|
|
||||||
VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes);
|
|
||||||
bool presentModeAvailable = false;
|
|
||||||
for (size_t i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (presentModes[i] == g_PresentMode)
|
|
||||||
{
|
|
||||||
presentModeAvailable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!presentModeAvailable)
|
|
||||||
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Logical Device
|
// Create Logical Device (with 1 queue)
|
||||||
{
|
{
|
||||||
int device_extension_count = 1;
|
int device_extension_count = 1;
|
||||||
const char* device_extensions[] = { "VK_KHR_swapchain" };
|
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 };
|
const float queue_priority[] = { 1.0f };
|
||||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||||
queue_info[0].queueCount = queue_count;
|
queue_info[0].queueCount = 1;
|
||||||
queue_info[0].pQueuePriorities = queue_priority;
|
queue_info[0].pQueuePriorities = queue_priority;
|
||||||
VkDeviceCreateInfo create_info = {};
|
VkDeviceCreateInfo create_info = {};
|
||||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
@ -396,18 +330,20 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e
|
|||||||
create_info.pQueueCreateInfos = queue_info;
|
create_info.pQueueCreateInfos = queue_info;
|
||||||
create_info.enabledExtensionCount = device_extension_count;
|
create_info.enabledExtensionCount = device_extension_count;
|
||||||
create_info.ppEnabledExtensionNames = device_extensions;
|
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);
|
check_vk_result(err);
|
||||||
vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue);
|
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Framebuffers
|
// Create Framebuffers
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
resize_vulkan(window, w, h);
|
CreateOrResizeSwapChainAndFrameBuffer(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Command Buffers
|
// Create Command Buffers
|
||||||
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||||
{
|
{
|
||||||
@ -493,9 +429,9 @@ static void cleanup_vulkan()
|
|||||||
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
|
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
// get the proc address of the function pointer, required for used extensions
|
// Remove the debug report callback
|
||||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||||
vkDestroyDebugReportCallbackEXT(g_Instance, g_Debug_Report, g_Allocator);
|
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
vkDestroyDevice(g_Device, g_Allocator);
|
vkDestroyDevice(g_Device, g_Allocator);
|
||||||
@ -613,18 +549,18 @@ int main(int, char**)
|
|||||||
// Setup ImGui binding
|
// Setup ImGui binding
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
|
||||||
ImGui_ImplVulkan_InitData init_data = {};
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||||
init_data.allocator = g_Allocator;
|
init_info.Allocator = g_Allocator;
|
||||||
init_data.gpu = g_Gpu;
|
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||||
init_data.device = g_Device;
|
init_info.Device = g_Device;
|
||||||
init_data.render_pass = g_RenderPass;
|
init_info.RenderPass = g_RenderPass;
|
||||||
init_data.pipeline_cache = g_PipelineCache;
|
init_info.PipelineCache = g_PipelineCache;
|
||||||
init_data.descriptor_pool = g_DescriptorPool;
|
init_info.DescriptorPool = g_DescriptorPool;
|
||||||
init_data.check_vk_result = check_vk_result;
|
init_info.CheckVkResultFn = check_vk_result;
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
ImGui_ImplVulkan_Init(&init_data);
|
ImGui_ImplVulkan_Init(&init_info);
|
||||||
ImGui_ImplSDL2_Init(window, NULL);
|
ImGui_ImplSDL2_Init(window, NULL);
|
||||||
|
|
||||||
// Setup style
|
// Setup style
|
||||||
@ -703,6 +639,8 @@ int main(int, char**)
|
|||||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
if (event.type == SDL_QUIT)
|
if (event.type == SDL_QUIT)
|
||||||
done = true;
|
done = true;
|
||||||
|
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
|
||||||
|
CreateOrResizeSwapChainAndFrameBuffer((int)event.window.data1, (int)event.window.data2);
|
||||||
}
|
}
|
||||||
ImGui_ImplVulkan_NewFrame();
|
ImGui_ImplVulkan_NewFrame();
|
||||||
ImGui_ImplSDL2_NewFrame(window);
|
ImGui_ImplSDL2_NewFrame(window);
|
||||||
|
@ -12,25 +12,25 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <vulkan/vulkan.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_MAX_POSSIBLE_BACK_BUFFERS 16
|
||||||
#define IMGUI_UNLIMITED_FRAME_RATE
|
#define IMGUI_UNLIMITED_FRAME_RATE
|
||||||
//#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
//#define IMGUI_VULKAN_DEBUG_REPORT
|
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||||
static VkSurfaceKHR g_Surface = 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 VkDevice g_Device = VK_NULL_HANDLE;
|
||||||
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
|
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
|
||||||
static VkRenderPass g_RenderPass = 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 VkQueue g_Queue = VK_NULL_HANDLE;
|
||||||
static VkDebugReportCallbackEXT g_Debug_Report = VK_NULL_HANDLE;
|
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||||
|
|
||||||
static VkSurfaceFormatKHR g_SurfaceFormat;
|
static VkSurfaceFormatKHR g_SurfaceFormat;
|
||||||
static VkImageSubresourceRange g_ImageRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
|
||||||
static VkPresentModeKHR g_PresentMode;
|
static VkPresentModeKHR g_PresentMode;
|
||||||
|
|
||||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||||
@ -60,24 +60,25 @@ static void check_vk_result(VkResult err)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resize_vulkan(GLFWwindow*, int w, int h)
|
static void CreateOrResizeSwapChainAndFrameBuffer(int w, int h)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkSwapchainKHR old_swapchain = g_Swapchain;
|
VkSwapchainKHR old_swapchain = g_Swapchain;
|
||||||
err = vkDeviceWaitIdle(g_Device);
|
err = vkDeviceWaitIdle(g_Device);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
// Destroy old Framebuffer:
|
// Destroy old Framebuffer
|
||||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||||
|
{
|
||||||
if (g_BackBufferView[i])
|
if (g_BackBufferView[i])
|
||||||
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
||||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
|
||||||
if (g_Framebuffer[i])
|
if (g_Framebuffer[i])
|
||||||
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
||||||
|
}
|
||||||
if (g_RenderPass)
|
if (g_RenderPass)
|
||||||
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
||||||
|
|
||||||
// Create Swapchain:
|
// Create Swapchain
|
||||||
{
|
{
|
||||||
VkSwapchainCreateInfoKHR info = {};
|
VkSwapchainCreateInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
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.imageFormat = g_SurfaceFormat.format;
|
||||||
info.imageColorSpace = g_SurfaceFormat.colorSpace;
|
info.imageColorSpace = g_SurfaceFormat.colorSpace;
|
||||||
info.imageArrayLayers = 1;
|
info.imageArrayLayers = 1;
|
||||||
info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
|
||||||
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
info.presentMode = g_PresentMode;
|
info.presentMode = g_PresentMode;
|
||||||
info.clipped = VK_TRUE;
|
info.clipped = VK_TRUE;
|
||||||
info.oldSwapchain = old_swapchain;
|
info.oldSwapchain = old_swapchain;
|
||||||
VkSurfaceCapabilitiesKHR cap;
|
VkSurfaceCapabilitiesKHR cap;
|
||||||
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_Gpu, g_Surface, &cap);
|
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, g_Surface, &cap);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
if (cap.maxImageCount > 0)
|
if (cap.maxImageCount > 0)
|
||||||
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
|
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)
|
if (cap.currentExtent.width == 0xffffffff)
|
||||||
{
|
{
|
||||||
fb_width = w;
|
info.imageExtent.width = fb_width = w;
|
||||||
fb_height = h;
|
info.imageExtent.height = fb_height = h;
|
||||||
info.imageExtent.width = fb_width;
|
|
||||||
info.imageExtent.height = fb_height;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fb_width = cap.currentExtent.width;
|
info.imageExtent.width = fb_width = cap.currentExtent.width;
|
||||||
fb_height = cap.currentExtent.height;
|
info.imageExtent.height = fb_height = cap.currentExtent.height;
|
||||||
info.imageExtent.width = fb_width;
|
|
||||||
info.imageExtent.height = fb_height;
|
|
||||||
}
|
}
|
||||||
err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain);
|
err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
@ -124,7 +121,7 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
|
|||||||
if (old_swapchain)
|
if (old_swapchain)
|
||||||
vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
|
vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
|
||||||
|
|
||||||
// Create the Render Pass:
|
// Create the Render Pass
|
||||||
{
|
{
|
||||||
VkAttachmentDescription attachment = {};
|
VkAttachmentDescription attachment = {};
|
||||||
attachment.format = g_SurfaceFormat.format;
|
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.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
info.components.b = VK_COMPONENT_SWIZZLE_B;
|
info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
info.components.a = VK_COMPONENT_SWIZZLE_A;
|
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++)
|
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||||
{
|
{
|
||||||
info.image = g_BackBuffer[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];
|
VkImageView attachment[1];
|
||||||
VkFramebufferCreateInfo info = {};
|
VkFramebufferCreateInfo info = {};
|
||||||
@ -191,10 +189,15 @@ static void resize_vulkan(GLFWwindow*, int w, int h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
static void GlfwResizeCallback(GLFWwindow*, int w, int h)
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(
|
|
||||||
VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
|
||||||
{
|
{
|
||||||
|
CreateOrResizeSwapChainAndFrameBuffer(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||||
|
{
|
||||||
|
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguemnts
|
||||||
printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
@ -212,38 +215,36 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
|
|||||||
create_info.ppEnabledExtensionNames = extensions;
|
create_info.ppEnabledExtensionNames = extensions;
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
// enabling multiple validation layers grouped as lunarg standard validation
|
// Enabling multiple validation layers grouped as LunarG standard validation
|
||||||
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
||||||
create_info.enabledLayerCount = 1;
|
create_info.enabledLayerCount = 1;
|
||||||
create_info.ppEnabledLayerNames = layers;
|
create_info.ppEnabledLayerNames = layers;
|
||||||
|
|
||||||
// need additional storage for char pointer to debug report extension
|
// Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
|
||||||
const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
||||||
for (size_t i = 0; i < extensions_count; i++)
|
memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
|
||||||
extensions[i] = extensions[i];
|
extensions_ext[extensions_count] = "VK_EXT_debug_report";
|
||||||
extensions[extensions_count] = "VK_EXT_debug_report";
|
|
||||||
create_info.enabledExtensionCount = extensions_count + 1;
|
create_info.enabledExtensionCount = extensions_count + 1;
|
||||||
create_info.ppEnabledExtensionNames = extensions;
|
create_info.ppEnabledExtensionNames = extensions_ext;
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
free(extensions);
|
free(extensions_ext);
|
||||||
|
|
||||||
// create the debug report callback
|
// Get the function pointer (required for any extensions)
|
||||||
|
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||||
|
IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
|
||||||
|
|
||||||
|
// Setup the debug report callback
|
||||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||||
debug_report_ci.pfnCallback = debug_report;
|
debug_report_ci.pfnCallback = debug_report;
|
||||||
debug_report_ci.pUserData = NULL;
|
debug_report_ci.pUserData = NULL;
|
||||||
|
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||||
// get the proc address of the function pointer, required for used extensions
|
|
||||||
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT =
|
|
||||||
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
|
||||||
|
|
||||||
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report);
|
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
}
|
}
|
||||||
@ -254,7 +255,7 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
|
|||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get GPU
|
// Select GPU
|
||||||
{
|
{
|
||||||
uint32_t gpu_count;
|
uint32_t gpu_count;
|
||||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||||
@ -267,31 +268,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
|
// 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.
|
// 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.
|
// 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);
|
free(gpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get queue
|
// Select graphics queue family
|
||||||
{
|
{
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL);
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
|
||||||
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
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++)
|
for (uint32_t i = 0; i < count; i++)
|
||||||
{
|
|
||||||
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
{
|
{
|
||||||
g_QueueFamily = i;
|
g_QueueFamily = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
free(queues);
|
free(queues);
|
||||||
|
IM_ASSERT(g_QueueFamily != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for WSI support
|
// Check for WSI support
|
||||||
{
|
{
|
||||||
VkBool32 res;
|
VkBool32 res;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res);
|
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, g_Surface, &res);
|
||||||
if (res != VK_TRUE)
|
if (res != VK_TRUE)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||||
@ -299,95 +299,35 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get Surface Format
|
// 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
|
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||||
// Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format
|
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
// additionally several new color spaces were introduced with Vulkan Spec v1.0.40
|
g_SurfaceFormat = ImGui_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, g_Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// first 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)
|
|
||||||
{
|
|
||||||
g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // no point in searching another format
|
|
||||||
g_SurfaceFormat = formats[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// request 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;
|
|
||||||
for (uint32_t j = 0; j < count; j++)
|
|
||||||
{
|
|
||||||
if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace)
|
|
||||||
{
|
|
||||||
g_SurfaceFormat = formats[j];
|
|
||||||
requestedFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if none of the requested image formats could be found, use the first available
|
|
||||||
if (!requestedFound)
|
|
||||||
g_SurfaceFormat = formats[0];
|
|
||||||
}
|
|
||||||
free(formats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get Present Mode
|
// Get Present Mode
|
||||||
{
|
{
|
||||||
// Requst 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
|
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
||||||
g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
#else
|
#else
|
||||||
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
#endif
|
#endif
|
||||||
uint32_t count = 0;
|
g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1);
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, NULL);
|
|
||||||
VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes);
|
|
||||||
bool presentModeAvailable = false;
|
|
||||||
for (size_t i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (presentModes[i] == g_PresentMode)
|
|
||||||
{
|
|
||||||
presentModeAvailable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!presentModeAvailable)
|
|
||||||
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Logical Device
|
// Create Logical Device (with 1 queue)
|
||||||
{
|
{
|
||||||
int device_extension_count = 1;
|
int device_extension_count = 1;
|
||||||
const char* device_extensions[] = { "VK_KHR_swapchain" };
|
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 };
|
const float queue_priority[] = { 1.0f };
|
||||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||||
queue_info[0].queueCount = queue_count;
|
queue_info[0].queueCount = 1;
|
||||||
queue_info[0].pQueuePriorities = queue_priority;
|
queue_info[0].pQueuePriorities = queue_priority;
|
||||||
VkDeviceCreateInfo create_info = {};
|
VkDeviceCreateInfo create_info = {};
|
||||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
@ -395,19 +335,21 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e
|
|||||||
create_info.pQueueCreateInfos = queue_info;
|
create_info.pQueueCreateInfos = queue_info;
|
||||||
create_info.enabledExtensionCount = device_extension_count;
|
create_info.enabledExtensionCount = device_extension_count;
|
||||||
create_info.ppEnabledExtensionNames = device_extensions;
|
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);
|
check_vk_result(err);
|
||||||
vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue);
|
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Framebuffers
|
// Create Framebuffers
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
glfwGetFramebufferSize(window, &w, &h);
|
glfwGetFramebufferSize(window, &w, &h);
|
||||||
resize_vulkan(window, w, h);
|
CreateOrResizeSwapChainAndFrameBuffer(w, h);
|
||||||
glfwSetFramebufferSizeCallback(window, resize_vulkan);
|
glfwSetFramebufferSizeCallback(window, GlfwResizeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create Command Buffers
|
// Create Command Buffers
|
||||||
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||||
{
|
{
|
||||||
@ -493,9 +435,9 @@ static void cleanup_vulkan()
|
|||||||
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
|
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
|
||||||
|
|
||||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
// get the proc address of the function pointer, required for used extensions
|
// Remove the debug report callback
|
||||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||||
vkDestroyDebugReportCallbackEXT(g_Instance, g_Debug_Report, g_Allocator);
|
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
vkDestroyDevice(g_Device, g_Allocator);
|
vkDestroyDevice(g_Device, g_Allocator);
|
||||||
@ -616,18 +558,19 @@ int main(int, char**)
|
|||||||
// Setup ImGui binding
|
// Setup ImGui binding
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
|
||||||
ImGui_ImplVulkan_InitData init_data = {};
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||||
init_data.allocator = g_Allocator;
|
init_info.Allocator = g_Allocator;
|
||||||
init_data.gpu = g_Gpu;
|
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||||
init_data.device = g_Device;
|
init_info.Device = g_Device;
|
||||||
init_data.render_pass = g_RenderPass;
|
init_info.RenderPass = g_RenderPass;
|
||||||
init_data.pipeline_cache = g_PipelineCache;
|
init_info.PipelineCache = g_PipelineCache;
|
||||||
init_data.descriptor_pool = g_DescriptorPool;
|
init_info.DescriptorPool = g_DescriptorPool;
|
||||||
init_data.check_vk_result = check_vk_result;
|
init_info.CheckVkResultFn = check_vk_result;
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
ImGui_ImplVulkan_Init(&init_data);
|
|
||||||
|
ImGui_ImplVulkan_Init(&init_info);
|
||||||
ImGui_ImplGlfw_Init(window, true);
|
ImGui_ImplGlfw_Init(window, true);
|
||||||
|
|
||||||
// Setup style
|
// Setup style
|
||||||
|
Loading…
Reference in New Issue
Block a user