more updates

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

View file

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

View file

@ -1,41 +1,59 @@
// Time measurements
#include <chrono>
// String formatting
#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_ENABLE_EXPERIMENTAL
// Provides various math-related data structures
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/hash.hpp>
// Used to load models
#define TINYOBJLOADER_IMPLEMENTATION
#include <tiny_obj_loader.h>
// 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 <vulkan/vulkan.hpp>
// 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<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
// macOS requires the portability extension to be enabled
#ifdef __APPLE__
constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtensionName,
vk::KHRPortabilitySubsetExtensionName };
@ -43,56 +61,27 @@ constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtens
constexpr std::array<const char*, 1> deviceExtensions = { vk::KHRSwapchainExtensionName };
#endif
// Enable validation layers only in debug mode
#ifdef NDEBUG
constexpr bool enableValidationLayers = false;
#else
constexpr std::array<const char*, 1> 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<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 {
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<VulkanApp*>(glfwGetWindowUserPointer(window));
app->mFramebufferResized = true;
mWindow->callbacks()->on_window_resize =
[](const vkfw::Window& window, u32 /*width*/, u32 /*height*/) -> void {
std::bit_cast<VulkanApp*>(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<char> vertShaderCode = readFile("shaders/vert.spv");
std::vector<char> fragShaderCode = readFile("shaders/frag.spv");
std::vector<char> vertShaderCode = readFile(VERTEX_SHADER_PATH);
std::vector<char> 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<vk::Offset3D, 2> {
{ { .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, 2> { 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<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
VULKAN_HPP_DEFAULT_DISPATCHER.init();
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);
}
};
}