From 780a7301f59b54763d944027495fd4b2bbbc45e6 Mon Sep 17 00:00:00 2001 From: Mars Date: Sat, 12 Oct 2024 15:39:20 -0400 Subject: [PATCH] more updates --- .clang-format | 1 + src/main.cpp | 128 ++++++++++++++++++++-------------------------- src/util/vertex.h | 52 +++++++++++++++++++ 3 files changed, 109 insertions(+), 72 deletions(-) create mode 100644 src/util/vertex.h diff --git a/.clang-format b/.clang-format index 9d2cbde..8a6c764 100644 --- a/.clang-format +++ b/.clang-format @@ -20,6 +20,7 @@ IndentWidth: 2 NamespaceIndentation: All SpaceBeforeCpp11BracedList: true SpacesBeforeTrailingComments: 1 +Standard: Latest IncludeBlocks: Regroup IncludeCategories: diff --git a/src/main.cpp b/src/main.cpp index f405818..9a8adfa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,41 +1,59 @@ +// Time measurements #include +// String formatting #include -#include -#include -#include +// Make depth go from 0 to 1 instead of -1 to 1 #define GLM_FORCE_DEPTH_ZERO_TO_ONE -#define GLM_ENABLE_EXPERIMENTAL +// Provides various math-related data structures #include -#include -#include +// Used to load models #define TINYOBJLOADER_IMPLEMENTATION #include +// Dynamic function loading #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 +// Use the beta extensions #define VK_ENABLE_BETA_EXTENSIONS +// Use {} instead of () #define VULKAN_HPP_NO_CONSTRUCTORS +// Vulkan itself #include +// Needed for dynamic function loading to work VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE +// Type aliases #include "util/types.h" + +// STB image helper #include "util/unique_image.h" -#define VKFW_NO_STD_FUNCTION_CALLBACKS +// Vertex class +#include "util/vertex.h" + +// Use {} instead of () +#define VKFW_NO_STRUCT_CONSTRUCTORS +// GLFW C++ wrapper #include "vkfw.hpp" +// Initial width and height constexpr i32 WIDTH = 800; constexpr i32 HEIGHT = 600; +// Paths for the model and texture to render constexpr const char* MODEL_PATH = "models/viking_room.obj"; constexpr const char* TEXTURE_PATH = "textures/viking_room.png"; +// Paths for the shaders +constexpr const char* FRAGMENT_SHADER_PATH = "shaders/frag.spv"; +constexpr const char* VERTEX_SHADER_PATH = "shaders/vert.spv"; + +// Maximum number of frames to be worked on at the same time constexpr i32 MAX_FRAMES_IN_FLIGHT = 2; -constexpr std::array validationLayers = { "VK_LAYER_KHRONOS_validation" }; - +// macOS requires the portability extension to be enabled #ifdef __APPLE__ constexpr std::array deviceExtensions = { vk::KHRSwapchainExtensionName, vk::KHRPortabilitySubsetExtensionName }; @@ -43,56 +61,27 @@ constexpr std::array deviceExtensions = { vk::KHRSwapchainExtens constexpr std::array deviceExtensions = { vk::KHRSwapchainExtensionName }; #endif +// Enable validation layers only in debug mode #ifdef NDEBUG constexpr bool enableValidationLayers = false; #else -constexpr bool enableValidationLayers = true; +constexpr std::array validationLayers = { "VK_LAYER_KHRONOS_validation" }; +constexpr bool enableValidationLayers = true; #endif -struct Vertex { - glm::vec3 pos; - glm::vec3 color; - glm::vec2 tex_coord; - - static fn getBindingDescription() -> vk::VertexInputBindingDescription { - return { .binding = 0, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex }; - } - - static fn getAttributeDescriptions() -> std::array { - using namespace vk; - - return { - VertexInputAttributeDescription { 0, 0, Format::eR32G32B32Sfloat, offsetof(Vertex, pos) }, - VertexInputAttributeDescription { 1, 0, Format::eR32G32B32Sfloat, offsetof(Vertex, color) }, - VertexInputAttributeDescription { 2, 0, Format::eR32G32Sfloat, offsetof(Vertex, tex_coord) } - }; - } - - fn operator==(const Vertex& other) const->bool { - return pos == other.pos && color == other.color && tex_coord == other.tex_coord; - } -}; - -namespace std { - template <> - struct hash { - fn operator()(Vertex const& vertex) const->size_t { - return ((hash()(vertex.pos) ^ (hash()(vertex.color) << 1)) >> 1) ^ - (hash()(vertex.tex_coord) << 1); - } - }; -} - class VulkanApp { public: fn run() -> void { + // Create window initWindow(); + // Setup vulkan initVulkan(); + // Render loop mainLoop(); } private: - vkfw::UniqueInstance mGLFWInstance; + vkfw::UniqueInstance mVKFWInstance; vkfw::UniqueWindow mWindow; vk::UniqueInstance mInstance; @@ -101,7 +90,7 @@ class VulkanApp { vk::UniqueSurfaceKHR mSurface; vk::PhysicalDevice mPhysicalDevice; - vk::SampleCountFlagBits mMsaaSamples = vk::SampleCountFlagBits::e1; + vk::SampleCountFlagBits mMsaaSamples; vk::UniqueDevice mDevice; vk::Queue mGraphicsQueue; @@ -195,21 +184,16 @@ class VulkanApp { } fn initWindow() -> void { - mGLFWInstance = vkfw::initUnique(); + mVKFWInstance = vkfw::initUnique(); - vkfw::WindowHints hints; - - hints.clientAPI = vkfw::ClientAPI::eNone; + vkfw::WindowHints hints { .clientAPI = vkfw::ClientAPI::eNone }; mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); mWindow->setUserPointer(this); - mWindow->setFramebufferSizeCallback(framebufferResizeCallback); - } - - static fn framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) -> void { - auto* app = std::bit_cast(glfwGetWindowUserPointer(window)); - - app->mFramebufferResized = true; + mWindow->callbacks()->on_window_resize = + [](const vkfw::Window& window, u32 /*width*/, u32 /*height*/) -> void { + std::bit_cast(window.getUserPointer())->mFramebufferResized = true; + }; } fn initVulkan() -> void { @@ -331,7 +315,7 @@ class VulkanApp { .messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, - .pfnUserCallback = debugCallback, + .pfnUserCallback = debugCallback }; mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr); @@ -547,8 +531,8 @@ class VulkanApp { } fn createGraphicsPipeline() -> void { - std::vector vertShaderCode = readFile("shaders/vert.spv"); - std::vector fragShaderCode = readFile("shaders/frag.spv"); + std::vector vertShaderCode = readFile(VERTEX_SHADER_PATH); + std::vector fragShaderCode = readFile(FRAGMENT_SHADER_PATH); vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode); vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode); @@ -670,10 +654,8 @@ class VulkanApp { fn createCommandPool() -> void { QueueFamilyIndices queueFamilyIndices = findQueueFamilies(mPhysicalDevice); - vk::CommandPoolCreateInfo poolInfo { - .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, - .queueFamilyIndex = queueFamilyIndices.graphics_family.value(), - }; + vk::CommandPoolCreateInfo poolInfo { .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, + .queueFamilyIndex = queueFamilyIndices.graphics_family.value() }; mCommandPool = mDevice->createCommandPoolUnique(poolInfo); } @@ -845,10 +827,15 @@ class VulkanApp { .mipLevel = i, .baseArrayLayer = 0, .layerCount = 1 }, - .dstOffsets = - std::array { - { { .x = 0, .y = 0, .z = 0 }, - { .x = mipWidth > 1 ? mipWidth / 2 : 1, .y = mipHeight > 1 ? mipHeight / 2 : 1, .z = 1 } } } + .dstOffsets = std::array { vk::Offset3D { + .x = 0, + .y = 0, + .z = 0, + }, vk::Offset3D { + .x = mipWidth > 1 ? mipWidth / 2 : 1, + .y = mipHeight > 1 ? mipHeight / 2 : 1, + .z = 1, + } } }; commandBuffer->blitImage( @@ -1653,10 +1640,7 @@ class VulkanApp { }; fn main() -> i32 { - vk::DynamicLoader dynamicLoader; - auto vkGetInstanceProcAddr = - dynamicLoader.getProcAddress("vkGetInstanceProcAddr"); - VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); + VULKAN_HPP_DEFAULT_DISPATCHER.init(); VulkanApp app; diff --git a/src/util/vertex.h b/src/util/vertex.h new file mode 100644 index 0000000..afdecc4 --- /dev/null +++ b/src/util/vertex.h @@ -0,0 +1,52 @@ +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#define VULKAN_HPP_NO_CONSTRUCTORS +#include + +#include "types.h" + +// Vertex data for the model +struct Vertex { + // Position of the vertex + glm::vec3 pos; + // Color of the vertex (in RGB) + glm::vec3 color; + // Texture coordinates of the vertex + glm::vec2 tex_coord; + + // Returns the binding description for the vertex + static fn getBindingDescription() -> vk::VertexInputBindingDescription { + return { .binding = 0, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex }; + } + + // Returns the attribute descriptions for the vertex + static fn getAttributeDescriptions() -> std::array { + return { + // Position attribute + vk::VertexInputAttributeDescription { 0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, pos) }, + // Color attribute + vk::VertexInputAttributeDescription { 1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color) }, + // Texture coordinate attribute + vk::VertexInputAttributeDescription { 2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, tex_coord) } + }; + } + + // Overload the equality operator for the vertex + fn operator==(const Vertex& other) const->bool { + return pos == other.pos && color == other.color && tex_coord == other.tex_coord; + } +}; + +// Hash function for the vertex +namespace std { + template <> + struct hash { + fn operator()(Vertex const& vertex) const->size_t { + return ((hash()(vertex.pos) ^ (hash()(vertex.color) << 1)) >> 1) ^ + (hash()(vertex.tex_coord) << 1); + } + }; +}