Compare commits
No commits in common. "d6fe7163228c370fc6b4ec1e67c2ee44783f9db1" and "d9b0e82be7160f378810df4dbea6db452829cb23" have entirely different histories.
d6fe716322
...
d9b0e82be7
|
|
@ -20,9 +20,7 @@ set(HEADER_FILES
|
||||||
physical_device.h
|
physical_device.h
|
||||||
device.h
|
device.h
|
||||||
swapchain.h
|
swapchain.h
|
||||||
pipeline.h
|
"pipeline.h")
|
||||||
queue_allocation.h
|
|
||||||
buffer.h)
|
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
logger.cpp
|
logger.cpp
|
||||||
|
|
@ -32,17 +30,16 @@ set(SOURCE_FILES
|
||||||
physical_device.cpp
|
physical_device.cpp
|
||||||
device.cpp
|
device.cpp
|
||||||
swapchain.cpp
|
swapchain.cpp
|
||||||
pipeline.cpp
|
pipeline.cpp)
|
||||||
buffer.cpp)
|
|
||||||
|
|
||||||
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||||
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)
|
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)
|
||||||
|
|
||||||
target_precompile_headers(aster_core PUBLIC global.h)
|
target_precompile_headers(aster_core PUBLIC global.h)
|
||||||
|
|
||||||
target_include_directories(aster_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(aster_core PUBLIC ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
target_link_libraries(aster_core PUBLIC glm::glm)
|
target_link_libraries(aster_core PUBLIC glm::glm-header-only)
|
||||||
target_link_libraries(aster_core PRIVATE glfw)
|
target_link_libraries(aster_core PRIVATE glfw)
|
||||||
target_include_directories(aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS})
|
target_include_directories(aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS})
|
||||||
target_link_libraries(aster_core PRIVATE fmt::fmt)
|
target_link_libraries(aster_core PRIVATE fmt::fmt)
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: buffer.cpp
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
#include "device.h"
|
|
||||||
Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlags usage, NameString &&name)
|
|
||||||
: m_Device(device)
|
|
||||||
, m_Allocation(nullptr)
|
|
||||||
, m_Size(0)
|
|
||||||
, m_Name(std::move(name))
|
|
||||||
{
|
|
||||||
const VkBufferCreateInfo bufferCreateInfo = vk::BufferCreateInfo{
|
|
||||||
.size = size,
|
|
||||||
.usage = usage,
|
|
||||||
.sharingMode = vk::SharingMode::eExclusive,
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr VmaAllocationCreateInfo allocationCreateInfo = {.usage = VMA_MEMORY_USAGE_AUTO};
|
|
||||||
|
|
||||||
VkBuffer buffer;
|
|
||||||
vk::Result result = Cast<vk::Result>(vmaCreateBuffer(m_Device->m_Allocator, &bufferCreateInfo,
|
|
||||||
&allocationCreateInfo, &buffer, &m_Allocation, nullptr));
|
|
||||||
ERROR_IF(Failed(result), "Could not create buffer. Cause: {}", result) THEN_ABORT(result);
|
|
||||||
|
|
||||||
m_Buffer = buffer;
|
|
||||||
|
|
||||||
m_Device->SetName(m_Buffer, m_Name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer::~Buffer()
|
|
||||||
{
|
|
||||||
vmaDestroyBuffer(m_Device->m_Allocator, m_Buffer, m_Allocation);
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: buffer.h
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
struct Device;
|
|
||||||
|
|
||||||
struct Buffer
|
|
||||||
{
|
|
||||||
const Device *m_Device{};
|
|
||||||
vk::Buffer m_Buffer{};
|
|
||||||
VmaAllocation m_Allocation{};
|
|
||||||
usize m_Size{};
|
|
||||||
NameString m_Name;
|
|
||||||
|
|
||||||
Buffer(const Device *device, usize size, vk::BufferUsageFlags usage, NameString &&name);
|
|
||||||
~Buffer();
|
|
||||||
};
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "physical_device.h"
|
#include "physical_device.h"
|
||||||
#include "queue_allocation.h"
|
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
#include <EASTL/fixed_vector.h>
|
#include <EASTL/fixed_vector.h>
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,15 @@
|
||||||
|
|
||||||
#include <EASTL/vector.h>
|
#include <EASTL/vector.h>
|
||||||
|
|
||||||
struct QueueAllocation;
|
|
||||||
struct Context;
|
struct Context;
|
||||||
struct PhysicalDevice;
|
struct PhysicalDevice;
|
||||||
|
|
||||||
|
struct QueueAllocation
|
||||||
|
{
|
||||||
|
u32 m_Family;
|
||||||
|
u32 m_Count;
|
||||||
|
};
|
||||||
|
|
||||||
struct Features
|
struct Features
|
||||||
{
|
{
|
||||||
vk::PhysicalDeviceFeatures m_Vulkan10Features;
|
vk::PhysicalDeviceFeatures m_Vulkan10Features;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: queue_allocation.h
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
struct QueueAllocation
|
|
||||||
{
|
|
||||||
u32 m_Family;
|
|
||||||
u32 m_Count;
|
|
||||||
};
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
# CMakeList.txt ; CMake project for Triangle
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
|
||||||
|
|
||||||
add_library(util_helper STATIC helpers.h helpers.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(util_helper PRIVATE aster_core)
|
|
||||||
target_include_directories(util_helper PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: helpers.cpp
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#include "helpers.h"
|
|
||||||
|
|
||||||
#include "device.h"
|
|
||||||
#include "physical_device.h"
|
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
|
||||||
|
|
||||||
constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics |
|
|
||||||
QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent |
|
|
||||||
QueueSupportFlagBits::eTransfer;
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsSuitableDevice(const PhysicalDevice *physicalDevice)
|
|
||||||
{
|
|
||||||
const bool hasAllRequiredQueues =
|
|
||||||
std::ranges::any_of(physicalDevice->m_QueueFamilies, [](const auto &queueFamilyProp) {
|
|
||||||
return (queueFamilyProp.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT;
|
|
||||||
});
|
|
||||||
|
|
||||||
const bool isNotCpu = physicalDevice->m_DeviceProperties.deviceType != vk::PhysicalDeviceType::eCpu;
|
|
||||||
|
|
||||||
const bool hasPresentMode = !physicalDevice->m_PresentModes.empty();
|
|
||||||
|
|
||||||
const bool hasSurfaceFormat = !physicalDevice->m_SurfaceFormats.empty();
|
|
||||||
|
|
||||||
return hasSurfaceFormat && hasPresentMode && isNotCpu && hasAllRequiredQueues;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalDevice
|
|
||||||
FindSuitableDevice(const PhysicalDevices &physicalDevices)
|
|
||||||
{
|
|
||||||
for (auto &physicalDevice : physicalDevices)
|
|
||||||
{
|
|
||||||
if (IsSuitableDevice(&physicalDevice))
|
|
||||||
{
|
|
||||||
return physicalDevice;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERROR("No suitable GPU available on the system.")
|
|
||||||
THEN_ABORT(vk::Result::eErrorUnknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueAllocation
|
|
||||||
FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
|
|
||||||
{
|
|
||||||
for (auto &queueFamilyInfo : physicalDevice->m_QueueFamilies)
|
|
||||||
{
|
|
||||||
if ((queueFamilyInfo.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.m_Family = queueFamilyInfo.m_Index,
|
|
||||||
.m_Count = queueFamilyInfo.m_Count,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ERROR("No suitable queue family on the GPU.")
|
|
||||||
THEN_ABORT(vk::Result::eErrorUnknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
eastl::vector<u32>
|
|
||||||
ReadFile(cstr fileName)
|
|
||||||
{
|
|
||||||
FILE *filePtr = fopen(fileName, "rb");
|
|
||||||
|
|
||||||
if (!filePtr)
|
|
||||||
{
|
|
||||||
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
eastl::vector<u32> outputVec;
|
|
||||||
eastl::array<u32, 1024> buffer{};
|
|
||||||
usize totalRead = 0;
|
|
||||||
usize readCount;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr);
|
|
||||||
const auto nextSize = totalRead + readCount;
|
|
||||||
outputVec.resize(nextSize);
|
|
||||||
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
|
|
||||||
totalRead = nextSize;
|
|
||||||
} while (readCount == 1024);
|
|
||||||
|
|
||||||
return outputVec;
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: helpers.h
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#include "queue_allocation.h"
|
|
||||||
#include <EASTL/vector.h>
|
|
||||||
|
|
||||||
struct PhysicalDevice;
|
|
||||||
class PhysicalDevices;
|
|
||||||
|
|
||||||
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
|
|
||||||
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
|
|
||||||
eastl::vector<u32> ReadFile(cstr fileName);
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
add_executable(triangle "triangle.cpp")
|
add_executable(triangle "triangle.cpp")
|
||||||
|
add_dependencies(triangle aster_core)
|
||||||
|
|
||||||
add_shader(triangle shader/triangle.vs.hlsl)
|
add_shader(triangle shader/triangle.vs.hlsl)
|
||||||
add_shader(triangle shader/triangle.frag.glsl)
|
add_shader(triangle shader/white.frag.glsl)
|
||||||
|
|
||||||
target_link_libraries(triangle PRIVATE aster_core)
|
target_link_libraries(triangle PRIVATE aster_core)
|
||||||
target_link_libraries(triangle PRIVATE util_helper)
|
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,27 @@
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
// Copyright (c) 2020-2024 Anish Bhobe
|
||||||
// =============================================
|
// =============================================
|
||||||
|
|
||||||
#include "constants.h"
|
#include "aster/constants.h"
|
||||||
#include "context.h"
|
#include "aster/context.h"
|
||||||
#include "device.h"
|
#include "aster/device.h"
|
||||||
#include "global.h"
|
#include "aster/physical_device.h"
|
||||||
#include "physical_device.h"
|
#include "aster/window.h"
|
||||||
#include "pipeline.h"
|
|
||||||
#include "swapchain.h"
|
|
||||||
#include "window.h"
|
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "aster/global.h"
|
||||||
|
#include "aster/pipeline.h"
|
||||||
|
#include "aster/swapchain.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
|
|
||||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
||||||
constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vs.hlsl.spv";
|
constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vs.hlsl.spv";
|
||||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/triangle.frag.glsl.spv";
|
constexpr auto FRAGMENT_SHADER_FILE = "shader/white.frag.glsl.spv";
|
||||||
|
|
||||||
|
bool IsSuitableDevice(const PhysicalDevice *physicalDevice);
|
||||||
|
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
|
||||||
|
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
|
||||||
|
eastl::vector<u32> ReadFile(cstr fileName);
|
||||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
||||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
|
|
||||||
|
|
||||||
struct Frame
|
struct Frame
|
||||||
{
|
{
|
||||||
|
|
@ -37,6 +39,15 @@ struct Frame
|
||||||
[[nodiscard]] vk::CommandBuffer AllocateCommandBuffer() const;
|
[[nodiscard]] vk::CommandBuffer AllocateCommandBuffer() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Shader
|
||||||
|
{
|
||||||
|
vk::ShaderModule m_ShaderModule;
|
||||||
|
vk::ShaderStageFlags m_Stage;
|
||||||
|
};
|
||||||
|
|
||||||
|
Pipeline
|
||||||
|
CreatePipeline(const Device *device, const Swapchain *swapchain, cstr vertexShaderFile, cstr fragmentShaderFile);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int, char **)
|
main(int, char **)
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +69,7 @@ main(int, char **)
|
||||||
|
|
||||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
||||||
|
|
||||||
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
Pipeline pipeline = CreatePipeline(&device, &swapchain, VERTEX_SHADER_FILE, FRAGMENT_SHADER_FILE);
|
||||||
|
|
||||||
// Persistent variables
|
// Persistent variables
|
||||||
vk::Viewport viewport = {
|
vk::Viewport viewport = {
|
||||||
|
|
@ -248,6 +259,68 @@ main(int, char **)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics |
|
||||||
|
QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent |
|
||||||
|
QueueSupportFlagBits::eTransfer;
|
||||||
|
|
||||||
|
PhysicalDevice
|
||||||
|
FindSuitableDevice(const PhysicalDevices &physicalDevices)
|
||||||
|
{
|
||||||
|
for (auto &physicalDevice : physicalDevices)
|
||||||
|
{
|
||||||
|
if (IsSuitableDevice(&physicalDevice))
|
||||||
|
{
|
||||||
|
return physicalDevice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR("No suitable GPU available on the system.")
|
||||||
|
THEN_ABORT(vk::Result::eErrorUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueAllocation
|
||||||
|
FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
|
||||||
|
{
|
||||||
|
for (auto &queueFamilyInfo : physicalDevice->m_QueueFamilies)
|
||||||
|
{
|
||||||
|
if ((queueFamilyInfo.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
.m_Family = queueFamilyInfo.m_Index,
|
||||||
|
.m_Count = queueFamilyInfo.m_Count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERROR("No suitable queue family on the GPU.")
|
||||||
|
THEN_ABORT(vk::Result::eErrorUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
eastl::vector<u32>
|
||||||
|
ReadFile(cstr fileName)
|
||||||
|
{
|
||||||
|
FILE *filePtr = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (!filePtr)
|
||||||
|
{
|
||||||
|
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
eastl::vector<u32> outputVec;
|
||||||
|
eastl::array<u32, 1024> buffer{};
|
||||||
|
usize totalRead = 0;
|
||||||
|
usize readCount;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr);
|
||||||
|
const auto nextSize = totalRead + readCount;
|
||||||
|
outputVec.resize(nextSize);
|
||||||
|
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
|
||||||
|
totalRead = nextSize;
|
||||||
|
} while (readCount == 1024);
|
||||||
|
|
||||||
|
return outputVec;
|
||||||
|
}
|
||||||
|
|
||||||
Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCount)
|
Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCount)
|
||||||
{
|
{
|
||||||
m_Device = device;
|
m_Device = device;
|
||||||
|
|
@ -290,11 +363,11 @@ Frame::AllocateCommandBuffer() const
|
||||||
return commandBuffer;
|
return commandBuffer;
|
||||||
}
|
}
|
||||||
Pipeline
|
Pipeline
|
||||||
CreatePipeline(const Device *device, const Swapchain *swapchain)
|
CreatePipeline(const Device *device, const Swapchain *swapchain, cstr vertexShaderFile, cstr fragmentShaderFile)
|
||||||
{
|
{
|
||||||
// Pipeline Setup
|
// Pipeline Setup
|
||||||
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
|
auto vertexShaderModule = CreateShader(device, vertexShaderFile);
|
||||||
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
|
auto fragmentShaderModule = CreateShader(device, fragmentShaderFile);
|
||||||
|
|
||||||
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
|
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
|
||||||
{
|
{
|
||||||
|
|
@ -437,4 +510,21 @@ Frame::~Frame()
|
||||||
m_Device->m_Device.destroy(m_Pool, nullptr);
|
m_Device->m_Device.destroy(m_Pool, nullptr);
|
||||||
|
|
||||||
DEBUG("Destoryed Frame");
|
DEBUG("Destoryed Frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsSuitableDevice(const PhysicalDevice *physicalDevice)
|
||||||
|
{
|
||||||
|
const bool hasAllRequiredQueues =
|
||||||
|
std::ranges::any_of(physicalDevice->m_QueueFamilies, [](const auto &queueFamilyProp) {
|
||||||
|
return (queueFamilyProp.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT;
|
||||||
|
});
|
||||||
|
|
||||||
|
const bool isNotCpu = physicalDevice->m_DeviceProperties.deviceType != vk::PhysicalDeviceType::eCpu;
|
||||||
|
|
||||||
|
const bool hasPresentMode = !physicalDevice->m_PresentModes.empty();
|
||||||
|
|
||||||
|
const bool hasSurfaceFormat = !physicalDevice->m_SurfaceFormats.empty();
|
||||||
|
|
||||||
|
return hasSurfaceFormat && hasPresentMode && isNotCpu && hasAllRequiredQueues;
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# CMakeList.txt ; CMake project for box
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
|
||||||
|
|
||||||
add_executable(box
|
|
||||||
box.cpp
|
|
||||||
camera.h
|
|
||||||
camera.cpp)
|
|
||||||
add_shader(box shader/box.vs.hlsl)
|
|
||||||
add_shader(box shader/box.ps.hlsl)
|
|
||||||
|
|
||||||
target_link_libraries(box PRIVATE aster_core)
|
|
||||||
target_link_libraries(box PRIVATE util_helper)
|
|
||||||
|
|
@ -1,455 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: box.cpp
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#include "../../aster/buffer.h"
|
|
||||||
#include "../../aster/constants.h"
|
|
||||||
#include "../../aster/context.h"
|
|
||||||
#include "../../aster/device.h"
|
|
||||||
#include "../../aster/physical_device.h"
|
|
||||||
#include "../../aster/window.h"
|
|
||||||
#include "camera.h"
|
|
||||||
|
|
||||||
#include "../../aster/global.h"
|
|
||||||
#include "../../aster/pipeline.h"
|
|
||||||
#include "../../aster/swapchain.h"
|
|
||||||
|
|
||||||
#include "helpers.h"
|
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
|
||||||
|
|
||||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
|
||||||
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
|
|
||||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
|
|
||||||
|
|
||||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
|
||||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
|
|
||||||
|
|
||||||
struct Frame
|
|
||||||
{
|
|
||||||
const Device *m_Device;
|
|
||||||
vk::CommandPool m_Pool;
|
|
||||||
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
|
|
||||||
main(int, char **)
|
|
||||||
{
|
|
||||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
|
||||||
|
|
||||||
Context context = {"Triangle", VERSION};
|
|
||||||
Window window = {"Triangle (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 = vk::True}};
|
|
||||||
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
|
||||||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
|
||||||
|
|
||||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 1);
|
|
||||||
|
|
||||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
|
||||||
|
|
||||||
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
|
||||||
|
|
||||||
Camera camera = {
|
|
||||||
{0.0f, 0.0f, 0.0f},
|
|
||||||
{0.0f, 0.0f, 1.0f},
|
|
||||||
70.0_deg,
|
|
||||||
Cast<f32>(swapchain.m_Extent.width / swapchain.m_Extent.height),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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::ImageMemoryBarrier topOfThePipeBarrier = {
|
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
|
||||||
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
||||||
.subresourceRange =
|
|
||||||
{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
vk::ImageMemoryBarrier renderToPresentBarrier = {
|
|
||||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
||||||
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
||||||
.subresourceRange =
|
|
||||||
{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Per-frame data
|
|
||||||
eastl::fixed_vector<Buffer, MAX_FRAMES_IN_FLIGHT> buffers;
|
|
||||||
|
|
||||||
// Frames
|
|
||||||
eastl::fixed_vector<Frame, MAX_FRAMES_IN_FLIGHT> frames;
|
|
||||||
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
|
|
||||||
{
|
|
||||||
// TODO FIX: This section can cause dangling pointers due to copy/bad moves.
|
|
||||||
buffers.emplace_back(&device, sizeof camera, vk::BufferUsageFlagBits::eUniformBuffer, "Camera Uniform");
|
|
||||||
frames.emplace_back(&device, queueAllocation.m_Family, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 frameIndex = 0;
|
|
||||||
while (window.Poll())
|
|
||||||
{
|
|
||||||
Frame *currentFrame = &frames[frameIndex];
|
|
||||||
|
|
||||||
auto result = device.m_Device.waitForFences(1, ¤tFrame->m_FrameAvailableFence, vk::True, MaxValue<u64>);
|
|
||||||
ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
u32 imageIndex;
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR("Waiting for swapchain image {} failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = device.m_Device.resetFences(1, ¤tFrame->m_FrameAvailableFence);
|
|
||||||
ERROR_IF(Failed(result), "Fence {} reset failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
result = device.m_Device.resetCommandPool(currentFrame->m_Pool, {});
|
|
||||||
ERROR_IF(Failed(result), "Command pool {} reset failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
|
||||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
|
||||||
vk::CommandBuffer cmd = currentFrame->AllocateCommandBuffer();
|
|
||||||
|
|
||||||
topOfThePipeBarrier.image = currentImage;
|
|
||||||
renderToPresentBarrier.image = currentImage;
|
|
||||||
|
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
|
||||||
result = cmd.begin(&beginInfo);
|
|
||||||
ERROR_IF(Failed(result), "Command buffer begin failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
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.draw(3, 1, 0, 0);
|
|
||||||
|
|
||||||
cmd.endRendering();
|
|
||||||
|
|
||||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe,
|
|
||||||
{}, 0, nullptr, 0, nullptr, 1, &renderToPresentBarrier);
|
|
||||||
|
|
||||||
result = cmd.end();
|
|
||||||
ERROR_IF(Failed(result), "Command buffer end failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
result = commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence);
|
|
||||||
ERROR_IF(Failed(result), "Command queue submit failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
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;
|
|
||||||
default:
|
|
||||||
ERROR("Command queue present failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = device.m_Device.waitIdle();
|
|
||||||
ERROR_IF(Failed(result), "Wait idle failed. Cause: {}", result);
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
vk::Result result = device->m_Device.createCommandPool(&commandPoolCreateInfo, nullptr, &m_Pool);
|
|
||||||
ERROR_IF(Failed(result), "Could not command pool for frame {}. Cause: {}", frameCount, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
constexpr vk::FenceCreateInfo fenceCreateInfo = {.flags = vk::FenceCreateFlagBits::eSignaled};
|
|
||||||
result = device->m_Device.createFence(&fenceCreateInfo, nullptr, &m_FrameAvailableFence);
|
|
||||||
ERROR_IF(Failed(result), "Could not create a fence for frame {}. Cause: {}", frameCount, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
constexpr vk::SemaphoreCreateInfo semaphoreCreateInfo = {};
|
|
||||||
result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_ImageAcquireSem);
|
|
||||||
ERROR_IF(Failed(result), "Could not create IA semaphore for frame {}. Cause: {}", frameCount, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_RenderFinishSem);
|
|
||||||
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);
|
|
||||||
ERROR_IF(Failed(result), "Command buffer allocation failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
return commandBuffer;
|
|
||||||
}
|
|
||||||
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::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
|
||||||
.setLayoutCount = 0,
|
|
||||||
.pSetLayouts = nullptr,
|
|
||||||
.pushConstantRangeCount = 0,
|
|
||||||
.pPushConstantRanges = nullptr,
|
|
||||||
};
|
|
||||||
vk::PipelineLayout pipelineLayout;
|
|
||||||
vk::Result result = device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
|
|
||||||
ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result);
|
|
||||||
device->SetName(pipelineLayout, "Triangle Layout");
|
|
||||||
|
|
||||||
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
|
|
||||||
.vertexBindingDescriptionCount = 0,
|
|
||||||
.pVertexBindingDescriptions = nullptr,
|
|
||||||
.vertexAttributeDescriptionCount = 0,
|
|
||||||
.pVertexAttributeDescriptions = nullptr,
|
|
||||||
};
|
|
||||||
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
|
|
||||||
.topology = vk::PrimitiveTopology::eTriangleList,
|
|
||||||
.primitiveRestartEnable = vk::False,
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
|
|
||||||
.viewportCount = 1,
|
|
||||||
.scissorCount = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
|
|
||||||
.depthClampEnable = vk::False,
|
|
||||||
.rasterizerDiscardEnable = vk::False,
|
|
||||||
.polygonMode = vk::PolygonMode::eFill,
|
|
||||||
.cullMode = vk::CullModeFlagBits::eNone,
|
|
||||||
.frontFace = vk::FrontFace::eCounterClockwise,
|
|
||||||
.depthBiasEnable = vk::False,
|
|
||||||
.lineWidth = 1.0,
|
|
||||||
};
|
|
||||||
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
|
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
|
||||||
.sampleShadingEnable = vk::False,
|
|
||||||
};
|
|
||||||
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
|
|
||||||
.depthTestEnable = vk::False,
|
|
||||||
.depthWriteEnable = vk::False,
|
|
||||||
};
|
|
||||||
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
|
|
||||||
.blendEnable = vk::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 = vk::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;
|
|
||||||
result = device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline);
|
|
||||||
ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
device->SetName(pipeline, "Triangle Pipeline");
|
|
||||||
|
|
||||||
device->m_Device.destroy(vertexShaderModule, nullptr);
|
|
||||||
device->m_Device.destroy(fragmentShaderModule, nullptr);
|
|
||||||
|
|
||||||
return {device, pipelineLayout, pipeline};
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
vk::Result result = device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule);
|
|
||||||
ERROR_IF(Failed(result), "Shader {} could not be created. Cause: {}", shaderFile, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: camera.cpp
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#include "camera.h"
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
Camera::Camera(const vec3 position, const vec3 direction, const f32 verticalFov, const f32 aspectRatio)
|
|
||||||
: m_Projection{glm::perspective(verticalFov, aspectRatio, 1.0f, 100.0f)}
|
|
||||||
, m_View{lookAt(position, direction + position, vec3(0, 1, 0))}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: camera.h
|
|
||||||
// Copyright (c) 2020-2024 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
struct Camera
|
|
||||||
{
|
|
||||||
mat4 m_Projection;
|
|
||||||
mat4 m_View;
|
|
||||||
|
|
||||||
Camera(vec3 position, vec3 direction, f32 verticalFov, f32 aspectRatio);
|
|
||||||
};
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
struct VSIn {
|
|
||||||
int idx : SV_VERTEXID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VSOut
|
|
||||||
{
|
|
||||||
float4 Pos : SV_POSITION;
|
|
||||||
[[vk::location(0)]] float3 Color : COLOR0;
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOut main(VSIn input) {
|
|
||||||
float3 points[] = {
|
|
||||||
float3(-0.5f, -0.5f, 0.0f),
|
|
||||||
float3(0.5f, -0.5f, 0.0f),
|
|
||||||
float3(0.0f, 0.5f, 0.0f)
|
|
||||||
};
|
|
||||||
float3 colors[] = {
|
|
||||||
float3( 1.0f, 0.0f, 0.0f ),
|
|
||||||
float3( 0.0f, 1.0f, 0.0f ),
|
|
||||||
float3( 0.0f, 0.0f, 1.0f ),
|
|
||||||
};
|
|
||||||
|
|
||||||
VSOut output;
|
|
||||||
output.Pos = float4(points[input.idx], 1.0f);
|
|
||||||
output.Color = colors[input.idx];
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,4 @@
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
add_subdirectory("00_util")
|
|
||||||
add_subdirectory("01_triangle")
|
add_subdirectory("01_triangle")
|
||||||
add_subdirectory("02_box")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue