forked from pupbrained/vulkan-test
idk why this isnt working rn but whatever
This commit is contained in:
parent
1732d56e22
commit
f0e85c0d88
232
src/main.cpp
232
src/main.cpp
|
@ -1,9 +1,13 @@
|
||||||
|
#include <chrono>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||||
#define VK_ENABLE_BETA_EXTENSIONS
|
#define VK_ENABLE_BETA_EXTENSIONS
|
||||||
#define VULKAN_HPP_NO_CONSTRUCTORS
|
#define VULKAN_HPP_NO_CONSTRUCTORS
|
||||||
|
@ -21,42 +25,6 @@ constexpr i32 HEIGHT = 600;
|
||||||
|
|
||||||
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
|
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
struct Vertex {
|
|
||||||
glm::vec2 pos;
|
|
||||||
glm::vec3 color;
|
|
||||||
|
|
||||||
static fn getBindingDescription() -> vk::VertexInputBindingDescription {
|
|
||||||
vk::VertexInputBindingDescription bindingDescription { .binding = 0,
|
|
||||||
.stride = sizeof(Vertex),
|
|
||||||
.inputRate = vk::VertexInputRate::eVertex };
|
|
||||||
|
|
||||||
return bindingDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 2> {
|
|
||||||
std::array<vk::VertexInputAttributeDescription, 2> attributeDescriptions {};
|
|
||||||
|
|
||||||
attributeDescriptions[0] = {
|
|
||||||
.location = 0, .binding = 0, .format = vk::Format::eR32G32Sfloat, .offset = offsetof(Vertex, pos)
|
|
||||||
};
|
|
||||||
|
|
||||||
attributeDescriptions[1] = {
|
|
||||||
.location = 1, .binding = 0, .format = vk::Format::eR32G32B32Sfloat, .offset = offsetof(Vertex, color)
|
|
||||||
};
|
|
||||||
|
|
||||||
return attributeDescriptions;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr std::array<Vertex, 4> vertices = {
|
|
||||||
{ { { -0.5F, -0.5F }, { 1.0F, 0.0F, 0.0F } },
|
|
||||||
{ { 0.5F, -0.5F }, { 0.0F, 1.0F, 0.0F } },
|
|
||||||
{ { 0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F } },
|
|
||||||
{ { -0.5F, 0.5F }, { 1.0F, 1.0F, 1.0F } } }
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr std::array<u16, 6> indices = { 0, 1, 2, 2, 3, 0 };
|
|
||||||
|
|
||||||
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -72,6 +40,31 @@ constexpr bool enableValidationLayers = false;
|
||||||
constexpr bool enableValidationLayers = true;
|
constexpr bool enableValidationLayers = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
glm::vec2 pos;
|
||||||
|
glm::vec3 color;
|
||||||
|
|
||||||
|
static fn getBindingDescription() -> vk::VertexInputBindingDescription {
|
||||||
|
return { .binding = 0, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex };
|
||||||
|
}
|
||||||
|
|
||||||
|
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 2> {
|
||||||
|
return {
|
||||||
|
vk::VertexInputAttributeDescription { 0, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, pos) },
|
||||||
|
vk::VertexInputAttributeDescription { 1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<Vertex, 4> vertices = {
|
||||||
|
{ { { -0.5F, -0.5F }, { 1.0F, 0.0F, 0.0F } },
|
||||||
|
{ { 0.5F, -0.5F }, { 0.0F, 1.0F, 0.0F } },
|
||||||
|
{ { 0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F } },
|
||||||
|
{ { -0.5F, 0.5F }, { 1.0F, 1.0F, 1.0F } } }
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u16, 6> indices = { 0, 1, 2, 2, 3, 0 };
|
||||||
|
|
||||||
class VulkanApp {
|
class VulkanApp {
|
||||||
public:
|
public:
|
||||||
fn run() -> void {
|
fn run() -> void {
|
||||||
|
@ -102,22 +95,31 @@ class VulkanApp {
|
||||||
std::vector<vk::UniqueImageView> mSwapChainImageViews;
|
std::vector<vk::UniqueImageView> mSwapChainImageViews;
|
||||||
std::vector<vk::UniqueFramebuffer> mSwapChainFramebuffers;
|
std::vector<vk::UniqueFramebuffer> mSwapChainFramebuffers;
|
||||||
|
|
||||||
vk::UniqueRenderPass mRenderPass;
|
vk::UniqueRenderPass mRenderPass;
|
||||||
vk::UniquePipelineLayout mPipelineLayout;
|
vk::UniqueDescriptorSetLayout mDescriptorSetLayout;
|
||||||
vk::UniquePipeline mGraphicsPipeline;
|
vk::UniquePipelineLayout mPipelineLayout;
|
||||||
|
vk::UniquePipeline mGraphicsPipeline;
|
||||||
|
|
||||||
vk::UniqueCommandPool mCommandPool;
|
vk::UniqueCommandPool mCommandPool;
|
||||||
std::vector<vk::UniqueCommandBuffer> mCommandBuffers;
|
|
||||||
|
|
||||||
std::vector<vk::UniqueSemaphore> mImageAvailableSemaphores;
|
|
||||||
std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores;
|
|
||||||
std::vector<vk::UniqueFence> mInFlightFences;
|
|
||||||
|
|
||||||
vk::UniqueBuffer mVertexBuffer;
|
vk::UniqueBuffer mVertexBuffer;
|
||||||
vk::UniqueDeviceMemory mVertexBufferMemory;
|
vk::UniqueDeviceMemory mVertexBufferMemory;
|
||||||
vk::UniqueBuffer mIndexBuffer;
|
vk::UniqueBuffer mIndexBuffer;
|
||||||
vk::UniqueDeviceMemory mIndexBufferMemory;
|
vk::UniqueDeviceMemory mIndexBufferMemory;
|
||||||
|
|
||||||
|
std::vector<vk::UniqueBuffer> mUniformBuffers;
|
||||||
|
std::vector<vk::UniqueDeviceMemory> mUniformBuffersMemory;
|
||||||
|
std::vector<void*> mUniformBuffersMapped;
|
||||||
|
|
||||||
|
vk::UniqueDescriptorPool mDescriptorPool;
|
||||||
|
std::vector<vk::DescriptorSet> mDescriptorSets;
|
||||||
|
|
||||||
|
std::vector<vk::UniqueCommandBuffer> mCommandBuffers;
|
||||||
|
|
||||||
|
std::vector<vk::UniqueSemaphore> mImageAvailableSemaphores;
|
||||||
|
std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores;
|
||||||
|
std::vector<vk::UniqueFence> mInFlightFences;
|
||||||
|
|
||||||
bool mFramebufferResized = false;
|
bool mFramebufferResized = false;
|
||||||
u32 mCurrentFrame = 0;
|
u32 mCurrentFrame = 0;
|
||||||
|
|
||||||
|
@ -134,6 +136,12 @@ class VulkanApp {
|
||||||
std::vector<vk::PresentModeKHR> present_modes;
|
std::vector<vk::PresentModeKHR> present_modes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UniformBufferObject {
|
||||||
|
alignas(16) glm::mat4 model;
|
||||||
|
alignas(16) glm::mat4 view;
|
||||||
|
alignas(16) glm::mat4 proj;
|
||||||
|
};
|
||||||
|
|
||||||
static fn readFile(const std::string& filename) -> std::vector<char> {
|
static fn readFile(const std::string& filename) -> std::vector<char> {
|
||||||
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
||||||
|
|
||||||
|
@ -178,11 +186,15 @@ class VulkanApp {
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
|
createDescriptorSetLayout();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFramebuffers();
|
createFramebuffers();
|
||||||
createCommandPool();
|
createCommandPool();
|
||||||
createVertexBuffer();
|
createVertexBuffer();
|
||||||
createIndexBuffer();
|
createIndexBuffer();
|
||||||
|
createUniformBuffers();
|
||||||
|
createDescriptorPool();
|
||||||
|
createDescriptorSets();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
createSyncObjects();
|
createSyncObjects();
|
||||||
}
|
}
|
||||||
|
@ -445,6 +457,23 @@ class VulkanApp {
|
||||||
mRenderPass = mDevice->createRenderPassUnique(renderPassInfo);
|
mRenderPass = mDevice->createRenderPassUnique(renderPassInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn createDescriptorSetLayout() -> void {
|
||||||
|
vk::DescriptorSetLayoutBinding uboLayoutBinding {
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
||||||
|
.pImmutableSamplers = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::DescriptorSetLayoutCreateInfo layoutInfo {
|
||||||
|
.bindingCount = 1,
|
||||||
|
.pBindings = &uboLayoutBinding,
|
||||||
|
};
|
||||||
|
|
||||||
|
mDescriptorSetLayout = mDevice->createDescriptorSetLayoutUnique(layoutInfo);
|
||||||
|
}
|
||||||
|
|
||||||
fn createGraphicsPipeline() -> void {
|
fn createGraphicsPipeline() -> void {
|
||||||
std::vector<char> vertShaderCode = readFile("src/shaders/vert.spv");
|
std::vector<char> vertShaderCode = readFile("src/shaders/vert.spv");
|
||||||
std::vector<char> fragShaderCode = readFile("src/shaders/frag.spv");
|
std::vector<char> fragShaderCode = readFile("src/shaders/frag.spv");
|
||||||
|
@ -493,7 +522,7 @@ class VulkanApp {
|
||||||
.rasterizerDiscardEnable = vk::False,
|
.rasterizerDiscardEnable = vk::False,
|
||||||
.polygonMode = vk::PolygonMode::eFill,
|
.polygonMode = vk::PolygonMode::eFill,
|
||||||
.cullMode = vk::CullModeFlagBits::eBack,
|
.cullMode = vk::CullModeFlagBits::eBack,
|
||||||
.frontFace = vk::FrontFace::eClockwise,
|
.frontFace = vk::FrontFace::eCounterClockwise,
|
||||||
.depthBiasEnable = vk::False,
|
.depthBiasEnable = vk::False,
|
||||||
.lineWidth = 1.0F,
|
.lineWidth = 1.0F,
|
||||||
};
|
};
|
||||||
|
@ -516,6 +545,7 @@ class VulkanApp {
|
||||||
.pAttachments = &colorBlendAttachment,
|
.pAttachments = &colorBlendAttachment,
|
||||||
.blendConstants = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 0.0F },
|
.blendConstants = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 0.0F },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<vk::DynamicState> dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
std::vector<vk::DynamicState> dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||||
|
|
||||||
vk::PipelineDynamicStateCreateInfo dynamicState {
|
vk::PipelineDynamicStateCreateInfo dynamicState {
|
||||||
|
@ -524,8 +554,8 @@ class VulkanApp {
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutInfo {
|
vk::PipelineLayoutCreateInfo pipelineLayoutInfo {
|
||||||
.setLayoutCount = 0,
|
.setLayoutCount = 1,
|
||||||
.pushConstantRangeCount = 0,
|
.pSetLayouts = &mDescriptorSetLayout.get(),
|
||||||
};
|
};
|
||||||
|
|
||||||
mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo);
|
mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo);
|
||||||
|
@ -593,7 +623,7 @@ class VulkanApp {
|
||||||
|
|
||||||
createBuffer(
|
createBuffer(
|
||||||
bufferSize,
|
bufferSize,
|
||||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
vk::BufferUsageFlagBits::eTransferSrc,
|
||||||
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
|
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
|
||||||
stagingBuffer,
|
stagingBuffer,
|
||||||
stagingBufferMemory
|
stagingBufferMemory
|
||||||
|
@ -649,6 +679,72 @@ class VulkanApp {
|
||||||
stagingBufferMemory.reset();
|
stagingBufferMemory.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn createUniformBuffers() -> void {
|
||||||
|
vk::DeviceSize bufferSize = sizeof(UniformBufferObject);
|
||||||
|
|
||||||
|
mUniformBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
mUniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
mUniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
for (usize i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
createBuffer(
|
||||||
|
bufferSize,
|
||||||
|
vk::BufferUsageFlagBits::eUniformBuffer,
|
||||||
|
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
|
||||||
|
mUniformBuffers[i],
|
||||||
|
mUniformBuffersMemory[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
mUniformBuffersMapped[i] = mDevice->mapMemory(mUniformBuffersMemory[i].get(), 0, bufferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createDescriptorPool() -> void {
|
||||||
|
vk::DescriptorPoolSize poolSize {
|
||||||
|
.type = vk::DescriptorType::eUniformBuffer,
|
||||||
|
.descriptorCount = static_cast<u32>(MAX_FRAMES_IN_FLIGHT),
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::DescriptorPoolCreateInfo poolInfo {
|
||||||
|
.maxSets = static_cast<u32>(MAX_FRAMES_IN_FLIGHT),
|
||||||
|
.poolSizeCount = 1,
|
||||||
|
.pPoolSizes = &poolSize,
|
||||||
|
};
|
||||||
|
|
||||||
|
mDescriptorPool = mDevice->createDescriptorPoolUnique(poolInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createDescriptorSets() -> void {
|
||||||
|
std::vector<vk::DescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, mDescriptorSetLayout.get());
|
||||||
|
|
||||||
|
vk::DescriptorSetAllocateInfo allocInfo {
|
||||||
|
.descriptorPool = mDescriptorPool.get(),
|
||||||
|
.descriptorSetCount = static_cast<u32>(MAX_FRAMES_IN_FLIGHT),
|
||||||
|
.pSetLayouts = layouts.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
mDescriptorSets = mDevice->allocateDescriptorSets(allocInfo);
|
||||||
|
|
||||||
|
for (usize i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
vk::DescriptorBufferInfo bufferInfo {
|
||||||
|
.buffer = mUniformBuffers[i].get(),
|
||||||
|
.offset = 0,
|
||||||
|
.range = sizeof(UniformBufferObject),
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::WriteDescriptorSet descriptorWrite {
|
||||||
|
.dstSet = mDescriptorSets[i],
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
|
.pBufferInfo = &bufferInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
mDevice->updateDescriptorSets(1, &descriptorWrite, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn createBuffer(
|
fn createBuffer(
|
||||||
vk::DeviceSize deviceSize,
|
vk::DeviceSize deviceSize,
|
||||||
vk::BufferUsageFlags bufferUsageFlags,
|
vk::BufferUsageFlags bufferUsageFlags,
|
||||||
|
@ -762,6 +858,16 @@ class VulkanApp {
|
||||||
|
|
||||||
commandBuffer.bindIndexBuffer(mIndexBuffer.get(), 0, vk::IndexType::eUint16);
|
commandBuffer.bindIndexBuffer(mIndexBuffer.get(), 0, vk::IndexType::eUint16);
|
||||||
|
|
||||||
|
commandBuffer.bindDescriptorSets(
|
||||||
|
vk::PipelineBindPoint::eGraphics,
|
||||||
|
mPipelineLayout.get(),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&mDescriptorSets[mCurrentFrame],
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
commandBuffer.drawIndexed(static_cast<u32>(indices.size()), 1, 0, 0, 0);
|
commandBuffer.drawIndexed(static_cast<u32>(indices.size()), 1, 0, 0, 0);
|
||||||
|
|
||||||
commandBuffer.endRenderPass();
|
commandBuffer.endRenderPass();
|
||||||
|
@ -784,6 +890,30 @@ class VulkanApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn updateUniformBuffer(u32 currentImage) -> void {
|
||||||
|
static auto StartTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||||
|
f32 time = std::chrono::duration<f32, std::chrono::seconds::period>(currentTime - StartTime).count();
|
||||||
|
|
||||||
|
UniformBufferObject ubo {
|
||||||
|
.model = glm::rotate(glm::mat4(1.0F), time * glm::radians(90.0F), glm::vec3(0.0F, 0.0F, 1.0F)),
|
||||||
|
.view =
|
||||||
|
glm::lookAt(glm::vec3(2.0F, 2.0F, 2.0F), glm::vec3(0.0F, 0.0F, 0.0F), glm::vec3(0.0F, 0.0F, 1.0F)),
|
||||||
|
.proj = glm::perspective(
|
||||||
|
glm::radians(45.0F),
|
||||||
|
static_cast<f32>(mSwapChainExtent.width) / static_cast<f32>(mSwapChainExtent.height),
|
||||||
|
0.1F,
|
||||||
|
10.0F
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Flip the Y axis, because glm was designed for OpenGL
|
||||||
|
ubo.proj[1][1] *= -1;
|
||||||
|
|
||||||
|
memcpy(mUniformBuffersMapped[currentImage], &ubo, sizeof(ubo));
|
||||||
|
}
|
||||||
|
|
||||||
fn drawFrame() -> void {
|
fn drawFrame() -> void {
|
||||||
try {
|
try {
|
||||||
vk::Result result =
|
vk::Result result =
|
||||||
|
@ -807,6 +937,8 @@ class VulkanApp {
|
||||||
if (imageIndexResult != vk::Result::eSuccess && imageIndexResult != vk::Result::eSuboptimalKHR)
|
if (imageIndexResult != vk::Result::eSuccess && imageIndexResult != vk::Result::eSuboptimalKHR)
|
||||||
throw std::runtime_error("Failed to acquire swap chain image!");
|
throw std::runtime_error("Failed to acquire swap chain image!");
|
||||||
|
|
||||||
|
updateUniformBuffer(mCurrentFrame);
|
||||||
|
|
||||||
mDevice->resetFences(mInFlightFences[mCurrentFrame].get());
|
mDevice->resetFences(mInFlightFences[mCurrentFrame].get());
|
||||||
|
|
||||||
mCommandBuffers[mCurrentFrame]->reset(vk::CommandBufferResetFlagBits::eReleaseResources);
|
mCommandBuffers[mCurrentFrame]->reset(vk::CommandBufferResetFlagBits::eReleaseResources);
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout(binding = 0) uniform UniformBufferObject {
|
||||||
|
mat4 model;
|
||||||
|
mat4 view;
|
||||||
|
mat4 proj;
|
||||||
|
} ubo;
|
||||||
|
|
||||||
layout(location = 0) in vec2 inPosition;
|
layout(location = 0) in vec2 inPosition;
|
||||||
layout(location = 1) in vec3 inColor;
|
layout(location = 1) in vec3 inColor;
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue