Examples: Vulkan: further work for device extensions + tentative use o fVK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME. (#6109, #6172, #6101)

This commit is contained in:
ocornut 2023-04-13 15:57:28 +02:00
parent 6324280432
commit ba98667c65
2 changed files with 100 additions and 78 deletions

View File

@ -18,6 +18,7 @@
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
//#include <vulkan/vulkan_beta.h>
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers. // [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma. // To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
@ -76,7 +77,32 @@ static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properti
return false; return false;
} }
static void SetupVulkan(ImVector<const char*> extensions) static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
{
uint32_t gpu_count;
VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
ImVector<VkPhysicalDevice> gpus;
gpus.resize(gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data);
check_vk_result(err);
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
// dedicated GPUs) is out of scope of this sample.
for (VkPhysicalDevice& device : gpus)
{
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
return device;
}
return VK_NULL_HANDLE;
}
static void SetupVulkan(ImVector<const char*> instance_extensions)
{ {
VkResult err; VkResult err;
@ -95,11 +121,11 @@ static void SetupVulkan(ImVector<const char*> extensions)
// Enable required extensions // Enable required extensions
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
{ {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
} }
#endif #endif
@ -109,12 +135,12 @@ static void SetupVulkan(ImVector<const char*> extensions)
const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1; create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers; create_info.ppEnabledLayerNames = layers;
extensions.push_back("VK_EXT_debug_report"); instance_extensions.push_back("VK_EXT_debug_report");
#endif #endif
// Create Vulkan Instance // Create Vulkan Instance
create_info.enabledExtensionCount = (uint32_t)extensions.size(); create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
create_info.ppEnabledExtensionNames = extensions.Data; create_info.ppEnabledExtensionNames = instance_extensions.Data;
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err); check_vk_result(err);
@ -132,35 +158,8 @@ static void SetupVulkan(ImVector<const char*> extensions)
#endif #endif
} }
// Select GPU // Select Physical Device (GPU)
{ g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice();
uint32_t gpu_count;
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
check_vk_result(err);
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
// dedicated GPUs) is out of scope of this sample.
int use_gpu = 0;
for (int i = 0; i < (int)gpu_count; i++)
{
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(gpus[i], &properties);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{
use_gpu = i;
break;
}
}
g_PhysicalDevice = gpus[use_gpu];
free(gpus);
}
// Select graphics queue family // Select graphics queue family
{ {
@ -180,8 +179,20 @@ static void SetupVulkan(ImVector<const char*> extensions)
// Create Logical Device (with 1 queue) // Create Logical Device (with 1 queue)
{ {
int device_extension_count = 1; ImVector<const char*> device_extensions;
const char* device_extensions[] = { "VK_KHR_swapchain" }; device_extensions.push_back("VK_KHR_swapchain");
// Enumerate physical device extension
uint32_t properties_count;
ImVector<VkExtensionProperties> properties;
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
properties.resize(properties_count);
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
#endif
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;
@ -192,8 +203,8 @@ static void SetupVulkan(ImVector<const char*> extensions)
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
create_info.pQueueCreateInfos = queue_info; create_info.pQueueCreateInfos = queue_info;
create_info.enabledExtensionCount = device_extension_count; create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
create_info.ppEnabledExtensionNames = device_extensions; create_info.ppEnabledExtensionNames = device_extensions.Data;
err = vkCreateDevice(g_PhysicalDevice, &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, 0, &g_Queue); vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);

View File

@ -17,6 +17,7 @@
#include <SDL.h> #include <SDL.h>
#include <SDL_vulkan.h> #include <SDL_vulkan.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
//#include <vulkan/vulkan_beta.h>
//#define IMGUI_UNLIMITED_FRAME_RATE //#define IMGUI_UNLIMITED_FRAME_RATE
#ifdef _DEBUG #ifdef _DEBUG
@ -64,7 +65,32 @@ static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properti
return false; return false;
} }
static void SetupVulkan(ImVector<const char*> extensions) static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
{
uint32_t gpu_count;
VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
ImVector<VkPhysicalDevice> gpus;
gpus.resize(gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data);
check_vk_result(err);
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
// dedicated GPUs) is out of scope of this sample.
for (VkPhysicalDevice& device : gpus)
{
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
return device;
}
return VK_NULL_HANDLE;
}
static void SetupVulkan(ImVector<const char*> instance_extensions)
{ {
VkResult err; VkResult err;
@ -83,11 +109,11 @@ static void SetupVulkan(ImVector<const char*> extensions)
// Enable required extensions // Enable required extensions
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME #ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
{ {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
} }
#endif #endif
@ -97,12 +123,12 @@ static void SetupVulkan(ImVector<const char*> extensions)
const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1; create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers; create_info.ppEnabledLayerNames = layers;
extensions.push_back("VK_EXT_debug_report"); instance_extensions.push_back("VK_EXT_debug_report");
#endif #endif
// Create Vulkan Instance // Create Vulkan Instance
create_info.enabledExtensionCount = (uint32_t)extensions.size(); create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
create_info.ppEnabledExtensionNames = extensions.Data; create_info.ppEnabledExtensionNames = instance_extensions.Data;
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err); check_vk_result(err);
@ -120,35 +146,8 @@ static void SetupVulkan(ImVector<const char*> extensions)
#endif #endif
} }
// Select GPU // Select Physical Device (GPU)
{ g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice();
uint32_t gpu_count;
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
check_vk_result(err);
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
// dedicated GPUs) is out of scope of this sample.
int use_gpu = 0;
for (int i = 0; i < (int)gpu_count; i++)
{
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(gpus[i], &properties);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{
use_gpu = i;
break;
}
}
g_PhysicalDevice = gpus[use_gpu];
free(gpus);
}
// Select graphics queue family // Select graphics queue family
{ {
@ -168,8 +167,20 @@ static void SetupVulkan(ImVector<const char*> extensions)
// Create Logical Device (with 1 queue) // Create Logical Device (with 1 queue)
{ {
int device_extension_count = 1; ImVector<const char*> device_extensions;
const char* device_extensions[] = { "VK_KHR_swapchain" }; device_extensions.push_back("VK_KHR_swapchain");
// Enumerate physical device extension
uint32_t properties_count;
ImVector<VkExtensionProperties> properties;
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
properties.resize(properties_count);
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
#endif
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;
@ -180,8 +191,8 @@ static void SetupVulkan(ImVector<const char*> extensions)
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
create_info.pQueueCreateInfos = queue_info; create_info.pQueueCreateInfos = queue_info;
create_info.enabledExtensionCount = device_extension_count; create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
create_info.ppEnabledExtensionNames = device_extensions; create_info.ppEnabledExtensionNames = device_extensions.Data;
err = vkCreateDevice(g_PhysicalDevice, &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, 0, &g_Queue); vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);