forked from pupbrained/vulkan-test
more updates
This commit is contained in:
parent
545975d6bb
commit
780a7301f5
|
@ -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:
|
||||||
|
|
128
src/main.cpp
128
src/main.cpp
|
@ -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 bool enableValidationLayers = true;
|
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||||
|
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
52
src/util/vertex.h
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue