Skip to content

Instantly share code, notes, and snippets.

@elix22
Forked from but0n/helloWorld.c
Created November 1, 2018 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elix22/d1847f6e716f40529d1e6b38bf82b29d to your computer and use it in GitHub Desktop.
Save elix22/d1847f6e716f40529d1e6b38bf82b29d to your computer and use it in GitHub Desktop.
#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