Vulkan Win32 WMI

Started by
1 comment, last by Aks9 8 years, 1 month ago

Has anyone encountered a problem with deallocating Win32 surface using NVIDIA drivers?

Unfortunately, there is no appropriate tutorial how to deal with the window system integration (WMI). I followed the samples from the LunarG SDK and modified a bit in order to incorporate into my code (framework). All functions return VK_SUCCESS, however, with 356.39-vkonly_geforce_win8 drivers, the application crashes at Vulkan instance destroy. With 356.45-vkonly_geforce_win8 drivers, the application doesn't crash, but there is a memory leak (pretty the same as if I prevent the instance destroying with 356.39).

Detected memory leaks!

Dumping objects ->
{355} normal block at 0x06B223F0, 16 bytes long.
Data: <` k P > 60 B1 6B 04 00 00 00 00 50 18 B2 06 00 00 00 00
{349} normal block at 0x046BD9C8, 12 bytes long.
Data: < > 02 00 00 00 03 00 00 00 01 00 00 00
{348} normal block at 0x046BD978, 16 bytes long.
Data: <, 2 > 2C 00 00 00 00 00 00 00 32 00 00 00 00 00 00 00

Also, is there any requirements for the window pixel format (like in OpenGL) in order to draw correctly on the surface?

So far it seems WMI is the most complicated part of the Vulkan. wacko.png

I hope after finishing correctly some interface functions for presentation on the windows I wouldn't have to change that code ever since.

Thanks in advance for any assistance or useful hints!

Aleksandar

Advertisement
Show creation and destruction code.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Huh! sad.png

It is not easy to post a reasonable amount of code when you code using Vulkan... I didn't expected that it needs about a thousand lines of code just to initialize...

Well, here is a code "fragment" that initializes swap chain:

char* APP_SHORT_NAME = "VkRenderer";
instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
 
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = NULL;
app_info.pApplicationName = APP_SHORT_NAME;
app_info.applicationVersion = 1;
app_info.pEngineName = APP_SHORT_NAME;
app_info.engineVersion = 1;
app_info.apiVersion = VK_API_VERSION;
 
VkInstanceCreateInfo inst_info = {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pNext = NULL;
inst_info.flags = 0;
inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = instance_extension_names.size();
inst_info.ppEnabledExtensionNames = inst_info.enabledExtensionCount ? instance_extension_names.data() : NULL;
inst_info.enabledLayerCount = 0;
inst_info.ppEnabledLayerNames = NULL;
 
VkResult res;
 
res = vkCreateInstance(&inst_info, NULL, &m_vkInst);
 
//...
 

VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = NULL;
createInfo.hinstance = GetModuleHandle(NULL); //info.connection;
createInfo.hwnd = wnd;
VkResult res = vkCreateWin32SurfaceKHR(m_vkInst, &createInfo, NULL, &m_surface);
 

VkBool32 *supportsPresent = (VkBool32 *)malloc(queue_count * sizeof(VkBool32));
for (uint32_t i = 0; i < queue_count; i++) {
vkGetPhysicalDeviceSurfaceSupportKHR(m_vGPU[0], i, m_surface, &supportsPresent[i]);
}
 

uint32_t graphicsQueueNodeIndex = UINT32_MAX;
for (uint32_t i = 0; i < queue_count; i++) {
if ((m_queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
if (supportsPresent[i] == VK_TRUE) {
graphicsQueueNodeIndex = i;
break;
}
}
}
//...

float queue_priorities[1] = { 0.0 };
device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
 
VkDeviceQueueCreateInfo queue_info = {};
queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_info.pNext = NULL;
queue_info.queueCount = 1;
queue_info.pQueuePriorities = queue_priorities;
 
VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_info.pNext = NULL;
device_info.queueCreateInfoCount = 1;
device_info.pQueueCreateInfos = &queue_info;
device_info.enabledExtensionCount = device_extension_names.size();
device_info.ppEnabledExtensionNames = device_info.enabledExtensionCount ? device_extension_names.data() : NULL;
device_info.enabledLayerCount = 0;
device_info.ppEnabledLayerNames = NULL;
device_info.pEnabledFeatures = NULL;
 
res = vkCreateDevice(m_vGPU[0], &device_info, NULL, &m_vkDevice);
 
//...
 

uint32_t formatCount;
VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(m_vGPU[0], m_surface, &formatCount, NULL);
assert(res == VK_SUCCESS);
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
res = vkGetPhysicalDeviceSurfaceFormatsKHR(m_vGPU[0], m_surface, &formatCount, surfFormats);
assert(res == VK_SUCCESS);
// If the format list includes just one entry of VK_FORMAT_UNDEFINED,
// the surface has no preferred format.  Otherwise, at least one
// supported format will be returned.
VkFormat format;
if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
format = VK_FORMAT_B8G8R8A8_UNORM;
}
else {
assert(formatCount >= 1);
format = surfFormats[0].format;
}
 
VkSurfaceCapabilitiesKHR surfCapabilities;
 
res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_vGPU[0], m_surface, &surfCapabilities);
 
uint32_t presentModeCount;
res = vkGetPhysicalDeviceSurfacePresentModesKHR(m_vGPU[0], m_surface, &presentModeCount, NULL);
 
VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
 
res = vkGetPhysicalDeviceSurfacePresentModesKHR(m_vGPU[0], m_surface, &presentModeCount, presentModes);
 

VkExtent2D swapChainExtent;
 
if (surfCapabilities.currentExtent.width == (uint32_t)-1) {
swapChainExtent.width = width;
swapChainExtent.height = height;
}
else {
swapChainExtent = surfCapabilities.currentExtent;
}
 

VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
for (size_t i = 0; i < presentModeCount; i++) {
if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
break;
}
if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
(presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
}
}
 

uint32_t desiredNumberOfSwapChainImages =
surfCapabilities.minImageCount + 1;
if ((surfCapabilities.maxImageCount > 0) &&
(desiredNumberOfSwapChainImages > surfCapabilities.maxImageCount)) {
desiredNumberOfSwapChainImages = surfCapabilities.maxImageCount;
}
 
VkSurfaceTransformFlagBitsKHR preTransform;
if (surfCapabilities.supportedTransforms &
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
}
else {
preTransform = surfCapabilities.currentTransform;
}
 
VkSwapchainCreateInfoKHR swap_chain = {};
swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swap_chain.pNext = NULL;
swap_chain.surface = m_surface;
swap_chain.minImageCount = desiredNumberOfSwapChainImages;
swap_chain.imageFormat = format;
swap_chain.imageExtent.width = swapChainExtent.width;
swap_chain.imageExtent.height = swapChainExtent.height;
swap_chain.preTransform = preTransform;
swap_chain.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swap_chain.imageArrayLayers = 1;
swap_chain.presentMode = swapchainPresentMode;
swap_chain.oldSwapchain = NULL;
swap_chain.clipped = true;
swap_chain.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
swap_chain.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swap_chain.queueFamilyIndexCount = 0;
swap_chain.pQueueFamilyIndices = NULL;
 
res = vkCreateSwapchainKHR(m_vkDevice, &swap_chain, NULL, &m_swap_chain);
 
res = vkGetSwapchainImagesKHR(m_vkDevice, m_swap_chain, &m_swapchainImageCount, NULL);
 
VkImage *swapchainImages = (VkImage *)malloc(m_swapchainImageCount * sizeof(VkImage));
 
res = vkGetSwapchainImagesKHR(m_vkDevice, m_swap_chain, &m_swapchainImageCount, swapchainImages);
 
m_buffers.resize(m_swapchainImageCount);
 
CreateCommandBuffer();
ExecuteBeginCommandBuffer();
 

vkGetDeviceQueue(m_vkDevice, m_graphicsQueueFamilyIndex, 0, &m_queue);
 
for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
VkImageViewCreateInfo color_image_view = {};
color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
color_image_view.pNext = NULL;
color_image_view.format = format;
color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
color_image_view.subresourceRange.baseMipLevel = 0;
color_image_view.subresourceRange.levelCount = 1;
color_image_view.subresourceRange.baseArrayLayer = 0;
color_image_view.subresourceRange.layerCount = 1;
color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
color_image_view.flags = 0;
 
m_buffers[i].image = swapchainImages[i];
 
SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
color_image_view.image = m_buffers[i].image;
 
res = vkCreateImageView(m_vkDevice, &color_image_view, NULL, &m_buffers[i].view);
 
}
 
ExecuteEndCommandBuffer();
ExecuteQueueCommandBuffer();









This is not the whole code. All handles are valid and functions always return VK_SUCCESS. The dealocation code is like following:

for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
vkDestroyImageView(m_vkDevice, m_buffers[i].view, NULL);
}
vkDestroySwapchainKHR(m_vkDevice, m_swap_chain, NULL);

I'm sorry for so much code, but that is Vulkan! unsure.png

This topic is closed to new replies.

Advertisement