(broken rn) ughghfgdhg

This commit is contained in:
Mars 2024-11-17 20:47:48 -05:00
parent 2b77ce40b5
commit 599eb29925
12 changed files with 289 additions and 139 deletions

View file

@ -37,7 +37,12 @@ deps += imgui_dep
executable(
'graphics-test',
sources: files('src/camera/camera.cpp', 'src/main.cpp'),
sources: [
'src/main.cpp',
'src/camera/camera.cpp',
'src/init/vulkan_instance.cpp',
'src/init/debug_messenger.cpp',
],
include_directories: include_directories('include', is_system: true),
dependencies: deps,
)

View file

@ -5,10 +5,6 @@
#include "../util/types.hpp"
struct CameraInfo {
alignas(16) glm::vec3 position; ///< Camera position
};
/**
* @brief Camera class for handling 3D camera movement and perspective
*/

View file

@ -0,0 +1,32 @@
#include <fmt/format.h>
#include "debug_messenger.hpp"
fn DebugMessenger::create(const vk::Instance& instance) -> vk::UniqueDebugUtilsMessengerEXT {
#ifdef NDEBUG
return nullptr;
#else
vk::DebugUtilsMessengerCreateInfoEXT createInfo {
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = debugCallback,
.pUserData = nullptr,
};
return instance.createDebugUtilsMessengerEXTUnique(createInfo);
#endif
}
VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessenger::debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
VkDebugUtilsMessageTypeFlagsEXT /*messageType*/,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* /*pUserData*/
) {
fmt::println("validation layer: {}", pCallbackData->pMessage);
return VK_FALSE;
}

View file

@ -0,0 +1,27 @@
#pragma once
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 // Use dynamic dispatch for Vulkan functions
#define VULKAN_HPP_NO_CONSTRUCTORS
#include <vulkan/vulkan.hpp>
#include "../util/types.hpp"
class DebugMessenger {
public:
DebugMessenger() = default;
DebugMessenger(const DebugMessenger&) = default;
DebugMessenger(DebugMessenger&&) = delete;
fn operator=(const DebugMessenger&)->DebugMessenger& = default;
fn operator=(DebugMessenger&&)->DebugMessenger& = delete;
~DebugMessenger() = default;
static fn create(const vk::Instance& instance) -> vk::UniqueDebugUtilsMessengerEXT;
private:
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData
);
};

View file

@ -0,0 +1,101 @@
#include <fmt/format.h>
#include "vulkan_instance.hpp"
#include "../util/constants.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
using namespace constants;
fn VulkanInstance::create() -> vk::UniqueInstance {
#ifndef NDEBUG
// Make sure validation layers are supported
if (!checkValidationLayerSupport())
throw std::runtime_error("Validation layers requested, but not available!");
#endif
// Application metadata
vk::ApplicationInfo appInfo {
.pApplicationName = "Vulkan App",
.applicationVersion = 1,
.pEngineName = "No Engine",
.engineVersion = 1,
.apiVersion = vk::ApiVersion13,
};
// Get required extensions
auto extensions = getRequiredExtensions();
#ifndef NDEBUG
fmt::println("Available extensions:");
for (const char* extension : extensions) { fmt::println("\t{}", extension); }
#endif
// Create the instance
vk::InstanceCreateInfo createInfo {
#ifdef __APPLE__
.flags = vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR,
#endif
.pApplicationInfo = &appInfo,
#ifdef NDEBUG
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
#else
.enabledLayerCount = static_cast<u32>(validationLayers.size()),
.ppEnabledLayerNames = validationLayers.data(),
#endif
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data()
};
auto instance = vk::createInstanceUnique(createInfo);
// Initialize the dynamic dispatcher with the instance
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance.get());
return instance;
}
fn VulkanInstance::getRequiredExtensions() -> std::vector<const char*> {
// Get the required extensions from GLFW
std::span<const char*> extensionsSpan = vkfw::getRequiredInstanceExtensions();
std::vector<const char*> extensions(extensionsSpan.begin(), extensionsSpan.end());
#ifndef NDEBUG
// Add debug utils extension in debug mode
extensions.push_back(vk::EXTDebugUtilsExtensionName);
#endif
#ifdef __APPLE__
// Add required macOS extensions
extensions.push_back(vk::KHRPortabilityEnumerationExtensionName);
extensions.push_back("VK_KHR_get_physical_device_properties2");
#endif
return extensions;
}
fn VulkanInstance::checkValidationLayerSupport() -> bool {
// Get available layers
auto availableLayers = vk::enumerateInstanceLayerProperties();
// Check if all requested validation layers are available
for (const char* layerName : validationLayers) {
bool layerFound = false;
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}

View file

@ -0,0 +1,25 @@
#pragma once
#define VKFW_NO_STRUCT_CONSTRUCTORS // Use aggregate initialization for GLFW structs
#include <vkfw.hpp>
#define VULKAN_HPP_NO_CONSTRUCTORS
#include <vulkan/vulkan.hpp>
#include "../util/types.hpp"
class VulkanInstance {
public:
VulkanInstance() = default;
VulkanInstance(const VulkanInstance&) = default;
VulkanInstance(VulkanInstance&&) = delete;
fn operator=(const VulkanInstance&)->VulkanInstance& = default;
fn operator=(VulkanInstance&&)->VulkanInstance& = delete;
~VulkanInstance() = default;
static fn create() -> vk::UniqueInstance;
private:
static fn getRequiredExtensions() -> std::vector<const char*>;
static fn checkValidationLayerSupport() -> bool;
};

View file

@ -19,11 +19,15 @@
#define VULKAN_HPP_NO_CONSTRUCTORS // Use aggregate initialization for Vulkan structs
#include <vulkan/vulkan.hpp> // Include Vulkan C++ bindings
// Necessary for dynamic dispatch to work
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
// Include custom utility headers
#include "camera/camera.hpp" // Camera class
#include "camera/camera.hpp" // Camera class
#include "init/debug_messenger.hpp"
#include "init/vulkan_instance.hpp"
#include "structs/camera_info.hpp"
#include "structs/light_info.hpp"
#include "structs/queue_family_indices.hpp"
#include "structs/swap_chain_support_details.hpp"
#include "structs/uniform_buffer_object.hpp"
#include "util/constants.hpp" // Constants definitions
#include "util/crosshair.hpp" // Crosshair definitions
#include "util/shaders.hpp" // Compiled shader code
@ -156,23 +160,10 @@ class VulkanApp {
Camera mCamera; ///< Camera object
// Light settings
struct {
glm::vec3 position = glm::vec3(2.0F, 2.0F, 2.0F);
glm::vec3 color = glm::vec3(1.0F, 1.0F, 1.0F);
float ambient_strength = 0.1F;
float specular_strength = 0.5F;
} mLightSettings;
std::vector<vk::UniqueSemaphore>
mImageAvailableSemaphores; ///< Signals that an image is available for rendering
std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores; ///< Signals that rendering has finished
std::vector<vk::UniqueFence> mInFlightFences; ///< Ensures CPU-GPU synchronization
std::vector<vk::Fence> mImagesInFlight; ///< Tracks which fences are in use by which swap chain images
bool mFramebufferResized = false; ///< Flag indicating if the framebuffer was resized
u32 mCurrentFrame = 0; ///< Index of the current frame being rendered
glm::mat4 mView; ///< View matrix
LightInfo mLightSettings { .position = glm::vec3(2.0F, 2.0F, 2.0F),
.color = glm::vec3(1.0F, 1.0F, 1.0F),
.ambient_strength = 0.1F,
.specular_strength = 0.5F };
// Mouse input tracking
bool mFirstMouse = true; ///< Flag for first mouse movement
@ -188,52 +179,16 @@ class VulkanApp {
f32 mMaxLineWidth = 1.0F; ///< Maximum supported line width
bool mWideLineSupport = false; ///< Whether wide lines are supported
/**
* @brief Struct to store queue family indices.
*
* This struct contains the indices of the graphics and presentation queue families.
*/
struct QueueFamilyIndices {
std::optional<u32> graphics_family; ///< Index of graphics queue family
std::optional<u32> present_family; ///< Index of presentation queue family
std::vector<vk::UniqueSemaphore>
mImageAvailableSemaphores; ///< Signals that an image is available for rendering
std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores; ///< Signals that rendering has finished
std::vector<vk::UniqueFence> mInFlightFences; ///< Ensures CPU-GPU synchronization
std::vector<vk::Fence> mImagesInFlight; ///< Tracks which fences are in use by which swap chain images
/**
* @brief Check if all required queue families are found.
*
* @return True if both graphics and presentation families are found, false otherwise.
*/
fn isComplete() -> bool { return graphics_family.has_value() && present_family.has_value(); }
};
bool mFramebufferResized = false; ///< Flag indicating if the framebuffer was resized
u32 mCurrentFrame = 0; ///< Index of the current frame being rendered
/**
* @brief Struct to hold swap chain support details.
*
* This struct contains information about the surface capabilities,
* supported formats, and presentation modes.
*/
struct SwapChainSupportDetails {
vk::SurfaceCapabilitiesKHR capabilities; ///< Surface capabilities
std::vector<vk::SurfaceFormatKHR> formats; ///< Supported surface formats
std::vector<vk::PresentModeKHR> present_modes; ///< Supported presentation modes
};
/**
* @brief Struct representing a uniform buffer object.
*
* This struct holds the model, view, and projection matrices for use in shaders.
*/
struct UniformBufferObject {
alignas(16) glm::mat4 model; ///< Model transformation matrix
alignas(16) glm::mat4 view; ///< View transformation matrix
alignas(16) glm::mat4 proj; ///< Projection matrix
};
struct LightInfo {
alignas(16) glm::vec3 position; ///< Light position
alignas(16) glm::vec3 color; ///< Light color
alignas(4) float ambient_strength; ///< Ambient strength
alignas(4) float specular_strength; ///< Specular strength
};
glm::mat4 mView; ///< View matrix
static fn processInput(vkfw::Window& window, Camera& camera, const f32& deltaTime, const f32& cameraSpeed)
-> void {
@ -699,63 +654,7 @@ class VulkanApp {
throw std::runtime_error("Validation layers requested, but not available!");
#endif
// Application metadata
vk::ApplicationInfo appInfo {
.pApplicationName = "Vulkan App",
.applicationVersion = 1,
.pEngineName = "No Engine",
.engineVersion = 1,
.apiVersion = vk::ApiVersion13,
};
// Get the required extensions
std::span<const char*> extensionsSpan = vkfw::getRequiredInstanceExtensions();
// Convert the span to a vector
std::vector extensions(extensionsSpan.begin(), extensionsSpan.end());
#ifndef NDEBUG
// Add the debug utils extension
extensions.emplace_back(vk::EXTDebugUtilsExtensionName);
#endif
#ifdef __APPLE__
// Add the portability extension
extensions.emplace_back(vk::KHRPortabilityEnumerationExtensionName);
// Technically deprecated but Vulkan complains if I don't include it for macOS,
// so instead of using the vk::KHRPortabilitySubsetExtensionName, I just use
// the direct string.
extensions.emplace_back("VK_KHR_get_physical_device_properties2");
#endif
// Create the instance
vk::InstanceCreateInfo createInfo {
#ifdef __APPLE__
// Enable the portability extension
.flags = vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR,
#endif
.pApplicationInfo = &appInfo,
#ifdef NDEBUG
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
#else
.enabledLayerCount = static_cast<u32>(validationLayers.size()),
.ppEnabledLayerNames = validationLayers.data(),
#endif
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data()
};
#ifndef NDEBUG
fmt::println("Available extensions:");
for (const char* extension : extensions) fmt::println("\t{}", extension);
#endif
// Create the instance
mInstance = vk::createInstanceUnique(createInfo);
// Load the instance functions
VULKAN_HPP_DEFAULT_DISPATCHER.init(mInstance.get());
mInstance = VulkanInstance::create();
}
/**
@ -768,17 +667,7 @@ class VulkanApp {
return;
#endif
vk::DebugUtilsMessengerCreateInfoEXT messengerCreateInfo {
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = debugCallback
};
mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr);
mDebugMessenger = DebugMessenger::create(mInstance.get());
}
/**
@ -1188,7 +1077,6 @@ class VulkanApp {
vk::PipelineColorBlendStateCreateInfo colorBlending {
.logicOpEnable = vk::False,
.logicOp = vk::LogicOp::eCopy,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachment,
.blendConstants = std::array<f32, 4> { 0.0F, 0.0F, 0.0F, 0.0F },

View file

@ -0,0 +1,10 @@
#pragma once
#include <glm/glm.hpp>
/**
* @brief Struct containing camera information for shading.
*/
struct CameraInfo {
alignas(16) glm::vec3 position; ///< Camera position in world space
};

View file

@ -0,0 +1,13 @@
#pragma once
#include <glm/glm.hpp>
/**
* @brief Struct containing light information for shading.
*/
struct LightInfo {
alignas(16) glm::vec3 position; ///< Light position
alignas(16) glm::vec3 color; ///< Light color
alignas(4) float ambient_strength; ///< Ambient strength
alignas(4) float specular_strength; ///< Specular strength
};

View file

@ -0,0 +1,23 @@
#pragma once
#include <optional>
#include "../util/types.hpp"
/**
* @brief Struct to store queue family indices.
*
* This struct contains the indices of the graphics and presentation queue families.
*/
struct QueueFamilyIndices {
std::optional<u32> graphics_family; ///< Index of graphics queue family
std::optional<u32> present_family; ///< Index of presentation queue family
/**
* @brief Check if all required queue families are found.
*
* @return True if both graphics and presentation families are found, false otherwise.
*/
[[nodiscard]] fn isComplete() const -> bool {
return graphics_family.has_value() && present_family.has_value();
}
};

View file

@ -0,0 +1,16 @@
#pragma once
#include <vector>
#include <vulkan/vulkan.hpp>
/**
* @brief Struct to hold swap chain support details.
*
* This struct contains information about the surface capabilities,
* supported formats, and presentation modes.
*/
struct SwapChainSupportDetails {
vk::SurfaceCapabilitiesKHR capabilities; ///< Surface capabilities
std::vector<vk::SurfaceFormatKHR> formats; ///< Supported surface formats
std::vector<vk::PresentModeKHR> present_modes; ///< Supported presentation modes
};

View file

@ -0,0 +1,14 @@
#pragma once
#include <glm/glm.hpp>
/**
* @brief Struct representing a uniform buffer object.
*
* This struct holds the model, view, and projection matrices for use in shaders.
*/
struct UniformBufferObject {
alignas(16) glm::mat4 model; ///< Model transformation matrix
alignas(16) glm::mat4 view; ///< View transformation matrix
alignas(16) glm::mat4 proj; ///< Projection matrix
};