Created
July 22, 2018 12:35
-
-
Save but0n/e5f2f9f680f756d397f8b344703d818c to your computer and use it in GitHub Desktop.
This file contains 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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <vulkan/vulkan.h> | |
#include <SDL2/SDL.h> | |
#include <SDL2/SDL_Vulkan.h> | |
typedef struct { | |
SDL_Window *SDLWindow; | |
SDL_Renderer *SDLRenderer; | |
}SDLCtx_t, *SDLCtx_tp; | |
SDLCtx_t gSDL_Context; | |
static int createWindow(SDLCtx_tp ctx, const char *windowName) { | |
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { | |
SDL_LogError( | |
SDL_LOG_CATEGORY_APPLICATION, | |
"Couldn't initialize SDL: %s", | |
SDL_GetError() | |
); | |
return 1; | |
} | |
ctx->SDLWindow = SDL_CreateWindow(windowName, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN); | |
return 0; | |
} | |
static unsigned char closeWindow(void *ctx) { | |
SDLCtx_tp pctx = ctx; | |
SDL_DestroyRenderer(pctx->SDLRenderer); | |
SDL_DestroyWindow(pctx->SDLWindow); | |
SDL_Quit(); | |
return 0; | |
} | |
// Custom delay function | |
void brs_Delay(unsigned int ms) { | |
for(unsigned int i = 0; i < ms; i++){ | |
SDL_PumpEvents(); | |
SDL_Delay(1); // void SDL_Delay(Uint32 ms) | |
} | |
} | |
VkInstance instance; | |
static const char *SDL_Extensions_name[10]; | |
static unsigned int SDL_Extensions_count = 0; | |
void initVulkan() { | |
SDL_Vulkan_GetInstanceExtensions(gSDL_Context.SDLWindow, &SDL_Extensions_count, NULL); | |
SDL_Vulkan_GetInstanceExtensions(gSDL_Context.SDLWindow, &SDL_Extensions_count, SDL_Extensions_name); | |
printf("\nSDL Extension Count : %d\n\n", SDL_Extensions_count); | |
for(unsigned int i = 0; i < SDL_Extensions_count; i++) { | |
printf("\n\tExtension %d: %s\n\n", i, SDL_Extensions_name[0]); | |
} | |
static const VkApplicationInfo appInfo = { | |
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, | |
.pNext = NULL, | |
.pApplicationName = "hello Vulkan", | |
.applicationVersion = VK_MAKE_VERSION(1, 0, 0), | |
.pEngineName = NULL, | |
.engineVersion = VK_MAKE_VERSION(1, 0, 0), | |
.apiVersion = VK_API_VERSION_1_1, | |
}; | |
static const VkInstanceCreateInfo createInfo = { | |
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, | |
.pNext = NULL, | |
.flags = 0, | |
.pApplicationInfo = &appInfo, | |
// Don't enable any layer | |
.enabledLayerCount = 0, | |
.ppEnabledLayerNames = NULL, | |
.enabledExtensionCount = (unsigned int const)2, | |
.ppEnabledExtensionNames = SDL_Extensions_name, | |
}; | |
VkResult result = vkCreateInstance(&createInfo, NULL, &instance); | |
if(result != VK_SUCCESS) { | |
printf("Error\n"); | |
return; | |
} | |
} | |
void destroyVulkan() { | |
vkDestroyInstance(instance, NULL); | |
} | |
void getDevices(SDLCtx_tp ctx) { | |
unsigned int count = 0; | |
VkResult result = vkEnumeratePhysicalDevices(instance, &count, NULL); | |
if(result != VK_SUCCESS) { | |
printf("Error\n"); | |
return; | |
} | |
printf("\nPhysical devices Count : %d\n\n", count); | |
VkPhysicalDevice GPU[10]; | |
result = vkEnumeratePhysicalDevices(instance, &count, GPU); | |
if(result != VK_SUCCESS) { | |
printf("\nFaied to enumerate physical devices present \n"); | |
return; | |
} | |
VkPhysicalDeviceProperties deviceProperties; | |
vkGetPhysicalDeviceProperties(GPU[0], &deviceProperties); | |
printf("\tDriver Version: %d\n", deviceProperties.driverVersion); | |
printf("\tDevice Name: %s\n", deviceProperties.deviceName); | |
printf("\tDevice Type: %d\n", deviceProperties.deviceType); | |
printf("\tAPI Version: %d.%d.%d\n", | |
// See note below regarding this: | |
(deviceProperties.apiVersion>>22)&0x3FF, | |
(deviceProperties.apiVersion>>12)&0x3FF, | |
(deviceProperties.apiVersion&0xFFF)); | |
// Check for supported queue families. | |
uint32_t queueFamilyCount = 0; | |
vkGetPhysicalDeviceQueueFamilyProperties(GPU[0], &queueFamilyCount, NULL); | |
VkQueueFamilyProperties familyProperties[10]; | |
vkGetPhysicalDeviceQueueFamilyProperties(GPU[0], &queueFamilyCount, familyProperties); | |
// Print the families | |
for (uint32_t j = 0; j < queueFamilyCount; j++) { | |
printf("GPU[%d] Count of Queues: %d\n", j, familyProperties[j].queueCount); | |
printf("Supported operationg on this queue:\n"); | |
if (familyProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) | |
printf("\t\t Graphics @ %d\n", j); | |
if (familyProperties[j].queueFlags & VK_QUEUE_COMPUTE_BIT) | |
printf("\t\t Compute @ %d\n", j); | |
if (familyProperties[j].queueFlags & VK_QUEUE_TRANSFER_BIT) | |
printf("\t\t Transfer @ %d\n", j); | |
if (familyProperties[j].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) | |
printf("\t\t Sparse Binding @ %d\n", j); | |
} | |
// VkDevice device; | |
float queue_priorities[1] = {0.0}; | |
const VkDeviceQueueCreateInfo queue = { | |
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, | |
.pNext = NULL, | |
.queueFamilyIndex = 0, | |
.queueCount = 1, | |
.pQueuePriorities = queue_priorities, | |
}; | |
VkDeviceCreateInfo device = { | |
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, | |
.pNext = NULL, | |
.queueCreateInfoCount = 1, | |
.pQueueCreateInfos = &queue, | |
.enabledLayerCount = 0, | |
.ppEnabledLayerNames = NULL, | |
.enabledExtensionCount = SDL_Extensions_count, | |
.ppEnabledExtensionNames = SDL_Extensions_name, | |
.pEnabledFeatures = NULL | |
}; | |
// Create device instance | |
VkDevice GPUdevice; | |
vkCreateDevice(GPU[0], &device, NULL, &GPUdevice); | |
// Create window surface! | |
VkSurfaceKHR surface; | |
SDL_Vulkan_CreateSurface(ctx->SDLWindow, (SDL_vulkanInstance)instance, (SDL_vulkanSurface*)&surface); | |
// Create the presentation queue. | |
VkBool32 supported; | |
vkGetPhysicalDeviceSurfaceSupportKHR(GPU[0], 0, surface, &supported); | |
printf("\nGPU supported? %s\n", supported?"Yes":"No"); | |
// Add a member variable for the VkQueue handle: | |
VkQueue vkque; | |
vkGetDeviceQueue(GPUdevice, 0, 0, &vkque); | |
// before create SwapChain | |
unsigned int extension; | |
vkEnumerateDeviceExtensionProperties(GPU[0], NULL, &extension, NULL); | |
VkExtensionProperties ep[10]; | |
vkEnumerateDeviceExtensionProperties(GPU[0], NULL, &extension, ep); | |
// show support | |
printf("\n - support extension amount: %d\n", extension); | |
for(int i = 0; i < extension; i++) { | |
printf("\t Name: %s\n", ep[i].extensionName); | |
} | |
// Adjust: 只要有一个 format 和 presentMode 我们就认为此显卡支持 Swap Chain 并且兼容 surface | |
VkSurfaceCapabilitiesKHR surfaceCapabilities; | |
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(GPU[0], surface, &surfaceCapabilities); | |
printf("Resolution:\n\tWidth - %d\n\tHeight - %d\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height); | |
printf("Max Resolution:\n\tWidth - %d\n\tHeight - %d\n", surfaceCapabilities.maxImageExtent.width, surfaceCapabilities.maxImageExtent.height); | |
unsigned int formatCount; | |
vkGetPhysicalDeviceSurfaceFormatsKHR(GPU[0], surface, &formatCount, NULL); | |
printf("Physical Device Surface Formats count: %d\n\n", formatCount); | |
VkSurfaceFormatKHR formats[10]; | |
vkGetPhysicalDeviceSurfaceFormatsKHR(GPU[0], surface, &formatCount, formats); | |
for(int i = 0; i < formatCount; i++) { | |
printf("\t Format %d:\n", i); | |
printf("\t\t * format: %x\n", formats[i].format); | |
printf("\t\t * colorSpace: %d\n", formats[i].colorSpace); | |
} | |
unsigned int presentModeCount; | |
vkGetPhysicalDeviceSurfacePresentModesKHR(GPU[0], surface, &presentModeCount, NULL); | |
VkPresentModeKHR presentModes[10]; | |
vkGetPhysicalDeviceSurfacePresentModesKHR(GPU[0], surface, &presentModeCount, presentModes); | |
printf("\nPhysical Device Surface Present Modes count: %d\n\n", presentModeCount); | |
for(int i = 0; i < presentModeCount; i++) { | |
printf("\t Present Modes %d:\n", i); | |
printf("\t\t * mode: %x\n", presentModes[i]); | |
} | |
// Create SwapChain | |
VkSwapchainCreateInfoKHR swapCreateInfo = { | |
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, | |
.pNext = NULL, | |
.surface = surface, | |
.minImageCount = 0, | |
.imageFormat = formats[1].format, | |
.imageColorSpace = formats[1].colorSpace, | |
.imageExtent = surfaceCapabilities.currentExtent, | |
.imageArrayLayers = 1, | |
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, | |
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, | |
.queueFamilyIndexCount = 0, | |
.pQueueFamilyIndices = NULL, | |
.clipped = VK_TRUE, | |
.presentMode = presentModes[0], | |
.preTransform = surfaceCapabilities.currentTransform, | |
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, | |
.oldSwapchain = VK_NULL_HANDLE, | |
}; | |
VkSwapchainKHR swapChain; | |
if(vkCreateSwapchainKHR(GPUdevice, &swapCreateInfo, NULL, &swapChain) != VK_SUCCESS) { | |
printf("Create SwapChain Error\n"); | |
return; | |
} | |
} | |
int main() { | |
createWindow(&gSDL_Context, "Hello world"); | |
initVulkan(); | |
getDevices(&gSDL_Context); | |
// brs_Delay(100); | |
closeWindow((void *)&gSDL_Context); | |
printf("hello vulkan\n"); | |
destroyVulkan(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment