Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 10 Jul 2009
Offline Last Active Yesterday, 07:22 AM

Posts I've Made

In Topic: Should I start with fixed-function-pipeline OpenGL or the newest possible?

30 March 2016 - 05:17 AM

Let me add my comment on the topic.
Although the fixed functionality is deprecated it is still very useful for an introduction to computer graphics. There are several reasons for this:
1. The learning curve is much steeper with new APIs. For the legacy OpenGL you should know only the API. For the modern OpenGL you should also know math and physics, while for the Vulkan you should also know operating systems and how HW works.
2. The number code lines increase exponentially. For the triangle drawing in the legacy OpenGL one needs a dozen lines of code, about 400 lines in modern OpenGL and about 1000 in Vulkan.
3. Being overwhelmed with non-graphics topics, the beginner usually misses the main concepts like transformations, lighting, texturing etc.
That's why I'm still teaching legacy OpenGL in the first course of Computer Graphics, while the programmable pipeline is left for the advanced course (next year, after passing the first one). So far it works well.

In Topic: Vulkan Win32 WMI

08 March 2016 - 07:38 AM

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";
VkApplicationInfo app_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.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.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;

float queue_priorities[1] = { 0.0 };
VkDeviceQueueCreateInfo queue_info = {};
queue_info.pNext = NULL;
queue_info.queueCount = 1;
queue_info.pQueuePriorities = queue_priorities;
VkDeviceCreateInfo device_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;
if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
(presentModes[i] == 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 &
else {
preTransform = surfCapabilities.currentTransform;
VkSwapchainCreateInfoKHR swap_chain = {};
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.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);

vkGetDeviceQueue(m_vkDevice, m_graphicsQueueFamilyIndex, 0, &m_queue);
for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
VkImageViewCreateInfo color_image_view = {};
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,
color_image_view.image = m_buffers[i].image;
res = vkCreateImageView(m_vkDevice, &color_image_view, NULL, &m_buffers[i].view);


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

In Topic: Vulkan is Next-Gen OpenGL

18 February 2016 - 09:43 AM

Also, AMD has a new version of their Vulkan drivers, which claim to fix the issues with the latest SDK version.


EDIT: Said drivers still aren't working for me, applications launch but freeze on launch.


The latest AMD drivers (17.02.) work fine with my R9 280. Please, take a look at http://vulkan.gpuinfo.org.

In Topic: Vulkan is Next-Gen OpenGL

17 February 2016 - 10:01 AM

I just want to report that Vulkan SDK works fine on NVIDIA hardware and with NV drivers. Even on the Optimus platform (I've got laptop with GTX 850M). Congratulations!


AMD drivers doesn't work, as all previous posts said. I've tried them on R280. Despite AMD is better "on the paper", the side by side comparison with NV reveals a quite different state of affairs. Maybe it is different in the DX world, but I have had bad experience with AMD OpenGL drivers. It is sad that AMD actually has very advanced architecture and some brilliant ideas, the state of its software (especially their drivers) spoils everything. :(


Does Intel Linux drivers work?

In Topic: Vulkan is Next-Gen OpenGL

26 January 2016 - 02:57 AM


It is very unlikely. Vulkan and OpenGL are two different paths. They will continue to coexist for many years to come.

He's just saying that because Khronos has actually done that exact thing before...
They were supposed to ve working on a new, modern, clean API called Longs Peak, which would break backwards compatibility with GL. And , after setting the hype train in motion, they released a new GL instead (and handed API war victory to D3D on a silver platter).

If they did the same thing this time, my bet would be on Valve taking to initiative to finish Mantle/Vulakn/Valven on their own, and form a new comittee making Khronos redundant. So, failure is not an option for them this time.



Well, the story about Longs Peak is a bit different. That was a threat to cease support for legacy OpenGL in the upcoming drivers. That's why OpenGL 3.0 didn't break backward compatibility. This time, Vulkan will coexist with OpenGL. Furthermore, OpenGL will be a more popular API for many years to come, because of the higher level of abstraction, the easiness of the usage and less responsibility for the programmers. Many of them are not aware of what the drivers do for them. Vulkan would change it a lot. Also, Vulkan is both graphics and computation API. Valve is deeply involved, but the support of big players and hardware vendors is even more important. NVIDIA already has support for Vulkan in its drivers.