diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/b.h | 9 | ||||
-rw-r--r-- | src/render.c | 629 | ||||
-rw-r--r-- | src/state.h | 76 | ||||
-rw-r--r-- | src/vksetup.h | 207 |
4 files changed, 596 insertions, 325 deletions
@@ -49,6 +49,7 @@ typedef enum { B_INFO, + B_CHANGE, B_WARNING, B_ERROR, } B_Log_Level; @@ -485,6 +486,9 @@ void b_log(B_Log_Level level, const char *fmt, ...) case B_INFO: fprintf(stderr, "[INFO] "); break; + case B_CHANGE: + fprintf(stderr, "[CHANGE] "); + break; case B_WARNING: fprintf(stderr, "[WARNING] "); break; @@ -723,7 +727,10 @@ int b_needs_rebuild(const char *output_path, const char **input_paths, size_t in } int input_path_time = statbuf.st_mtime; // NOTE: if even a single input_path is fresher than output_path that's 100% rebuild - if (input_path_time > output_path_time) return 1; + if (input_path_time > output_path_time) { + b_log(B_CHANGE, "%s", input_path); + return 1; + } } return 0; diff --git a/src/render.c b/src/render.c index 0f80d3a..2ab38e1 100644 --- a/src/render.c +++ b/src/render.c @@ -1,5 +1,3 @@ - -#include <emmintrin.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> @@ -22,9 +20,6 @@ #define STB_IMAGE_IMPLEMENTATION #include "../lib/stb_image.h" -#define VKSETUP_IMPLEMENTATION -#include "vksetup.h" - #define FAST_OBJ_IMPLEMENTATION #include "../lib/fast_obj.h" @@ -38,6 +33,8 @@ #define MODEL_PATH "assets/human.obj" #define TEXTURE_PATH "assets/viking_room.png" +#define PARTICLE_COUNT 2048 + void load_model_obj(); void load_model_gltf(); // embedded clgm library @@ -106,7 +103,9 @@ static int resizing_event_watcher(void *data, SDL_Event *event) { return 0; } -void move_towards(vec3 position, vec3 front, float step) { +void +move_towards(vec3 position, vec3 front, float step) +{ // Calculate the direction vector from position to front float direction[3] = { front[0] - position[0], @@ -131,13 +130,13 @@ init() return false; } - s.sdl_window = SDL_CreateWindow("Vulkanizater", + s.vk.window = SDL_CreateWindow("Vulkanizater", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, s.window_w, s.window_h, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); - if (s.sdl_window == NULL) { + if (s.vk.window == NULL) { vk_log(VK_INFO, "Window could not be created! SDL_Error: %s\n", SDL_GetError()); return false; } @@ -150,16 +149,16 @@ init() void closeSDL() { - SDL_DestroyWindow(s.sdl_window); - s.sdl_window = NULL; + SDL_DestroyWindow(s.vk.window); + s.vk.window = NULL; SDL_Quit(); } static VKAPI_ATTR VkBool32 VKAPI_CALL -debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, +debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData) + void* pUserData) { (void) messageSeverity; (void) messageType; @@ -181,10 +180,10 @@ vulkan_setup_debug_messenger() // TODO: func pointers returned are NULL - s.pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkCreateDebugUtilsMessengerEXT"); - s.pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkDestroyDebugUtilsMessengerEXT"); + s.pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk.instance, "vkCreateDebugUtilsMessengerEXT"); + s.pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk.instance, "vkDestroyDebugUtilsMessengerEXT"); - VkResult result = s.pfnCreateDebugUtilsMessengerEXT(s.vk_instance, &createInfo, NULL, &s.vk_debug_messenger); + VkResult result = s.pfnCreateDebugUtilsMessengerEXT(s.vk.instance, &createInfo, NULL, &s.vk_debug_messenger); if (result != VK_SUCCESS) { vk_log(VK_WARN, "failed to set up debug messenger!\n"); } else { @@ -199,7 +198,7 @@ chooseSwapExtent(const VkSurfaceCapabilitiesKHR * capabilities) return capabilities->currentExtent; } else { int width, height; - SDL_GetWindowSize(s.sdl_window, &width, &height); + SDL_GetWindowSize(s.vk.window, &width, &height); VkExtent2D actualExtent; actualExtent.width = (uint32_t) width; @@ -259,27 +258,27 @@ 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); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, s.vk.surface, &details.capabilities); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk_surface, &details.formatCount, NULL); + 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); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, s.vk.surface, &details.formatCount, details.formats); } - vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk_surface, &details.presentModeCount, NULL); + 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); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, s.vk.surface, &details.presentModeCount, details.presentModes); } return details; } typedef struct QueueFamilyIndices { - uint32_t graphicsFamily; + uint32_t graphicsAndComputeFamily; bool graphicsFlag; uint32_t presentFamily; bool presentFlag; @@ -303,13 +302,13 @@ QueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice device) { vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies); for (uint32_t i = 0; i < queueFamilyCount; i++) { - if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = 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, s.vk_surface, &presentSupport); + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, s.vk.surface, &presentSupport); if (presentSupport) { indices.presentFamily = i; indices.presentFlag = true; @@ -366,7 +365,7 @@ vulkan_is_device_suitable(VkPhysicalDevice device) VkSampleCountFlagBits getMaxUsableSampleCount() { VkPhysicalDeviceProperties physicalDeviceProperties; - vkGetPhysicalDeviceProperties(s.vk_physical_device, &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; } @@ -383,28 +382,28 @@ void vulkan_pick_physical_device() { uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(s.vk_instance, &deviceCount, NULL); + 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); + 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.vk.physical_device = devices[i]; s.msaa_samples = getMaxUsableSampleCount(); break; } } - if (s.vk_physical_device == VK_NULL_HANDLE) { + 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); + vkGetPhysicalDeviceProperties(s.vk.physical_device, &deviceProperties); vk_log(VK_INFO, "Picked [%s] physical device.\n", deviceProperties.deviceName); uint32_t extensionCount = 0; @@ -422,14 +421,14 @@ vulkan_pick_physical_device() void vulkan_create_logical_device() { - QueueFamilyIndices indices = vulkan_find_queue_families(s.vk_physical_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.graphicsFamily, + .queueFamilyIndex = indices.graphicsAndComputeFamily, .queueCount = 1, }; @@ -437,7 +436,7 @@ vulkan_create_logical_device() queueCreateInfo.pQueuePriorities = &queuePriority; VkPhysicalDeviceFeatures deviceFeatures = {0}; - vkGetPhysicalDeviceFeatures(s.vk_physical_device, &deviceFeatures); + vkGetPhysicalDeviceFeatures(s.vk.physical_device, &deviceFeatures); deviceFeatures.samplerAnisotropy = VK_TRUE; //deviceFeatures.sampleRateShading = VK_TRUE; #ifndef VKDEBUG @@ -461,13 +460,13 @@ vulkan_create_logical_device() .enabledLayerCount = 0, }; - if (vkCreateDevice(s.vk_physical_device, &createInfo, NULL, &s.vk_device) != VK_SUCCESS) { + 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.graphicsFamily, 0, &s.vk_graphics_queue); - vkGetDeviceQueue(s.vk_device, indices.presentFamily, 0, &s.vk_present_queue); + vkGetDeviceQueue(s.vk.device, indices.graphicsAndComputeFamily, 0, &s.vk_graphics_queue); + vkGetDeviceQueue(s.vk.device, indices.presentFamily, 0, &s.vk_present_queue); } void move_relative(vec3 position, vec3 front, float step, int x) { @@ -554,7 +553,7 @@ mouseCallback(SDL_Event *event) void vulkan_create_surface() { - if (SDL_Vulkan_CreateSurface(s.sdl_window, s.vk_instance, &s.vk_surface) == SDL_FALSE) { + 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"); @@ -564,7 +563,7 @@ vulkan_create_surface() void vulkan_create_swap_chain() { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(s.vk_physical_device); + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(s.vk.physical_device); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats, swapChainSupport.formatCount); VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes, swapChainSupport.presentModeCount); @@ -578,7 +577,7 @@ vulkan_create_swap_chain() VkSwapchainCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = s.vk_surface, + .surface = s.vk.surface, .minImageCount = imageCount, .imageFormat = surfaceFormat.format, .imageColorSpace = surfaceFormat.colorSpace, @@ -587,11 +586,11 @@ vulkan_create_swap_chain() .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, }; - QueueFamilyIndices indices = vulkan_find_queue_families(s.vk_physical_device); + QueueFamilyIndices indices = vulkan_find_queue_families(s.vk.physical_device); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; + uint32_t queueFamilyIndices[] = {indices.graphicsAndComputeFamily, indices.presentFamily}; - if (indices.graphicsFamily != indices.presentFamily) { + if (indices.graphicsAndComputeFamily != indices.presentFamily) { createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = 2; createInfo.pQueueFamilyIndices = queueFamilyIndices; @@ -607,18 +606,18 @@ vulkan_create_swap_chain() createInfo.clipped = VK_TRUE; createInfo.oldSwapchain = VK_NULL_HANDLE; - VK_CHECK(vkCreateSwapchainKHR(s.vk_device, &createInfo, NULL, &s.vk_swap_chain)); + 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_swap_chain, &s.vk_swap_chain_image_count, NULL)); - //vk_log(VK_INFO, "vk_swap_chain_images count: %d\n", s.vk_swap_chain_image_count); + 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_swap_chain, &s.vk_swap_chain_image_count, s.vk_swap_chain_images)); + VK_CHECK(vkGetSwapchainImagesKHR(s.vk.device, s.vk.swapchain.handle, &s.vk.swapchain.image_count, s.vk.swapchain.images)); - s.vk_swap_chain_image_format = surfaceFormat.format; - s.vk_swap_chain_extent = extent; + s.vk.swapchain.image_format = surfaceFormat.format; + s.vk.swapchain.extent = extent; vk_log(VK_INFO, "Vulkan swapchain created!\n"); } @@ -639,7 +638,7 @@ create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags viewInfo.subresourceRange.layerCount = 1; VkImageView imageView; - VK_CHECK(vkCreateImageView(s.vk_device, &viewInfo, NULL, &imageView)); + VK_CHECK(vkCreateImageView(s.vk.device, &viewInfo, NULL, &imageView)); return imageView; } @@ -647,8 +646,8 @@ create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags void vulkan_create_image_views() { - for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) { - s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT, 1); + 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"); } @@ -662,7 +661,7 @@ createShaderModule(const char * code, long size) createInfo.pCode = (const uint32_t *)code; VkShaderModule shaderModule; - if (vkCreateShaderModule(s.vk_device, &createInfo, NULL, &shaderModule) != VK_SUCCESS) { + if (vkCreateShaderModule(s.vk.device, &createInfo, NULL, &shaderModule) != VK_SUCCESS) { vk_log(VK_ERROR, "failed to create shader module!\n"); } @@ -725,7 +724,7 @@ uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(s.vk_physical_device, &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) { @@ -758,19 +757,19 @@ createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format imageInfo.samples = numSamples; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK(vkCreateImage(s.vk_device, &imageInfo, NULL, image)); + VK_CHECK(vkCreateImage(s.vk.device, &imageInfo, NULL, image)); VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(s.vk_device, *image, &memRequirements); + vkGetImageMemoryRequirements(s.vk.device, *image, &memRequirements); VkMemoryAllocateInfo allocInfo = {0}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - VK_CHECK(vkAllocateMemory(s.vk_device, &allocInfo, NULL, imageMemory)); + VK_CHECK(vkAllocateMemory(s.vk.device, &allocInfo, NULL, imageMemory)); - vkBindImageMemory(s.vk_device, *image, *imageMemory , 0); + vkBindImageMemory(s.vk.device, *image, *imageMemory , 0); } VkCommandBuffer @@ -783,7 +782,7 @@ beginSingleTimeCommands() allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &commandBuffer)); + VK_CHECK(vkAllocateCommandBuffers(s.vk.device, &allocInfo, &commandBuffer)); VkCommandBufferBeginInfo beginInfo = {0}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -807,7 +806,7 @@ endSingleTimeCommands(VkCommandBuffer commandBuffer) VK_CHECK(vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK(vkQueueWaitIdle(s.vk_graphics_queue)); - vkFreeCommandBuffers(s.vk_device, s.vk_command_pool, 1, &commandBuffer); + vkFreeCommandBuffers(s.vk.device, s.vk_command_pool, 1, &commandBuffer); } int @@ -867,7 +866,7 @@ findSupportedFormat(VkFormat *candidates, size_t n, for (size_t i = 0; i < n; i++) { VkFormat format = candidates[i]; VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(s.vk_physical_device, format, &props); + vkGetPhysicalDeviceFormatProperties(s.vk.physical_device, format, &props); if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { return format; @@ -893,30 +892,30 @@ void vulkan_create_depth_resources() { VkFormat depthFormat = findDepthFormat(); - createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, 1, - depthFormat, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_depth_image, &s.vk_depth_image_memory, s.msaa_samples); - s.vk_depth_image_view = create_image_view(s.vk_depth_image, depthFormat, + vks_create_image(s.vk, s.vk.swapchain.extent.width, s.vk.swapchain.extent.height, 1, + depthFormat, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.msaa_samples, + &s.depth_image); + s.depth_image.view = create_image_view(s.depth_image.handle, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); - transitionImageLayout(s.vk_depth_image, depthFormat, + transitionImageLayout(s.depth_image.handle, depthFormat, VK_ACCESS_NONE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1); } void vulkan_create_color_resources() { - VkFormat colorFormat = s.vk_swap_chain_image_format; + VkFormat colorFormat = s.vk.swapchain.image_format; - createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, 1, - colorFormat, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_color_image, &s.vk_color_image_memory, s.msaa_samples); - s.vk_color_image_view = create_image_view(s.vk_color_image, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); + vks_create_image(s.vk, s.vk.swapchain.extent.width, s.vk.swapchain.extent.height, 1, + 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, + &s.color_image); + s.color_image.view = create_image_view(s.color_image.handle, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); } void @@ -945,7 +944,6 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) long vert_size = shaderc_result_get_length(vert_result); const char * frag_data = shaderc_result_get_bytes(frag_result); long frag_size = shaderc_result_get_length(frag_result); - vk_log(VK_INFO, "Shaders loaded\n"); VkShaderModule vertShaderModule = createShaderModule(vert_data, vert_size); @@ -1015,14 +1013,14 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) VkViewport viewport = {0}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float) s.vk_swap_chain_extent.width; - viewport.height = (float) s.vk_swap_chain_extent.height; + viewport.width = (float) s.vk.swapchain.extent.width; + viewport.height = (float) s.vk.swapchain.extent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor = {0}; scissor.offset = (VkOffset2D){0, 0}; - scissor.extent = s.vk_swap_chain_extent; + scissor.extent = s.vk.swapchain.extent; VkPipelineViewportStateCreateInfo viewportState = {0}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; @@ -1082,7 +1080,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional pipelineLayoutInfo.pPushConstantRanges = NULL; // Optional - if (vkCreatePipelineLayout(s.vk_device, &pipelineLayoutInfo, NULL, &s.vk_pipeline_layout) != VK_SUCCESS) { + if (vkCreatePipelineLayout(s.vk.device, &pipelineLayoutInfo, NULL, &s.graphics_pipeline.layout) != VK_SUCCESS) { vk_log(VK_ERROR, "failed to create pipeline layout!\n"); } @@ -1101,7 +1099,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) VkPipelineRenderingCreateInfo pipeline_rendering_create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, .colorAttachmentCount = 1, - .pColorAttachmentFormats = &s.vk_swap_chain_image_format, + .pColorAttachmentFormats = &s.vk.swapchain.image_format, .depthAttachmentFormat = findDepthFormat(), }; VkGraphicsPipelineCreateInfo pipelineInfo = {0}; @@ -1118,13 +1116,13 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) pipelineInfo.pDepthStencilState = &depthStencil; pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.layout = s.vk_pipeline_layout; + pipelineInfo.layout = s.graphics_pipeline.layout; pipelineInfo.renderPass = VK_NULL_HANDLE; pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional pipelineInfo.basePipelineIndex = -1; // Optional - if (vkCreateGraphicsPipelines(s.vk_device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &s.vk_graphics_pipeline) != VK_SUCCESS) { + if (vkCreateGraphicsPipelines(s.vk.device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &s.graphics_pipeline.handle) != VK_SUCCESS) { vk_log(VK_ERROR, "failed to create graphics pipeline!\n"); } @@ -1135,22 +1133,22 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) shaderc_result_release(frag_result); } - vkDestroyShaderModule(s.vk_device, fragShaderModule, NULL); - vkDestroyShaderModule(s.vk_device, vertShaderModule, NULL); + vkDestroyShaderModule(s.vk.device, fragShaderModule, NULL); + vkDestroyShaderModule(s.vk.device, vertShaderModule, NULL); } void vulkan_create_command_pool() { - QueueFamilyIndices queueFamilyIndices = vulkan_find_queue_families(s.vk_physical_device); + QueueFamilyIndices queueFamilyIndices = vulkan_find_queue_families(s.vk.physical_device); VkCommandPoolCreateInfo poolInfo = {0}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; // AMD doesn't like this flag for some reason poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; + poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsAndComputeFamily; - VK_CHECK(vkCreateCommandPool(s.vk_device, &poolInfo, NULL, &s.vk_command_pool)); + VK_CHECK(vkCreateCommandPool(s.vk.device, &poolInfo, NULL, &s.vk_command_pool)); } void @@ -1164,7 +1162,7 @@ vulkan_create_command_buffer() allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = 1; - VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &s.frames[i].vk_command_buffer)); + VK_CHECK(vkAllocateCommandBuffers(s.vk.device, &allocInfo, &s.frames[i].vk_command_buffer)); } } @@ -1183,17 +1181,17 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) //vkCmdSetPolygonModeEXT(commandBuffer, s.polygon_mode); transitionImageLayout( - s.vk_swap_chain_images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, + s.vk.swapchain.images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1); VkRenderingAttachmentInfo colorAttachment = {0}; colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - colorAttachment.imageView = s.vk_color_image_view; + colorAttachment.imageView = s.color_image.view; colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; colorAttachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; - colorAttachment.resolveImageView = s.vk_swap_chain_image_views[imageIndex]; + colorAttachment.resolveImageView = s.vk.swapchain.image_views[imageIndex]; colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -1202,7 +1200,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VkRenderingAttachmentInfo depthAttachment = {0}; depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - depthAttachment.imageView = s.vk_depth_image_view; + depthAttachment.imageView = s.depth_image.view; depthAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; @@ -1211,7 +1209,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VkRenderingInfo renderingInfo = {}; renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; renderingInfo.renderArea = - (VkRect2D){{0, 0}, s.vk_swap_chain_extent}; + (VkRect2D){{0, 0}, s.vk.swapchain.extent}; renderingInfo.layerCount = 1; renderingInfo.colorAttachmentCount = 1; renderingInfo.pColorAttachments = &colorAttachment; @@ -1220,36 +1218,36 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) vkCmdBeginRendering(commandBuffer, &renderingInfo); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - s.vk_graphics_pipeline); + s.graphics_pipeline.handle); VkViewport viewport = {0}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)(s.vk_swap_chain_extent.width); - viewport.height = (float)(s.vk_swap_chain_extent.height); + viewport.width = (float)(s.vk.swapchain.extent.width); + viewport.height = (float)(s.vk.swapchain.extent.height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vkCmdSetViewport(commandBuffer, 0, 1, &viewport); VkRect2D scissor = {0}; scissor.offset = (VkOffset2D){0, 0}; - scissor.extent = s.vk_swap_chain_extent; + scissor.extent = s.vk.swapchain.extent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - VkBuffer vertexBuffers[] = {s.vk_vertex_buffer}; + VkBuffer vertexBuffers[] = {s.vertex_buffer.handle}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, s.vk_index_buffer, 0, + vkCmdBindIndexBuffer(commandBuffer, s.index_buffer.handle, 0, VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - s.vk_pipeline_layout, 0, 1, + s.graphics_pipeline.layout, 0, 1, &s.frames[currentFrame].vk_descriptor_set, 0, NULL); vkCmdDrawIndexed(commandBuffer, s.indices_count, 1, 0, 0, 0); vkCmdEndRendering(commandBuffer); - transitionImageLayout(s.vk_swap_chain_images[imageIndex], + transitionImageLayout(s.vk.swapchain.images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, @@ -1271,40 +1269,12 @@ vulkan_create_sync_objects() fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].image_available_semaphore)); - VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].render_finished_semaphore)); - VK_CHECK(vkCreateFence(s.vk_device, &fenceInfo, NULL, &s.frames[i].in_flight_fence)); + VK_CHECK(vkCreateSemaphore(s.vk.device, &semaphoreInfo, NULL, &s.frames[i].image_available_semaphore)); + VK_CHECK(vkCreateSemaphore(s.vk.device, &semaphoreInfo, NULL, &s.frames[i].render_finished_semaphore)); + VK_CHECK(vkCreateFence(s.vk.device, &fenceInfo, NULL, &s.frames[i].in_flight_fence)); } } -void -createBuffer(VkDeviceSize size, - VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, - VkBuffer *buffer, VkDeviceMemory *bufferMemory) -{ - VkBufferCreateInfo bufferInfo = {0}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = size; - bufferInfo.usage = usage; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK(vkCreateBuffer(s.vk_device, &bufferInfo, NULL, buffer)); - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(s.vk_device, *buffer, &memRequirements); - - VkMemoryAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - - // TODO: group allocations etc... (allocations limited by hardware) - VK_CHECK(vkAllocateMemory(s.vk_device, &allocInfo, NULL, bufferMemory)); - - VK_CHECK(vkBindBufferMemory(s.vk_device, *buffer, *bufferMemory, 0)); -} - void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { VkCommandBuffer commandBuffer = beginSingleTimeCommands(); VkBufferCopy copyRegion = {0}; @@ -1321,29 +1291,28 @@ vulkan_create_vertex_buffer() VkDeviceSize bufferSize = sizeof(s.vertices[0]) * s.vertices_count; /* VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; */ - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; + vks_buffer stagingBuffer = {0}; - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, &stagingBufferMemory); + vks_create_buffer(s.vk, bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &stagingBuffer); - void* data; - VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); + void *data; + VK_CHECK(vkMapMemory(s.vk.device, stagingBuffer.memory, 0, bufferSize, 0, &data)); // memcpy(data, vertices, (size_t) bufferSize); memcpy(data, s.vertices, (size_t) bufferSize); - vkUnmapMemory(s.vk_device, stagingBufferMemory); + vkUnmapMemory(s.vk.device, stagingBuffer.memory); - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_vertex_buffer, &s.vk_vertex_buffer_memory); + vks_create_buffer(s.vk, bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &s.vertex_buffer); - copy_buffer(stagingBuffer, s.vk_vertex_buffer, bufferSize); + copy_buffer(stagingBuffer.handle, s.vertex_buffer.handle, bufferSize); - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); + vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); + vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); } void @@ -1352,29 +1321,28 @@ vulkan_create_index_buffer() VkDeviceSize bufferSize = sizeof(s.indices[0]) * s.indices_count; /* VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE; */ - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; + vks_buffer stagingBuffer = {0}; - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &stagingBuffer, &stagingBufferMemory); + vks_create_buffer(s.vk, bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &stagingBuffer); void* data; - VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); + VK_CHECK(vkMapMemory(s.vk.device, stagingBuffer.memory, 0, bufferSize, 0, &data)); memcpy(data, s.indices, (size_t) bufferSize); /* memcpy(data, indices, (size_t) bufferSize); */ - vkUnmapMemory(s.vk_device, stagingBufferMemory); + vkUnmapMemory(s.vk.device, stagingBuffer.memory); - createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_index_buffer, &s.vk_index_buffer_memory); + vks_create_buffer(s.vk, bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &s.index_buffer); - copy_buffer(stagingBuffer, s.vk_index_buffer, bufferSize); + copy_buffer(stagingBuffer.handle, s.index_buffer.handle, bufferSize); - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); + vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); + vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); } void @@ -1402,7 +1370,7 @@ vulkan_create_descriptor_set_layout() layoutInfo.bindingCount = VK_ARRAY_LEN(bindings); layoutInfo.pBindings = bindings; - VK_CHECK(vkCreateDescriptorSetLayout(s.vk_device, &layoutInfo, NULL, &s.vk_descriptor_set_layout)); + VK_CHECK(vkCreateDescriptorSetLayout(s.vk.device, &layoutInfo, NULL, &s.vk_descriptor_set_layout)); } void @@ -1411,23 +1379,25 @@ vulkan_create_uniform_buffers() VkDeviceSize bufferSize = sizeof(UniformBufferObject); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - createBuffer(bufferSize, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &s.frames[i].vk_uniform_buffer, &s.frames[i].vk_uniform_buffer_memory); + vks_create_buffer(s.vk, bufferSize, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &s.frames[i].uniform_buffer); - VK_CHECK(vkMapMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, 0, bufferSize, 0, &s.frames[i].vk_uniform_buffer_mapped)); + VK_CHECK(vkMapMemory(s.vk.device, s.frames[i].uniform_buffer.memory, 0, bufferSize, 0, &s.frames[i].uniform_buffer_mapped)); } } void vulkan_create_descriptor_pool() { - VkDescriptorPoolSize poolSizes[2] = {0}; + VkDescriptorPoolSize poolSizes[3] = {0}; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; poolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT; poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; poolSizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT; + poolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + poolSizes[2].descriptorCount = (uint32_t)(MAX_FRAMES_IN_FLIGHT) * 2; VkDescriptorPoolCreateInfo poolInfo = {0}; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; @@ -1435,7 +1405,7 @@ vulkan_create_descriptor_pool() poolInfo.pPoolSizes = poolSizes; poolInfo.maxSets = MAX_FRAMES_IN_FLIGHT; - VK_CHECK(vkCreateDescriptorPool(s.vk_device, &poolInfo, NULL, &s.vk_descriptor_pool)); + VK_CHECK(vkCreateDescriptorPool(s.vk.device, &poolInfo, NULL, &s.vk_descriptor_pool)); } void @@ -1455,20 +1425,15 @@ vulkan_create_descriptor_sets() allocInfo.descriptorSetCount = 1; allocInfo.pSetLayouts = layouts; - VK_CHECK(vkAllocateDescriptorSets(s.vk_device, &allocInfo, &s.frames[i].vk_descriptor_set)); + VK_CHECK(vkAllocateDescriptorSets(s.vk.device, &allocInfo, &s.frames[i].vk_descriptor_set)); } for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { VkDescriptorBufferInfo bufferInfo = {0}; - bufferInfo.buffer = s.frames[i].vk_uniform_buffer; + bufferInfo.buffer = s.frames[i].uniform_buffer.handle; bufferInfo.offset = 0; bufferInfo.range = sizeof(UniformBufferObject); - VkDescriptorImageInfo imageInfo = {0}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = s.vk_texture_image_view; - imageInfo.sampler = s.vk_texture_sampler; - VkWriteDescriptorSet descriptorWrites[2] = {0}; descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrites[0].dstSet = s.frames[i].vk_descriptor_set; @@ -1478,6 +1443,11 @@ vulkan_create_descriptor_sets() descriptorWrites[0].descriptorCount = 1; descriptorWrites[0].pBufferInfo = &bufferInfo; + VkDescriptorImageInfo imageInfo = {0}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.imageView = s.texture_image.view; + imageInfo.sampler = s.vk_texture_sampler; + descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrites[1].dstSet = s.frames[i].vk_descriptor_set; descriptorWrites[1].dstBinding = 1; @@ -1486,31 +1456,58 @@ vulkan_create_descriptor_sets() descriptorWrites[1].descriptorCount = 1; descriptorWrites[1].pImageInfo = &imageInfo; - vkUpdateDescriptorSets(s.vk_device, VK_ARRAY_LEN(descriptorWrites), descriptorWrites, 0, NULL); + /* VkDescriptorBufferInfo storageBufferInfoLastFrame = {0}; */ + /* storageBufferInfoLastFrame.buffer = s.frames[(i - 1) % MAX_FRAMES_IN_FLIGHT].vk_shader_storage_buffer; */ + /* storageBufferInfoLastFrame.offset = 0; */ + /* storageBufferInfoLastFrame.range = sizeof(Particle) * PARTICLE_COUNT; */ + + /* descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; */ + /* descriptorWrites[2].dstSet = s.frames[i].vk_compute_descriptor_set; */ + /* descriptorWrites[2].dstBinding = 1; */ + /* descriptorWrites[2].dstArrayElement = 0; */ + /* descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; */ + /* descriptorWrites[2].descriptorCount = 1; */ + /* descriptorWrites[2].pBufferInfo = &storageBufferInfoLastFrame; */ + + /* VkDescriptorBufferInfo storageBufferInfoCurrentFrame = {0}; */ + /* storageBufferInfoCurrentFrame.buffer = s.frames[i].vk_shader_storage_buffer; */ + /* storageBufferInfoCurrentFrame.offset = 0; */ + /* storageBufferInfoCurrentFrame.range = sizeof(Particle) * PARTICLE_COUNT; */ + + /* descriptorWrites[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; */ + /* descriptorWrites[3].dstSet = s.frames[i].vk_compute_descriptor_set; */ + /* descriptorWrites[3].dstBinding = 2; */ + /* descriptorWrites[3].dstArrayElement = 0; */ + /* descriptorWrites[3].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; */ + /* descriptorWrites[3].descriptorCount = 1; */ + /* descriptorWrites[3].pBufferInfo = &storageBufferInfoCurrentFrame; */ + + + vkUpdateDescriptorSets(s.vk.device, VK_ARRAY_LEN(descriptorWrites), descriptorWrites, 0, NULL); } } void cleanupSwapChain() { - vkDestroyImageView(s.vk_device, s.vk_color_image_view, NULL); - vkDestroyImage(s.vk_device, s.vk_color_image, NULL); - vkFreeMemory(s.vk_device, s.vk_color_image_memory, NULL); + vkDestroyImageView(s.vk.device, s.color_image.view, NULL); + vkDestroyImage(s.vk.device, s.color_image.handle, NULL); + vkFreeMemory(s.vk.device, s.color_image.memory, NULL); - vkDestroyImageView(s.vk_device, s.vk_depth_image_view, NULL); - vkDestroyImage(s.vk_device, s.vk_depth_image, NULL); - vkFreeMemory(s.vk_device, s.vk_depth_image_memory, NULL); + vkDestroyImageView(s.vk.device, s.depth_image.view, NULL); + vkDestroyImage(s.vk.device, s.depth_image.handle, NULL); + vkFreeMemory(s.vk.device, s.depth_image.memory, NULL); - for (uint32_t i = 0; i < s.vk_swap_chain_image_count; i++) { - vkDestroyImageView(s.vk_device, s.vk_swap_chain_image_views[i], NULL); + for (uint32_t i = 0; i < s.vk.swapchain.image_count; i++) { + vkDestroyImageView(s.vk.device, s.vk.swapchain.image_views[i], NULL); } - vkDestroySwapchainKHR(s.vk_device, s.vk_swap_chain, NULL); + vkDestroySwapchainKHR(s.vk.device, s.vk.swapchain.handle, NULL); } void recreateSwapChain() { - vkDeviceWaitIdle(s.vk_device); + vkDeviceWaitIdle(s.vk.device); cleanupSwapChain(); @@ -1524,8 +1521,8 @@ void recreate_graphics_pipeline() { recreateSwapChain(); - vkDestroyPipeline(s.vk_device, s.vk_graphics_pipeline, NULL); - vkDestroyPipelineLayout(s.vk_device, s.vk_pipeline_layout, NULL); + vkDestroyPipeline(s.vk.device, s.graphics_pipeline.handle, NULL); + vkDestroyPipelineLayout(s.vk.device, s.graphics_pipeline.layout, NULL); vulkan_create_graphics_pipeline(s.polygon_mode); } @@ -1586,7 +1583,7 @@ handle_input(bool * quit) s.rotate = s.rotate ? 0 : 1; break; case SDLK_m: - vkDeviceWaitIdle(s.vk_device); + vkDeviceWaitIdle(s.vk.device); free(s.vertices); free(s.indices); /* if (!strcmp(s.model_path, "assets/human.obj")) */ @@ -1604,11 +1601,11 @@ handle_input(bool * quit) toggle = 1; load_model_gltf(); } - vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); + vkDestroyBuffer(s.vk.device, s.vertex_buffer.handle, NULL); + vkFreeMemory(s.vk.device, s.vertex_buffer.memory, NULL); - vkDestroyBuffer(s.vk_device, s.vk_index_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_index_buffer_memory, NULL); + vkDestroyBuffer(s.vk.device, s.index_buffer.handle, NULL); + vkFreeMemory(s.vk.device, s.index_buffer.memory, NULL); vulkan_create_vertex_buffer(); vulkan_create_index_buffer(); break; @@ -1784,46 +1781,44 @@ vulkan_create_texture_image() vk_log(VK_ERROR, "failed to load texture image!\n"); } - VkBuffer stagingBuffer; - VkDeviceMemory stagingBufferMemory; + vks_buffer stagingBuffer = {0}; - createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, &stagingBufferMemory); - void* data; - vkMapMemory(s.vk_device, stagingBufferMemory, 0, imageSize, 0, &data); + vks_create_buffer(s.vk, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer); + void *data; + vkMapMemory(s.vk.device, stagingBuffer.memory, 0, imageSize, 0, &data); memcpy(data, pixels, (size_t)imageSize); - vkUnmapMemory(s.vk_device, stagingBufferMemory); + vkUnmapMemory(s.vk.device, stagingBuffer.memory); stbi_image_free(pixels); - createImage(texWidth, texHeight, s.vk_mip_levels, VK_FORMAT_R8G8B8A8_SRGB, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_texture_image, - &s.vk_texture_image_memory, VK_SAMPLE_COUNT_1_BIT); + vks_create_image(s.vk, texWidth, texHeight, s.vk_mip_levels, VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_SAMPLE_COUNT_1_BIT, &s.texture_image); transitionImageLayout( - s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, 0, + s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, s.vk_mip_levels); - copyBufferToImage(stagingBuffer, s.vk_texture_image, (uint32_t)texWidth, + copyBufferToImage(stagingBuffer.handle, s.texture_image.handle, (uint32_t)texWidth, (uint32_t)texHeight); - generateMipmaps(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels); + generateMipmaps(s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels); transitionImageLayout( - s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, + s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, s.vk_mip_levels); - vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); - vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); + vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); + vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); } void vulkan_create_texture_image_view() { - s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels); + s.texture_image.view = create_image_view(s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels); } void vulkan_create_texture_sampler() { @@ -1837,7 +1832,7 @@ void vulkan_create_texture_sampler() { samplerInfo.anisotropyEnable = VK_TRUE; VkPhysicalDeviceProperties properties = {0}; - vkGetPhysicalDeviceProperties(s.vk_physical_device, &properties); + vkGetPhysicalDeviceProperties(s.vk.physical_device, &properties); samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; @@ -1849,7 +1844,7 @@ void vulkan_create_texture_sampler() { samplerInfo.minLod = 0.0f; samplerInfo.maxLod = VK_LOD_CLAMP_NONE; - VK_CHECK(vkCreateSampler(s.vk_device, &samplerInfo, NULL, &s.vk_texture_sampler)); + VK_CHECK(vkCreateSampler(s.vk.device, &samplerInfo, NULL, &s.vk_texture_sampler)); } void @@ -2001,6 +1996,127 @@ void load_model_gltf() { cgltf_free(data); } +float rand_float() { + return rand() / (float)RAND_MAX; +} + +void vulkan_create_compute_stuff() +{ + shaderc_compilation_result_t comp_result = load_compile_shader_data("src/shader.comp", shaderc_compute_shader); + if (!comp_result) { + vk_log(VK_ERROR, "Can't load compupte shader\n"); + if (s.prev_comp_result) { + comp_result = s.prev_comp_result; + } + } + if (s.prev_comp_result && comp_result != s.prev_comp_result) shaderc_result_release(s.prev_comp_result); + s.prev_comp_result = comp_result; + + const char * comp_data = shaderc_result_get_bytes(comp_result); + long comp_size = shaderc_result_get_length(comp_result); + + VkShaderModule compShaderModule = createShaderModule(comp_data, comp_size); + VkPipelineShaderStageCreateInfo computeShaderStageInfo = {0}; + computeShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + computeShaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + computeShaderStageInfo.module = compShaderModule; + computeShaderStageInfo.pName = "main"; + + + srand((unsigned int)time(NULL)); + + Particle particles[PARTICLE_COUNT]; + int width, height; + SDL_GetWindowSize(s.vk.window, &width, &height); + + for (int i = 0; i < PARTICLE_COUNT; i++) { + float r = 0.25f * sqrtf(rand_float()); + float theta = rand_float() * 2 * 3.14159265358979323846; + float x = r * cosf(theta) * height / width; + float y = r * sinf(theta); + + particles[i].position[0] = x; + particles[i].position[1] = y; + + vec2 norm; + glm_vec2_copy((vec2){x, y}, norm); + glm_vec2_normalize(norm); + + particles[i].velocity[0] = norm[0] * 0.00025f; + particles[i].velocity[1] = norm[1] * 0.00025f; + + particles[i].color[0] = rand_float(); + particles[i].color[1] = rand_float(); + particles[i].color[2] = rand_float(); + particles[i].color[3] = 1.0f; + } + + VkDeviceSize bufferSize = sizeof(Particle) * PARTICLE_COUNT; + + vks_buffer stagingBuffer = {0}; + vks_create_buffer(s.vk, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer); + + void* data; + vkMapMemory(s.vk.device, stagingBuffer.memory, 0, bufferSize, 0, &data); + memcpy(data, particles, (size_t)bufferSize); + vkUnmapMemory(s.vk.device, stagingBuffer.memory); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + vks_create_buffer(s.vk, bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.frames[i].shader_storage_buffer); + // Copy data from the staging buffer (host) to the shader storage buffer (GPU) + copy_buffer(stagingBuffer.handle, s.frames[i].shader_storage_buffer.handle, bufferSize); + } + + VkDescriptorSetLayoutBinding layoutBindings[3]; + layoutBindings[0].binding = 0; + layoutBindings[0].descriptorCount = 1; + layoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layoutBindings[0].pImmutableSamplers = NULL; + layoutBindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + layoutBindings[1].binding = 1; + layoutBindings[1].descriptorCount = 1; + layoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + layoutBindings[1].pImmutableSamplers = NULL; + layoutBindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + layoutBindings[2].binding = 2; + layoutBindings[2].descriptorCount = 1; + layoutBindings[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + layoutBindings[2].pImmutableSamplers = NULL; + layoutBindings[2].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + VkDescriptorSetLayoutCreateInfo layoutInfo = {0}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = 3; + layoutInfo.pBindings = layoutBindings; + + 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; + pipelineInfo.stage = computeShaderStageInfo; + + VK_CHECK(vkCreateComputePipelines(s.vk.device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &s.vk_compute_pipeline)); + + VkPipelineLayoutCreateInfo pipelineLayoutInfo = {0}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &s.vk_compute_descriptor_set_layout; + + VK_CHECK(vkCreatePipelineLayout(s.vk.device, &pipelineLayoutInfo, NULL, &s.vk_compute_pipeline_layout)); + + if (s.prev_comp_result != comp_result) { + shaderc_result_release(comp_result); + } + + vkDestroyShaderModule(s.vk.device, compShaderModule, NULL); + +} + void init_vulkan() { @@ -2009,9 +2125,9 @@ init_vulkan() vk_log(VK_WARN, "====================================\n"); //vulkan_create_instance(); - s.vk_instance = + s.vk.instance = vks_create_instance(enableValidationLayers, validation_layers, - validation_layer_count, s.sdl_window); + validation_layer_count, s.vk.window); // vulkan_setup_debug_messenger(); vulkan_create_surface(); vulkan_pick_physical_device(); @@ -2020,6 +2136,7 @@ init_vulkan() vulkan_create_image_views(); vulkan_create_descriptor_set_layout(); vulkan_create_graphics_pipeline(s.polygon_mode); + //vulkan_create_compute_stuff(); vulkan_create_command_pool(); vulkan_create_depth_resources(); vulkan_create_color_resources(); @@ -2040,45 +2157,45 @@ init_vulkan() void close_vulkan() { - vkDeviceWaitIdle(s.vk_device); + vkDeviceWaitIdle(s.vk.device); // Cleanup for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(s.vk_device, s.frames[i].image_available_semaphore, NULL); - vkDestroySemaphore(s.vk_device, s.frames[i].render_finished_semaphore, NULL); - vkDestroyFence(s.vk_device, s.frames[i].in_flight_fence, NULL); + vkDestroySemaphore(s.vk.device, s.frames[i].image_available_semaphore, NULL); + vkDestroySemaphore(s.vk.device, s.frames[i].render_finished_semaphore, NULL); + vkDestroyFence(s.vk.device, s.frames[i].in_flight_fence, NULL); } - vkDestroyCommandPool(s.vk_device, s.vk_command_pool, NULL); + vkDestroyCommandPool(s.vk.device, s.vk_command_pool, NULL); cleanupSwapChain(); - vkDestroySampler(s.vk_device, s.vk_texture_sampler, NULL); - vkDestroyImageView(s.vk_device, s.vk_texture_image_view, NULL); + vkDestroySampler(s.vk.device, s.vk_texture_sampler, NULL); + vkDestroyImageView(s.vk.device, s.texture_image.view, NULL); - vkDestroyImage(s.vk_device, s.vk_texture_image, NULL); - vkFreeMemory(s.vk_device, s.vk_texture_image_memory, NULL); + vkDestroyImage(s.vk.device, s.texture_image.handle, NULL); + vkFreeMemory(s.vk.device, s.texture_image.memory, NULL); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroyBuffer(s.vk_device, s.frames[i].vk_uniform_buffer, NULL); - vkFreeMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, NULL); + vkDestroyBuffer(s.vk.device, s.frames[i].uniform_buffer.handle, NULL); + vkFreeMemory(s.vk.device, s.frames[i].uniform_buffer.memory, NULL); } - vkDestroyDescriptorPool(s.vk_device, s.vk_descriptor_pool, NULL); - vkDestroyDescriptorSetLayout(s.vk_device, s.vk_descriptor_set_layout, NULL); + vkDestroyDescriptorPool(s.vk.device, s.vk_descriptor_pool, NULL); + vkDestroyDescriptorSetLayout(s.vk.device, s.vk_descriptor_set_layout, NULL); - vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); + vkDestroyBuffer(s.vk.device, s.vertex_buffer.handle, NULL); + vkFreeMemory(s.vk.device, s.vertex_buffer.memory, NULL); - vkDestroyBuffer(s.vk_device, s.vk_index_buffer, NULL); - vkFreeMemory(s.vk_device, s.vk_index_buffer_memory, NULL); + vkDestroyBuffer(s.vk.device, s.index_buffer.handle, NULL); + vkFreeMemory(s.vk.device, s.index_buffer.memory, NULL); - vkDestroyPipeline(s.vk_device, s.vk_graphics_pipeline, NULL); - vkDestroyPipelineLayout(s.vk_device, s.vk_pipeline_layout, NULL); - vkDestroyDevice(s.vk_device, NULL); - vkDestroySurfaceKHR(s.vk_instance, s.vk_surface, NULL); + vkDestroyPipeline(s.vk.device, s.graphics_pipeline.handle, NULL); + vkDestroyPipelineLayout(s.vk.device, s.graphics_pipeline.layout, NULL); + vkDestroyDevice(s.vk.device, NULL); + vkDestroySurfaceKHR(s.vk.instance, s.vk.surface, NULL); /* if (enableValidationLayers) { */ - /* DestroyDebugUtilsMessengerEXT(s.vk_instance, s.vk_debug_messenger, NULL); */ + /* DestroyDebugUtilsMessengerEXT(s.vk.instance, s.vk_debug_messenger, NULL); */ /* } */ - vkDestroyInstance(s.vk_instance, NULL); + vkDestroyInstance(s.vk.instance, NULL); if (s.prev_vert_result) { shaderc_result_release(s.prev_vert_result); @@ -2117,8 +2234,8 @@ updateUniformBuffer(uint32_t currentImage, float dt) ubo.time = current_time(); ubo.dt = dt; - ubo.resolution[0] = s.vk_swap_chain_extent.width; - ubo.resolution[1] = s.vk_swap_chain_extent.height; + ubo.resolution[0] = s.vk.swapchain.extent.width; + ubo.resolution[1] = s.vk.swapchain.extent.height; //glm_mat4_identity(ubo.model); glm_mat4_dup(s.ubo.model, ubo.model); @@ -2137,13 +2254,13 @@ updateUniformBuffer(uint32_t currentImage, float dt) /* glm_lookat(eye, center, GLM_ZUP, ubo.view); */ - float aspect = s.vk_swap_chain_extent.width / (float)s.vk_swap_chain_extent.height; + float aspect = s.vk.swapchain.extent.width / (float)s.vk.swapchain.extent.height; glm_perspective(glm_rad(45.0f + s.zoom ), aspect, 0.1f, 100.0f, ubo.proj); // Inverting the Y axis for Vulkan ubo.proj[1][1] *= -1; - memcpy(s.frames[currentImage].vk_uniform_buffer_mapped, &ubo, sizeof(ubo)); + memcpy(s.frames[currentImage].uniform_buffer_mapped, &ubo, sizeof(ubo)); } float prev_time = 0; @@ -2154,10 +2271,10 @@ draw_frame() { float dt = time - prev_time; - vkWaitForFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); + vkWaitForFences(s.vk.device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(s.vk_device, s.vk_swap_chain, UINT64_MAX, s.frames[currentFrame].image_available_semaphore, VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR(s.vk.device, s.vk.swapchain.handle, UINT64_MAX, s.frames[currentFrame].image_available_semaphore, VK_NULL_HANDLE, &imageIndex); if (result == VK_ERROR_OUT_OF_DATE_KHR) { recreateSwapChain(); @@ -2168,10 +2285,10 @@ draw_frame() { updateUniformBuffer(currentFrame, dt); - vkResetFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence); + vkResetFences(s.vk.device, 1, &s.frames[currentFrame].in_flight_fence); // both could work - //vkResetCommandPool(s.vk_device, s.vk_command_pool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); + //vkResetCommandPool(s.vk.device, s.vk_command_pool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); vkResetCommandBuffer(s.frames[currentFrame].vk_command_buffer, 0); recordCommandBuffer(s.frames[currentFrame].vk_command_buffer, imageIndex); @@ -2192,7 +2309,7 @@ draw_frame() { vk_log(VK_ERROR, "failed to submit draw command buffer!\n"); } - VkSwapchainKHR swapChains[] = {s.vk_swap_chain}; + VkSwapchainKHR swapChains[] = {s.vk.swapchain.handle}; VkPresentInfoKHR presentInfo = {0}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; @@ -2240,9 +2357,9 @@ main(int argc, char* argv[]) VmaAllocatorCreateInfo allocatorCreateInfo = {0}; allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2; - allocatorCreateInfo.physicalDevice = s.vk_physical_device; - allocatorCreateInfo.device = s.vk_device; - allocatorCreateInfo.instance = s.vk_instance; + allocatorCreateInfo.physicalDevice = s.vk.physical_device; + allocatorCreateInfo.device = s.vk.device; + allocatorCreateInfo.instance = s.vk.instance; allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; VmaAllocator allocator; diff --git a/src/state.h b/src/state.h index 95f636b..28f49e6 100644 --- a/src/state.h +++ b/src/state.h @@ -3,8 +3,10 @@ #include <shaderc/shaderc.h> #include <vulkan/vulkan_core.h> -#define CGLM_FORCE_DEPTH_ZERO_TO_ONE +#define VKSETUP_IMPLEMENTATION +#include "vksetup.h" +#define CGLM_FORCE_DEPTH_ZERO_TO_ONE #include "../lib/cglm/include/cglm/cglm.h" #pragma once @@ -38,11 +40,13 @@ typedef struct { VkSemaphore render_finished_semaphore; VkFence in_flight_fence; - VkBuffer vk_uniform_buffer; - VkDeviceMemory vk_uniform_buffer_memory; - void * vk_uniform_buffer_mapped; + vks_buffer uniform_buffer; + void * uniform_buffer_mapped; VkDescriptorSet vk_descriptor_set; + + VkDescriptorSet vk_compute_descriptor_set; + vks_buffer shader_storage_buffer; } frame_data; typedef struct { @@ -62,6 +66,13 @@ typedef struct { V2 texCoord; } Vertex; +typedef struct { + vec2 position; + vec2 velocity; + vec4 color; +} Particle; + + typedef struct state { camera3d camera; @@ -75,62 +86,44 @@ typedef struct state { int mouse_pressed; int middle_click; - UniformBufferObject ubo; - float x; int zoom; - SDL_Window *sdl_window; + UniformBufferObject ubo; + int sdl_window_resized; - VkInstance vk_instance; VkDebugUtilsMessengerEXT vk_debug_messenger; PFN_vkCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT; PFN_vkDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT; - VkPhysicalDevice vk_physical_device; - VkDevice vk_device; + vks_context vk; + VkQueue vk_graphics_queue; - VkSurfaceKHR vk_surface; VkQueue vk_present_queue; - VkSwapchainKHR vk_swap_chain; - - uint32_t vk_swap_chain_image_count; - VkImage vk_swap_chain_images[5]; - VkImageView vk_swap_chain_image_views[5]; // 5 for some reason - - VkFormat vk_swap_chain_image_format; - VkExtent2D vk_swap_chain_extent; - VkDescriptorSetLayout vk_descriptor_set_layout; - VkPipelineLayout vk_pipeline_layout; - VkPipeline vk_graphics_pipeline; + + vks_pipeline graphics_pipeline; VkCommandPool vk_command_pool; frame_data frames[MAX_FRAMES_IN_FLIGHT]; - VkBuffer vk_vertex_buffer; - VkDeviceMemory vk_vertex_buffer_memory; - - VkBuffer vk_index_buffer; - VkDeviceMemory vk_index_buffer_memory; + vks_buffer vertex_buffer; + vks_buffer index_buffer; VkDescriptorPool vk_descriptor_pool; shaderc_compilation_result_t prev_vert_result; shaderc_compilation_result_t prev_frag_result; + shaderc_compilation_result_t prev_comp_result; uint32_t vk_mip_levels; - VkImage vk_texture_image; - VkDeviceMemory vk_texture_image_memory; - VkImageView vk_texture_image_view; + vks_image texture_image; VkSampler vk_texture_sampler; - VkImage vk_depth_image; - VkDeviceMemory vk_depth_image_memory; - VkImageView vk_depth_image_view; + vks_image depth_image; VkPolygonMode polygon_mode; @@ -138,22 +131,21 @@ typedef struct state { size_t vertices_count; uint32_t * indices; size_t indices_count; - VkBuffer vertexBuffer; - VkDeviceMemory vertexBufferMemory; char model_path[1000]; VkSampleCountFlagBits msaa_samples; - VkImage vk_color_image; - VkDeviceMemory vk_color_image_memory; - VkImageView vk_color_image_view; + vks_image color_image; + + VkDescriptorSetLayout vk_compute_descriptor_set_layout; + VkPipelineLayout vk_compute_pipeline_layout; + VkPipeline vk_compute_pipeline; } state_t; static void init_state(state_t *s) { - strcpy(s->model_path, "assets/monkey.obj"); s->camera.pos[0] = 2.0f; s->camera.pos[1] = 2.0f; @@ -195,10 +187,10 @@ init_state(state_t *s) glm_mat4_identity(s->ubo.model); - s->sdl_window = NULL; + s->vk.window = NULL; - s->vk_swap_chain_image_count = 0; - s->vk_physical_device = VK_NULL_HANDLE; + s->vk.swapchain.image_count = 0; + s->vk.physical_device = VK_NULL_HANDLE; s->prev_vert_result = NULL; s->prev_frag_result = NULL; diff --git a/src/vksetup.h b/src/vksetup.h index 88f579a..4f05347 100644 --- a/src/vksetup.h +++ b/src/vksetup.h @@ -34,6 +34,7 @@ */ +#include <vulkan/vulkan_core.h> #define SDL_MAIN_HANDLED #define VK_USE_PLATFORM_XCB_KHR #include <stdarg.h> @@ -144,14 +145,62 @@ extern "C" { // TODO Create structs for vulkan data -typedef struct {void * a;} vks_vulkan; -typedef struct {void * a;} vks_image; -typedef struct {void * a;} vks_; +typedef struct vks_swapchain { + VkSwapchainKHR handle; -/** - Create a VkInstance - */ + VkFormat image_format; + VkExtent2D extent; + + uint32_t image_count; + VkImage images[5]; + VkImageView image_views[5]; // 5 for some reason +} vks_swapchain; + +typedef struct vks_buffer { + VkBuffer handle; + VkDeviceMemory memory; +} vks_buffer; + +typedef struct vks_image { + VkImage handle; + VkDeviceMemory memory; + VkImageView view; +} vks_image; + +typedef struct vks_pipeline { + VkPipeline handle; + VkPipelineLayout layout; +} vks_pipeline; + +typedef struct vks_context { + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + + SDL_Window *window; + VkSurfaceKHR surface; + + vks_swapchain swapchain; +} vks_context; + +typedef struct vks_frame_data { + VkCommandBuffer vk_command_buffer; + + VkSemaphore image_available_semaphore; + VkSemaphore render_finished_semaphore; + VkFence in_flight_fence; + + vks_buffer uniform_buffer; + void * uniform_buffer_mapped; + + VkDescriptorSet vk_descriptor_set; +} vks_frame_data; + + +/* 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 vulkan_create_surface(); */ /* VKSDEF void vulkan_pick_physical_device(); */ /* VKSDEF void vulkan_create_logical_device(); */ @@ -188,7 +237,8 @@ VKSDEF VkInstance vks_create_instance(bool validation_layers_toggle, const char /* Vks helpers */ bool -vks_check_validation_layer_support(const char * const validation_layers[], uint32_t validation_layer_count) +vks_check_validation_layer_support(const char* const validation_layers[], + uint32_t validation_layer_count) { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, NULL); @@ -209,13 +259,109 @@ vks_check_validation_layer_support(const char * const validation_layers[], uint3 return layerFound; } +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); + + for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++) { + if ((typeFilter & (1 << i)) && + (mem_properties.memoryTypes[i].propertyFlags & properties) == + properties) { + return i; + } + } + + vk_log(VK_ERROR, "failed to find suitable memory type!\n"); + return 9999; +} + /* Vks API implementation */ +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) +{ + VkImageCreateInfo imageInfo = { 0 }; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent.width = width; + imageInfo.extent.height = height; + imageInfo.extent.depth = 1; + imageInfo.mipLevels = mipLevels; + imageInfo.arrayLayers = 1; + imageInfo.format = format; + imageInfo.tiling = tiling; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.usage = usage; + imageInfo.samples = numSamples; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VK_CHECK(vkCreateImage(vk.device, &imageInfo, NULL, &image->handle)); + + VkMemoryRequirements memRequirements; + vkGetImageMemoryRequirements(vk.device, image->handle, &memRequirements); + + VkMemoryAllocateInfo allocInfo = { 0 }; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.allocationSize = memRequirements.size; + allocInfo.memoryTypeIndex = + find_memory_type(vk, memRequirements.memoryTypeBits, properties); + + // TODO: group allocations etc... (allocations limited by hardware) + VK_CHECK(vkAllocateMemory(vk.device, &allocInfo, NULL, &image->memory)); + + vkBindImageMemory(vk.device, image->handle, image->memory, 0); +} + +VKSDEF void +vks_create_buffer(const vks_context vk, + const VkDeviceSize size, + const VkBufferUsageFlags usage, + const VkMemoryPropertyFlags properties, + vks_buffer* buffer) +{ + VkBufferCreateInfo bufferInfo = { 0 }; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = size; + bufferInfo.usage = usage; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VK_CHECK(vkCreateBuffer(vk.device, &bufferInfo, NULL, &buffer->handle)); + + VkMemoryRequirements mem_requirements; + vkGetBufferMemoryRequirements(vk.device, buffer->handle, &mem_requirements); + + VkMemoryAllocateInfo allocInfo = { 0 }; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.allocationSize = mem_requirements.size; + allocInfo.memoryTypeIndex = + 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) +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)) { + 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(); } @@ -227,30 +373,36 @@ vks_create_instance(bool validation_layers_toggle, const char * const validation 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_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"); + 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", + .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), + .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()); + if (SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, NULL) == + SDL_FALSE) { + vk_log(VK_ERROR, + "SDL_Vulkan_GetInstanceExtensions failed: %s\n", + SDL_GetError()); abort(); } @@ -261,8 +413,11 @@ vks_create_instance(bool validation_layers_toggle, const char * const validation 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()); + if (SDL_Vulkan_GetInstanceExtensions( + window, &sdlExtensionCount, sdlExtensions) == SDL_FALSE) { + vk_log(VK_ERROR, + "SDL_Vulkan_GetInstanceExtensions failed: %s\n", + SDL_GetError()); abort(); } @@ -277,15 +432,15 @@ vks_create_instance(bool validation_layers_toggle, const char * const validation } VkInstanceCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &appInfo, - .enabledExtensionCount = sdlExtensionCount, + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &appInfo, + .enabledExtensionCount = sdlExtensionCount, .ppEnabledExtensionNames = sdlExtensions, - .enabledLayerCount = 0, + .enabledLayerCount = 0, }; if (validation_layers_toggle) { - createInfo.enabledLayerCount = validation_layer_count; + createInfo.enabledLayerCount = validation_layer_count; createInfo.ppEnabledLayerNames = validation_layers; } |