Created
February 22, 2016 07:08
-
-
Save TheBuzzSaw/9f54493b83b27fe36818 to your computer and use it in GitHub Desktop.
WIP -- SDL2 + Vulkan sample program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL.h> | |
#include <SDL_syswm.h> | |
#define VK_USE_PLATFORM_WIN32_KHR | |
#include <vulkan/vulkan.h> | |
#include <iostream> | |
#include <cassert> | |
using namespace std; | |
#define ArraySize(a) (sizeof(a)/sizeof(*a)) | |
void SetImageLayout( | |
VkCommandBuffer commandBuffer, | |
VkImage image, | |
VkImageAspectFlags aspectMask, | |
VkImageLayout oldLayout, | |
VkImageLayout newLayout) | |
{ | |
VkImageMemoryBarrier imb = {}; | |
imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; | |
imb.pNext = nullptr; | |
imb.srcAccessMask = 0; | |
imb.dstAccessMask = 0; | |
imb.oldLayout = oldLayout; | |
imb.newLayout = newLayout; | |
imb.image = image; | |
imb.subresourceRange.aspectMask = aspectMask; | |
imb.subresourceRange.baseMipLevel = 0; | |
imb.subresourceRange.levelCount = 1; | |
imb.subresourceRange.layerCount = 1; | |
if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) | |
imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; | |
if (newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) | |
imb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; | |
if (newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) | |
{ | |
imb.srcAccessMask = | |
VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; | |
imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; | |
} | |
if (newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) | |
imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; | |
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) | |
imb.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; | |
vkCmdPipelineBarrier( | |
commandBuffer, | |
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
0, | |
0, | |
nullptr, | |
0, | |
nullptr, | |
1, | |
&imb); | |
} | |
int main(int argc, char** argv) | |
{ | |
SDL_Init(SDL_INIT_EVERYTHING); | |
SDL_Window* window = SDL_CreateWindow( | |
"SDL Vulkan", | |
SDL_WINDOWPOS_CENTERED, | |
SDL_WINDOWPOS_CENTERED, | |
1024, | |
768, | |
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); | |
const char* instanceExtensionNames[] = { | |
VK_KHR_SURFACE_EXTENSION_NAME, | |
VK_KHR_WIN32_SURFACE_EXTENSION_NAME | |
}; | |
VkApplicationInfo ai = {}; | |
ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; | |
ai.pNext = nullptr; | |
ai.pApplicationName = "SDL Vulkan"; | |
ai.applicationVersion = 1; | |
ai.pEngineName = "SDLV"; | |
ai.engineVersion = 1; | |
ai.apiVersion = VK_API_VERSION; | |
VkInstanceCreateInfo ici = {}; | |
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; | |
ici.pNext = nullptr; | |
ici.flags = 0; | |
ici.pApplicationInfo = &ai; | |
ici.enabledLayerCount = 0; | |
ici.ppEnabledLayerNames = nullptr; | |
ici.enabledExtensionCount = 0; | |
ici.ppEnabledExtensionNames = nullptr; | |
VkInstance instance; | |
assert(vkCreateInstance(&ici, nullptr, &instance) == VK_SUCCESS); | |
VkPhysicalDevice physicalDevices[8]; | |
uint32_t physicalDeviceCount = ArraySize(physicalDevices); | |
assert( | |
vkEnumeratePhysicalDevices( | |
instance, | |
&physicalDeviceCount, | |
physicalDevices) | |
== VK_SUCCESS); | |
cout << physicalDeviceCount << " physical device"; | |
if (physicalDeviceCount != 1) cout << 's'; | |
cout << '\n'; | |
assert(physicalDeviceCount > 0); | |
VkQueueFamilyProperties queueFamilyProperties[8]; | |
uint32_t queueFamilyPropertiesCount = ArraySize(queueFamilyProperties); | |
vkGetPhysicalDeviceQueueFamilyProperties( | |
physicalDevices[0], | |
&queueFamilyPropertiesCount, | |
queueFamilyProperties); | |
cout << queueFamilyPropertiesCount << " queue family property set"; | |
if (queueFamilyPropertiesCount != 1) cout << 's'; | |
cout << '\n'; | |
SDL_SysWMinfo info; | |
SDL_VERSION(&info.version); | |
assert(SDL_GetWindowWMInfo(window, &info) == SDL_TRUE); | |
VkWin32SurfaceCreateInfoKHR w32sci = {}; | |
w32sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; | |
w32sci.pNext = NULL; | |
w32sci.hinstance = GetModuleHandle(NULL); | |
w32sci.hwnd = info.info.win.window; | |
VkSurfaceKHR surface; | |
assert( | |
vkCreateWin32SurfaceKHR( | |
instance, | |
&w32sci, | |
nullptr, | |
&surface) | |
== VK_SUCCESS); | |
VkBool32 supportsPresent[8]; | |
for (uint32_t i = 0; i < queueFamilyPropertiesCount; ++i) | |
{ | |
vkGetPhysicalDeviceSurfaceSupportKHR( | |
physicalDevices[i], | |
i, | |
surface, | |
supportsPresent + i); | |
} | |
bool foundQueue = false; | |
uint32_t queueIndex; | |
for (uint32_t i = 0; i < queueFamilyPropertiesCount; ++i) | |
{ | |
if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && | |
supportsPresent[i] == VK_TRUE) | |
{ | |
foundQueue = true; | |
queueIndex = i; | |
} | |
} | |
assert(foundQueue); | |
cout << "queue index " << queueIndex << '\n'; | |
VkSurfaceFormatKHR formats[8]; | |
uint32_t formatCount = ArraySize(formats); | |
assert( | |
vkGetPhysicalDeviceSurfaceFormatsKHR( | |
physicalDevices[0], | |
surface, | |
&formatCount, | |
formats) | |
== VK_SUCCESS); | |
cout << formatCount << " format"; | |
if (formatCount != 1) cout << 's'; | |
cout << '\n'; | |
assert(formatCount > 0); | |
VkFormat format = formats[0].format; | |
if (formatCount == 1 && formats[0].format == VK_FORMAT_UNDEFINED) | |
format = VK_FORMAT_B8G8R8A8_UNORM; | |
float queuePriority = 0.0f; | |
VkDeviceQueueCreateInfo dqci = {}; | |
dqci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; | |
dqci.pNext = nullptr; | |
dqci.queueCount = 1; | |
dqci.pQueuePriorities = &queuePriority; | |
dqci.queueFamilyIndex = queueIndex; | |
const char* deviceExtensionNames[] = { | |
VK_KHR_SWAPCHAIN_EXTENSION_NAME | |
}; | |
VkDeviceCreateInfo dci = {}; | |
dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; | |
dci.pNext = nullptr; | |
dci.queueCreateInfoCount = 1; | |
dci.pQueueCreateInfos = &dqci; | |
dci.enabledExtensionCount = ArraySize(deviceExtensionNames); | |
dci.ppEnabledExtensionNames = deviceExtensionNames; | |
VkDevice device; | |
assert( | |
vkCreateDevice(physicalDevices[0], &dci, nullptr, &device) == | |
VK_SUCCESS); | |
VkCommandPoolCreateInfo cpci = {}; | |
cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; | |
cpci.pNext = nullptr; | |
cpci.queueFamilyIndex = queueIndex; | |
cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; | |
VkCommandPool commandPool; | |
assert( | |
vkCreateCommandPool(device, &cpci, nullptr, &commandPool) == | |
VK_SUCCESS); | |
VkCommandBufferAllocateInfo cbai = {}; | |
cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; | |
cbai.pNext = nullptr; | |
cbai.commandPool = commandPool; | |
cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; | |
cbai.commandBufferCount = 1; | |
VkCommandBuffer commandBuffer; | |
assert( | |
vkAllocateCommandBuffers(device, &cbai, &commandBuffer) == VK_SUCCESS); | |
VkCommandBufferBeginInfo cbbi = {}; | |
cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | |
cbbi.pNext = nullptr; | |
cbbi.flags = 0; | |
cbbi.pInheritanceInfo = nullptr; | |
assert(vkBeginCommandBuffer(commandBuffer, &cbbi) == VK_SUCCESS); | |
VkQueue queue; | |
vkGetDeviceQueue(device, queueIndex, 0, &queue); | |
VkSurfaceCapabilitiesKHR surfaceCapabilities; | |
assert( | |
vkGetPhysicalDeviceSurfaceCapabilitiesKHR( | |
physicalDevices[0], | |
surface, | |
&surfaceCapabilities) | |
== VK_SUCCESS); | |
VkPresentModeKHR presentModes[8]; | |
uint32_t presentModeCount = ArraySize(presentModes); | |
assert( | |
vkGetPhysicalDeviceSurfacePresentModesKHR( | |
physicalDevices[0], | |
surface, | |
&presentModeCount, | |
presentModes) == VK_SUCCESS); | |
cout << presentModeCount << " present mode"; | |
if (presentModeCount != 1) cout << 's'; | |
cout << '\n'; | |
VkExtent2D swapChainExtent = surfaceCapabilities.currentExtent; | |
if (swapChainExtent.width == ~uint32_t(0)) | |
{ | |
cout << "surface size undefined\n"; | |
int w; | |
int h; | |
SDL_GetWindowSize(window, &w, &h); | |
swapChainExtent.width = w; | |
swapChainExtent.height = h; | |
} | |
cout << swapChainExtent.width << "x" << swapChainExtent.height << '\n'; | |
VkPresentModeKHR swapChainPresentMode = VK_PRESENT_MODE_FIFO_KHR; | |
for (uint32_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 desiredSwapChainImageCount = surfaceCapabilities.minImageCount + 1; | |
if (surfaceCapabilities.maxImageCount > 0 && | |
desiredSwapChainImageCount > surfaceCapabilities.maxImageCount) | |
{ | |
desiredSwapChainImageCount = surfaceCapabilities.maxImageCount; | |
} | |
VkSurfaceTransformFlagBitsKHR preTransform = | |
surfaceCapabilities.currentTransform; | |
if (surfaceCapabilities.supportedTransforms & | |
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) | |
{ | |
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; | |
} | |
VkSwapchainCreateInfoKHR scci = {}; | |
scci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; | |
scci.pNext = nullptr; | |
scci.surface = surface; | |
scci.minImageCount = desiredSwapChainImageCount; | |
scci.imageFormat = format; | |
scci.imageExtent = swapChainExtent; | |
scci.preTransform = preTransform; | |
scci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; | |
scci.imageArrayLayers = 1; | |
scci.presentMode = swapChainPresentMode; | |
scci.oldSwapchain = VK_NULL_HANDLE; | |
scci.clipped = VK_TRUE; | |
scci.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; | |
scci.imageUsage = | |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | | |
VK_IMAGE_USAGE_TRANSFER_DST_BIT; | |
scci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; | |
scci.queueFamilyIndexCount = 0; | |
scci.pQueueFamilyIndices = nullptr; | |
VkSwapchainKHR swapChain; | |
assert( | |
vkCreateSwapchainKHR(device, &scci, nullptr, &swapChain) == VK_SUCCESS); | |
VkImage swapChainImages[8]; | |
uint32_t swapChainImageCount = ArraySize(swapChainImages); | |
assert( | |
vkGetSwapchainImagesKHR( | |
device, | |
swapChain, | |
&swapChainImageCount, | |
swapChainImages) | |
== VK_SUCCESS); | |
cout << swapChainImageCount << " swap chain image"; | |
if (swapChainImageCount != 1) cout << 's'; | |
cout << '\n'; | |
struct { VkImage image; VkImageView view; } swapChainBuffers[8]; | |
for (uint32_t i = 0; i < swapChainImageCount; ++i) | |
{ | |
VkImageViewCreateInfo ivci = {}; | |
ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | |
ivci.pNext = nullptr; | |
ivci.format = format; | |
ivci.components.r = VK_COMPONENT_SWIZZLE_R; | |
ivci.components.g = VK_COMPONENT_SWIZZLE_G; | |
ivci.components.b = VK_COMPONENT_SWIZZLE_B; | |
ivci.components.a = VK_COMPONENT_SWIZZLE_A; | |
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | |
ivci.subresourceRange.baseMipLevel = 0; | |
ivci.subresourceRange.levelCount = 1; | |
ivci.subresourceRange.baseArrayLayer = 0; | |
ivci.subresourceRange.layerCount = 1; | |
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; | |
ivci.flags = 0; | |
swapChainBuffers[i].image = swapChainImages[i]; | |
SetImageLayout( | |
commandBuffer, | |
swapChainBuffers[i].image, | |
VK_IMAGE_ASPECT_COLOR_BIT, | |
VK_IMAGE_LAYOUT_UNDEFINED, | |
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); | |
ivci.image = swapChainBuffers[i].image; | |
assert( | |
vkCreateImageView( | |
device, | |
&ivci, | |
nullptr, | |
&swapChainBuffers[i].view) | |
== VK_SUCCESS); | |
} | |
struct | |
{ | |
VkFormat format; | |
VkImage image; | |
VkDeviceMemory memory; | |
VkImageView view; | |
} depth; | |
depth.format = VK_FORMAT_D16_UNORM; | |
VkFormatProperties formatProperties; | |
vkGetPhysicalDeviceFormatProperties( | |
physicalDevices[0], | |
VK_FORMAT_D16_UNORM, | |
&formatProperties); | |
VkImageCreateInfo ici2 = {}; | |
if (formatProperties.linearTilingFeatures & | |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) | |
{ | |
ici2.tiling = VK_IMAGE_TILING_LINEAR; | |
} | |
else if (formatProperties.optimalTilingFeatures & | |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) | |
{ | |
ici2.tiling = VK_IMAGE_TILING_OPTIMAL; | |
} | |
else | |
{ | |
assert(false); | |
} | |
// util_init.cpp line 605 | |
/// /// /// Display Window /// /// /// | |
bool running = true; | |
while (running) | |
{ | |
SDL_Event event; | |
while (SDL_PollEvent(&event)) | |
{ | |
if (event.type == SDL_KEYDOWN) running = false; | |
if (event.type == SDL_QUIT) running = false; | |
} | |
SDL_Delay(1); | |
} | |
vkDestroyInstance(instance, nullptr); | |
SDL_DestroyWindow(window); | |
SDL_Quit(); | |
return 0; | |
} |
It would be nice if this example is not Windows specific.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@cappah Oh I never saw this comment. I'm sure you've moved on by now, but no, at the time, this was not a working sample. I was unrolling another tutorial. However, it did build and run. It properly enumerated Vulkan devices and whatnot. I didn't have any lib problems.