|
@@ -1,17 +1,20 @@
|
|
#include "core/VulkanWrapper.h"
|
|
#include "core/VulkanWrapper.h"
|
|
|
|
|
|
-#define GLFW_INCLUDE_VULKAN
|
|
|
|
-#include <GLFW/glfw3.h>
|
|
|
|
#include <core/Logger.h>
|
|
#include <core/Logger.h>
|
|
#include <core/Utility.h>
|
|
#include <core/Utility.h>
|
|
-#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
-#include <uchar.h>
|
|
|
|
|
|
+
|
|
|
|
+#include "core/internal/GLFW.h"
|
|
|
|
|
|
typedef struct {
|
|
typedef struct {
|
|
VkInstance instance;
|
|
VkInstance instance;
|
|
|
|
+ u32 graphicsFamily;
|
|
VkPhysicalDevice physicalDevice;
|
|
VkPhysicalDevice physicalDevice;
|
|
VkDevice device;
|
|
VkDevice device;
|
|
|
|
+ VkSurfaceKHR surface;
|
|
|
|
+ VkSwapchainKHR swapchain;
|
|
|
|
+ u32 width;
|
|
|
|
+ u32 height;
|
|
} VulkanData;
|
|
} VulkanData;
|
|
static VulkanData vk = {0};
|
|
static VulkanData vk = {0};
|
|
|
|
|
|
@@ -55,7 +58,7 @@ static bool initInstance() {
|
|
.ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
|
|
.ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"},
|
|
.enabledExtensionCount = 4,
|
|
.enabledExtensionCount = 4,
|
|
.ppEnabledExtensionNames =
|
|
.ppEnabledExtensionNames =
|
|
- (const char*[]){"VK_KHR_surface", "VK_KHR_xcb_surface",
|
|
|
|
|
|
+ (const char*[]){"VK_KHR_surface", "VK_KHR_wayland_surface",
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
|
VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
|
|
VK_EXT_DEBUG_REPORT_EXTENSION_NAME}};
|
|
VK_ASSERT(vkCreateInstance(&ci, nullptr, &vk.instance));
|
|
VK_ASSERT(vkCreateInstance(&ci, nullptr, &vk.instance));
|
|
@@ -121,15 +124,15 @@ static bool initDevice() {
|
|
VkPhysicalDeviceFeatures deviceFeatures = {0};
|
|
VkPhysicalDeviceFeatures deviceFeatures = {0};
|
|
vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
|
|
vkGetPhysicalDeviceFeatures(vk.physicalDevice, &deviceFeatures);
|
|
|
|
|
|
- u32 graphicsFamily =
|
|
|
|
|
|
+ vk.graphicsFamily =
|
|
findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
|
|
findQueueFamilies(vk.physicalDevice, VK_QUEUE_GRAPHICS_BIT);
|
|
- if(graphicsFamily == (u32)-1) {
|
|
|
|
|
|
+ if(vk.graphicsFamily == (u32)-1) {
|
|
LOG_ERROR("Cannot find queue family");
|
|
LOG_ERROR("Cannot find queue family");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
VkDeviceQueueCreateInfo dqInfo = {
|
|
VkDeviceQueueCreateInfo dqInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
|
- .queueFamilyIndex = graphicsFamily,
|
|
|
|
|
|
+ .queueFamilyIndex = vk.graphicsFamily,
|
|
.queueCount = 1,
|
|
.queueCount = 1,
|
|
.pQueuePriorities = (float[]){1.0f}};
|
|
.pQueuePriorities = (float[]){1.0f}};
|
|
VkDeviceCreateInfo deviceCreateInfo = {
|
|
VkDeviceCreateInfo deviceCreateInfo = {
|
|
@@ -145,11 +148,105 @@ static bool initDevice() {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool initSurface() {
|
|
|
|
+ VK_ASSERT(glfwCreateWindowSurface(vk.instance, getWindow(), nullptr,
|
|
|
|
+ &vk.surface));
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
|
|
|
|
+ u32 c = caps->minImageCount + 1;
|
|
|
|
+ // according to VkSurfaceCapabilitiesKHR doc:
|
|
|
|
+ // maxImageCount is 0 when there is no strict limit
|
|
|
|
+ if(caps->maxImageCount != 0 && c > caps->maxImageCount) {
|
|
|
|
+ return caps->maxImageCount;
|
|
|
|
+ }
|
|
|
|
+ return c;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool getSurfaceFormat(VkSurfaceFormatKHR* sf) {
|
|
|
|
+ u32 c = 0;
|
|
|
|
+ VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physicalDevice,
|
|
|
|
+ vk.surface, &c, nullptr));
|
|
|
|
+ VkSurfaceFormatKHR* formats = coreAllocate(sizeof(VkSurfaceFormatKHR) * c);
|
|
|
|
+ VK_ASSERT(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.physicalDevice,
|
|
|
|
+ vk.surface, &c, formats));
|
|
|
|
+ for(u32 i = 0; i < c; i++) {
|
|
|
|
+ if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
|
|
|
|
+ formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
|
|
|
+ *sf = formats[i];
|
|
|
|
+ coreFree(formats);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ coreFree(formats);
|
|
|
|
+ LOG_ERROR("Could not find any matching surface format");
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool getPresentMode(VkPresentModeKHR* pm) {
|
|
|
|
+ u32 c = 0;
|
|
|
|
+ VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(
|
|
|
|
+ vk.physicalDevice, vk.surface, &c, nullptr));
|
|
|
|
+ VkPresentModeKHR* modes = coreAllocate(sizeof(VkPresentModeKHR) * c);
|
|
|
|
+ VK_ASSERT(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.physicalDevice,
|
|
|
|
+ vk.surface, &c, modes));
|
|
|
|
+ for(u32 i = 0; i < c; i++) {
|
|
|
|
+ if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
|
|
|
|
+ *pm = modes[i];
|
|
|
|
+ coreFree(modes);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ coreFree(modes);
|
|
|
|
+ LOG_ERROR("Could not find any matching present modes");
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool initSwapchain() {
|
|
|
|
+ VkSurfaceCapabilitiesKHR caps = {0};
|
|
|
|
+ VK_ASSERT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.physicalDevice,
|
|
|
|
+ vk.surface, &caps));
|
|
|
|
+ VkSurfaceFormatKHR sf = {0};
|
|
|
|
+ if(getSurfaceFormat(&sf)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ VkPresentModeKHR pm = {0};
|
|
|
|
+ if(getPresentMode(&pm)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ VkSwapchainCreateInfoKHR ci = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
|
|
|
+ .surface = vk.surface,
|
|
|
|
+ .minImageCount = getSwapImageCount(&caps),
|
|
|
|
+ .imageFormat = sf.format,
|
|
|
|
+ .imageColorSpace = sf.colorSpace,
|
|
|
|
+ .imageExtent = {.width = vk.width, .height = vk.height},
|
|
|
|
+ .imageArrayLayers = 1,
|
|
|
|
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
|
|
|
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
|
|
+ .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
+ .queueFamilyIndexCount = 1,
|
|
|
|
+ .pQueueFamilyIndices = &vk.graphicsFamily,
|
|
|
|
+ .preTransform = caps.currentTransform,
|
|
|
|
+ .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
|
|
|
+ .presentMode = pm,
|
|
|
|
+ .clipped = VK_TRUE,
|
|
|
|
+ .oldSwapchain = VK_NULL_HANDLE};
|
|
|
|
+ VK_ASSERT(vkCreateSwapchainKHR(vk.device, &ci, nullptr, &vk.swapchain));
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
bool initVulkan() {
|
|
bool initVulkan() {
|
|
- return initInstance() || initPhysicalDevice() || initDevice();
|
|
|
|
|
|
+ vk.width = 400;
|
|
|
|
+ vk.height = 300;
|
|
|
|
+ return initInstance() || initPhysicalDevice() || initDevice() ||
|
|
|
|
+ initSurface() || initSwapchain();
|
|
}
|
|
}
|
|
|
|
|
|
void destroyVulkan(void) {
|
|
void destroyVulkan(void) {
|
|
|
|
+ vkDestroySwapchainKHR(vk.device, vk.swapchain, nullptr);
|
|
|
|
+ vkDestroySurfaceKHR(vk.instance, vk.surface, nullptr);
|
|
vkDestroyDevice(vk.device, nullptr);
|
|
vkDestroyDevice(vk.device, nullptr);
|
|
vkDestroyInstance(vk.instance, nullptr);
|
|
vkDestroyInstance(vk.instance, nullptr);
|
|
}
|
|
}
|