Descriptor Set use started.
Fixed unbounded memory consumption bug.
This commit is contained in:
parent
8fab687a20
commit
63af9954d9
|
|
@ -1,27 +1,27 @@
|
|||
{
|
||||
"version": 2,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
|
||||
"CMAKE_MAKE_PROGRAM": "ninja",
|
||||
"CMAKE_C_COMPILER": "/usr/bin/clang",
|
||||
"CMAKE_CXX_COMPILER": "/usr/bin/clang++",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
|
||||
"CMAKE_MAKE_PROGRAM": "ninja",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
}
|
||||
]
|
||||
"version": 2,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "linux",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
|
||||
"CMAKE_MAKE_PROGRAM": "ninja",
|
||||
"CMAKE_C_COMPILER": "/usr/bin/clang",
|
||||
"CMAKE_CXX_COMPILER": "/usr/bin/clang++",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
|
||||
"CMAKE_MAKE_PROGRAM": "ninja",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
|
||||
#define VULKAN_HPP_NO_EXCEPTIONS 1
|
||||
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
|
|
|
|||
|
|
@ -7,15 +7,22 @@
|
|||
|
||||
#include "device.h"
|
||||
|
||||
Pipeline::Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline)
|
||||
Pipeline::Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline,
|
||||
eastl::vector<vk::DescriptorSetLayout> &&setLayouts)
|
||||
: m_Device(device)
|
||||
, m_Layout(layout)
|
||||
, m_Pipeline(pipeline)
|
||||
, m_SetLayouts(std::move(setLayouts))
|
||||
{
|
||||
}
|
||||
|
||||
Pipeline::~Pipeline()
|
||||
{
|
||||
for (const auto setLayout : m_SetLayouts)
|
||||
{
|
||||
m_Device->m_Device.destroy(setLayout, nullptr);
|
||||
}
|
||||
m_SetLayouts.clear();
|
||||
m_Device->m_Device.destroy(m_Pipeline, nullptr);
|
||||
m_Device->m_Device.destroy(m_Layout, nullptr);
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "global.h"
|
||||
|
||||
#include <EASTL/vector.h>
|
||||
|
||||
struct Device;
|
||||
|
||||
struct Pipeline
|
||||
|
|
@ -14,7 +16,9 @@ struct Pipeline
|
|||
const Device *m_Device;
|
||||
vk::PipelineLayout m_Layout;
|
||||
vk::Pipeline m_Pipeline;
|
||||
eastl::vector<vk::DescriptorSetLayout> m_SetLayouts;
|
||||
|
||||
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline);
|
||||
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline,
|
||||
eastl::vector<vk::DescriptorSetLayout> &&setLayouts);
|
||||
~Pipeline();
|
||||
};
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "queue_allocation.h"
|
||||
#include <EASTL/vector.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
struct PhysicalDevice;
|
||||
class PhysicalDevices;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
|
|||
|
||||
struct Vertex
|
||||
{
|
||||
float m_Position[4];
|
||||
float m_Color[4];
|
||||
vec3 m_Position;
|
||||
vec3 m_Color;
|
||||
|
||||
constexpr static vk::VertexInputBindingDescription
|
||||
GetBinding(const u32 binding)
|
||||
|
|
@ -43,13 +43,13 @@ struct Vertex
|
|||
vk::VertexInputAttributeDescription{
|
||||
.location = 0,
|
||||
.binding = binding,
|
||||
.format = vk::Format::eR32G32B32A32Sfloat,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, m_Position),
|
||||
},
|
||||
vk::VertexInputAttributeDescription{
|
||||
.location = 1,
|
||||
.binding = binding,
|
||||
.format = vk::Format::eR32G32B32A32Sfloat,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, m_Color),
|
||||
},
|
||||
};
|
||||
|
|
@ -60,14 +60,13 @@ struct Frame
|
|||
{
|
||||
const Device *m_Device;
|
||||
vk::CommandPool m_Pool;
|
||||
vk::CommandBuffer m_CommandBuffer;
|
||||
vk::Fence m_FrameAvailableFence;
|
||||
vk::Semaphore m_ImageAcquireSem;
|
||||
vk::Semaphore m_RenderFinishSem;
|
||||
|
||||
Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount);
|
||||
~Frame();
|
||||
|
||||
[[nodiscard]] vk::CommandBuffer AllocateCommandBuffer() const;
|
||||
};
|
||||
|
||||
int
|
||||
|
|
@ -86,11 +85,8 @@ main(int, char **)
|
|||
Features enabledDeviceFeatures = {.m_Vulkan13Features = {.dynamicRendering = true}};
|
||||
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
||||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
||||
|
||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||
|
||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
||||
|
||||
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
||||
|
||||
vk::CommandPool copyPool;
|
||||
|
|
@ -113,9 +109,9 @@ main(int, char **)
|
|||
|
||||
// eastl::array<Vertex, 3> vertices{};
|
||||
eastl::array vertices = {
|
||||
Vertex{.m_Position = {-0.5f, -0.5f, 0.0f, 1.0f}, .m_Color = {1.0f, 0.0f, 0.0f, 1.0f}},
|
||||
Vertex{.m_Position = {0.5f, -0.5f, 0.0f, 1.0f}, .m_Color = {0.0f, 1.0f, 0.0f, 1.0f}},
|
||||
Vertex{.m_Position = {0.0f, 0.5f, 0.0f, 1.0f}, .m_Color = {0.0f, 0.0f, 1.0f, 1.0f}},
|
||||
Vertex{.m_Position = {-0.5f, -0.5f, 0.0f}, .m_Color = {1.0f, 0.0f, 0.0f}},
|
||||
Vertex{.m_Position = {0.5f, -0.5f, 0.0f}, .m_Color = {0.0f, 1.0f, 0.0f}},
|
||||
Vertex{.m_Position = {0.0f, 0.5f, 0.0f}, .m_Color = {0.0f, 0.0f, 1.0f}},
|
||||
};
|
||||
VertexBuffer vbo;
|
||||
vbo.Init(&device, vertices.size() * sizeof vertices[0], "VBO");
|
||||
|
|
@ -243,7 +239,7 @@ main(int, char **)
|
|||
|
||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
||||
vk::CommandBuffer cmd = currentFrame->AllocateCommandBuffer();
|
||||
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
||||
|
||||
topOfThePipeBarrier.image = currentImage;
|
||||
renderToPresentBarrier.image = currentImage;
|
||||
|
|
@ -369,21 +365,14 @@ Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCo
|
|||
ERROR_IF(Failed(result), "Could not create RF semaphore for frame {}. Cause: {}", frameCount, result)
|
||||
THEN_ABORT(result);
|
||||
|
||||
DEBUG("Frame {} created successfully.", frameCount);
|
||||
}
|
||||
|
||||
vk::CommandBuffer
|
||||
Frame::AllocateCommandBuffer() const
|
||||
{
|
||||
const vk::CommandBufferAllocateInfo allocateInfo = {
|
||||
.commandPool = m_Pool, .level = vk::CommandBufferLevel::ePrimary, .commandBufferCount = 1};
|
||||
|
||||
vk::CommandBuffer commandBuffer;
|
||||
vk::Result result = m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &commandBuffer);
|
||||
result = m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &m_CommandBuffer);
|
||||
ERROR_IF(Failed(result), "Command buffer allocation failed. Cause: {}", result)
|
||||
THEN_ABORT(result);
|
||||
|
||||
return commandBuffer;
|
||||
DEBUG("Frame {} created successfully.", frameCount);
|
||||
}
|
||||
|
||||
Pipeline
|
||||
|
|
@ -509,7 +498,7 @@ CreatePipeline(const Device *device, const Swapchain *swapchain)
|
|||
device->m_Device.destroy(vertexShaderModule, nullptr);
|
||||
device->m_Device.destroy(fragmentShaderModule, nullptr);
|
||||
|
||||
return {device, pipelineLayout, pipeline};
|
||||
return {device, pipelineLayout, pipeline, {}};
|
||||
}
|
||||
|
||||
vk::ShaderModule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
# CMakeList.txt ; CMake project for box
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address")
|
||||
|
||||
add_executable(box box.cpp)
|
||||
add_shader(box shader/box.vert.glsl)
|
||||
add_shader(box shader/box.frag.glsl)
|
||||
|
||||
target_link_libraries(box PRIVATE aster_core)
|
||||
target_link_libraries(box PRIVATE util_helper)
|
||||
|
|
@ -0,0 +1,604 @@
|
|||
// =============================================
|
||||
// Aster: box.cpp
|
||||
// Copyright (c) 2020-2024 Anish Bhobe
|
||||
// =============================================
|
||||
|
||||
#include "buffer.h"
|
||||
#include "constants.h"
|
||||
#include "context.h"
|
||||
#include "device.h"
|
||||
#include "physical_device.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "global.h"
|
||||
#include "pipeline.h"
|
||||
#include "swapchain.h"
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#include <EASTL/array.h>
|
||||
|
||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
||||
constexpr auto VERTEX_SHADER_FILE = "shader/box.vert.glsl.spv";
|
||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.frag.glsl.spv";
|
||||
|
||||
#define AbortIfFailed(RESULT) \
|
||||
do \
|
||||
{ \
|
||||
vk::Result _checkResultValue_; \
|
||||
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
|
||||
THEN_ABORT(_checkResultValue_); \
|
||||
} while (false)
|
||||
|
||||
#define AbortIfFailedMV(RESULT, MSG, EXTRA) \
|
||||
do \
|
||||
{ \
|
||||
vk::Result _checkResultValue_; \
|
||||
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
|
||||
THEN_ABORT(_checkResultValue_); \
|
||||
} while (false)
|
||||
|
||||
#define AbortIfFailedM(RESULT, MSG) \
|
||||
do \
|
||||
{ \
|
||||
auto _checkResultValue_ = Cast<vk::Result>(RESULT); \
|
||||
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
|
||||
} while (false)
|
||||
|
||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
vec3 m_Position;
|
||||
vec3 m_Color;
|
||||
|
||||
constexpr static vk::VertexInputBindingDescription
|
||||
GetBinding(const u32 binding)
|
||||
{
|
||||
return {.binding = binding, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex};
|
||||
}
|
||||
|
||||
constexpr static eastl::array<vk::VertexInputAttributeDescription, 2>
|
||||
GetAttributes(const u32 binding)
|
||||
{
|
||||
return {
|
||||
vk::VertexInputAttributeDescription{
|
||||
.location = 0,
|
||||
.binding = binding,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, m_Position),
|
||||
},
|
||||
vk::VertexInputAttributeDescription{
|
||||
.location = 1,
|
||||
.binding = binding,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, m_Color),
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct Camera
|
||||
{
|
||||
mat4 m_Model;
|
||||
mat4 m_View;
|
||||
mat4 m_Perspective;
|
||||
};
|
||||
|
||||
struct Frame
|
||||
{
|
||||
const Device *m_Device;
|
||||
vk::CommandPool m_Pool;
|
||||
vk::CommandBuffer m_CommandBuffer;
|
||||
vk::Fence m_FrameAvailableFence;
|
||||
vk::Semaphore m_ImageAcquireSem;
|
||||
vk::Semaphore m_RenderFinishSem;
|
||||
|
||||
Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount);
|
||||
~Frame();
|
||||
};
|
||||
|
||||
int
|
||||
main(int, char **)
|
||||
{
|
||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
||||
|
||||
Context context = {"Box", VERSION};
|
||||
Window window = {"Box (Aster)", &context, {640, 480}};
|
||||
|
||||
PhysicalDevices physicalDevices = {&window, &context};
|
||||
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
|
||||
|
||||
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
||||
|
||||
Features enabledDeviceFeatures = {.m_Vulkan13Features = {.dynamicRendering = true}};
|
||||
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
||||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
||||
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
||||
|
||||
Camera camera = {
|
||||
.m_Model = {1.0f},
|
||||
.m_View = glm::lookAt(vec3(-1.0f, 0.0f, 1.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)),
|
||||
.m_Perspective = glm::perspective(
|
||||
70_deg, Cast<f32>(swapchain.m_Extent.width) / Cast<f32>(swapchain.m_Extent.height), 0.1f, 100.0f),
|
||||
};
|
||||
|
||||
vk::DescriptorPool descriptorPool;
|
||||
vk::DescriptorSet descriptorSet;
|
||||
{
|
||||
vk::DescriptorSetLayout descriptorSetLayout = pipeline.m_SetLayouts.front();
|
||||
vk::DescriptorPoolSize poolSize = {
|
||||
.type = vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = 1,
|
||||
};
|
||||
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
||||
.maxSets = 1, .poolSizeCount = 1, .pPoolSizes = &poolSize};
|
||||
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||
|
||||
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
||||
.descriptorPool = descriptorPool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &descriptorSetLayout,
|
||||
};
|
||||
AbortIfFailed(device.m_Device.allocateDescriptorSets(&descriptorSetAllocateInfo, &descriptorSet));
|
||||
}
|
||||
|
||||
vk::CommandPool copyPool;
|
||||
vk::CommandBuffer copyBuffer;
|
||||
{
|
||||
vk::CommandPoolCreateInfo poolCreateInfo = {
|
||||
.flags = vk::CommandPoolCreateFlagBits::eTransient,
|
||||
.queueFamilyIndex = queueAllocation.m_Family,
|
||||
};
|
||||
AbortIfFailedM(device.m_Device.createCommandPool(&poolCreateInfo, nullptr, ©Pool),
|
||||
"Copy command pool creation failed.");
|
||||
vk::CommandBufferAllocateInfo bufferAllocateInfo = {
|
||||
.commandPool = copyPool,
|
||||
.level = vk::CommandBufferLevel::ePrimary,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
AbortIfFailedM(device.m_Device.allocateCommandBuffers(&bufferAllocateInfo, ©Buffer),
|
||||
"Copy command buffer allocation failed.");
|
||||
}
|
||||
|
||||
// eastl::array<Vertex, 3> vertices{};
|
||||
eastl::array vertices = {
|
||||
Vertex{.m_Position = {-0.5f, -0.5f, 0.0f}, .m_Color = {1.0f, 0.0f, 0.0f}},
|
||||
Vertex{.m_Position = {0.5f, -0.5f, 0.0f}, .m_Color = {0.0f, 1.0f, 0.0f}},
|
||||
Vertex{.m_Position = {0.0f, 0.5f, 0.0f}, .m_Color = {0.0f, 0.0f, 1.0f}},
|
||||
};
|
||||
VertexBuffer vbo;
|
||||
vbo.Init(&device, vertices.size() * sizeof vertices[0], "VBO");
|
||||
{
|
||||
StagingBuffer staging;
|
||||
staging.Init(&device, vertices.size() * sizeof vertices[0], "Staging");
|
||||
staging.Write(&device, 0, vertices.size() * sizeof vertices[0], vertices.data());
|
||||
|
||||
vk::Fence fence;
|
||||
vk::FenceCreateInfo fenceCreateInfo = {};
|
||||
AbortIfFailed(device.m_Device.createFence(&fenceCreateInfo, nullptr, &fence));
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
||||
AbortIfFailed(copyBuffer.begin(&beginInfo));
|
||||
|
||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = staging.GetSize()};
|
||||
copyBuffer.copyBuffer(staging.m_Buffer, vbo.m_Buffer, 1, &bufferCopy);
|
||||
|
||||
AbortIfFailed(copyBuffer.end());
|
||||
|
||||
vk::SubmitInfo submitInfo = {
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = ©Buffer,
|
||||
};
|
||||
|
||||
AbortIfFailed(commandQueue.submit(1, &submitInfo, fence));
|
||||
INFO("Submit copy");
|
||||
|
||||
AbortIfFailed(device.m_Device.waitForFences(1, &fence, true, MaxValue<u64>));
|
||||
INFO("Fence wait");
|
||||
|
||||
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
|
||||
|
||||
device.m_Device.destroy(fence, nullptr);
|
||||
staging.Destroy(&device);
|
||||
}
|
||||
|
||||
UniformBuffer ubo;
|
||||
ubo.Init(&device, sizeof camera, "Camera UBO");
|
||||
ubo.Write(&device, 0, sizeof camera, &camera);
|
||||
vk::DescriptorBufferInfo descriptorBufferInfo = {
|
||||
.buffer = ubo.m_Buffer,
|
||||
.offset = 0,
|
||||
.range = ubo.GetSize(),
|
||||
};
|
||||
vk::WriteDescriptorSet writeDescriptors = {
|
||||
.dstSet = descriptorSet,
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &descriptorBufferInfo,
|
||||
};
|
||||
device.m_Device.updateDescriptorSets(1, &writeDescriptors, 0, nullptr);
|
||||
|
||||
// Persistent variables
|
||||
vk::Viewport viewport = {
|
||||
.x = 0,
|
||||
.y = Cast<f32>(swapchain.m_Extent.height),
|
||||
.width = Cast<f32>(swapchain.m_Extent.width),
|
||||
.height = -Cast<f32>(swapchain.m_Extent.height),
|
||||
.minDepth = 0.0,
|
||||
.maxDepth = 1.0,
|
||||
};
|
||||
|
||||
vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = swapchain.m_Extent,
|
||||
};
|
||||
|
||||
vk::ImageSubresourceRange subresourceRange = {
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
vk::ImageMemoryBarrier topOfThePipeBarrier = {
|
||||
.oldLayout = vk::ImageLayout::eUndefined,
|
||||
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||
.subresourceRange = subresourceRange,
|
||||
};
|
||||
vk::ImageMemoryBarrier renderToPresentBarrier = {
|
||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||
.subresourceRange = subresourceRange,
|
||||
};
|
||||
|
||||
// Frames
|
||||
eastl::fixed_vector<Frame, MAX_FRAMES_IN_FLIGHT> frames;
|
||||
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
|
||||
{
|
||||
frames.emplace_back(&device, queueAllocation.m_Family, i);
|
||||
}
|
||||
|
||||
Time::Init();
|
||||
|
||||
INFO("Starting loop");
|
||||
u32 frameIndex = 0;
|
||||
while (window.Poll())
|
||||
{
|
||||
Frame *currentFrame = &frames[frameIndex];
|
||||
Time::Update();
|
||||
|
||||
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
|
||||
ubo.Write(&device, 0, sizeof camera, &camera);
|
||||
|
||||
AbortIfFailedMV(device.m_Device.waitForFences(1, ¤tFrame->m_FrameAvailableFence, true, MaxValue<u64>),
|
||||
"Waiting for fence {} failed.", frameIndex);
|
||||
|
||||
u32 imageIndex;
|
||||
auto result = device.m_Device.acquireNextImageKHR(swapchain.m_Swapchain, MaxValue<u64>,
|
||||
currentFrame->m_ImageAcquireSem, nullptr, &imageIndex);
|
||||
if (Failed(result))
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case vk::Result::eErrorOutOfDateKHR:
|
||||
case vk::Result::eSuboptimalKHR:
|
||||
INFO("Recreating Swapchain. Cause: {}", result);
|
||||
swapchain.Create(&window);
|
||||
viewport.y = Cast<f32>(swapchain.m_Extent.height);
|
||||
viewport.width = Cast<f32>(swapchain.m_Extent.width);
|
||||
viewport.height = -Cast<f32>(swapchain.m_Extent.height);
|
||||
scissor.extent = swapchain.m_Extent;
|
||||
continue; // Image acquire has failed. We move to the next frame.
|
||||
default:
|
||||
AbortIfFailedMV(result, "Waiting for swapchain image {} failed.", frameIndex);
|
||||
}
|
||||
}
|
||||
// Reset fences here. In case swapchain was out of date, we leave the fences signalled.
|
||||
AbortIfFailedMV(device.m_Device.resetFences(1, ¤tFrame->m_FrameAvailableFence), "Fence {} reset failed.",
|
||||
frameIndex);
|
||||
|
||||
AbortIfFailedMV(device.m_Device.resetCommandPool(currentFrame->m_Pool, {}), "Command pool {} reset failed.",
|
||||
frameIndex);
|
||||
|
||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
||||
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
||||
|
||||
topOfThePipeBarrier.image = currentImage;
|
||||
renderToPresentBarrier.image = currentImage;
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
||||
AbortIfFailed(cmd.begin(&beginInfo));
|
||||
|
||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||
{}, 0, nullptr, 0, nullptr, 1, &topOfThePipeBarrier);
|
||||
|
||||
// Render
|
||||
vk::RenderingAttachmentInfo attachmentInfo = {
|
||||
.imageView = currentImageView,
|
||||
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 1.0f},
|
||||
};
|
||||
|
||||
vk::RenderingInfo renderingInfo = {
|
||||
.renderArea = {.extent = swapchain.m_Extent},
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &attachmentInfo,
|
||||
};
|
||||
|
||||
cmd.beginRendering(&renderingInfo);
|
||||
|
||||
cmd.setViewport(0, 1, &viewport);
|
||||
cmd.setScissor(0, 1, &scissor);
|
||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
usize offsets = 0;
|
||||
cmd.bindVertexBuffers(0, 1, &vbo.m_Buffer, &offsets);
|
||||
cmd.draw(3, 1, 0, 0);
|
||||
|
||||
cmd.endRendering();
|
||||
|
||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe,
|
||||
{}, 0, nullptr, 0, nullptr, 1, &renderToPresentBarrier);
|
||||
|
||||
AbortIfFailed(cmd.end());
|
||||
|
||||
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||
vk::SubmitInfo submitInfo = {
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = ¤tFrame->m_ImageAcquireSem,
|
||||
.pWaitDstStageMask = &waitDstStage,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = ¤tFrame->m_RenderFinishSem,
|
||||
};
|
||||
AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
|
||||
|
||||
vk::PresentInfoKHR presentInfo = {
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = ¤tFrame->m_RenderFinishSem,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapchain.m_Swapchain,
|
||||
.pImageIndices = &imageIndex,
|
||||
.pResults = nullptr,
|
||||
};
|
||||
result = commandQueue.presentKHR(&presentInfo);
|
||||
if (Failed(result))
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case vk::Result::eErrorOutOfDateKHR:
|
||||
case vk::Result::eSuboptimalKHR:
|
||||
INFO("Recreating Swapchain. Cause: {}", result);
|
||||
swapchain.Create(&window);
|
||||
viewport.y = Cast<f32>(swapchain.m_Extent.height);
|
||||
viewport.width = Cast<f32>(swapchain.m_Extent.width);
|
||||
viewport.height = -Cast<f32>(swapchain.m_Extent.height);
|
||||
scissor.extent = swapchain.m_Extent;
|
||||
break; // Present failed. We redo the frame.
|
||||
default:
|
||||
AbortIfFailedM(result, "Swapchain Present failed.");
|
||||
}
|
||||
}
|
||||
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
AbortIfFailed(device.m_Device.waitIdle());
|
||||
|
||||
ubo.Destroy(&device);
|
||||
device.m_Device.destroy(descriptorPool, nullptr);
|
||||
device.m_Device.destroy(copyPool, nullptr);
|
||||
vbo.Destroy(&device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCount)
|
||||
{
|
||||
m_Device = device;
|
||||
|
||||
const vk::CommandPoolCreateInfo commandPoolCreateInfo = {
|
||||
.flags = vk::CommandPoolCreateFlagBits::eTransient,
|
||||
.queueFamilyIndex = queueFamilyIndex,
|
||||
};
|
||||
AbortIfFailedMV(device->m_Device.createCommandPool(&commandPoolCreateInfo, nullptr, &m_Pool),
|
||||
"Could not command pool for frame {}", frameCount);
|
||||
|
||||
constexpr vk::FenceCreateInfo fenceCreateInfo = {.flags = vk::FenceCreateFlagBits::eSignaled};
|
||||
AbortIfFailedMV(device->m_Device.createFence(&fenceCreateInfo, nullptr, &m_FrameAvailableFence),
|
||||
"Could not create a fence for frame {}", frameCount);
|
||||
|
||||
constexpr vk::SemaphoreCreateInfo semaphoreCreateInfo = {};
|
||||
AbortIfFailedMV(device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_ImageAcquireSem),
|
||||
"Could not create IA semaphore for frame {}.", frameCount);
|
||||
AbortIfFailedMV(device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_RenderFinishSem),
|
||||
"Could not create RF semaphore for frame {}.", frameCount);
|
||||
|
||||
const vk::CommandBufferAllocateInfo allocateInfo = {
|
||||
.commandPool = m_Pool,
|
||||
.level = vk::CommandBufferLevel::ePrimary,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
|
||||
AbortIfFailed(m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &m_CommandBuffer));
|
||||
|
||||
DEBUG("Frame {} created successfully.", frameCount);
|
||||
}
|
||||
|
||||
Pipeline
|
||||
CreatePipeline(const Device *device, const Swapchain *swapchain)
|
||||
{
|
||||
// Pipeline Setup
|
||||
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
|
||||
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
|
||||
|
||||
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
|
||||
{
|
||||
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||
.module = vertexShaderModule,
|
||||
.pName = "main",
|
||||
},
|
||||
{
|
||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||
.module = fragmentShaderModule,
|
||||
.pName = "main",
|
||||
},
|
||||
}};
|
||||
|
||||
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding = {
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
||||
};
|
||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||
.bindingCount = 1,
|
||||
.pBindings = &descriptorSetLayoutBinding,
|
||||
};
|
||||
vk::DescriptorSetLayout descriptorSetLayout;
|
||||
AbortIfFailed(
|
||||
device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout));
|
||||
|
||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptorSetLayout,
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
};
|
||||
vk::PipelineLayout pipelineLayout;
|
||||
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||
device->SetName(pipelineLayout, "Box Layout");
|
||||
|
||||
vk::VertexInputBindingDescription inputBindingDescription = Vertex::GetBinding(0);
|
||||
auto inputAttributeDescription = Vertex::GetAttributes(0);
|
||||
|
||||
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = &inputBindingDescription,
|
||||
.vertexAttributeDescriptionCount = Cast<u32>(inputAttributeDescription.size()),
|
||||
.pVertexAttributeDescriptions = inputAttributeDescription.data(),
|
||||
};
|
||||
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
|
||||
.topology = vk::PrimitiveTopology::eTriangleList,
|
||||
.primitiveRestartEnable = false,
|
||||
};
|
||||
|
||||
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1,
|
||||
};
|
||||
|
||||
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
|
||||
.depthClampEnable = false,
|
||||
.rasterizerDiscardEnable = false,
|
||||
.polygonMode = vk::PolygonMode::eFill,
|
||||
.cullMode = vk::CullModeFlagBits::eNone,
|
||||
.frontFace = vk::FrontFace::eCounterClockwise,
|
||||
.depthBiasEnable = false,
|
||||
.lineWidth = 1.0,
|
||||
};
|
||||
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||
.sampleShadingEnable = false,
|
||||
};
|
||||
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
|
||||
.depthTestEnable = false,
|
||||
.depthWriteEnable = false,
|
||||
};
|
||||
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
|
||||
.blendEnable = false,
|
||||
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
|
||||
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
|
||||
.colorBlendOp = vk::BlendOp::eAdd,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.alphaBlendOp = vk::BlendOp::eAdd,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
};
|
||||
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
|
||||
.logicOpEnable = false,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &colorBlendAttachmentState,
|
||||
};
|
||||
|
||||
eastl::array dynamicStates = {
|
||||
vk::DynamicState::eScissor,
|
||||
vk::DynamicState::eViewport,
|
||||
};
|
||||
|
||||
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
|
||||
.pDynamicStates = dynamicStates.data(),
|
||||
};
|
||||
|
||||
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
|
||||
.viewMask = 0,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachmentFormats = &swapchain->m_Format,
|
||||
};
|
||||
|
||||
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||
.pNext = &renderingCreateInfo,
|
||||
.stageCount = Cast<u32>(shaderStages.size()),
|
||||
.pStages = shaderStages.data(),
|
||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
||||
.pViewportState = &viewportStateCreateInfo,
|
||||
.pRasterizationState = &rasterizationStateCreateInfo,
|
||||
.pMultisampleState = &multisampleStateCreateInfo,
|
||||
.pDepthStencilState = &depthStencilStateCreateInfo,
|
||||
.pColorBlendState = &colorBlendStateCreateInfo,
|
||||
.pDynamicState = &dynamicStateCreateInfo,
|
||||
.layout = pipelineLayout,
|
||||
};
|
||||
vk::Pipeline pipeline;
|
||||
AbortIfFailed(device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
||||
device->SetName(pipeline, "Box Pipeline");
|
||||
|
||||
device->m_Device.destroy(vertexShaderModule, nullptr);
|
||||
device->m_Device.destroy(fragmentShaderModule, nullptr);
|
||||
|
||||
return {device, pipelineLayout, pipeline, {descriptorSetLayout}};
|
||||
}
|
||||
|
||||
vk::ShaderModule
|
||||
CreateShader(const Device *device, cstr shaderFile)
|
||||
{
|
||||
eastl::vector<u32> shaderCode = ReadFile(shaderFile);
|
||||
|
||||
const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {
|
||||
.codeSize = shaderCode.size() * sizeof(u32),
|
||||
.pCode = shaderCode.data(),
|
||||
};
|
||||
vk::ShaderModule shaderModule;
|
||||
|
||||
AbortIfFailedMV(device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule),
|
||||
"Shader {} could not be created.", shaderFile);
|
||||
return shaderModule;
|
||||
}
|
||||
|
||||
Frame::~Frame()
|
||||
{
|
||||
m_Device->m_Device.destroy(m_RenderFinishSem, nullptr);
|
||||
m_Device->m_Device.destroy(m_ImageAcquireSem, nullptr);
|
||||
m_Device->m_Device.destroy(m_FrameAvailableFence, nullptr);
|
||||
m_Device->m_Device.destroy(m_Pool, nullptr);
|
||||
|
||||
DEBUG("Destoryed Frame");
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
layout (location = 0) in vec3 inColor;
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(inColor, 1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
layout(location=0) in vec4 position;
|
||||
layout(location=1) in vec4 color;
|
||||
|
||||
layout(location=0) out vec3 outColor;
|
||||
|
||||
layout(binding=0) uniform Camera {
|
||||
mat4 model;
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(position.xyz, 1.0f);
|
||||
outColor = vec3(color.rgb);
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
add_subdirectory("01_triangle")
|
||||
add_subdirectory("00_util")
|
||||
|
||||
|
||||
add_subdirectory("01_triangle")
|
||||
add_subdirectory("02_box")
|
||||
|
|
|
|||
Loading…
Reference in New Issue