Commit: c155c108881bf5ab6e6d20967027fe717fb4222c
Author: Clément Foucault
Date: Fri Jul 24 00:42:44 2020 +0200
Branches: tmp-vulkan
https://developer.blender.org/rBc155c108881bf5ab6e6d20967027fe717fb4222c
GHOST: Vulkan: Add swapchain creation
===================================================================
M intern/ghost/intern/GHOST_ContextVK.cpp
M intern/ghost/intern/GHOST_ContextVK.h
===================================================================
diff --git a/intern/ghost/intern/GHOST_ContextVK.cpp
b/intern/ghost/intern/GHOST_ContextVK.cpp
index 0e1e5d518f4..78dd6b072b7 100644
--- a/intern/ghost/intern/GHOST_ContextVK.cpp
+++ b/intern/ghost/intern/GHOST_ContextVK.cpp
@@ -112,7 +112,6 @@ static const char *vulkan_error_as_string(VkResult result)
GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
#ifdef _WIN32
HWND hwnd,
- HINSTANCE hinstance,
#else
Window window,
Display *display,
@@ -132,14 +131,18 @@ GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
m_contextMinorVersion(contextMinorVersion),
m_useValidationLayers(useValidationLayers),
m_instance(VK_NULL_HANDLE),
- m_surface(VK_NULL_HANDLE),
m_physical_device(VK_NULL_HANDLE),
- m_device(VK_NULL_HANDLE)
+ m_device(VK_NULL_HANDLE),
+ m_surface(VK_NULL_HANDLE),
+ m_swapchain(VK_NULL_HANDLE)
{
}
GHOST_ContextVK::~GHOST_ContextVK()
{
+ if (m_swapchain != VK_NULL_HANDLE) {
+ vkDestroySwapchainKHR(m_device, m_swapchain, NULL);
+ }
if (m_device != VK_NULL_HANDLE) {
vkDestroyDevice(m_device, NULL);
}
@@ -233,7 +236,32 @@ static void enableLayer(vector<VkLayerProperties>
&layers_available,
}
}
-static VkPhysicalDevice pickPhysicalDevice(VkInstance instance)
+static bool device_extensions_support(VkPhysicalDevice device, vector<const
char *> required_exts)
+{
+ uint32_t ext_count;
+ vkEnumerateDeviceExtensionProperties(device, NULL, &ext_count, NULL);
+
+ vector<VkExtensionProperties> available_exts(ext_count);
+ vkEnumerateDeviceExtensionProperties(device, NULL, &ext_count,
available_exts.data());
+
+ for (const auto &extension_needed : required_exts) {
+ bool found = false;
+ for (const auto &extension : available_exts) {
+ if (strcmp(extension_needed, extension.extensionName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static VkPhysicalDevice pickPhysicalDevice(VkInstance instance,
+ VkSurfaceKHR surface,
+ vector<const char *> required_exts)
{
uint32_t device_count = 0;
vkEnumeratePhysicalDevices(instance, &device_count, NULL);
@@ -257,6 +285,24 @@ static VkPhysicalDevice pickPhysicalDevice(VkInstance
instance)
VkPhysicalDeviceFeatures device_features;
vkGetPhysicalDeviceFeatures(device, &device_features);
+ if (!device_extensions_support(device, required_exts)) {
+ continue;
+ }
+
+ if (surface != VK_NULL_HANDLE) {
+ uint32_t format_count;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &format_count,
NULL);
+ /* TODO(fclem) This is where we should check for HDR surface format. */
+
+ uint32_t present_count;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface,
&present_count, NULL);
+
+ /* For now anything will do. */
+ if (format_count == 0 || present_count == 0) {
+ continue;
+ }
+ }
+
// List of REQUIRED features.
if (device_features.geometryShader && // Needed for wide lines
device_features.dualSrcBlend && // Needed by EEVEE
@@ -349,6 +395,87 @@ static GHOST_TSuccess
getPresetQueueFamily(VkPhysicalDevice device,
return GHOST_kFailure;
}
+GHOST_TSuccess GHOST_ContextVK::createSwapChain(void)
+{
+ VkPhysicalDevice device = m_physical_device;
+
+ uint32_t format_count;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &format_count, NULL);
+ vector<VkSurfaceFormatKHR> formats(format_count);
+ vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &format_count,
formats.data());
+
+ /* TODO choose appropriate format. */
+ VkSurfaceFormatKHR format = formats[0];
+
+ uint32_t present_count;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &present_count,
NULL);
+ vector<VkPresentModeKHR> presents(present_count);
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &present_count,
presents.data());
+
+ /* TODO choose appropriate present mode . */
+ VkPresentModeKHR present_mode = presents[0];
+
+ VkSurfaceCapabilitiesKHR capabilities;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &capabilities);
+
+ VkExtent2D extent = capabilities.currentExtent;
+ if (extent.width == UINT32_MAX) {
+ /* Window Manager is going to set the surface size based on the given size.
+ * Choose something between minImageExtent and maxImageExtent. */
+ /* TODO(fclem) choose more wisely. */
+ extent = capabilities.minImageExtent;
+ }
+
+ /* Driver can stall if only using minimal image count. */
+ uint32_t image_count = capabilities.minImageCount;
+ /* Note: maxImageCount == 0 means no limit. */
+ if (image_count > capabilities.maxImageCount && capabilities.maxImageCount >
0) {
+ image_count = capabilities.maxImageCount;
+ }
+
+ VkSwapchainCreateInfoKHR create_info = {
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ .surface = m_surface,
+ .minImageCount = image_count,
+ .imageFormat = format.format,
+ .imageColorSpace = format.colorSpace,
+ .imageExtent = extent,
+ .imageArrayLayers = 1,
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ .preTransform = capabilities.currentTransform, // No transform
+ .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ .presentMode = present_mode,
+ .clipped = VK_TRUE,
+ .oldSwapchain = VK_NULL_HANDLE, // TODO Window resize
+ };
+
+ uint32_t queueFamilyIndices[] = {m_queue_family_graphic,
m_queue_family_present};
+
+ if (m_queue_family_graphic != m_queue_family_present) {
+ create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ create_info.queueFamilyIndexCount = 2;
+ create_info.pQueueFamilyIndices = queueFamilyIndices;
+ }
+ else {
+ create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ create_info.queueFamilyIndexCount = 0; // Optional
+ create_info.pQueueFamilyIndices = NULL; // Optional
+ }
+
+ VK_CHECK(vkCreateSwapchainKHR(m_device, &create_info, NULL, &m_swapchain));
+
+ /* Save infos for rendering. */
+ m_swapChainImageFormat = format.format;
+ m_swapChainExtent = extent;
+
+ /* image_count may not be what we requested! Getter for final value. */
+ vkGetSwapchainImagesKHR(m_device, m_swapchain, &image_count, NULL);
+ m_swapChainImages.resize(image_count);
+ vkGetSwapchainImagesKHR(m_device, m_swapchain, &image_count,
m_swapChainImages.data());
+
+ return GHOST_kSuccess;
+}
+
GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
{
#ifdef _WIN32
@@ -365,6 +492,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
enableLayer(layers_available, layers_enabled,
"VK_LAYER_KHRONOS_validation");
}
+ vector<const char *> extensions_device;
vector<const char *> extensions_enabled;
if (use_window_surface) {
@@ -375,6 +503,8 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
#endif
requireExtension(extensions_available, extensions_enabled,
"VK_KHR_surface");
requireExtension(extensions_available, extensions_enabled,
native_surface_extension_name);
+
+ extensions_device.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
VkApplicationInfo app_info = {
@@ -383,7 +513,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Blender",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
- .apiVersion = VK_API_VERSION_1_0,
+ .apiVersion = VK_MAKE_VERSION(m_contextMajorVersion,
m_contextMinorVersion, 0),
};
VkInstanceCreateInfo create_info = {
@@ -397,15 +527,11 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
VK_CHECK(vkCreateInstance(&create_info, NULL, &m_instance));
- m_physical_device = pickPhysicalDevice(m_instance);
-
- vector<VkDeviceQueueCreateInfo> queue_create_infos;
-
if (use_window_surface) {
#ifdef _WIN32
VkWin32SurfaceCreateInfoKHR surface_create_info = {
.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
- hinstance = m_hinstance,
+ hinstance = GetModuleHandle(NULL),
hwnd = m_hwnd,
};
VK_CHECK(vkCreateWin32SurfaceKHR(m_instance, &surface_create_info, NULL,
&m_surface));
@@ -417,38 +543,48 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
};
VK_CHECK(vkCreateXlibSurfaceKHR(m_instance, &surface_create_info, NULL,
&m_surface));
#endif
+ }
- /* A present queue is required only if we render to a window. */
- if (!getPresetQueueFamily(m_physical_device, m_surface,
&m_queue_family_present)) {
+ m_physical_device = pickPhysicalDevice(m_instance, m_surface,
extensions_device);
+
+ if (m_physical_device == VK_NULL_HANDLE) {
+ return GHOST_kFailure;
+ }
+
+ vector<VkDeviceQueueCreateInfo> queue_create_infos;
+
+ {
+ /* A graphic queue is required to draw anything. */
+ if (!getGraphicQueueFamily(m_physical_device, &m_queue_family_graphic)) {
return GHOST_kFailure;
}
float queue_priorities[] = {1.0f};
- VkDeviceQueueCreateInfo present_queue_create_info = {
+ VkDeviceQueueCreateInfo graphic_queue_create_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- .queueFamilyIndex = m_queue_family_present,
+ .queueFamilyIndex = m_queue_family_graphic,
.queueCount = 1,
.pQueuePriorities = queue_priorities,
};
- queue_create_infos.push_back(present_queue_create_info);
+ queue_create_infos.push_back(graphic_queue_create_info);
}
- {
- /* A graphic queue is required to draw anything. */
- if (!getGraphicQueueFamily(m_physical_device, &m_queue_family_graphic)) {
+ if (use_window_surface) {
+ /* A present queue is required only if we render to a window. */
+ if (!getPresetQueueFamily(m_physical_device, m_surface,
&m_queue_family_present)) {
return GHOST_kFailure;
}
float queue_priorities[] = {1.0f};
- VkDeviceQueueCreateInfo graphic_queue_create_info = {
+ VkDeviceQueueCreateInfo present_queue_cr
@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs