Refactoring and extracting helpers.

This commit is contained in:
Anish Bhobe 2024-07-01 21:51:07 +02:00
parent d9b0e82be7
commit 0ca2779014
11 changed files with 156 additions and 116 deletions

View File

@ -20,7 +20,8 @@ set(HEADER_FILES
physical_device.h physical_device.h
device.h device.h
swapchain.h swapchain.h
"pipeline.h") "pipeline.h"
queue_allocation.h)
set(SOURCE_FILES set(SOURCE_FILES
logger.cpp logger.cpp
@ -37,7 +38,7 @@ 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_SOURCE_DIR}) target_include_directories(aster_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(aster_core PUBLIC glm::glm-header-only) target_link_libraries(aster_core PUBLIC glm::glm-header-only)
target_link_libraries(aster_core PRIVATE glfw) target_link_libraries(aster_core PRIVATE glfw)

View File

@ -7,6 +7,7 @@
#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>

View File

@ -9,15 +9,10 @@
#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;

14
aster/queue_allocation.h Normal file
View File

@ -0,0 +1,14 @@
// =============================================
// Aster: queue_allocation.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
struct QueueAllocation
{
u32 m_Family;
u32 m_Count;
};

View File

@ -0,0 +1,8 @@
# 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})

View File

@ -0,0 +1,90 @@
// =============================================
// 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;
}

18
samples/00_util/helpers.h Normal file
View File

@ -0,0 +1,18 @@
// =============================================
// 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);

View File

@ -3,9 +3,8 @@
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/white.frag.glsl) add_shader(triangle shader/triangle.frag.glsl)
target_link_libraries(triangle PRIVATE aster_core) target_link_libraries(triangle PRIVATE aster_core)
target_link_libraries(triangle PRIVATE util_helper)

View File

@ -3,27 +3,26 @@
// Copyright (c) 2020-2024 Anish Bhobe // Copyright (c) 2020-2024 Anish Bhobe
// ============================================= // =============================================
#include "aster/constants.h" #include "constants.h"
#include "aster/context.h" #include "context.h"
#include "aster/device.h" #include "device.h"
#include "aster/physical_device.h" #include "physical_device.h"
#include "aster/window.h" #include "window.h"
#include "aster/global.h" #include "global.h"
#include "aster/pipeline.h" #include "pipeline.h"
#include "aster/swapchain.h" #include "swapchain.h"
#include "helpers.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/white.frag.glsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/triangle.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
{ {
@ -39,15 +38,6 @@ 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 **)
{ {
@ -69,7 +59,7 @@ main(int, char **)
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&window, &device, "Primary Chain"};
Pipeline pipeline = CreatePipeline(&device, &swapchain, VERTEX_SHADER_FILE, FRAGMENT_SHADER_FILE); Pipeline pipeline = CreatePipeline(&device, &swapchain);
// Persistent variables // Persistent variables
vk::Viewport viewport = { vk::Viewport viewport = {
@ -259,68 +249,6 @@ 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;
@ -363,11 +291,11 @@ Frame::AllocateCommandBuffer() const
return commandBuffer; return commandBuffer;
} }
Pipeline Pipeline
CreatePipeline(const Device *device, const Swapchain *swapchain, cstr vertexShaderFile, cstr fragmentShaderFile) CreatePipeline(const Device *device, const Swapchain *swapchain)
{ {
// Pipeline Setup // Pipeline Setup
auto vertexShaderModule = CreateShader(device, vertexShaderFile); auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, fragmentShaderFile); auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{ eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{ {
@ -510,21 +438,4 @@ 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;
} }

View File

@ -3,3 +3,6 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
add_subdirectory("01_triangle") add_subdirectory("01_triangle")
add_subdirectory("00_util")