more updates

This commit is contained in:
Mars 2024-10-12 15:39:20 -04:00
parent 545975d6bb
commit 780a7301f5
Signed by untrusted user: pupbrained
GPG key ID: 874E22DF2F9DFCB5
3 changed files with 109 additions and 72 deletions

View file

@ -20,6 +20,7 @@ IndentWidth: 2
NamespaceIndentation: All NamespaceIndentation: All
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: true
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
Standard: Latest
IncludeBlocks: Regroup IncludeBlocks: Regroup
IncludeCategories: IncludeCategories:

View file

@ -1,41 +1,59 @@
// Time measurements
#include <chrono> #include <chrono>
// String formatting
#include <fmt/format.h> #include <fmt/format.h>
#include <fstream>
#include <iostream>
#include <set>
// Make depth go from 0 to 1 instead of -1 to 1
#define GLM_FORCE_DEPTH_ZERO_TO_ONE #define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL // Provides various math-related data structures
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/hash.hpp>
// Used to load models
#define TINYOBJLOADER_IMPLEMENTATION #define TINYOBJLOADER_IMPLEMENTATION
#include <tiny_obj_loader.h> #include <tiny_obj_loader.h>
// Dynamic function loading
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
// Use the beta extensions
#define VK_ENABLE_BETA_EXTENSIONS #define VK_ENABLE_BETA_EXTENSIONS
// Use {} instead of ()
#define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_CONSTRUCTORS
// Vulkan itself
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
// Needed for dynamic function loading to work
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
// Type aliases
#include "util/types.h" #include "util/types.h"
// STB image helper
#include "util/unique_image.h" #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" #include "vkfw.hpp"
// Initial width and height
constexpr i32 WIDTH = 800; constexpr i32 WIDTH = 800;
constexpr i32 HEIGHT = 600; constexpr i32 HEIGHT = 600;
// Paths for the model and texture to render
constexpr const char* MODEL_PATH = "models/viking_room.obj"; constexpr const char* MODEL_PATH = "models/viking_room.obj";
constexpr const char* TEXTURE_PATH = "textures/viking_room.png"; 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 i32 MAX_FRAMES_IN_FLIGHT = 2;
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" }; // macOS requires the portability extension to be enabled
#ifdef __APPLE__ #ifdef __APPLE__
constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtensionName, constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtensionName,
vk::KHRPortabilitySubsetExtensionName }; vk::KHRPortabilitySubsetExtensionName };
@ -43,56 +61,27 @@ constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtens
constexpr std::array<const char*, 1> deviceExtensions = { vk::KHRSwapchainExtensionName }; constexpr std::array<const char*, 1> deviceExtensions = { vk::KHRSwapchainExtensionName };
#endif #endif
// Enable validation layers only in debug mode
#ifdef NDEBUG #ifdef NDEBUG
constexpr bool enableValidationLayers = false; constexpr bool enableValidationLayers = false;
#else #else
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
constexpr bool enableValidationLayers = true; constexpr bool enableValidationLayers = true;
#endif #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<vk::VertexInputAttributeDescription, 3> {
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<Vertex> {
fn operator()(Vertex const& vertex) const->size_t {
return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^
(hash<glm::vec2>()(vertex.tex_coord) << 1);
}
};
}
class VulkanApp { class VulkanApp {
public: public:
fn run() -> void { fn run() -> void {
// Create window
initWindow(); initWindow();
// Setup vulkan
initVulkan(); initVulkan();
// Render loop
mainLoop(); mainLoop();
} }
private: private:
vkfw::UniqueInstance mGLFWInstance; vkfw::UniqueInstance mVKFWInstance;
vkfw::UniqueWindow mWindow; vkfw::UniqueWindow mWindow;
vk::UniqueInstance mInstance; vk::UniqueInstance mInstance;
@ -101,7 +90,7 @@ class VulkanApp {
vk::UniqueSurfaceKHR mSurface; vk::UniqueSurfaceKHR mSurface;
vk::PhysicalDevice mPhysicalDevice; vk::PhysicalDevice mPhysicalDevice;
vk::SampleCountFlagBits mMsaaSamples = vk::SampleCountFlagBits::e1; vk::SampleCountFlagBits mMsaaSamples;
vk::UniqueDevice mDevice; vk::UniqueDevice mDevice;
vk::Queue mGraphicsQueue; vk::Queue mGraphicsQueue;
@ -195,21 +184,16 @@ class VulkanApp {
} }
fn initWindow() -> void { fn initWindow() -> void {
mGLFWInstance = vkfw::initUnique(); mVKFWInstance = vkfw::initUnique();
vkfw::WindowHints hints; vkfw::WindowHints hints { .clientAPI = vkfw::ClientAPI::eNone };
hints.clientAPI = vkfw::ClientAPI::eNone;
mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints);
mWindow->setUserPointer(this); mWindow->setUserPointer(this);
mWindow->setFramebufferSizeCallback(framebufferResizeCallback); mWindow->callbacks()->on_window_resize =
} [](const vkfw::Window& window, u32 /*width*/, u32 /*height*/) -> void {
std::bit_cast<VulkanApp*>(window.getUserPointer())->mFramebufferResized = true;
static fn framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) -> void { };
auto* app = std::bit_cast<VulkanApp*>(glfwGetWindowUserPointer(window));
app->mFramebufferResized = true;
} }
fn initVulkan() -> void { fn initVulkan() -> void {
@ -331,7 +315,7 @@ class VulkanApp {
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | .messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = debugCallback, .pfnUserCallback = debugCallback
}; };
mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr); mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr);
@ -547,8 +531,8 @@ class VulkanApp {
} }
fn createGraphicsPipeline() -> void { fn createGraphicsPipeline() -> void {
std::vector<char> vertShaderCode = readFile("shaders/vert.spv"); std::vector<char> vertShaderCode = readFile(VERTEX_SHADER_PATH);
std::vector<char> fragShaderCode = readFile("shaders/frag.spv"); std::vector<char> fragShaderCode = readFile(FRAGMENT_SHADER_PATH);
vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode); vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode);
vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode); vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode);
@ -670,10 +654,8 @@ class VulkanApp {
fn createCommandPool() -> void { fn createCommandPool() -> void {
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(mPhysicalDevice); QueueFamilyIndices queueFamilyIndices = findQueueFamilies(mPhysicalDevice);
vk::CommandPoolCreateInfo poolInfo { vk::CommandPoolCreateInfo poolInfo { .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, .queueFamilyIndex = queueFamilyIndices.graphics_family.value() };
.queueFamilyIndex = queueFamilyIndices.graphics_family.value(),
};
mCommandPool = mDevice->createCommandPoolUnique(poolInfo); mCommandPool = mDevice->createCommandPoolUnique(poolInfo);
} }
@ -845,10 +827,15 @@ class VulkanApp {
.mipLevel = i, .mipLevel = i,
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = 1 }, .layerCount = 1 },
.dstOffsets = .dstOffsets = std::array<vk::Offset3D, 2> { vk::Offset3D {
std::array<vk::Offset3D, 2> { .x = 0,
{ { .x = 0, .y = 0, .z = 0 }, .y = 0,
{ .x = mipWidth > 1 ? mipWidth / 2 : 1, .y = mipHeight > 1 ? mipHeight / 2 : 1, .z = 1 } } } .z = 0,
}, vk::Offset3D {
.x = mipWidth > 1 ? mipWidth / 2 : 1,
.y = mipHeight > 1 ? mipHeight / 2 : 1,
.z = 1,
} }
}; };
commandBuffer->blitImage( commandBuffer->blitImage(
@ -1653,10 +1640,7 @@ class VulkanApp {
}; };
fn main() -> i32 { fn main() -> i32 {
vk::DynamicLoader dynamicLoader; VULKAN_HPP_DEFAULT_DISPATCHER.init();
auto vkGetInstanceProcAddr =
dynamicLoader.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
VulkanApp app; VulkanApp app;

52
src/util/vertex.h Normal file
View file

@ -0,0 +1,52 @@
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/hash.hpp>
#define VULKAN_HPP_NO_CONSTRUCTORS
#include <vulkan/vulkan.hpp>
#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<vk::VertexInputAttributeDescription, 3> {
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<Vertex> {
fn operator()(Vertex const& vertex) const->size_t {
return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^
(hash<glm::vec2>()(vertex.tex_coord) << 1);
}
};
}