summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/render.c428
-rw-r--r--src/state.h3
-rw-r--r--src/vksetup.h896
3 files changed, 708 insertions, 619 deletions
diff --git a/src/render.c b/src/render.c
index 810db51..ae9c05b 100644
--- a/src/render.c
+++ b/src/render.c
@@ -170,7 +170,7 @@ debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
void
vulkan_setup_debug_messenger()
{
- if (!enableValidationLayers) return;
+ if (!enable_validation_layers) return;
VkDebugUtilsMessengerCreateInfoEXT createInfo = {0};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
@@ -191,92 +191,6 @@ vulkan_setup_debug_messenger()
}
}
-VkExtent2D
-chooseSwapExtent(const VkSurfaceCapabilitiesKHR * capabilities)
-{
- if (capabilities->currentExtent.width != UINT32_MAX) {
- return capabilities->currentExtent;
- } else {
- int width, height;
- SDL_GetWindowSize(s.vk.window, &width, &height);
-
- VkExtent2D actualExtent;
- actualExtent.width = (uint32_t) width;
- actualExtent.height = (uint32_t) height;
-
- // Manual implementation of std::clamp since it is not available in C
- actualExtent.width = (actualExtent.width < capabilities->minImageExtent.width) ? capabilities->minImageExtent.width :
- (actualExtent.width > capabilities->maxImageExtent.width) ? capabilities->maxImageExtent.width :
- actualExtent.width;
-
- actualExtent.height = (actualExtent.height < capabilities->minImageExtent.height) ? capabilities->minImageExtent.height :
- (actualExtent.height > capabilities->maxImageExtent.height) ? capabilities->maxImageExtent.height :
- actualExtent.height;
-
- return actualExtent;
- }
-}
-
-VkSurfaceFormatKHR
-chooseSwapSurfaceFormat(const VkSurfaceFormatKHR * availableFormats, uint32_t formatCount)
-{
- for (uint32_t i = 0 ; i < formatCount; i ++) {
- if (availableFormats[i].format == VK_FORMAT_B8G8R8A8_SRGB &&
- availableFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
- return availableFormats[i];
- }
- }
-
- // if it fails pick the first one
- return availableFormats[0];
-}
-
-VkPresentModeKHR
-chooseSwapPresentMode(const VkPresentModeKHR * presentModes, uint32_t presentModeCount)
-{
- for (uint32_t i = 0 ; i < presentModeCount; i ++) {
- if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
- return presentModes[i];
- }
- }
-
- // if it fails pick the the FIFO one
- return VK_PRESENT_MODE_FIFO_KHR;
-}
-
-typedef struct SwapChainSupportDetails {
- VkSurfaceCapabilitiesKHR capabilities;
- VkSurfaceFormatKHR formats[100];
- uint32_t formatCount;
- VkPresentModeKHR presentModes[100];
- uint32_t presentModeCount;
-} SwapChainSupportDetails;
-
-SwapChainSupportDetails
-querySwapChainSupport(VkPhysicalDevice device)
-{
- // TODO Make SwapChainSupportDetails malloc it;s arrays and free it after it is used.
- SwapChainSupportDetails details;
-
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, s.vk.surface, &details.capabilities);
-
- vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk.surface, &details.formatCount, NULL);
-
- if (details.formatCount != 0) {
- // todo alloc format arrray
- vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk.surface, &details.formatCount, details.formats);
- }
-
- vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk.surface, &details.presentModeCount, NULL);
-
- if (details.presentModeCount != 0) {
- // todo alloc presentModes array
- vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk.surface, &details.presentModeCount, details.presentModes);
- }
-
- return details;
-}
-
typedef struct QueueFamilyIndices {
uint32_t graphicsAndComputeFamily;
bool graphicsFlag;
@@ -320,154 +234,6 @@ QueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice device) {
return indices;
}
-bool
-vulkan_check_device_extension_support(VkPhysicalDevice device)
-{
- uint32_t extensionCount;
- vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
-
- VkExtensionProperties availableExtensions[extensionCount];
- vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, availableExtensions);
-
- uint32_t flag = 0;
-
- for (uint32_t i = 0; i < deviceExtensionCount; i++) {
- for (uint32_t j = 0; j < extensionCount; j++) {
- if (strcmp(device_extensions[i], availableExtensions[j].extensionName) == 0) {
- flag++;
- break;
- }
- }
- }
-
- return flag == deviceExtensionCount;
-}
-
-bool
-vulkan_is_device_suitable(VkPhysicalDevice device)
-{
- QueueFamilyIndices indices = vulkan_find_queue_families(device);
- bool extensionsSupported = vulkan_check_device_extension_support(device);
-
- bool swapChainAdequate = false;
- if (extensionsSupported) {
- SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
- swapChainAdequate = !(swapChainSupport.formatCount == 0) && !(swapChainSupport.presentModeCount == 0);
- }
-
- VkPhysicalDeviceFeatures supportedFeatures;
- vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
-
- return vulkan_queue_family_check_flags(indices) && extensionsSupported
- && swapChainAdequate && supportedFeatures.samplerAnisotropy;
-}
-
-VkSampleCountFlagBits getMaxUsableSampleCount() {
- VkPhysicalDeviceProperties physicalDeviceProperties;
- vkGetPhysicalDeviceProperties(s.vk.physical_device, &physicalDeviceProperties);
-
- VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
- if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
- if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
- if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
- if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
- if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
- if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
-
- return VK_SAMPLE_COUNT_1_BIT;
-}
-
-void
-vulkan_pick_physical_device()
-{
- uint32_t deviceCount = 0;
- vkEnumeratePhysicalDevices(s.vk.instance, &deviceCount, NULL);
- if (deviceCount == 0) {
- vk_log(VK_INFO, "failed to find GPUs with Vulkan support!\n");
- }
-
- VkPhysicalDevice devices[deviceCount];
- vkEnumeratePhysicalDevices(s.vk.instance, &deviceCount, devices);
-
- for (uint32_t i = 0; i < deviceCount; i++) {
- if (vulkan_is_device_suitable(devices[i])) {
- s.vk.physical_device = devices[i];
- s.msaa_samples = getMaxUsableSampleCount();
- break;
- }
- }
-
- if (s.vk.physical_device == VK_NULL_HANDLE) {
- vk_log(VK_ERROR, "failed to find a suitable GPU!\n");
- }
-
- VkPhysicalDeviceProperties deviceProperties;
- vkGetPhysicalDeviceProperties(s.vk.physical_device, &deviceProperties);
- vk_log(VK_INFO, "Picked [%s] physical device.\n", deviceProperties.deviceName);
-
- uint32_t extensionCount = 0;
- vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
- VkExtensionProperties extensions[extensionCount];
- VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions);
-
- vk_log(VK_INFO, "Vulkan enabled extensions: %s\n", string_VkResult(result));
- for (uint32_t i = 0; i < extensionCount; i++) {
- vk_log(VK_INFO, "\t%s\n", extensions[i].extensionName);
- }
-
-}
-
-void
-vulkan_create_logical_device()
-{
- QueueFamilyIndices indices = vulkan_find_queue_families(s.vk.physical_device);
-
- // TODO CREATE MULPILE QUEUES
- // https://vulkan-tutorial.com/en/Drawing_a_triangle/Presentation/Window_surface#page_Creating-the-presentation-queue
-
- VkDeviceQueueCreateInfo queueCreateInfo = {
- .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- .queueFamilyIndex = indices.graphicsAndComputeFamily,
- .queueCount = 1,
- };
-
- float queuePriority = 1.0f;
- queueCreateInfo.pQueuePriorities = &queuePriority;
-
- VkPhysicalDeviceFeatures deviceFeatures = {0};
- vkGetPhysicalDeviceFeatures(s.vk.physical_device, &deviceFeatures);
- deviceFeatures.samplerAnisotropy = VK_TRUE;
- //deviceFeatures.sampleRateShading = VK_TRUE;
-#ifndef VKDEBUG
- /* Disable robust buffer access when building without debug */
- deviceFeatures.robustBufferAccess = VK_FALSE;
-#endif
-
- VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamic_rendering_feature = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR,
- .dynamicRendering = VK_TRUE,
- };
-
- VkDeviceCreateInfo createInfo = {
- .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .pQueueCreateInfos = &queueCreateInfo,
- .queueCreateInfoCount = 1,
- .pNext = &dynamic_rendering_feature,
- .pEnabledFeatures = &deviceFeatures,
- .enabledExtensionCount = deviceExtensionCount,
- .ppEnabledExtensionNames = device_extensions,
- .enabledLayerCount = 0,
- };
-
- if (vkCreateDevice(s.vk.physical_device, &createInfo, NULL, &s.vk.device) != VK_SUCCESS) {
- vk_log(VK_ERROR, "failed to create logical device!\n");
- }
- vk_log(VK_INFO, "Vulkan logical device created\n");
-
- vkGetDeviceQueue(s.vk.device, indices.graphicsAndComputeFamily, 0, &s.vk_graphics_and_compute_queue);
- vkGetDeviceQueue(s.vk.device, indices.presentFamily, 0, &s.vk_present_queue);
-}
-
void move_relative(vec3 position, vec3 front, float step, int x) {
// Calculate the direction vector from position to front
float direction_vec[3] = {
@@ -549,108 +315,6 @@ mouseCallback(SDL_Event *event)
return;
}
-void
-vulkan_create_surface()
-{
- if (SDL_Vulkan_CreateSurface(s.vk.window, s.vk.instance, &s.vk.surface) == SDL_FALSE) {
- vk_log(VK_ERROR, "Failed to create surface\n");
- } else {
- vk_log(VK_INFO, "Vulkan surface created\n");
- }
-}
-
-void
-vulkan_create_swap_chain()
-{
- SwapChainSupportDetails swapChainSupport = querySwapChainSupport(s.vk.physical_device);
-
- VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats, swapChainSupport.formatCount);
- VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes, swapChainSupport.presentModeCount);
- VkExtent2D extent = chooseSwapExtent(&swapChainSupport.capabilities);
-
- uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
-
- if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
- imageCount = swapChainSupport.capabilities.maxImageCount;
- }
-
- VkSwapchainCreateInfoKHR createInfo = {
- .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
- .surface = s.vk.surface,
- .minImageCount = imageCount,
- .imageFormat = surfaceFormat.format,
- .imageColorSpace = surfaceFormat.colorSpace,
- .imageExtent = extent,
- .imageArrayLayers = 1,
- .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
- };
-
- QueueFamilyIndices indices = vulkan_find_queue_families(s.vk.physical_device);
-
- uint32_t queueFamilyIndices[] = {indices.graphicsAndComputeFamily, indices.presentFamily};
-
- if (indices.graphicsAndComputeFamily != indices.presentFamily) {
- createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- createInfo.queueFamilyIndexCount = 2;
- createInfo.pQueueFamilyIndices = queueFamilyIndices;
- } else {
- createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- createInfo.queueFamilyIndexCount = 0; // Optional
- createInfo.pQueueFamilyIndices = NULL; // Optional
- }
-
- createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
- createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- createInfo.presentMode = presentMode;
- createInfo.clipped = VK_TRUE;
- createInfo.oldSwapchain = VK_NULL_HANDLE;
-
- VK_CHECK(vkCreateSwapchainKHR(s.vk.device, &createInfo, NULL, &s.vk.swapchain.handle));
- /* if (result != VK_SUCCESS) { */
- /* vk_log(VK_ERROR, "ERROR: failed to create swap chain! %s\n", string_VkResult(result)); */
- /* } */
-
- VK_CHECK(vkGetSwapchainImagesKHR(s.vk.device, s.vk.swapchain.handle, &s.vk.swapchain.image_count, NULL));
- //vk_log(VK_INFO, "vk_swap_chain_images count: %d\n", s.vk.swapchain.image_count);
- // todo alloc space for images
- VK_CHECK(vkGetSwapchainImagesKHR(s.vk.device, s.vk.swapchain.handle, &s.vk.swapchain.image_count, s.vk.swapchain.images));
-
- s.vk.swapchain.image_format = surfaceFormat.format;
- s.vk.swapchain.extent = extent;
-
- vk_log(VK_INFO, "Vulkan swapchain created!\n");
-}
-
-
-VkImageView
-create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels)
-{
- VkImageViewCreateInfo viewInfo = {0};
- viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- viewInfo.image = image;
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- viewInfo.format = format;
- viewInfo.subresourceRange.aspectMask = aspectFlags;
- viewInfo.subresourceRange.baseMipLevel = 0;
- viewInfo.subresourceRange.levelCount = mipLevels;
- viewInfo.subresourceRange.baseArrayLayer = 0;
- viewInfo.subresourceRange.layerCount = 1;
-
- VkImageView imageView;
- VK_CHECK(vkCreateImageView(s.vk.device, &viewInfo, NULL, &imageView));
-
- return imageView;
-}
-
-void
-vulkan_create_image_views()
-{
- for (size_t i = 0; i < s.vk.swapchain.image_count; i++) {
- s.vk.swapchain.image_views[i] = create_image_view(s.vk.swapchain.images[i], s.vk.swapchain.image_format, VK_IMAGE_ASPECT_COLOR_BIT, 1);
- }
- vk_log(VK_INFO, "Vulkan image views created!\n");
-}
-
VkShaderModule
createShaderModule(const char * code, long size)
{
@@ -719,59 +383,6 @@ load_compile_shader_data(const char * path, shaderc_shader_kind shader_kind)
return result;
}
-uint32_t
-findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
-{
- VkPhysicalDeviceMemoryProperties memProperties;
- vkGetPhysicalDeviceMemoryProperties(s.vk.physical_device, &memProperties);
-
- for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
- if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
- return i;
- }
- }
-
- vk_log(VK_ERROR, "failed to find suitable memory type!\n");
- return 9999;
-}
-
-VkCommandBuffer
-beginSingleTimeCommands()
-{
- VkCommandBufferAllocateInfo allocInfo = {0};
- allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- allocInfo.commandPool = s.vk_command_pool;
- allocInfo.commandBufferCount = 1;
-
- VkCommandBuffer commandBuffer;
- VK_CHECK(vkAllocateCommandBuffers(s.vk.device, &allocInfo, &commandBuffer));
-
- VkCommandBufferBeginInfo beginInfo = {0};
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
-
- VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo));
-
- return commandBuffer;
-}
-
-void
-endSingleTimeCommands(VkCommandBuffer commandBuffer)
-{
- VK_CHECK(vkEndCommandBuffer(commandBuffer));
-
- VkSubmitInfo submitInfo = {0};
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &commandBuffer;
-
- VK_CHECK(vkQueueSubmit(s.vk_graphics_and_compute_queue, 1, &submitInfo, VK_NULL_HANDLE));
- VK_CHECK(vkQueueWaitIdle(s.vk_graphics_and_compute_queue));
-
- vkFreeCommandBuffers(s.vk.device, s.vk_command_pool, 1, &commandBuffer);
-}
-
VkFormat
findSupportedFormat(VkFormat *candidates, size_t n,
VkImageTiling tiling,
@@ -809,10 +420,10 @@ vulkan_create_depth_resources()
vks_create_image(s.vk, s.vk.swapchain.extent.width, s.vk.swapchain.extent.height, 1,
depth_format, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.msaa_samples,
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.vk.msaa_samples,
&s.depth_image);
- s.depth_image.view = create_image_view(s.depth_image.handle, depth_format,
- VK_IMAGE_ASPECT_DEPTH_BIT, 1);
+ s.depth_image.view = vks_create_image_view(s.vk, s.depth_image.handle, depth_format,
+ VK_IMAGE_ASPECT_DEPTH_BIT, 1);
vks_transition_image_layout_info transition_info = { 0 };
transition_info.cmd_info.vk = s.vk;
@@ -839,9 +450,9 @@ void vulkan_create_color_resources() {
colorFormat, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.msaa_samples,
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.vk.msaa_samples,
&s.color_image);
- s.color_image.view = create_image_view(s.color_image.handle, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
+ s.color_image.view = vks_create_image_view(s.vk, s.color_image.handle, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
void
@@ -972,7 +583,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode)
VkPipelineMultisampleStateCreateInfo multisampling = {0};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = s.msaa_samples;
+ multisampling.rasterizationSamples = s.vk.msaa_samples;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = NULL; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
@@ -1441,8 +1052,7 @@ recreateSwapChain()
cleanupSwapChain();
- vulkan_create_swap_chain();
- vulkan_create_image_views();
+ _vulkan_create_swap_chain(&s.vk);
vulkan_create_color_resources();
vulkan_create_depth_resources();
}
@@ -1665,7 +1275,7 @@ vulkan_create_texture_image()
void
vulkan_create_texture_image_view()
{
- s.texture_image.view = create_image_view(s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels);
+ s.texture_image.view = vks_create_image_view(s.vk, s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels);
}
void vulkan_create_texture_sampler() {
@@ -1765,7 +1375,6 @@ load_model_obj()
vk_log(VK_INFO, "[obj] %s: Loaded %ld vertices %ld indices\n", s.model_path, s.vertices_count, s.indices_count);
-
fast_obj_destroy(m);
}
@@ -1941,8 +1550,6 @@ void vulkan_create_compute_stuff()
VK_CHECK(vkCreateDescriptorSetLayout(s.vk.device, &layoutInfo, NULL, &s.vk_compute_descriptor_set_layout));
-
-
VkComputePipelineCreateInfo pipelineInfo = {0};
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipelineInfo.layout = s.vk_compute_pipeline_layout;
@@ -1972,16 +1579,8 @@ init_vulkan()
vk_log(VK_WARN, " DEBUG ON \n");
vk_log(VK_WARN, "====================================\n");
- //vulkan_create_instance();
- s.vk.instance =
- vks_create_instance(enableValidationLayers, validation_layers,
- validation_layer_count, s.vk.window);
- // vulkan_setup_debug_messenger();
- vulkan_create_surface();
- vulkan_pick_physical_device();
- vulkan_create_logical_device();
- vulkan_create_swap_chain();
- vulkan_create_image_views();
+ vks_create_vulkan_context(&s.vk, &s.vk_graphics_and_compute_queue, &s.vk_present_queue);
+
vulkan_create_descriptor_set_layout();
vulkan_create_graphics_pipeline(s.polygon_mode);
//vulkan_create_compute_stuff();
@@ -2040,7 +1639,7 @@ close_vulkan()
vkDestroyPipelineLayout(s.vk.device, s.graphics_pipeline.layout, NULL);
vkDestroyDevice(s.vk.device, NULL);
vkDestroySurfaceKHR(s.vk.instance, s.vk.surface, NULL);
- /* if (enableValidationLayers) { */
+ /* if (enable_validation_layers) { */
/* DestroyDebugUtilsMessengerEXT(s.vk.instance, s.vk_debug_messenger, NULL); */
/* } */
vkDestroyInstance(s.vk.instance, NULL);
@@ -2113,7 +1712,8 @@ updateUniformBuffer(uint32_t currentImage, float dt)
float prev_time = 0;
void
-draw_frame() {
+draw_frame()
+{
float time = current_time();
float dt = time - prev_time;
diff --git a/src/state.h b/src/state.h
index b9c9921..d4f7e6c 100644
--- a/src/state.h
+++ b/src/state.h
@@ -134,7 +134,6 @@ typedef struct state {
char model_path[1000];
- VkSampleCountFlagBits msaa_samples;
vks_image color_image;
@@ -197,5 +196,5 @@ init_state(state_t *s)
s->polygon_mode = VK_POLYGON_MODE_FILL;
- s->msaa_samples = VK_SAMPLE_COUNT_1_BIT;
+ s->vk.msaa_samples = VK_SAMPLE_COUNT_1_BIT;
}
diff --git a/src/vksetup.h b/src/vksetup.h
index e78b887..e3b8f75 100644
--- a/src/vksetup.h
+++ b/src/vksetup.h
@@ -124,9 +124,9 @@ const char *const device_extensions[] = {
const uint32_t deviceExtensionCount = VK_ARRAY_LEN(device_extensions);
#ifdef VKDEBUG
- const bool enableValidationLayers = true;
+ const bool enable_validation_layers = true;
#else
- const bool enableValidationLayers = false;
+ const bool enable_validation_layers = false;
#endif
@@ -143,8 +143,6 @@ extern "C" {
#endif
#endif
-// TODO Create structs for vulkan data
-
typedef struct vks_swapchain {
VkSwapchainKHR handle;
@@ -181,6 +179,8 @@ typedef struct vks_context {
VkSurfaceKHR surface;
vks_swapchain swapchain;
+
+ VkSampleCountFlagBits msaa_samples;
} vks_context;
typedef struct vks_frame_data {
@@ -222,19 +222,15 @@ typedef struct vks_transition_image_layout_info
/* Exported API */
-VKSDEF VkInstance vks_create_instance (bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window);
-VKSDEF void vks_create_buffer (const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer);
-VKSDEF void vks_create_image (const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image);
-VKSDEF void vks_transition_image_layout (const vks_transition_image_layout_info *info);
-VKSDEF void vks_copy_buffer (const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size);
-VKSDEF void vks_copy_buffer_to_image (const vks_command_info* cmd_info, const VkBuffer buffer, VkImage image, const uint32_t width, const uint32_t height);
-VKSDEF void vks_generate_mipmaps (const vks_command_info* cmd_info, VkImage image, const VkFormat imageFormat, const int32_t texWidth, const int32_t texHeight, const uint32_t mipLevels);
-
-/* VKSDEF void vulkan_create_surface(); */
-/* VKSDEF void vulkan_pick_physical_device(); */
-/* VKSDEF void vulkan_create_logical_device(); */
-/* VKSDEF void vulkan_create_swap_chain(); */
-/* VKSDEF void vulkan_create_image_views(); */
+VKSDEF void vks_create_vulkan_context (vks_context *vk, VkQueue *graphics_and_compute_queue, VkQueue *present_queue);
+VKSDEF void vks_create_buffer (const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer);
+VKSDEF void vks_create_image (const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image);
+VKSDEF void vks_transition_image_layout (const vks_transition_image_layout_info *info);
+VKSDEF void vks_copy_buffer (const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size);
+VKSDEF void vks_copy_buffer_to_image (const vks_command_info* cmd_info, const VkBuffer buffer, VkImage image, const uint32_t width, const uint32_t height);
+VKSDEF void vks_generate_mipmaps (const vks_command_info* cmd_info, VkImage image, const VkFormat imageFormat, const int32_t texWidth, const int32_t texHeight, const uint32_t mipLevels);
+VKSDEF VkImageView vks_create_image_view (const vks_context vk, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels);
+
/* VKSDEF void vulkan_create_descriptor_set_layout(); */
/* VKSDEF void vulkan_create_graphics_pipeline(); */
/* VKSDEF void vulkan_create_command_pool(); */
@@ -265,9 +261,9 @@ VKSDEF void vks_generate_mipmaps (const vks_command_info* cmd_info,
/* Vks helpers */
-bool
-vks_check_validation_layer_support(const char* const validation_layers[],
- uint32_t validation_layer_count)
+static bool
+_vks_check_validation_layer_support(const char* const validation_layers[],
+ uint32_t validation_layer_count)
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
@@ -288,10 +284,10 @@ vks_check_validation_layer_support(const char* const validation_layers[],
return layerFound;
}
-uint32_t
-find_memory_type(const vks_context vk,
- const uint32_t typeFilter,
- const VkMemoryPropertyFlags properties)
+static uint32_t
+_find_memory_type(const vks_context vk,
+ const uint32_t typeFilter,
+ const VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties mem_properties;
vkGetPhysicalDeviceMemoryProperties(vk.physical_device, &mem_properties);
@@ -308,8 +304,8 @@ find_memory_type(const vks_context vk,
return 9999;
}
-VkCommandBuffer
-begin_single_time_commands(const vks_command_info *info)
+static VkCommandBuffer
+_vks_begin_single_time_commands(const vks_command_info *info)
{
VkCommandBufferAllocateInfo allocInfo = {0};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@@ -328,9 +324,8 @@ begin_single_time_commands(const vks_command_info *info)
return commandBuffer;
}
-
-void
-end_single_time_commands(const vks_command_info *info, VkCommandBuffer command_buffer)
+static void
+_vks_end_single_time_commands(const vks_command_info *info, VkCommandBuffer command_buffer)
{
VK_CHECK(vkEndCommandBuffer(command_buffer));
@@ -345,132 +340,729 @@ end_single_time_commands(const vks_command_info *info, VkCommandBuffer command_b
vkFreeCommandBuffers(info->vk.device, info->pool, 1, &command_buffer);
}
-int
-has_stencil_component(VkFormat format)
+static int
+_has_stencil_component(VkFormat format)
+{
+ return format == VK_FORMAT_D32_SFLOAT_S8_UINT ||
+ format == VK_FORMAT_D24_UNORM_S8_UINT;
+}
+
+static VkInstance
+_vks_create_instance(bool validation_layers_toggle,
+ const char* const validation_layers[],
+ uint32_t validation_layer_count,
+ SDL_Window* window)
+{
+ if (validation_layers_toggle &&
+ !_vks_check_validation_layer_support(validation_layers,
+ validation_layer_count)) {
+ vk_log(VK_ERROR, "validation layers requested, but not available!\n");
+ abort();
+ }
+
+ uint32_t instanceVersion;
+ VkResult result = vkEnumerateInstanceVersion(&instanceVersion);
+ if (result == VK_SUCCESS) {
+ if (instanceVersion < VK_MAKE_API_VERSION(0, 1, 3, 0)) {
+ vk_log(VK_ERROR, "Vulkan version 1.3 or greater required!\n");
+ exit(1);
+ }
+ vk_log(VK_INFO,
+ "Vulkan version found (%d) %d.%d.%d\n",
+ VK_API_VERSION_VARIANT(instanceVersion),
+ VK_API_VERSION_MAJOR(instanceVersion),
+ VK_API_VERSION_MINOR(instanceVersion),
+ VK_API_VERSION_PATCH(instanceVersion));
+ } else {
+ vk_log(VK_ERROR,
+ "Failed to retrieve vulkan version, is vulkan supported in this "
+ "system?\n");
+ exit(1);
+ }
+
+ // Load Vulkan and create instance
+ VkApplicationInfo appInfo = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pApplicationName = "Vulkan Application",
+ .applicationVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
+ .pEngineName = NULL,
+ .engineVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
+ .apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
+ };
+
+ uint32_t sdlExtensionCount = 0;
+
+ if (SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, NULL) ==
+ SDL_FALSE) {
+ vk_log(VK_ERROR,
+ "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
+ SDL_GetError());
+ abort();
+ }
+
+ // make space for debug extenetion
+ if (validation_layers_toggle) {
+ sdlExtensionCount++;
+ }
+
+ const char* sdlExtensions[sdlExtensionCount];
+
+ if (SDL_Vulkan_GetInstanceExtensions(
+ window, &sdlExtensionCount, sdlExtensions) == SDL_FALSE) {
+ vk_log(VK_ERROR,
+ "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
+ SDL_GetError());
+ abort();
+ }
+
+ // add debug extenetion
+ if (validation_layers_toggle) {
+ sdlExtensions[sdlExtensionCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ }
+
+ vk_log(VK_INFO, "The sdl extensions:\n");
+ for (uint32_t i = 0; i < sdlExtensionCount; i++) {
+ vk_log(VK_INFO, "\t%s\n", sdlExtensions[i]);
+ }
+
+ VkInstanceCreateInfo createInfo = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pApplicationInfo = &appInfo,
+ .enabledExtensionCount = sdlExtensionCount,
+ .ppEnabledExtensionNames = sdlExtensions,
+ .enabledLayerCount = 0,
+ };
+
+ if (validation_layers_toggle) {
+ createInfo.enabledLayerCount = validation_layer_count;
+ createInfo.ppEnabledLayerNames = validation_layers;
+ }
+
+ VkInstance instance;
+
+ if (vkCreateInstance(&createInfo, NULL, &instance) != VK_SUCCESS) {
+ vk_log(VK_ERROR, "Can't start vulkan instance\n");
+ }
+ vk_log(VK_INFO, "Vulkan instance created\n");
+
+ return instance;
+}
+
+static bool
+_vulkan_check_device_extension_support(VkPhysicalDevice device)
+{
+ uint32_t extensionCount;
+ vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
+
+ VkExtensionProperties availableExtensions[extensionCount];
+ vkEnumerateDeviceExtensionProperties(
+ device, NULL, &extensionCount, availableExtensions);
+
+ uint32_t flag = 0;
+
+ for (uint32_t i = 0; i < deviceExtensionCount; i++) {
+ for (uint32_t j = 0; j < extensionCount; j++) {
+ if (strcmp(device_extensions[i], availableExtensions[j].extensionName) ==
+ 0) {
+ flag++;
+ break;
+ }
+ }
+ }
+
+ return flag == deviceExtensionCount;
+}
+
+typedef struct _QueueFamilyIndices
+{
+ uint32_t graphicsAndComputeFamily;
+ bool graphicsFlag;
+ uint32_t presentFamily;
+ bool presentFlag;
+} _QueueFamilyIndices;
+
+static bool
+_vulkan_queue_family_check_flags(_QueueFamilyIndices x)
+{
+ return x.graphicsFlag && x.presentFlag;
+}
+
+static _QueueFamilyIndices
+_vulkan_find_queue_families(vks_context* vk, VkPhysicalDevice device)
+{
+ _QueueFamilyIndices indices;
+ indices.graphicsFlag = false;
+ indices.presentFlag = false;
+
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, NULL);
+
+ VkQueueFamilyProperties queueFamilies[queueFamilyCount];
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ device, &queueFamilyCount, queueFamilies);
+
+ for (uint32_t i = 0; i < queueFamilyCount; i++) {
+ if ((queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) &&
+ (queueFamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT)) {
+ indices.graphicsAndComputeFamily = i;
+ indices.graphicsFlag = true;
+ }
+
+ VkBool32 presentSupport = false;
+ vkGetPhysicalDeviceSurfaceSupportKHR(
+ device, i, vk->surface, &presentSupport);
+ if (presentSupport) {
+ indices.presentFamily = i;
+ indices.presentFlag = true;
+ }
+
+ if (_vulkan_queue_family_check_flags(indices))
+ break;
+ }
+
+ return indices;
+}
+
+typedef struct _swap_chain_support_details
+{
+ VkSurfaceCapabilitiesKHR capabilities;
+ VkSurfaceFormatKHR formats[100];
+ uint32_t formatCount;
+ VkPresentModeKHR presentModes[100];
+ uint32_t presentModeCount;
+} _swap_chain_support_details;
+
+static _swap_chain_support_details
+_query_swap_chain_support(const vks_context* vk, VkPhysicalDevice device)
+{
+ // TODO Make SwapChainSupportDetails malloc it;s arrays and free it after it
+ // is used.
+ _swap_chain_support_details details;
+
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ device, vk->surface, &details.capabilities);
+
+ vkGetPhysicalDeviceSurfaceFormatsKHR(
+ device, vk->surface, &details.formatCount, NULL);
+
+ if (details.formatCount != 0) {
+ // todo alloc format arrray
+ vkGetPhysicalDeviceSurfaceFormatsKHR(
+ device, vk->surface, &details.formatCount, details.formats);
+ }
+
+ vkGetPhysicalDeviceSurfacePresentModesKHR(
+ device, vk->surface, &details.presentModeCount, NULL);
+
+ if (details.presentModeCount != 0) {
+ // todo alloc presentModes array
+ vkGetPhysicalDeviceSurfacePresentModesKHR(
+ device, vk->surface, &details.presentModeCount, details.presentModes);
+ }
+
+ return details;
+}
+
+static bool
+_vulkan_is_device_suitable(vks_context* vk, VkPhysicalDevice device)
+{
+ _QueueFamilyIndices indices = _vulkan_find_queue_families(vk, device);
+ bool extensionsSupported = _vulkan_check_device_extension_support(device);
+
+ bool swapChainAdequate = false;
+ if (extensionsSupported) {
+ _swap_chain_support_details swapChainSupport =
+ _query_swap_chain_support(vk, device);
+ swapChainAdequate = !(swapChainSupport.formatCount == 0) &&
+ !(swapChainSupport.presentModeCount == 0);
+ }
+
+ VkPhysicalDeviceFeatures supportedFeatures;
+ vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
+
+ return _vulkan_queue_family_check_flags(indices) && extensionsSupported &&
+ swapChainAdequate && supportedFeatures.samplerAnisotropy;
+}
+
+static VkSampleCountFlagBits
+_get_max_usable_sample_count(vks_context* vk)
+{
+ VkPhysicalDeviceProperties physicalDeviceProperties;
+ vkGetPhysicalDeviceProperties(vk->physical_device, &physicalDeviceProperties);
+
+ VkSampleCountFlags counts =
+ physicalDeviceProperties.limits.framebufferColorSampleCounts &
+ physicalDeviceProperties.limits.framebufferDepthSampleCounts;
+ if (counts & VK_SAMPLE_COUNT_64_BIT) {
+ return VK_SAMPLE_COUNT_64_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_32_BIT) {
+ return VK_SAMPLE_COUNT_32_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_16_BIT) {
+ return VK_SAMPLE_COUNT_16_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_8_BIT) {
+ return VK_SAMPLE_COUNT_8_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_4_BIT) {
+ return VK_SAMPLE_COUNT_4_BIT;
+ }
+ if (counts & VK_SAMPLE_COUNT_2_BIT) {
+ return VK_SAMPLE_COUNT_2_BIT;
+ }
+
+ return VK_SAMPLE_COUNT_1_BIT;
+}
+
+static void
+_vulkan_pick_physical_device(vks_context* vk)
+{
+ uint32_t deviceCount = 0;
+ vkEnumeratePhysicalDevices(vk->instance, &deviceCount, NULL);
+ if (deviceCount == 0) {
+ vk_log(VK_INFO, "failed to find GPUs with Vulkan support!\n");
+ }
+
+ VkPhysicalDevice devices[deviceCount];
+ vkEnumeratePhysicalDevices(vk->instance, &deviceCount, devices);
+
+ for (uint32_t i = 0; i < deviceCount; i++) {
+ if (_vulkan_is_device_suitable(vk, devices[i])) {
+ vk->physical_device = devices[i];
+ vk->msaa_samples = _get_max_usable_sample_count(vk);
+ break;
+ }
+ }
+
+ if (vk->physical_device == VK_NULL_HANDLE) {
+ vk_log(VK_ERROR, "failed to find a suitable GPU!\n");
+ }
+
+ VkPhysicalDeviceProperties deviceProperties;
+ vkGetPhysicalDeviceProperties(vk->physical_device, &deviceProperties);
+ vk_log(
+ VK_INFO, "Picked [%s] physical device.\n", deviceProperties.deviceName);
+
+ uint32_t extensionCount = 0;
+ vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
+ VkExtensionProperties extensions[extensionCount];
+ VkResult result =
+ vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions);
+
+ vk_log(VK_INFO, "Vulkan enabled extensions:\n");
+ for (uint32_t i = 0; i < extensionCount; i++) {
+ vk_log(VK_INFO, "\t%s\n", extensions[i].extensionName);
+ }
+}
+
+static void
+_vulkan_create_logical_device(vks_context* vk,
+ VkQueue* graphics_and_compute_queue,
+ VkQueue* present_queue)
+{
+ _QueueFamilyIndices indices =
+ _vulkan_find_queue_families(vk, vk->physical_device);
+
+ // TODO CREATE MULPILE QUEUES
+ // https://vulkan-tutorial.com/en/Drawing_a_triangle/Presentation/Window_surface#page_Creating-the-presentation-queue
+
+ VkDeviceQueueCreateInfo queueCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ .queueFamilyIndex = indices.graphicsAndComputeFamily,
+ .queueCount = 1,
+ };
+
+ float queuePriority = 1.0f;
+ queueCreateInfo.pQueuePriorities = &queuePriority;
+
+ VkPhysicalDeviceFeatures deviceFeatures = { 0 };
+ vkGetPhysicalDeviceFeatures(vk->physical_device, &deviceFeatures);
+ deviceFeatures.samplerAnisotropy = VK_TRUE;
+ // deviceFeatures.sampleRateShading = VK_TRUE;
+#ifndef VKDEBUG
+ /* Disable robust buffer access when building without debug */
+ deviceFeatures.robustBufferAccess = VK_FALSE;
+#endif
+
+ VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamic_rendering_feature = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR,
+ .dynamicRendering = VK_TRUE,
+ };
+
+ VkDeviceCreateInfo createInfo = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .pQueueCreateInfos = &queueCreateInfo,
+ .queueCreateInfoCount = 1,
+ .pNext = &dynamic_rendering_feature,
+ .pEnabledFeatures = &deviceFeatures,
+ .enabledExtensionCount = deviceExtensionCount,
+ .ppEnabledExtensionNames = device_extensions,
+ .enabledLayerCount = 0,
+ };
+
+ if (vkCreateDevice(vk->physical_device, &createInfo, NULL, &vk->device) !=
+ VK_SUCCESS) {
+ vk_log(VK_ERROR, "failed to create logical device!\n");
+ }
+ vk_log(VK_INFO, "Vulkan logical device created\n");
+
+ vkGetDeviceQueue(vk->device,
+ indices.graphicsAndComputeFamily,
+ 0,
+ graphics_and_compute_queue);
+ vkGetDeviceQueue(vk->device, indices.presentFamily, 0, present_queue);
+}
+
+static VkSurfaceFormatKHR
+_chooseSwapSurfaceFormat(const VkSurfaceFormatKHR* availableFormats,
+ uint32_t formatCount)
+{
+ for (uint32_t i = 0; i < formatCount; i++) {
+ if (availableFormats[i].format == VK_FORMAT_B8G8R8A8_SRGB &&
+ availableFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+ return availableFormats[i];
+ }
+ }
+
+ // if it fails pick the first one
+ return availableFormats[0];
+}
+
+static VkPresentModeKHR
+_chooseSwapPresentMode(const VkPresentModeKHR* presentModes,
+ uint32_t presentModeCount)
{
- return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
+ for (uint32_t i = 0; i < presentModeCount; i++) {
+ if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
+ return presentModes[i];
+ }
+ }
+
+ // if it fails pick the the FIFO one
+ return VK_PRESENT_MODE_FIFO_KHR;
+}
+
+static VkExtent2D
+_chooseSwapExtent(const vks_context* vk,
+ const VkSurfaceCapabilitiesKHR* capabilities)
+{
+ if (capabilities->currentExtent.width != UINT32_MAX) {
+ return capabilities->currentExtent;
+ } else {
+ int width, height;
+ SDL_GetWindowSize(vk->window, &width, &height);
+
+ VkExtent2D actualExtent;
+ actualExtent.width = (uint32_t)width;
+ actualExtent.height = (uint32_t)height;
+
+ // Manual implementation of std::clamp since it is not available in C
+ actualExtent.width =
+ (actualExtent.width < capabilities->minImageExtent.width)
+ ? capabilities->minImageExtent.width
+ : (actualExtent.width > capabilities->maxImageExtent.width)
+ ? capabilities->maxImageExtent.width
+ : actualExtent.width;
+
+ actualExtent.height =
+ (actualExtent.height < capabilities->minImageExtent.height)
+ ? capabilities->minImageExtent.height
+ : (actualExtent.height > capabilities->maxImageExtent.height)
+ ? capabilities->maxImageExtent.height
+ : actualExtent.height;
+
+ return actualExtent;
+ }
+}
+
+static void bla() {printf("blah\n");}
+
+VKSDEF void
+_vulkan_create_swap_chain(vks_context* vk)
+{
+ _swap_chain_support_details swapChainSupport =
+ _query_swap_chain_support(vk, vk->physical_device);
+
+ VkSurfaceFormatKHR surfaceFormat = _chooseSwapSurfaceFormat(
+ swapChainSupport.formats, swapChainSupport.formatCount);
+ VkPresentModeKHR presentMode = _chooseSwapPresentMode(
+ swapChainSupport.presentModes, swapChainSupport.presentModeCount);
+ VkExtent2D extent = _chooseSwapExtent(vk, &swapChainSupport.capabilities);
+
+ uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
+
+ if (swapChainSupport.capabilities.maxImageCount > 0 &&
+ imageCount > swapChainSupport.capabilities.maxImageCount) {
+ imageCount = swapChainSupport.capabilities.maxImageCount;
+ }
+
+ VkSwapchainCreateInfoKHR createInfo = {
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ .surface = vk->surface,
+ .minImageCount = imageCount,
+ .imageFormat = surfaceFormat.format,
+ .imageColorSpace = surfaceFormat.colorSpace,
+ .imageExtent = extent,
+ .imageArrayLayers = 1,
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ };
+
+ _QueueFamilyIndices indices =
+ _vulkan_find_queue_families(vk, vk->physical_device);
+
+ uint32_t queueFamilyIndices[] = { indices.graphicsAndComputeFamily,
+ indices.presentFamily };
+
+ if (indices.graphicsAndComputeFamily != indices.presentFamily) {
+ createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ createInfo.queueFamilyIndexCount = 2;
+ createInfo.pQueueFamilyIndices = queueFamilyIndices;
+ } else {
+ createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ createInfo.queueFamilyIndexCount = 0; // Optional
+ createInfo.pQueueFamilyIndices = NULL; // Optional
+ }
+
+ createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
+ createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ createInfo.presentMode = presentMode;
+ createInfo.clipped = VK_TRUE;
+ createInfo.oldSwapchain = VK_NULL_HANDLE;
+
+ VK_CHECK(
+ vkCreateSwapchainKHR(vk->device, &createInfo, NULL, &vk->swapchain.handle));
+ /* if (result != VK_SUCCESS) { */
+ /* vk_log(VK_ERROR, "ERROR: failed to create swap chain! %s\n",
+ * string_VkResult(result)); */
+ /* } */
+
+ VK_CHECK(vkGetSwapchainImagesKHR(
+ vk->device, vk->swapchain.handle, &vk->swapchain.image_count, NULL));
+ // vk_log(VK_INFO, "vk_swap_chain_images count: %d\n",
+ // vk->swapchain.image_count);
+ // todo alloc space for images
+ VK_CHECK(vkGetSwapchainImagesKHR(vk->device,
+ vk->swapchain.handle,
+ &vk->swapchain.image_count,
+ vk->swapchain.images));
+
+ vk->swapchain.image_format = surfaceFormat.format;
+ vk->swapchain.extent = extent;
+
+ vk_log(VK_INFO, "Vulkan swapchain created!\n");
+
+ for (size_t i = 0; i < vk->swapchain.image_count; i++) {
+ vk->swapchain.image_views[i] =
+ vks_create_image_view(*vk,
+ vk->swapchain.images[i],
+ vk->swapchain.image_format,
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 1);
+ }
}
/* Vks API implementation */
+
+VKSDEF void
+vks_create_vulkan_context(vks_context* vk,
+ VkQueue* graphics_and_compute_queue,
+ VkQueue* present_queue)
+{
+ /* Create vulkan instance */
+ vk->instance = _vks_create_instance(enable_validation_layers,
+ validation_layers,
+ validation_layer_count,
+ vk->window);
+
+ /* Create render surface */
+ if (SDL_Vulkan_CreateSurface(vk->window, vk->instance, &vk->surface) ==
+ SDL_FALSE) {
+ vk_log(VK_ERROR, "Failed to create surface\n");
+ } else {
+ vk_log(VK_INFO, "Vulkan surface created\n");
+ }
+
+ /* Pick physical device */
+ _vulkan_pick_physical_device(vk);
+
+ /* Create logical device and get queues */
+ /* TODO: Create vks_get_queue helpers?? */
+ _vulkan_create_logical_device(vk, graphics_and_compute_queue, present_queue);
+
+ /* Create swapchain */
+ /* TODO: Make swapchain api */
+ _vulkan_create_swap_chain(vk);
+}
+
+VKSDEF VkImageView
+vks_create_image_view(const vks_context vk,
+ VkImage image,
+ VkFormat format,
+ VkImageAspectFlags aspectFlags,
+ uint32_t mipLevels)
+{
+ VkImageViewCreateInfo viewInfo = { 0 };
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = image;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = format;
+ viewInfo.subresourceRange.aspectMask = aspectFlags;
+ viewInfo.subresourceRange.baseMipLevel = 0;
+ viewInfo.subresourceRange.levelCount = mipLevels;
+ viewInfo.subresourceRange.baseArrayLayer = 0;
+ viewInfo.subresourceRange.layerCount = 1;
+
+ VkImageView imageView;
+ VK_CHECK(vkCreateImageView(vk.device, &viewInfo, NULL, &imageView));
+
+ return imageView;
+}
+
VKSDEF void
vks_generate_mipmaps(const vks_command_info* cmd_info,
- VkImage image,
- const VkFormat imageFormat,
- const int32_t texWidth,
- const int32_t texHeight,
- const uint32_t mipLevels)
+ VkImage image,
+ const VkFormat imageFormat,
+ const int32_t texWidth,
+ const int32_t texHeight,
+ const uint32_t mipLevels)
{
- VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info);
+ VkCommandBuffer command_buffer = _vks_begin_single_time_commands(cmd_info);
- VkImageMemoryBarrier barrier = {0};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.image = image;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ VkImageMemoryBarrier barrier = { 0 };
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = image;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
- barrier.subresourceRange.layerCount = 1;
- barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.layerCount = 1;
+ barrier.subresourceRange.levelCount = 1;
- int32_t mipWidth = texWidth;
+ int32_t mipWidth = texWidth;
int32_t mipHeight = texHeight;
for (uint32_t i = 1; i < mipLevels; i++) {
barrier.subresourceRange.baseMipLevel = i - 1;
- barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
+ vkCmdPipelineBarrier(command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 1,
&barrier);
- VkImageBlit blit = {0};
- blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 };
- blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 };
- blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- blit.srcSubresource.mipLevel = i - 1;
+ VkImageBlit blit = { 0 };
+ blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 };
+ blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 };
+ blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.srcSubresource.mipLevel = i - 1;
blit.srcSubresource.baseArrayLayer = 0;
- blit.srcSubresource.layerCount = 1;
- blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 };
- blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
- blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- blit.dstSubresource.mipLevel = i;
+ blit.srcSubresource.layerCount = 1;
+ blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 };
+ blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1,
+ mipHeight > 1 ? mipHeight / 2 : 1,
+ 1 };
+ blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.dstSubresource.mipLevel = i;
blit.dstSubresource.baseArrayLayer = 0;
- blit.dstSubresource.layerCount = 1;
-
- vkCmdBlitImage(command_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
+ blit.dstSubresource.layerCount = 1;
+
+ vkCmdBlitImage(command_buffer,
+ image,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1,
+ &blit,
VK_FILTER_LINEAR);
- barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0,
- NULL, 1, &barrier);
+ vkCmdPipelineBarrier(command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 1,
+ &barrier);
- if (mipWidth > 1) mipWidth /= 2;
- if (mipHeight > 1) mipHeight /= 2;
+ if (mipWidth > 1)
+ mipWidth /= 2;
+ if (mipHeight > 1)
+ mipHeight /= 2;
}
- end_single_time_commands(cmd_info, command_buffer);
+ _vks_end_single_time_commands(cmd_info, command_buffer);
}
VKSDEF void
vks_copy_buffer_to_image(const vks_command_info* cmd_info,
- const VkBuffer buffer,
- VkImage image,
- const uint32_t width,
- const uint32_t height)
+ const VkBuffer buffer,
+ VkImage image,
+ const uint32_t width,
+ const uint32_t height)
{
- VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info);
+ VkCommandBuffer command_buffer = _vks_begin_single_time_commands(cmd_info);
- VkBufferImageCopy region = {0};
- region.bufferOffset = 0;
- region.bufferRowLength = 0;
+ VkBufferImageCopy region = { 0 };
+ region.bufferOffset = 0;
+ region.bufferRowLength = 0;
region.bufferImageHeight = 0;
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.mipLevel = 0;
+ region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
- region.imageSubresource.layerCount = 1;
+ region.imageSubresource.layerCount = 1;
- region.imageOffset = (VkOffset3D){0, 0, 0};
- region.imageExtent = (VkExtent3D){width, height, 1};
+ region.imageOffset = (VkOffset3D){ 0, 0, 0 };
+ region.imageExtent = (VkExtent3D){ width, height, 1 };
vkCmdCopyBufferToImage(command_buffer,
buffer,
image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
- &region
- );
+ &region);
- end_single_time_commands(cmd_info, command_buffer);
+ _vks_end_single_time_commands(cmd_info, command_buffer);
}
VKSDEF void
-vks_copy_buffer(const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size)
+vks_copy_buffer(const vks_command_info* cmd_info,
+ const VkBuffer src_buffer,
+ VkBuffer dst_buffer,
+ const VkDeviceSize size)
{
- VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info);
+ VkCommandBuffer command_buffer = _vks_begin_single_time_commands(cmd_info);
- VkBufferCopy copy_region = {0};
- copy_region.srcOffset = 0; // Optional
- copy_region.dstOffset = 0; // Optional
- copy_region.size = size;
+ VkBufferCopy copy_region = { 0 };
+ copy_region.srcOffset = 0; // Optional
+ copy_region.dstOffset = 0; // Optional
+ copy_region.size = size;
vkCmdCopyBuffer(command_buffer, src_buffer, dst_buffer, 1, &copy_region);
- end_single_time_commands(cmd_info, command_buffer);
+ _vks_end_single_time_commands(cmd_info, command_buffer);
}
VKSDEF void
-vks_transition_image_layout(const vks_transition_image_layout_info *info)
+vks_transition_image_layout(const vks_transition_image_layout_info* info)
{
- VkCommandBuffer command_buffer = begin_single_time_commands(&info->cmd_info);
+ VkCommandBuffer command_buffer = _vks_begin_single_time_commands(&info->cmd_info);
VkImageMemoryBarrier barrier = { 0 };
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -486,7 +1078,7 @@ vks_transition_image_layout(const vks_transition_image_layout_info *info)
if (info->newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- if (has_stencil_component(info->format)) {
+ if (_has_stencil_component(info->format)) {
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
} else {
@@ -509,7 +1101,7 @@ vks_transition_image_layout(const vks_transition_image_layout_info *info)
1,
&barrier);
- end_single_time_commands(&info->cmd_info, command_buffer);
+ _vks_end_single_time_commands(&info->cmd_info, command_buffer);
}
VKSDEF void
@@ -548,7 +1140,7 @@ vks_create_image(const vks_context vk,
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex =
- find_memory_type(vk, memRequirements.memoryTypeBits, properties);
+ _find_memory_type(vk, memRequirements.memoryTypeBits, properties);
// TODO: group allocations etc... (allocations limited by hardware)
VK_CHECK(vkAllocateMemory(vk.device, &allocInfo, NULL, &image->memory));
@@ -578,112 +1170,10 @@ vks_create_buffer(const vks_context vk,
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = mem_requirements.size;
allocInfo.memoryTypeIndex =
- find_memory_type(vk, mem_requirements.memoryTypeBits, properties);
+ _find_memory_type(vk, mem_requirements.memoryTypeBits, properties);
// TODO: group allocations etc... (allocations limited by hardware)
VK_CHECK(vkAllocateMemory(vk.device, &allocInfo, NULL, &buffer->memory));
VK_CHECK(vkBindBufferMemory(vk.device, buffer->handle, buffer->memory, 0));
}
-
-VKSDEF VkInstance
-vks_create_instance(bool validation_layers_toggle,
- const char* const validation_layers[],
- uint32_t validation_layer_count,
- SDL_Window* window)
-{
- if (validation_layers_toggle &&
- !vks_check_validation_layer_support(validation_layers,
- validation_layer_count)) {
- vk_log(VK_ERROR, "validation layers requested, but not available!\n");
- abort();
- }
-
- uint32_t instanceVersion;
- VkResult result = vkEnumerateInstanceVersion(&instanceVersion);
- if (result == VK_SUCCESS) {
- if (instanceVersion < VK_MAKE_API_VERSION(0, 1, 3, 0)) {
- vk_log(VK_ERROR, "Vulkan version 1.3 or greater required!\n");
- exit(1);
- }
- vk_log(VK_INFO,
- "Vulkan version found (%d) %d.%d.%d\n",
- VK_API_VERSION_VARIANT(instanceVersion),
- VK_API_VERSION_MAJOR(instanceVersion),
- VK_API_VERSION_MINOR(instanceVersion),
- VK_API_VERSION_PATCH(instanceVersion));
- } else {
- vk_log(VK_ERROR,
- "Failed to retrieve vulkan version, is vulkan supported in this "
- "system?\n");
- exit(1);
- }
-
- // Load Vulkan and create instance
- VkApplicationInfo appInfo = {
- .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
- .pApplicationName = "Vulkan Application",
- .applicationVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
- .pEngineName = NULL,
- .engineVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
- .apiVersion = VK_MAKE_API_VERSION(0, 1, 3, 0),
- };
-
- uint32_t sdlExtensionCount = 0;
-
- if (SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, NULL) ==
- SDL_FALSE) {
- vk_log(VK_ERROR,
- "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
- SDL_GetError());
- abort();
- }
-
- // make space for debug extenetion
- if (validation_layers_toggle) {
- sdlExtensionCount++;
- }
-
- const char* sdlExtensions[sdlExtensionCount];
-
- if (SDL_Vulkan_GetInstanceExtensions(
- window, &sdlExtensionCount, sdlExtensions) == SDL_FALSE) {
- vk_log(VK_ERROR,
- "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
- SDL_GetError());
- abort();
- }
-
- // add debug extenetion
- if (validation_layers_toggle) {
- sdlExtensions[sdlExtensionCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- }
-
- vk_log(VK_INFO, "The sdl extensions:\n");
- for (uint32_t i = 0; i < sdlExtensionCount; i++) {
- vk_log(VK_INFO, "\t%s\n", sdlExtensions[i]);
- }
-
- VkInstanceCreateInfo createInfo = {
- .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- .pApplicationInfo = &appInfo,
- .enabledExtensionCount = sdlExtensionCount,
- .ppEnabledExtensionNames = sdlExtensions,
- .enabledLayerCount = 0,
- };
-
- if (validation_layers_toggle) {
- createInfo.enabledLayerCount = validation_layer_count;
- createInfo.ppEnabledLayerNames = validation_layers;
- }
-
- VkInstance instance;
-
- if (vkCreateInstance(&createInfo, NULL, &instance) != VK_SUCCESS) {
- vk_log(VK_ERROR, "Can't start vulkan instance\n");
- }
- vk_log(VK_INFO, "Vulkan instance created\n");
-
- return instance;
-}
-
#endif /* VKSETUP_IMPLEMENTATION */