Refactored for new coding scheme. No exceptions.
This commit is contained in:
parent
7bf87f5127
commit
f603bd5752
196
.clang-format
196
.clang-format
|
|
@ -3,86 +3,14 @@
|
||||||
# chosen value in case the base style changes (last sync: Clang 14.0).
|
# chosen value in case the base style changes (last sync: Clang 14.0).
|
||||||
---
|
---
|
||||||
### General config, applies to all languages ###
|
### General config, applies to all languages ###
|
||||||
BasedOnStyle: LLVM
|
BasedOnStyle: Microsoft
|
||||||
AccessModifierOffset: -4
|
#AccessModifierOffset: -2
|
||||||
AlignAfterOpenBracket: DontAlign
|
AlwaysBreakAfterReturnType: AllDefinitions
|
||||||
# AlignArrayOfStructures: None
|
BreakConstructorInitializers: BeforeComma
|
||||||
# AlignConsecutiveMacros: None
|
#ColumnLimit: 0
|
||||||
# AlignConsecutiveAssignments: None
|
#ConstructorInitializerIndentWidth: 4
|
||||||
# AlignConsecutiveBitFields: None
|
#ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
# AlignConsecutiveDeclarations: None
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
# AlignEscapedNewlines: Right
|
|
||||||
AlignOperands: DontAlign
|
|
||||||
AlignTrailingComments: false
|
|
||||||
# AllowAllArgumentsOnNextLine: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
# AllowShortEnumsOnASingleLine: true
|
|
||||||
# AllowShortBlocksOnASingleLine: Never
|
|
||||||
# AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
# AllowShortFunctionsOnASingleLine: All
|
|
||||||
# AllowShortLambdasOnASingleLine: All
|
|
||||||
# AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
# AllowShortLoopsOnASingleLine: false
|
|
||||||
# AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
# AlwaysBreakAfterReturnType: None
|
|
||||||
# AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
# AlwaysBreakTemplateDeclarations: MultiLine
|
|
||||||
# AttributeMacros:
|
|
||||||
# - __capability
|
|
||||||
# BinPackArguments: true
|
|
||||||
# BinPackParameters: true
|
|
||||||
# BraceWrapping:
|
|
||||||
# AfterCaseLabel: false
|
|
||||||
# AfterClass: false
|
|
||||||
# AfterControlStatement: Never
|
|
||||||
# AfterEnum: false
|
|
||||||
# AfterFunction: false
|
|
||||||
# AfterNamespace: false
|
|
||||||
# AfterObjCDeclaration: false
|
|
||||||
# AfterStruct: false
|
|
||||||
# AfterUnion: false
|
|
||||||
# AfterExternBlock: false
|
|
||||||
# BeforeCatch: false
|
|
||||||
# BeforeElse: false
|
|
||||||
# BeforeLambdaBody: false
|
|
||||||
# BeforeWhile: false
|
|
||||||
# IndentBraces: false
|
|
||||||
# SplitEmptyFunction: true
|
|
||||||
# SplitEmptyRecord: true
|
|
||||||
# SplitEmptyNamespace: true
|
|
||||||
# BreakBeforeBinaryOperators: None
|
|
||||||
# BreakBeforeConceptDeclarations: true
|
|
||||||
# BreakBeforeBraces: Attach
|
|
||||||
# BreakBeforeInheritanceComma: false
|
|
||||||
# BreakInheritanceList: BeforeColon
|
|
||||||
# BreakBeforeTernaryOperators: true
|
|
||||||
# BreakConstructorInitializersBeforeComma: false
|
|
||||||
BreakConstructorInitializers: AfterColon
|
|
||||||
# BreakStringLiterals: true
|
|
||||||
ColumnLimit: 0
|
|
||||||
# CommentPragmas: '^ IWYU pragma:'
|
|
||||||
# QualifierAlignment: Leave
|
|
||||||
# CompactNamespaces: false
|
|
||||||
ConstructorInitializerIndentWidth: 8
|
|
||||||
ContinuationIndentWidth: 8
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
# DeriveLineEnding: true
|
|
||||||
# DerivePointerAlignment: false
|
|
||||||
# DisableFormat: false
|
|
||||||
# EmptyLineAfterAccessModifier: Never
|
|
||||||
# EmptyLineBeforeAccessModifier: LogicalBlock
|
|
||||||
# ExperimentalAutoDetectBinPacking: false
|
|
||||||
# PackConstructorInitializers: BinPack
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
||||||
# AllowAllConstructorInitializersOnNextLine: true
|
|
||||||
# FixNamespaceComments: true
|
|
||||||
# ForEachMacros:
|
|
||||||
# - foreach
|
|
||||||
# - Q_FOREACH
|
|
||||||
# - BOOST_FOREACH
|
|
||||||
# IfMacros:
|
|
||||||
# - KJ_IF_MAYBE
|
|
||||||
# IncludeBlocks: Preserve
|
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '".*"'
|
- Regex: '".*"'
|
||||||
Priority: 1
|
Priority: 1
|
||||||
|
|
@ -90,110 +18,10 @@ IncludeCategories:
|
||||||
Priority: 2
|
Priority: 2
|
||||||
- Regex: '^<.*'
|
- Regex: '^<.*'
|
||||||
Priority: 3
|
Priority: 3
|
||||||
# IncludeIsMainRegex: '(Test)?$'
|
#IndentCaseLabels: true
|
||||||
# IncludeIsMainSourceRegex: ''
|
|
||||||
# IndentAccessModifiers: false
|
|
||||||
IndentCaseLabels: true
|
|
||||||
# IndentCaseBlocks: false
|
|
||||||
# IndentGotoLabels: true
|
|
||||||
# IndentPPDirectives: None
|
|
||||||
# IndentExternBlock: AfterExternBlock
|
|
||||||
# IndentRequires: false
|
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
# IndentWrappedFunctionNames: false
|
#KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
# InsertTrailingCommas: None
|
PenaltyReturnTypeOnItsOwnLine: 0
|
||||||
# JavaScriptQuotes: Leave
|
|
||||||
# JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
# LambdaBodyIndentation: Signature
|
|
||||||
# MacroBlockBegin: ''
|
|
||||||
# MacroBlockEnd: ''
|
|
||||||
# MaxEmptyLinesToKeep: 1
|
|
||||||
# NamespaceIndentation: None
|
|
||||||
# PenaltyBreakAssignment: 2
|
|
||||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
# PenaltyBreakComment: 300
|
|
||||||
# PenaltyBreakFirstLessLess: 120
|
|
||||||
# PenaltyBreakOpenParenthesis: 0
|
|
||||||
# PenaltyBreakString: 1000
|
|
||||||
# PenaltyBreakTemplateDeclaration: 10
|
|
||||||
# PenaltyExcessCharacter: 1000000
|
|
||||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
# PenaltyIndentedWhitespace: 0
|
|
||||||
# PointerAlignment: Right
|
|
||||||
# PPIndentWidth: -1
|
|
||||||
# ReferenceAlignment: Pointer
|
|
||||||
# ReflowComments: true
|
|
||||||
# RemoveBracesLLVM: false
|
|
||||||
# SeparateDefinitionBlocks: Leave
|
|
||||||
# ShortNamespaceLines: 1
|
|
||||||
# SortIncludes: CaseSensitive
|
|
||||||
# SortJavaStaticImport: Before
|
|
||||||
# SortUsingDeclarations: true
|
|
||||||
# SpaceAfterCStyleCast: false
|
|
||||||
# SpaceAfterLogicalNot: false
|
|
||||||
# SpaceAfterTemplateKeyword: true
|
|
||||||
# SpaceBeforeAssignmentOperators: true
|
|
||||||
# SpaceBeforeCaseColon: false
|
|
||||||
# SpaceBeforeCpp11BracedList: false
|
|
||||||
# SpaceBeforeCtorInitializerColon: true
|
|
||||||
# SpaceBeforeInheritanceColon: true
|
|
||||||
# SpaceBeforeParens: ControlStatements
|
|
||||||
# SpaceBeforeParensOptions:
|
|
||||||
# AfterControlStatements: true
|
|
||||||
# AfterForeachMacros: true
|
|
||||||
# AfterFunctionDefinitionName: false
|
|
||||||
# AfterFunctionDeclarationName: false
|
|
||||||
# AfterIfMacros: true
|
|
||||||
# AfterOverloadedOperator: false
|
|
||||||
# BeforeNonEmptyParentheses: false
|
|
||||||
# SpaceAroundPointerQualifiers: Default
|
|
||||||
# SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
# SpaceInEmptyBlock: false
|
|
||||||
# SpaceInEmptyParentheses: false
|
|
||||||
# SpacesBeforeTrailingComments: 1
|
|
||||||
# SpacesInAngles: Never
|
|
||||||
# SpacesInConditionalStatement: false
|
|
||||||
# SpacesInContainerLiterals: true
|
|
||||||
# SpacesInCStyleCastParentheses: false
|
|
||||||
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
|
|
||||||
## our comment capitalization at the same time.
|
|
||||||
SpacesInLineCommentPrefix:
|
|
||||||
Minimum: 0
|
|
||||||
Maximum: -1
|
|
||||||
# SpacesInParentheses: false
|
|
||||||
# SpacesInSquareBrackets: false
|
|
||||||
# SpaceBeforeSquareBrackets: false
|
|
||||||
# BitFieldColonSpacing: Both
|
|
||||||
# StatementAttributeLikeMacros:
|
|
||||||
# - Q_EMIT
|
|
||||||
# StatementMacros:
|
|
||||||
# - Q_UNUSED
|
|
||||||
# - QT_REQUIRE_VERSION
|
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
# UseCRLF: false
|
|
||||||
UseTab: Always
|
|
||||||
# WhitespaceSensitiveMacros:
|
|
||||||
# - STRINGIZE
|
|
||||||
# - PP_STRINGIZE
|
|
||||||
# - BOOST_PP_STRINGIZE
|
|
||||||
# - NS_SWIFT_NAME
|
|
||||||
# - CF_SWIFT_NAME
|
|
||||||
---
|
|
||||||
### C++ specific config ###
|
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
Standard: c++17
|
Standard: c++20
|
||||||
---
|
|
||||||
### ObjC specific config ###
|
|
||||||
Language: ObjC
|
|
||||||
# ObjCBinPackProtocolList: Auto
|
|
||||||
ObjCBlockIndentWidth: 4
|
|
||||||
# ObjCBreakBeforeNestedBlockParam: true
|
|
||||||
# ObjCSpaceAfterProperty: false
|
|
||||||
# ObjCSpaceBeforeProtocolList: true
|
|
||||||
---
|
|
||||||
### Java specific config ###
|
|
||||||
Language: Java
|
|
||||||
# BreakAfterJavaFieldAnnotations: false
|
|
||||||
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
|
|
||||||
...
|
|
||||||
|
|
@ -29,9 +29,9 @@ CheckOptions:
|
||||||
- key: modernize-loop-convert.NamingStyle
|
- key: modernize-loop-convert.NamingStyle
|
||||||
value: CamelCase
|
value: CamelCase
|
||||||
- key: modernize-pass-by-value.IncludeStyle
|
- key: modernize-pass-by-value.IncludeStyle
|
||||||
value: llvm
|
value: microsoft
|
||||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||||
value: llvm
|
value: microsoft
|
||||||
- key: modernize-use-bool-literals.IgnoreMacros
|
- key: modernize-use-bool-literals.IgnoreMacros
|
||||||
value: '0'
|
value: '0'
|
||||||
- key: modernize-use-default-member-init.IgnoreMacros
|
- key: modernize-use-default-member-init.IgnoreMacros
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS -Wall)
|
set(CMAKE_CXX_FLAGS "-Wall -fno-rtti -fno-exceptions")
|
||||||
|
|
||||||
add_subdirectory("aster")
|
add_subdirectory("aster")
|
||||||
add_subdirectory("triangle")
|
add_subdirectory("triangle")
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ find_package(glm CONFIG REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
find_path(SCOTTT_DEBUGBREAK_INCLUDE_DIRS "debugbreak.h")
|
find_path(SCOTTT_DEBUGBREAK_INCLUDE_DIRS "debugbreak.h")
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
# find_package( VulkanHeaders CONFIG REQUIRED )
|
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||||
|
find_package(EASTL CONFIG REQUIRED)
|
||||||
|
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
constants.h
|
constants.h
|
||||||
|
|
@ -37,5 +37,6 @@ 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)
|
||||||
target_link_libraries(aster_core PRIVATE Vulkan::Vulkan Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
target_link_libraries(aster_core PRIVATE EASTL)
|
||||||
|
target_link_libraries(aster_core PUBLIC Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,15 @@
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||||
|
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
|
||||||
|
|
||||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||||
|
|
||||||
|
#define EASTL_NO_EXCEPTIONS 1
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
|
#define _HAS_EXCEPTIONS 0
|
||||||
|
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
#define USE_OPTICK (0)
|
#define USE_OPTICK (0)
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <optional>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
|
@ -28,53 +28,69 @@ using b8 = bool;
|
||||||
using b32 = u32;
|
using b32 = u32;
|
||||||
using usize = size_t;
|
using usize = size_t;
|
||||||
using p64 = intptr_t;
|
using p64 = intptr_t;
|
||||||
|
using cstr = const char *;
|
||||||
|
|
||||||
constexpr usize strlen_c(const char *s) {
|
constexpr usize
|
||||||
|
strlenC(const char *s)
|
||||||
|
{
|
||||||
usize len = 0;
|
usize len = 0;
|
||||||
char c = '\0';
|
char c = '\0';
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
c = s[len];
|
c = s[len];
|
||||||
len++;
|
len++;
|
||||||
} while (c != '\0');
|
} while (c != '\0');
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto ANSI_Black = "\u001b[30m";
|
namespace ansi_color
|
||||||
constexpr auto ANSI_Red = "\u001b[31m";
|
{
|
||||||
constexpr auto ANSI_Green = "\u001b[32m";
|
constexpr auto Black = "\u001b[30m";
|
||||||
constexpr auto ANSI_Yellow = "\u001b[33m";
|
constexpr auto Red = "\u001b[31m";
|
||||||
constexpr auto ANSI_Blue = "\u001b[34m";
|
constexpr auto Green = "\u001b[32m";
|
||||||
constexpr auto ANSI_Magenta = "\u001b[35m";
|
constexpr auto Yellow = "\u001b[33m";
|
||||||
constexpr auto ANSI_Cyan = "\u001b[36m";
|
constexpr auto Blue = "\u001b[34m";
|
||||||
constexpr auto ANSI_White = "\u001b[37m";
|
constexpr auto Magenta = "\u001b[35m";
|
||||||
constexpr auto ANSI_Reset = "\u001b[0m";
|
constexpr auto Cyan = "\u001b[36m";
|
||||||
|
constexpr auto White = "\u001b[37m";
|
||||||
|
constexpr auto Reset = "\u001b[0m";
|
||||||
|
} // namespace ansi_color
|
||||||
|
|
||||||
template <typename T>
|
template <typename TypeT, typename FromT>
|
||||||
using Option = std::optional<T>;
|
constexpr auto
|
||||||
|
cast(FromT &&in)
|
||||||
template <typename type_t, typename from_t>
|
{
|
||||||
constexpr auto cast(from_t &&_in) {
|
return static_cast<TypeT>(std::forward<FromT>(in));
|
||||||
return static_cast<type_t>(std::forward<from_t>(_in));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename type_t, typename from_t>
|
template <typename TypeT, typename FromT>
|
||||||
constexpr auto recast(from_t &&_in) {
|
constexpr auto
|
||||||
return reinterpret_cast<type_t>(std::forward<from_t>(_in));
|
recast(FromT &&in)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TypeT>(std::forward<FromT>(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32 operator""_deg(long double degrees) {
|
constexpr f32
|
||||||
|
operator""_deg(long double degrees)
|
||||||
|
{
|
||||||
return glm::radians<f32>(cast<f32>(degrees));
|
return glm::radians<f32>(cast<f32>(degrees));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32 operator""_deg(unsigned long long int degrees) {
|
constexpr f32
|
||||||
|
operator""_deg(unsigned long long int degrees)
|
||||||
|
{
|
||||||
return glm::radians<f32>(cast<f32>(degrees));
|
return glm::radians<f32>(cast<f32>(degrees));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32 operator""_rad(long double rads) {
|
constexpr f32
|
||||||
|
operator""_rad(long double rads)
|
||||||
|
{
|
||||||
return cast<f32>(rads);
|
return cast<f32>(rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32 operator""_rad(unsigned long long int rads) {
|
constexpr f32
|
||||||
|
operator""_rad(unsigned long long int rads)
|
||||||
|
{
|
||||||
return cast<f32>(rads);
|
return cast<f32>(rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,38 +107,45 @@ using glm::mat4;
|
||||||
|
|
||||||
constexpr auto *PROJECT_NAME = "Aster";
|
constexpr auto *PROJECT_NAME = "Aster";
|
||||||
|
|
||||||
struct Version {
|
struct Version
|
||||||
u32 major;
|
{
|
||||||
u32 minor;
|
u8 m_Major;
|
||||||
u32 patch;
|
u8 m_Minor;
|
||||||
|
u8 m_Patch;
|
||||||
|
|
||||||
|
[[nodiscard]] u32
|
||||||
|
GetVkVersion() const
|
||||||
|
{
|
||||||
|
return VK_MAKE_API_VERSION(0, m_Major, m_Minor, m_Patch);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Version VERSION = {
|
constexpr Version VERSION = {
|
||||||
.major = 0,
|
.m_Major = 0,
|
||||||
.minor = 1,
|
.m_Minor = 1,
|
||||||
.patch = 0,
|
.m_Patch = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T max_value = std::numeric_limits<T>::max();
|
constexpr T MaxValue = std::numeric_limits<T>::max();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T min_value = std::numeric_limits<T>::min();
|
constexpr T MinValue = std::numeric_limits<T>::min();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T lowest_value = std::numeric_limits<T>::lowest();
|
constexpr T LowestValue = std::numeric_limits<T>::lowest();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T err_epsilon = std::numeric_limits<T>::epsilon();
|
constexpr T ErrEpsilon = std::numeric_limits<T>::epsilon();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T positive_inf = std::numeric_limits<T>::infinity();
|
constexpr T PositiveInf = std::numeric_limits<T>::infinity();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T negative_inf = -std::numeric_limits<T>::infinity();
|
constexpr T NegativeInf = -std::numeric_limits<T>::infinity();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T qnan = std::numeric_limits<T>::quiet_NaN();
|
constexpr T Qnan = std::numeric_limits<T>::quiet_NaN();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T snan = std::numeric_limits<T>::signalling_NaN();
|
constexpr T Snan = std::numeric_limits<T>::signalling_NaN();
|
||||||
|
|
|
||||||
|
|
@ -4,58 +4,69 @@
|
||||||
// =============================================
|
// =============================================
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include <EASTL/array.h>
|
||||||
|
#include <EASTL/fixed_vector.h>
|
||||||
|
|
||||||
VKAPI_ATTR b32 VKAPI_CALL Context::debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT _message_severity, VkDebugUtilsMessageTypeFlagsEXT _message_type, const VkDebugUtilsMessengerCallbackDataEXT *_callback_data, [[maybe_unused]] void *_user_data) {
|
constexpr eastl::array VALIDATION_LAYERS = {
|
||||||
|
"VK_LAYER_KHRONOS_validation",
|
||||||
|
};
|
||||||
|
|
||||||
|
VKAPI_ATTR b32 VKAPI_CALL
|
||||||
|
debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||||
|
const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
|
||||||
|
{
|
||||||
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
|
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
|
||||||
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
||||||
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
|
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
|
||||||
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
||||||
|
|
||||||
const auto severity = Severity(_message_severity);
|
const auto severity = Severity(messageSeverity);
|
||||||
const auto message_type = MessageType(_message_type);
|
|
||||||
|
|
||||||
if (message_type & MessageTypeBits::eValidation) {
|
if (MessageType(messageType) & MessageTypeBits::eValidation)
|
||||||
|
{
|
||||||
if (severity & SeverityBits::eError)
|
if (severity & SeverityBits::eError)
|
||||||
ERROR("{}", _callback_data->pMessage);
|
ERROR("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eWarning)
|
if (severity & SeverityBits::eWarning)
|
||||||
WARN("{}", _callback_data->pMessage);
|
WARN("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eInfo)
|
if (severity & SeverityBits::eInfo)
|
||||||
INFO("{}", _callback_data->pMessage);
|
INFO("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eVerbose)
|
if (severity & SeverityBits::eVerbose)
|
||||||
VERBOSE("{}", _callback_data->pMessage);
|
VERBOSE("{}", callbackData->pMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::init(const std::string_view &_app_name, const Version &_app_version) {
|
Context::Context(cstr appName, Version version, bool enableValidation)
|
||||||
INFO_IF(enable_validation_layers, "Validation Layers enabled");
|
{
|
||||||
|
INFO_IF(enableValidation, "Validation Layers enabled");
|
||||||
|
|
||||||
// Creating Instance
|
// Creating Instance
|
||||||
const vk::ApplicationInfo app_info = {
|
const vk::ApplicationInfo appInfo = {
|
||||||
.pApplicationName = _app_name.data(),
|
.pApplicationName = appName,
|
||||||
.applicationVersion = VK_MAKE_VERSION(_app_version.major, _app_version.minor, _app_version.patch),
|
.applicationVersion = version.GetVkVersion(),
|
||||||
.pEngineName = PROJECT_NAME,
|
.pEngineName = PROJECT_NAME,
|
||||||
.engineVersion = VK_MAKE_VERSION(VERSION.major, VERSION.minor, VERSION.patch),
|
.engineVersion = version.GetVkVersion(),
|
||||||
.apiVersion = ASTER_API_VERSION,
|
.apiVersion = ASTER_API_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_create_info = {
|
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfo = {
|
||||||
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo,
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo,
|
||||||
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
|
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation,
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation,
|
||||||
.pfnUserCallback = debug_callback,
|
.pfnUserCallback = debugCallback,
|
||||||
.pUserData = nullptr,
|
.pUserData = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 glfw_extension_count = 0;
|
u32 glfwExtensionCount = 0;
|
||||||
const char **glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
|
cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||||
std::vector vulkan_extensions(glfw_extensions, glfw_extensions + glfw_extension_count);
|
eastl::fixed_vector<cstr, 3> instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
|
||||||
if (enable_validation_layers) {
|
if (enableValidation)
|
||||||
vulkan_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
{
|
||||||
|
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::DynamicLoader dl;
|
const vk::DynamicLoader dl;
|
||||||
|
|
@ -63,38 +74,38 @@ void Context::init(const std::string_view &_app_name, const Version &_app_versio
|
||||||
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
const auto instance_create_info = vk::InstanceCreateInfo{
|
const auto instanceCreateInfo = vk::InstanceCreateInfo{
|
||||||
.pNext = enable_validation_layers ? &debug_messenger_create_info : nullptr,
|
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
|
||||||
.pApplicationInfo = &app_info,
|
.pApplicationInfo = &appInfo,
|
||||||
.enabledLayerCount = enable_validation_layers ? cast<u32>(validation_layers.size()) : 0,
|
.enabledLayerCount = enableValidation ? cast<u32>(VALIDATION_LAYERS.size()) : 0,
|
||||||
.ppEnabledLayerNames = enable_validation_layers ? validation_layers.data() : nullptr,
|
.ppEnabledLayerNames = enableValidation ? VALIDATION_LAYERS.data() : nullptr,
|
||||||
.enabledExtensionCount = cast<u32>(vulkan_extensions.size()),
|
.enabledExtensionCount = cast<u32>(instanceExtensions.size()),
|
||||||
.ppEnabledExtensionNames = vulkan_extensions.data(),
|
.ppEnabledExtensionNames = instanceExtensions.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// May throw. Irrecoverable.
|
// May throw. Irrecoverable.
|
||||||
instance = vk::createInstance(instance_create_info);
|
vk::Result result = vk::createInstance(&instanceCreateInfo, nullptr, &m_Instance);
|
||||||
INFO("Instance Created.");
|
ERROR_IF(result, "Instance creation failed. Cause: {}", to_string(result))
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
|
THEN_ABORT(result)
|
||||||
|
ELSE_DEBUG("Instance Created.");
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_Instance);
|
||||||
|
|
||||||
// Debug Messenger
|
// Debug Messenger
|
||||||
if (enable_validation_layers) {
|
if (enableValidation)
|
||||||
try {
|
{
|
||||||
debug_messenger = instance.createDebugUtilsMessengerEXT(debug_messenger_create_info);
|
result = m_Instance.createDebugUtilsMessengerEXT(&debugUtilsMessengerCreateInfo, nullptr, &m_DebugMessenger);
|
||||||
} catch (const std::exception &_err) {
|
ERROR_IF(result, "Debug Messenger creation failed. Cause: {}", to_string(result)) // Non-critical. Continue.
|
||||||
ERROR("Debug Messenger creation failed. Cause: {}", _err.what());
|
ELSE_DEBUG("Debug Messenger Created.");
|
||||||
// Non-critical. Continue.
|
|
||||||
}
|
|
||||||
INFO("Debug Messenger Created.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::~Context() {
|
Context::~Context()
|
||||||
if (instance) {
|
{
|
||||||
if (enable_validation_layers && debug_messenger) {
|
if (m_DebugMessenger)
|
||||||
instance.destroyDebugUtilsMessengerEXT(debug_messenger);
|
{
|
||||||
}
|
m_Instance.destroy(m_DebugMessenger, nullptr);
|
||||||
instance.destroy();
|
DEBUG("Debug Messenger destroyed");
|
||||||
INFO("Context destroyed");
|
|
||||||
}
|
}
|
||||||
|
m_Instance.destroy(nullptr);
|
||||||
|
DEBUG("Instance destroyed");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Context
|
* @class Context
|
||||||
|
|
@ -16,71 +14,13 @@
|
||||||
*
|
*
|
||||||
* Handles the required hardware interactions.
|
* Handles the required hardware interactions.
|
||||||
*/
|
*/
|
||||||
class Context final {
|
struct Context final
|
||||||
public:
|
{
|
||||||
Context(const std::string_view &_app_name, const Version &_app_version, const b8 _enable_validation = true) :
|
// Members
|
||||||
enable_validation_layers{ _enable_validation } {
|
vk::Instance m_Instance = nullptr;
|
||||||
init(_app_name, _app_version);
|
vk::DebugUtilsMessengerEXT m_DebugMessenger = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
Context(const std::string_view &_app_name, const Version &_app_version, const std::vector<const char *> &_additional_device_extensions, const b8 _enable_validation = true) :
|
|
||||||
enable_validation_layers{ _enable_validation } {
|
|
||||||
device_extensions.reserve(device_extensions.size() + _additional_device_extensions.size());
|
|
||||||
device_extensions.insert(device_extensions.end(), _additional_device_extensions.begin(), _additional_device_extensions.end());
|
|
||||||
|
|
||||||
init(_app_name, _app_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context(const std::string_view &_app_name, const Version &_app_version, const std::vector<const char *> &_additional_device_extensions, const std::vector<const char *> &_additional_validation_layers) {
|
|
||||||
device_extensions.reserve(device_extensions.size() + _additional_device_extensions.size());
|
|
||||||
device_extensions.insert(device_extensions.end(), _additional_device_extensions.begin(), _additional_device_extensions.end());
|
|
||||||
|
|
||||||
validation_layers.reserve(validation_layers.size() + _additional_validation_layers.size());
|
|
||||||
validation_layers.insert(validation_layers.end(), _additional_validation_layers.begin(), _additional_validation_layers.end());
|
|
||||||
|
|
||||||
init(_app_name, _app_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context(const Context &_other) = delete;
|
|
||||||
|
|
||||||
Context(Context &&_other) noexcept :
|
|
||||||
enable_validation_layers{ _other.enable_validation_layers }, validation_layers{ std::move(_other.validation_layers) }, device_extensions{ std::move(_other.device_extensions) }, instance{ std::exchange(_other.instance, nullptr) }, debug_messenger{ std::exchange(_other.debug_messenger, nullptr) } {}
|
|
||||||
|
|
||||||
Context &operator=(const Context &_other) = delete;
|
|
||||||
|
|
||||||
Context &operator=(Context &&_other) noexcept {
|
|
||||||
if (this == &_other)
|
|
||||||
return *this;
|
|
||||||
enable_validation_layers = _other.enable_validation_layers;
|
|
||||||
validation_layers = std::move(_other.validation_layers);
|
|
||||||
device_extensions = std::move(_other.device_extensions);
|
|
||||||
instance = std::exchange(_other.instance, nullptr);
|
|
||||||
debug_messenger = std::exchange(_other.debug_messenger, nullptr);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Ctor/Dtor
|
||||||
|
Context(cstr appName, Version version, bool enableValidation = true);
|
||||||
~Context();
|
~Context();
|
||||||
|
|
||||||
// Fields
|
|
||||||
bool enable_validation_layers{ true };
|
|
||||||
|
|
||||||
std::vector<const char *> validation_layers = {
|
|
||||||
"VK_LAYER_KHRONOS_validation",
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<const char *> device_extensions = {
|
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
||||||
VK_KHR_MULTIVIEW_EXTENSION_NAME,
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::Instance instance;
|
|
||||||
vk::DebugUtilsMessengerEXT debug_messenger;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init(const std::string_view &_app_name, const Version &_app_version);
|
|
||||||
|
|
||||||
static VKAPI_ATTR b32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT _message_severity,
|
|
||||||
VkDebugUtilsMessageTypeFlagsEXT _message_type,
|
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT *_callback_data,
|
|
||||||
void *_user_data);
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
102
aster/device.cpp
102
aster/device.cpp
|
|
@ -5,76 +5,80 @@
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
Device::Device(const Context *_context, PhysicalDevice &&_physical_device, const vk::PhysicalDeviceFeatures *_enabled_features, const std::vector<QueueAllocation> &_queue_allocation, std::optional<std::string> _name) :
|
#include <EASTL/array.h>
|
||||||
physical_device{ std::move(_physical_device) },
|
|
||||||
name{ std::move(_name) } {
|
|
||||||
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
|
|
||||||
queue_create_infos.reserve(_queue_allocation.size());
|
|
||||||
|
|
||||||
u32 num_priorities = 0;
|
constexpr eastl::array DEVICE_EXTENSIONS = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||||
for (auto [_, count] : _queue_allocation) {
|
|
||||||
num_priorities = std::max(count, num_priorities);
|
Device::Device(const Context *context, PhysicalDevice *physicalDevice,
|
||||||
|
const vk::PhysicalDeviceFeatures *enabledFeatures,
|
||||||
|
const eastl::vector<QueueAllocation> &queueAllocations, NameString name)
|
||||||
|
: m_Name(std::move(name))
|
||||||
|
{
|
||||||
|
// Shouldn't have more than 4 deviceQueueFamilies in use anyway. Else we can heap
|
||||||
|
eastl::fixed_vector<vk::DeviceQueueCreateInfo, 4> deviceQueueCreateInfos;
|
||||||
|
deviceQueueCreateInfos.reserve(queueAllocations.size());
|
||||||
|
|
||||||
|
u32 numPriorities = 0;
|
||||||
|
for (auto [_, count] : queueAllocations)
|
||||||
|
{
|
||||||
|
numPriorities = std::max(count, numPriorities);
|
||||||
}
|
}
|
||||||
std::vector priorities(num_priorities, 1.0f);
|
// Shouldn't have more than 4 queues either.
|
||||||
|
eastl::fixed_vector<f32, 4> priorities(numPriorities, 1.0f);
|
||||||
|
|
||||||
for (auto [family, count] : _queue_allocation) {
|
for (auto [family, count] : queueAllocations)
|
||||||
queue_create_infos.push_back({
|
{
|
||||||
|
deviceQueueCreateInfos.push_back({
|
||||||
.queueFamilyIndex = family,
|
.queueFamilyIndex = family,
|
||||||
.queueCount = count,
|
.queueCount = count,
|
||||||
.pQueuePriorities = priorities.data(),
|
.pQueuePriorities = priorities.data(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
vk::DeviceCreateInfo deviceCreateInfo = {
|
||||||
device = physical_device.device.createDevice({
|
.queueCreateInfoCount = cast<u32>(deviceQueueCreateInfos.size()),
|
||||||
.queueCreateInfoCount = cast<u32>(queue_create_infos.size()),
|
.pQueueCreateInfos = deviceQueueCreateInfos.data(),
|
||||||
.pQueueCreateInfos = queue_create_infos.data(),
|
.enabledExtensionCount = cast<u32>(DEVICE_EXTENSIONS.size()),
|
||||||
.enabledLayerCount = _context->enable_validation_layers ? cast<u32>(_context->validation_layers.size()) : 0,
|
.ppEnabledExtensionNames = DEVICE_EXTENSIONS.data(),
|
||||||
.ppEnabledLayerNames = _context->enable_validation_layers ? _context->validation_layers.data() : nullptr,
|
.pEnabledFeatures = enabledFeatures,
|
||||||
.enabledExtensionCount = cast<u32>(_context->device_extensions.size()),
|
};
|
||||||
.ppEnabledExtensionNames = _context->device_extensions.data(),
|
|
||||||
.pEnabledFeatures = _enabled_features,
|
|
||||||
});
|
|
||||||
} catch (const std::exception &_err) {
|
|
||||||
ERROR("Could not initialize Vulkan Device. Cause: {}", _err.what());
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO("{} ({}) Initialized!", name.value_or(DEFAULT_DEVICE_NAME), physical_device.properties.deviceName.data());
|
vk::Result result = physicalDevice->m_PhysicalDevice.createDevice(&deviceCreateInfo, nullptr, &m_Device);
|
||||||
|
ERROR_IF(failed(result), "Could not initialize Vulkan Device. Cause: {}", result)
|
||||||
|
THEN_ABORT(result)
|
||||||
|
ELSE_DEBUG("{} ({}) Initialized.", m_Name, physicalDevice->m_DeviceProperties.deviceName.data());
|
||||||
|
|
||||||
VmaVulkanFunctions vma_vulkan_functions = {
|
VmaVulkanFunctions vmaVulkanFunctions = {
|
||||||
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
||||||
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VmaAllocatorCreateInfo vma_allocator_create_info = {
|
const VmaAllocatorCreateInfo allocatorCreateInfo = {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.physicalDevice = physical_device.device,
|
.physicalDevice = physicalDevice->m_PhysicalDevice,
|
||||||
.device = device,
|
.device = m_Device,
|
||||||
.pVulkanFunctions = &vma_vulkan_functions,
|
.pVulkanFunctions = &vmaVulkanFunctions,
|
||||||
.instance = _context->instance,
|
.instance = context->m_Instance,
|
||||||
.vulkanApiVersion = ASTER_API_VERSION,
|
.vulkanApiVersion = ASTER_API_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto result = cast<vk::Result>(vmaCreateAllocator(&vma_allocator_create_info, &allocator));
|
result = cast<vk::Result>(vmaCreateAllocator(&allocatorCreateInfo, &m_Allocator));
|
||||||
if (failed(result)) {
|
ERROR_IF(failed(result), "Memory allocator creation failed. Cause: {}", to_string(result))
|
||||||
device.destroy();
|
DO(m_Device.destroy(nullptr))
|
||||||
auto _err = fmt::format("Memory allocator creation failed. Cause: {}", to_string(result));
|
THEN_ABORT(result)
|
||||||
ERROR("{}", _err);
|
ELSE_VERBOSE("Memory Allocator Created");
|
||||||
throw std::runtime_error(_err);
|
|
||||||
}
|
|
||||||
VERBOSE("Memory Allocator Created");
|
|
||||||
|
|
||||||
INFO("Created '{}' Successfully", name.value_or(DEFAULT_DEVICE_NAME));
|
DEBUG("Created '{}' Successfully", m_Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device()
|
||||||
if (allocator) {
|
{
|
||||||
vmaDestroyAllocator(allocator);
|
if (m_Allocator)
|
||||||
allocator = nullptr;
|
{
|
||||||
VERBOSE("Memory Allocator Destroyed");
|
vmaDestroyAllocator(m_Allocator);
|
||||||
|
m_Allocator = nullptr;
|
||||||
|
DEBUG("Memory Allocator Destroyed");
|
||||||
}
|
}
|
||||||
device.destroy();
|
m_Device.destroy(nullptr);
|
||||||
INFO("Device '{}' Destroyed", name.value_or(DEFAULT_DEVICE_NAME));
|
DEBUG("Device '{}' Destroyed", m_Name);
|
||||||
name = std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,20 +8,22 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "physical_device.h"
|
#include "physical_device.h"
|
||||||
|
|
||||||
constexpr std::string DEFAULT_DEVICE_NAME = "<Unnamed GPU>";
|
struct QueueAllocation
|
||||||
|
{
|
||||||
struct QueueAllocation {
|
u32 m_Family;
|
||||||
u32 family;
|
u32 m_Count;
|
||||||
u32 count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Device final {
|
struct Device final
|
||||||
vk::Device device;
|
{
|
||||||
PhysicalDevice physical_device;
|
using NameString = eastl::fixed_string<char, 32, false>;
|
||||||
VmaAllocator allocator{ nullptr };
|
|
||||||
std::optional<std::string> name{ nullptr };
|
|
||||||
|
|
||||||
Device(const Context *_context, PhysicalDevice &&_physical_device, const vk::PhysicalDeviceFeatures *_enabled_features, const std::vector<QueueAllocation> &_queue_allocation, std::optional<std::string> _name = std::nullopt);
|
NameString m_Name;
|
||||||
|
vk::Device m_Device = nullptr;
|
||||||
|
VmaAllocator m_Allocator = nullptr;
|
||||||
|
|
||||||
|
Device(const Context *context, PhysicalDevice *physicalDevice, const vk::PhysicalDeviceFeatures *enabledFeatures,
|
||||||
|
const eastl::vector<QueueAllocation> &queueAllocations, NameString name);
|
||||||
|
|
||||||
~Device();
|
~Device();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,28 +7,36 @@
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
struct GlfwContext {
|
struct GlfwContext
|
||||||
static i32 post_error() noexcept {
|
{
|
||||||
static const char *error_ = nullptr;
|
|
||||||
const auto code = glfwGetError(&error_);
|
static i32
|
||||||
ERROR("GLFW {}", error_);
|
PostError() noexcept
|
||||||
|
{
|
||||||
|
static const char *error = nullptr;
|
||||||
|
const auto code = glfwGetError(&error);
|
||||||
|
ERROR("GLFW {}", error);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static u32 count = 0;
|
inline static u32 m_Count = 0;
|
||||||
|
|
||||||
GlfwContext() {
|
GlfwContext()
|
||||||
if (count++ > 0)
|
{
|
||||||
|
if (m_Count++ > 0)
|
||||||
return;
|
return;
|
||||||
if (glfwInit() == GLFW_FALSE) {
|
if (glfwInit() == GLFW_FALSE)
|
||||||
CRASH(post_error());
|
{
|
||||||
|
ABORT(PostError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~GlfwContext() {
|
~GlfwContext()
|
||||||
if (--count == 0) {
|
{
|
||||||
|
if (--m_Count == 0)
|
||||||
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
}
|
}
|
||||||
count = 0;
|
m_Count = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,16 @@
|
||||||
|
|
||||||
// NOTE: Vulkan Dispatch Loader Storage - Should only appear once.
|
// NOTE: Vulkan Dispatch Loader Storage - Should only appear once.
|
||||||
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
|
void *
|
||||||
|
operator new[](size_t size, const char *pName, int flags, unsigned debugFlags, const char *file, int line)
|
||||||
|
{
|
||||||
|
return new u8[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char *pName, int flags, unsigned debugFlags,
|
||||||
|
const char *file, int line)
|
||||||
|
{
|
||||||
|
return new u8[size];
|
||||||
|
}
|
||||||
132
aster/global.h
132
aster/global.h
|
|
@ -11,30 +11,52 @@
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <string>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
// Macros that can collide with functions.
|
||||||
|
#if defined(max)
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(min)
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed")
|
#define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed")
|
||||||
|
#include <EASTL/fixed_string.h>
|
||||||
|
#include <EASTL/string.h>
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
constexpr u32 ASTER_API_VERSION = vk::ApiVersion13;
|
constexpr u32 ASTER_API_VERSION = vk::ApiVersion13;
|
||||||
|
|
||||||
#define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__)
|
#define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__)
|
||||||
[[nodiscard]] inline bool failed(const vk::Result _result) {
|
|
||||||
return _result != vk::Result::eSuccess;
|
[[nodiscard]] inline bool
|
||||||
|
failed(const vk::Result result)
|
||||||
|
{
|
||||||
|
return result != vk::Result::eSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept IsVkEnum = requires(T _t) {
|
concept IsVkEnum = requires(T t) {
|
||||||
{ std::is_enum_v<T> };
|
{
|
||||||
{ vk::to_string(_t) } -> std::same_as<std::string>;
|
std::is_enum_v<T>
|
||||||
|
};
|
||||||
|
{
|
||||||
|
vk::to_string(t)
|
||||||
|
} -> std::same_as<std::string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires IsVkEnum<T> [[nodiscard]] const char *to_cstr(const T &_val) {
|
requires IsVkEnum<T>
|
||||||
|
[[nodiscard]] const char *
|
||||||
|
toCstr(const T &val)
|
||||||
|
{
|
||||||
static std::string buffer;
|
static std::string buffer;
|
||||||
buffer = vk::to_string(_val);
|
buffer = vk::to_string(val);
|
||||||
return buffer.c_str();
|
return buffer.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,49 +65,87 @@ using namespace std::literals::string_literals;
|
||||||
using namespace std::literals::string_view_literals;
|
using namespace std::literals::string_view_literals;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires vk::isVulkanHandleType<T>::value [[nodiscard]] constexpr u64
|
requires vk::isVulkanHandleType<T>::value
|
||||||
get_vk_handle(const T &_vk_handle) noexcept {
|
[[nodiscard]] constexpr u64
|
||||||
return reinterpret_cast<u64>(cast<T::CType>(_vk_handle));
|
getVkHandle(const T &vkHandle) noexcept
|
||||||
|
{
|
||||||
|
return reinterpret_cast<u64>(cast<T::CType>(vkHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
struct std::hash<vk::Flags<F>> {
|
struct std::hash<vk::Flags<F>>
|
||||||
[[nodiscard]] usize operator()(const vk::Flags<F> &_val) {
|
{
|
||||||
return std::hash<u32>()(cast<u32>(_val));
|
[[nodiscard]] usize
|
||||||
|
operator()(const vk::Flags<F> &val)
|
||||||
|
{
|
||||||
|
return std::hash<u32>()(cast<u32>(val));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] usize hash_any(const T &_val) {
|
[[nodiscard]] usize
|
||||||
return std::hash<std::remove_cvref_t<T>>()(_val);
|
hashAny(const T &val)
|
||||||
|
{
|
||||||
|
return std::hash<std::remove_cvref_t<T>>()(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline usize hash_combine(const usize _hash0,
|
[[nodiscard]] inline usize
|
||||||
const usize _hash1) {
|
hashCombine(const usize hash0, const usize hash1)
|
||||||
constexpr usize salt_value = 0x9e3779b9;
|
{
|
||||||
return _hash0 ^ (_hash1 + salt_value + (_hash0 << 6) + (_hash0 >> 2));
|
constexpr usize saltValue = 0x9e3779b9;
|
||||||
|
return hash0 ^ (hash1 + saltValue + (hash0 << 6) + (hash0 >> 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Time {
|
struct Time
|
||||||
static constexpr f64 max_delta = 0.1;
|
{
|
||||||
|
static constexpr f64 c_MaxDelta = 0.1;
|
||||||
|
|
||||||
inline static f64 elapsed{ qnan<f64> };
|
inline static f64 m_Elapsed{Qnan<f64>};
|
||||||
inline static f64 delta{ qnan<f64> };
|
inline static f64 m_Delta{Qnan<f64>};
|
||||||
|
|
||||||
static void init() {
|
static void
|
||||||
WARN_IF(!std::isnan(elapsed), "Time already init.");
|
Init()
|
||||||
elapsed = glfwGetTime();
|
{
|
||||||
delta = 1.0 / 60.0;
|
WARN_IF(!std::isnan(m_Elapsed), "Time already init.");
|
||||||
|
m_Elapsed = glfwGetTime();
|
||||||
|
m_Delta = 1.0 / 60.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update() {
|
static void
|
||||||
ERROR_IF(std::isnan(elapsed), "Time not init.");
|
Update()
|
||||||
const auto new_elapsed = glfwGetTime();
|
{
|
||||||
delta = std::clamp(new_elapsed - elapsed, 0.0, max_delta);
|
ERROR_IF(std::isnan(m_Elapsed), "Time not init.");
|
||||||
elapsed = new_elapsed;
|
const auto newElapsed = glfwGetTime();
|
||||||
|
m_Delta = std::clamp(newElapsed - m_Elapsed, 0.0, c_MaxDelta);
|
||||||
|
m_Elapsed = newElapsed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline usize closest_multiple(const usize _val, const usize _of) {
|
[[nodiscard]] inline usize
|
||||||
return _of * ((_val + _of - 1) / _of);
|
closestMultiple(const usize val, const usize of)
|
||||||
|
{
|
||||||
|
return of * ((val + of - 1) / of);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<vk::Result> : nested_formatter<std::string>
|
||||||
|
{
|
||||||
|
auto
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
|
format(vk::Result result, format_context &ctx) const
|
||||||
|
{
|
||||||
|
return write_padded(ctx,
|
||||||
|
[this, result](auto out) { return v10::format_to(out, "{}", nested(to_string(result))); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, usize N, bool B>
|
||||||
|
struct fmt::formatter<eastl::fixed_string<T, N, B>> : nested_formatter<cstr>
|
||||||
|
{
|
||||||
|
auto
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
|
format(const eastl::fixed_string<T, N, B> &str, format_context &ctx) const
|
||||||
|
{
|
||||||
|
return write_padded(ctx, [this, str](auto out) { return v10::format_to(out, "{}", nested(str.c_str())); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -5,13 +5,16 @@
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
Logger g_logger = Logger();
|
Logger g_Logger = Logger();
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
|
|
||||||
/* Credits to Const-me */
|
/* Credits to Const-me */
|
||||||
//namespace eastl {
|
namespace eastl
|
||||||
// void __cdecl AssertionFailure(const char* af)
|
{
|
||||||
// {
|
void
|
||||||
// ERROR(af);
|
AssertionFailure(const char *af)
|
||||||
// __debugbreak();
|
{
|
||||||
// }
|
ERROR("{}", af);
|
||||||
//}
|
debug_break();
|
||||||
|
}
|
||||||
|
} // namespace eastl
|
||||||
|
|
|
||||||
127
aster/logger.h
127
aster/logger.h
|
|
@ -9,10 +9,10 @@
|
||||||
#include <debugbreak.h>
|
#include <debugbreak.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include <string>
|
struct Logger
|
||||||
|
{
|
||||||
struct Logger {
|
enum class LogType : u32
|
||||||
enum class LogType : u32 {
|
{
|
||||||
eError,
|
eError,
|
||||||
eWarning,
|
eWarning,
|
||||||
eInfo,
|
eInfo,
|
||||||
|
|
@ -20,14 +20,18 @@ struct Logger {
|
||||||
eVerbose,
|
eVerbose,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 minimum_logging_level{ cast<u32>(LogType::eDebug) };
|
u32 m_MinimumLoggingLevel{cast<u32>(LogType::eDebug)};
|
||||||
|
|
||||||
void set_minimum_logging_level(LogType _log_type) {
|
void
|
||||||
minimum_logging_level = cast<u32>(_log_type);
|
SetMinimumLoggingLevel(LogType logType)
|
||||||
|
{
|
||||||
|
m_MinimumLoggingLevel = cast<u32>(logType);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <LogType LogLevel>
|
template <LogType LogLevel>
|
||||||
constexpr static const char *to_cstr() {
|
constexpr static const char *
|
||||||
|
ToCstr()
|
||||||
|
{
|
||||||
if constexpr (LogLevel == LogType::eError)
|
if constexpr (LogLevel == LogType::eError)
|
||||||
return "[ERROR]:";
|
return "[ERROR]:";
|
||||||
if constexpr (LogLevel == LogType::eWarning)
|
if constexpr (LogLevel == LogType::eWarning)
|
||||||
|
|
@ -42,99 +46,116 @@ struct Logger {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <LogType LogLevel>
|
template <LogType LogLevel>
|
||||||
constexpr static const char *to_color_cstr() {
|
constexpr static const char *
|
||||||
|
ToColorCstr()
|
||||||
|
{
|
||||||
if constexpr (LogLevel == LogType::eError)
|
if constexpr (LogLevel == LogType::eError)
|
||||||
return ANSI_Red;
|
return ansi_color::Red;
|
||||||
if constexpr (LogLevel == LogType::eWarning)
|
if constexpr (LogLevel == LogType::eWarning)
|
||||||
return ANSI_Yellow;
|
return ansi_color::Yellow;
|
||||||
if constexpr (LogLevel == LogType::eInfo)
|
if constexpr (LogLevel == LogType::eInfo)
|
||||||
return ANSI_Green;
|
return ansi_color::Green;
|
||||||
if constexpr (LogLevel == LogType::eDebug)
|
if constexpr (LogLevel == LogType::eDebug)
|
||||||
return ANSI_White;
|
return ansi_color::White;
|
||||||
if constexpr (LogLevel == LogType::eVerbose)
|
if constexpr (LogLevel == LogType::eVerbose)
|
||||||
return ANSI_Blue;
|
return ansi_color::Blue;
|
||||||
return ANSI_White;
|
return ansi_color::White;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <LogType LogLevel>
|
template <LogType LogLevel>
|
||||||
void log(const std::string_view &_message, const char *_loc, u32 _line) const {
|
void
|
||||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
Log(const std::string_view &message, const char *loc, u32 line) const
|
||||||
fmt::println("{}{} {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
{
|
||||||
|
if (cast<u32>(LogLevel) <= m_MinimumLoggingLevel)
|
||||||
|
{
|
||||||
|
fmt::println("{}{} {} {} at {}:{}{}", ToColorCstr<LogLevel>(), ToCstr<LogLevel>(), message.data(),
|
||||||
|
ansi_color::Black, loc, line, ansi_color::Reset);
|
||||||
}
|
}
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
if constexpr (LogLevel == LogType::eError) {
|
if constexpr (LogLevel == LogType::eError)
|
||||||
|
{
|
||||||
debug_break();
|
debug_break();
|
||||||
}
|
}
|
||||||
#endif // !defined(NDEBUG)
|
#endif // !defined(NDEBUG)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <LogType LogLevel>
|
template <LogType LogLevel>
|
||||||
void log_cond(const char *_expr_str, const std::string_view &_message, const char *_loc, u32 _line) const {
|
void
|
||||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
LogCond(const char *exprStr, const std::string_view &message, const char *loc, u32 line) const
|
||||||
fmt::println("{}{} ({}) {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _expr_str, _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
{
|
||||||
|
if (cast<u32>(LogLevel) <= m_MinimumLoggingLevel)
|
||||||
|
{
|
||||||
|
fmt::println("{}{} ({}) {} {} at {}:{}{}", ToColorCstr<LogLevel>(), ToCstr<LogLevel>(), exprStr,
|
||||||
|
message.data(), ansi_color::Black, loc, line, ansi_color::Reset);
|
||||||
}
|
}
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
if constexpr (LogLevel == LogType::eError) {
|
if constexpr (LogLevel == LogType::eError)
|
||||||
|
{
|
||||||
debug_break();
|
debug_break();
|
||||||
}
|
}
|
||||||
#endif // !defined(NDEBUG)
|
#endif // !defined(NDEBUG)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Logger g_logger;
|
extern Logger g_Logger;
|
||||||
|
|
||||||
#define MIN_LOG_LEVEL(LOG_LVL) g_logger.set_minimum_logging_level(LOG_LVL)
|
#define MIN_LOG_LEVEL(LOG_LVL) g_Logger.SetMinimumLoggingLevel(LOG_LVL)
|
||||||
#define ERROR(...) g_logger.log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
#define ERROR(...) g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define WARN(...) g_logger.log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
#define WARN(...) g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define INFO(...) g_logger.log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
#define INFO(...) g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ERROR_IF(expr, ...) \
|
#define ERROR_IF(expr, ...) \
|
||||||
if (cast<bool>(expr)) [[unlikely]] \
|
if (cast<bool>(expr)) [[unlikely]] \
|
||||||
g_logger.log_cond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define WARN_IF(expr, ...) \
|
#define WARN_IF(expr, ...) \
|
||||||
if (cast<bool>(expr)) [[unlikely]] \
|
if (cast<bool>(expr)) [[unlikely]] \
|
||||||
g_logger.log_cond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define INFO_IF(expr, ...) \
|
#define INFO_IF(expr, ...) \
|
||||||
if (cast<bool>(expr)) \
|
if (cast<bool>(expr)) \
|
||||||
g_logger.log_cond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ELSE_IF_ERROR(expr, ...) \
|
#define ELSE_IF_ERROR(expr, ...) \
|
||||||
; \
|
; \
|
||||||
else if (cast<bool>(expr)) [[unlikely]] g_logger.log_cond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else if (cast<bool>(expr)) \
|
||||||
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_WARN(expr, ...) \
|
#define ELSE_IF_WARN(expr, ...) \
|
||||||
; \
|
; \
|
||||||
else if (cast<bool>(expr)) [[unlikely]] g_logger.log_cond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else if (cast<bool>(expr)) \
|
||||||
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_INFO(expr, ...) \
|
#define ELSE_IF_INFO(expr, ...) \
|
||||||
; \
|
; \
|
||||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else if (cast<bool>(expr)) \
|
||||||
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ELSE_ERROR(...) \
|
#define ELSE_ERROR(...) \
|
||||||
; \
|
; \
|
||||||
else [[unlikely]] g_logger.log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else [[unlikely]] g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_WARN(...) \
|
#define ELSE_WARN(...) \
|
||||||
; \
|
; \
|
||||||
else [[unlikely]] g_logger.log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else [[unlikely]] g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_INFO(...) \
|
#define ELSE_INFO(...) \
|
||||||
; \
|
; \
|
||||||
else g_logger.log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#if !defined(DEBUG_LOG_DISABLED) && !defined(NDEBUG)
|
#if !defined(DEBUG_LOG_DISABLED) && !defined(NDEBUG)
|
||||||
|
|
||||||
#define DEBUG(...) g_logger.log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
#define DEBUG(...) g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define DEBUG_IF(expr, ...) \
|
#define DEBUG_IF(expr, ...) \
|
||||||
if (cast<bool>(expr)) \
|
if (cast<bool>(expr)) \
|
||||||
g_logger.log_cond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_DEBUG(expr, ...) \
|
#define ELSE_IF_DEBUG(expr, ...) \
|
||||||
; \
|
; \
|
||||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else if (cast<bool>(expr)) \
|
||||||
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_DEBUG(...) \
|
#define ELSE_DEBUG(...) \
|
||||||
; \
|
; \
|
||||||
else [[unlikely]] g_logger.log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#else // !defined(DEBUG_LOG_DISABLED)
|
#else // !defined(DEBUG_LOG_DISABLED)
|
||||||
|
|
||||||
#define DEBUG(msg) \
|
#define DEBUG(msg) \
|
||||||
{}
|
{ \
|
||||||
|
}
|
||||||
#define DEBUG_IF(expr, msg) \
|
#define DEBUG_IF(expr, msg) \
|
||||||
if (expr) \
|
if (expr) \
|
||||||
(void)msg
|
(void)msg
|
||||||
|
|
@ -144,27 +165,30 @@ extern Logger g_logger;
|
||||||
(void)msg
|
(void)msg
|
||||||
#define ELSE_DEBUG(msg) \
|
#define ELSE_DEBUG(msg) \
|
||||||
; \
|
; \
|
||||||
{}
|
{ \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !defined(DEBUG_LOG_DISABLED)
|
#endif // !defined(DEBUG_LOG_DISABLED)
|
||||||
|
|
||||||
#if !defined(VERBOSE_LOG_DISABLED) && !defined(NDEBUG)
|
#if !defined(VERBOSE_LOG_DISABLED) && !defined(NDEBUG)
|
||||||
|
|
||||||
#define VERBOSE(...) g_logger.log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
#define VERBOSE(...) g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define VERBOSE_IF(expr, ...) \
|
#define VERBOSE_IF(expr, ...) \
|
||||||
if (cast<bool>(expr)) \
|
if (cast<bool>(expr)) \
|
||||||
g_logger.log_cond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_VERBOSE(expr, ...) \
|
#define ELSE_IF_VERBOSE(expr, ...) \
|
||||||
; \
|
; \
|
||||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else if (cast<bool>(expr)) \
|
||||||
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_VERBOSE(...) \
|
#define ELSE_VERBOSE(...) \
|
||||||
; \
|
; \
|
||||||
else g_logger.log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
else g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#else // !defined(DEBUG_LOG_DISABLED)
|
#else // !defined(DEBUG_LOG_DISABLED)
|
||||||
|
|
||||||
#define VERBOSE(msg) \
|
#define VERBOSE(msg) \
|
||||||
{}
|
{ \
|
||||||
|
}
|
||||||
#define VERBOSE_IF(expr, msg) \
|
#define VERBOSE_IF(expr, msg) \
|
||||||
if (expr) \
|
if (expr) \
|
||||||
(void)msg
|
(void)msg
|
||||||
|
|
@ -174,10 +198,11 @@ extern Logger g_logger;
|
||||||
(void)msg
|
(void)msg
|
||||||
#define ELSE_VERBOSE(msg) \
|
#define ELSE_VERBOSE(msg) \
|
||||||
; \
|
; \
|
||||||
{}
|
{ \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !defined(VERBOSE_LOG_DISABLED)
|
#endif // !defined(VERBOSE_LOG_DISABLED)
|
||||||
|
|
||||||
#define DO(code) , code
|
#define DO(code) , code
|
||||||
#define CRASH(code) exit(cast<i32>(code))
|
#define ABORT(code) exit(cast<i32>(code))
|
||||||
#define THEN_CRASH(code) , CRASH(code)
|
#define THEN_ABORT(code) , ABORT(code)
|
||||||
|
|
|
||||||
|
|
@ -5,95 +5,145 @@
|
||||||
|
|
||||||
#include "physical_device.h"
|
#include "physical_device.h"
|
||||||
|
|
||||||
[[nodiscard]] std::vector<vk::SurfaceFormatKHR> get_surface_formats(const Window *_window, const vk::PhysicalDevice *_physical_device) {
|
[[nodiscard]] eastl::vector<vk::SurfaceFormatKHR>
|
||||||
try {
|
getSurfaceFormats(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||||
return _physical_device->getSurfaceFormatsKHR(_window->surface);
|
{
|
||||||
} catch (const std::exception &_err) {
|
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
|
||||||
ERROR("Could not get surface formats. Cause: {}", _err.what());
|
u32 count = 0;
|
||||||
throw;
|
vk::Result result = physicalDevice.getSurfaceFormatsKHR(surface, &count, nullptr);
|
||||||
}
|
ERROR_IF(failed(result), "Could not get surface formats. Cause: {}", to_string(result))
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
eastl::vector<vk::SurfaceFormatKHR> surfaceFormats(count);
|
||||||
|
result = physicalDevice.getSurfaceFormatsKHR(surface, &count, surfaceFormats.data());
|
||||||
|
ERROR_IF(failed(result), "Could not get surface formats. Cause: {}", to_string(result))
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
return surfaceFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::vector<vk::PresentModeKHR> get_present_modes(const Window *_window, const vk::PhysicalDevice *_physical_device) {
|
[[nodiscard]] eastl::vector<vk::PresentModeKHR>
|
||||||
try {
|
getSurfacePresentModes(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||||
return _physical_device->getSurfacePresentModesKHR(_window->surface);
|
{
|
||||||
} catch (const std::exception &_err) {
|
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
|
||||||
ERROR("Could not get present modes. Cause: {}", _err.what());
|
u32 count = 0;
|
||||||
throw;
|
vk::Result result = physicalDevice.getSurfacePresentModesKHR(surface, &count, nullptr);
|
||||||
}
|
ERROR_IF(failed(result), "Could not get present modes. Cause: {}", to_string(result))
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
eastl::vector<vk::PresentModeKHR> presentModes(count);
|
||||||
|
result = physicalDevice.getSurfacePresentModesKHR(surface, &count, presentModes.data());
|
||||||
|
ERROR_IF(failed(result), "Could not get present modes. Cause: {}", to_string(result))
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
return presentModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool get_present_support(const u32 _family_index, const Window *_window, const vk::PhysicalDevice *_device) {
|
[[nodiscard]] bool
|
||||||
try {
|
getQueuePresentSupport(const u32 queueFamilyIndex, vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||||
return _device->getSurfaceSupportKHR(_family_index, _window->surface);
|
{
|
||||||
} catch (const std::exception &_err) {
|
b32 supported = false;
|
||||||
ERROR("Could not get queue family surface support. Cause: {}", _err.what());
|
const vk::Result result = physicalDevice.getSurfaceSupportKHR(queueFamilyIndex, surface, &supported);
|
||||||
throw;
|
ERROR_IF(failed(result), "Could not get queue family surface support. Cause: {}", to_string(result))
|
||||||
}
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::vector<QueueFamilyInfo> get_queue_families(const Window *_window, const vk::PhysicalDevice *_device) {
|
[[nodiscard]] eastl::fixed_vector<vk::QueueFamilyProperties, 32>
|
||||||
auto queue_family_props = _device->getQueueFamilyProperties();
|
getQueueFamilyProperties(const vk::PhysicalDevice physicalDevice)
|
||||||
|
{
|
||||||
|
// Devices rarely have more than 32 queue families. Thus fixed vector
|
||||||
|
u32 count = 0;
|
||||||
|
physicalDevice.getQueueFamilyProperties(&count, nullptr);
|
||||||
|
|
||||||
std::vector<QueueFamilyInfo> queue_family_infos;
|
eastl::fixed_vector<vk::QueueFamilyProperties, 32> queueFamilyProperties(count);
|
||||||
queue_family_infos.reserve(queue_family_props.size());
|
physicalDevice.getQueueFamilyProperties(&count, queueFamilyProperties.data());
|
||||||
|
|
||||||
u32 family_index = 0;
|
return queueFamilyProperties;
|
||||||
for (auto qfp : queue_family_props) {
|
}
|
||||||
|
|
||||||
|
// Size 384 return.
|
||||||
|
[[nodiscard]] eastl::vector<QueueFamilyInfo>
|
||||||
|
getQueueFamilies(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto queueFamilyProperties = getQueueFamilyProperties(physicalDevice);
|
||||||
|
|
||||||
|
eastl::vector<QueueFamilyInfo> queueFamilyInfos;
|
||||||
|
queueFamilyInfos.reserve(queueFamilyProperties.size());
|
||||||
|
|
||||||
|
u32 familyIndex = 0;
|
||||||
|
for (auto qfp : queueFamilyProperties)
|
||||||
|
{
|
||||||
QueueSupportFlags support = {};
|
QueueSupportFlags support = {};
|
||||||
|
|
||||||
if (qfp.queueFlags | vk::QueueFlagBits::eGraphics) {
|
if (qfp.queueFlags | vk::QueueFlagBits::eGraphics)
|
||||||
|
{
|
||||||
support |= QueueSupportFlagBits::eGraphics;
|
support |= QueueSupportFlagBits::eGraphics;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qfp.queueFlags | vk::QueueFlagBits::eTransfer) {
|
if (qfp.queueFlags | vk::QueueFlagBits::eTransfer)
|
||||||
|
{
|
||||||
support |= QueueSupportFlagBits::eTransfer;
|
support |= QueueSupportFlagBits::eTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qfp.queueFlags | vk::QueueFlagBits::eCompute) {
|
if (qfp.queueFlags | vk::QueueFlagBits::eCompute)
|
||||||
|
{
|
||||||
support |= QueueSupportFlagBits::eCompute;
|
support |= QueueSupportFlagBits::eCompute;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_present_support(family_index, _window, _device)) {
|
if (getQueuePresentSupport(familyIndex, surface, physicalDevice))
|
||||||
|
{
|
||||||
support |= QueueSupportFlagBits::ePresent;
|
support |= QueueSupportFlagBits::ePresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_family_infos.push_back({
|
queueFamilyInfos.push_back({
|
||||||
.index = family_index,
|
.m_Index = familyIndex,
|
||||||
.count = qfp.queueCount,
|
.m_Count = qfp.queueCount,
|
||||||
.support = support,
|
.m_Support = support,
|
||||||
});
|
});
|
||||||
|
|
||||||
family_index++;
|
familyIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return queue_family_infos;
|
return queueFamilyInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDevice::PhysicalDevice(const Window *_window, vk::PhysicalDevice _physical_device) {
|
PhysicalDevice::PhysicalDevice(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||||
_physical_device.getProperties(&properties);
|
{
|
||||||
_physical_device.getFeatures(&features);
|
physicalDevice.getProperties(&m_DeviceProperties);
|
||||||
|
physicalDevice.getFeatures(&m_DeviceFeatures);
|
||||||
|
|
||||||
surface_formats = get_surface_formats(_window, &_physical_device);
|
m_SurfaceFormats = getSurfaceFormats(surface, physicalDevice);
|
||||||
present_modes = get_present_modes(_window, &_physical_device);
|
m_PresentModes = getSurfacePresentModes(surface, physicalDevice);
|
||||||
queue_families = get_queue_families(_window, &_physical_device);
|
m_QueueFamilies = getQueueFamilies(surface, physicalDevice);
|
||||||
|
|
||||||
device = _physical_device;
|
m_PhysicalDevice = physicalDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<vk::PhysicalDevice> enumerate_physical_devices(const Context *_context) {
|
eastl::fixed_vector<vk::PhysicalDevice, 8>
|
||||||
try {
|
enumeratePhysicalDevices(const vk::Instance instance)
|
||||||
return _context->instance.enumeratePhysicalDevices();
|
{
|
||||||
} catch (const std::exception &_err) {
|
u32 count = 0;
|
||||||
ERROR("Could not fetch vulkan devices. Cause: {}", _err.what());
|
vk::Result result = instance.enumeratePhysicalDevices(&count, nullptr);
|
||||||
throw;
|
ERROR_IF(failed(result), "Could not fetch vulkan devices. Cause: {}", to_string(result))
|
||||||
}
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
eastl::fixed_vector<vk::PhysicalDevice, 8> physicalDevices(count);
|
||||||
|
result = instance.enumeratePhysicalDevices(&count, physicalDevices.data());
|
||||||
|
ERROR_IF(failed(result), "Could not fetch vulkan devices. Cause: {}", to_string(result))
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
return physicalDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDevices::PhysicalDevices(const Window *_window, const Context *_context) {
|
PhysicalDevices::PhysicalDevices(const Window *window, const Context *context)
|
||||||
auto physical_devices = enumerate_physical_devices(_context);
|
{
|
||||||
this->reserve(physical_devices.size());
|
auto surface = window->m_Surface;
|
||||||
for (auto physical_device : physical_devices) {
|
auto physicalDevices = enumeratePhysicalDevices(context->m_Instance);
|
||||||
this->emplace_back(_window, physical_device);
|
for (auto physicalDevice : physicalDevices)
|
||||||
|
{
|
||||||
|
this->emplace_back(surface, physicalDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
#include <EASTL/fixed_vector.h>
|
||||||
|
|
||||||
enum class QueueSupportFlagBits {
|
enum class QueueSupportFlagBits
|
||||||
|
{
|
||||||
eGraphics = 0b0001,
|
eGraphics = 0b0001,
|
||||||
eTransfer = 0b0010,
|
eTransfer = 0b0010,
|
||||||
eCompute = 0b0100,
|
eCompute = 0b0100,
|
||||||
|
|
@ -17,24 +19,27 @@ enum class QueueSupportFlagBits {
|
||||||
|
|
||||||
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
||||||
|
|
||||||
struct QueueFamilyInfo {
|
struct QueueFamilyInfo
|
||||||
u32 index;
|
{
|
||||||
u32 count;
|
u32 m_Index;
|
||||||
QueueSupportFlags support;
|
u32 m_Count;
|
||||||
|
QueueSupportFlags m_Support;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhysicalDevice {
|
struct PhysicalDevice
|
||||||
vk::PhysicalDevice device;
|
{
|
||||||
vk::PhysicalDeviceProperties properties;
|
vk::PhysicalDevice m_PhysicalDevice;
|
||||||
vk::PhysicalDeviceFeatures features;
|
vk::PhysicalDeviceProperties m_DeviceProperties;
|
||||||
std::vector<vk::SurfaceFormatKHR> surface_formats;
|
vk::PhysicalDeviceFeatures m_DeviceFeatures;
|
||||||
std::vector<vk::PresentModeKHR> present_modes;
|
eastl::vector<vk::SurfaceFormatKHR> m_SurfaceFormats;
|
||||||
std::vector<QueueFamilyInfo> queue_families;
|
eastl::vector<vk::PresentModeKHR> m_PresentModes;
|
||||||
|
eastl::vector<QueueFamilyInfo> m_QueueFamilies;
|
||||||
|
|
||||||
PhysicalDevice(const Window *_window, vk::PhysicalDevice _physical_device);
|
PhysicalDevice(vk::SurfaceKHR surface, vk::PhysicalDevice physicalDevice);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhysicalDevices : public std::vector<PhysicalDevice> {
|
class PhysicalDevices : public eastl::fixed_vector<PhysicalDevice, 4>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
PhysicalDevices(const Window *_window, const Context *_context);
|
PhysicalDevices(const Window *window, const Context *context);
|
||||||
};
|
};
|
||||||
|
|
@ -8,65 +8,72 @@
|
||||||
#include "glfw_context.h"
|
#include "glfw_context.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
Window::Window(const std::string_view &_title, Context *_context, vk::Extent2D _extent, b8 _full_screen) :
|
void
|
||||||
parent_context{ std::move(_context) }, extent{ _extent }, name{ _title }, full_screen{ _full_screen } {
|
Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
|
||||||
monitor = glfwGetPrimaryMonitor();
|
{
|
||||||
ERROR_IF(monitor == nullptr, "No monitor found");
|
SetWindowSize(extent.width, extent.height);
|
||||||
|
}
|
||||||
|
|
||||||
i32 x_, y_, w_, h_;
|
void
|
||||||
glfwGetMonitorWorkarea(monitor, &x_, &y_, &w_, &h_);
|
Window::SetWindowSize(const u32 width, const u32 height) const noexcept
|
||||||
|
{
|
||||||
|
glfwSetWindowSize(m_Window, cast<i32>(width), cast<i32>(height));
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen)
|
||||||
|
{
|
||||||
|
m_Context = context;
|
||||||
|
m_Name = title;
|
||||||
|
|
||||||
|
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||||
|
ERROR_IF(!monitor, "No monitor found");
|
||||||
|
|
||||||
|
i32 windowX, windowY, windowWidth, windowHeight;
|
||||||
|
glfwGetMonitorWorkarea(monitor, &windowX, &windowY, &windowWidth, &windowHeight);
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
|
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
|
||||||
|
|
||||||
window = glfwCreateWindow(extent.width, extent.height, name.data(), full_screen ? monitor : nullptr, nullptr);
|
m_Window = glfwCreateWindow(cast<i32>(extent.width), cast<i32>(extent.height), m_Name.c_str(),
|
||||||
ERROR_IF(window == nullptr, "Window creation failed")
|
isFullScreen ? monitor : nullptr, nullptr);
|
||||||
ELSE_INFO("Window '{}' created with resolution '{}x{}'", name, extent.width, extent.height);
|
ERROR_IF(m_Window == nullptr, "Window creation failed")
|
||||||
if (window == nullptr) {
|
ELSE_DEBUG("Window '{}' created with resolution '{}x{}'", m_Name.c_str(), extent.width, extent.height);
|
||||||
auto code = GlfwContext::post_error();
|
if (m_Window == nullptr)
|
||||||
|
{
|
||||||
|
auto code = GlfwContext::PostError();
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
CRASH(code);
|
ABORT(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_screen == false) {
|
if (isFullScreen == false)
|
||||||
glfwSetWindowPos(window, (w_ - extent.width) / 2, (h_ - extent.height) / 2);
|
{
|
||||||
|
glfwSetWindowPos(m_Window, cast<i32>(windowWidth - extent.width) / 2,
|
||||||
|
cast<i32>(windowHeight - extent.height) / 2);
|
||||||
}
|
}
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
|
||||||
VkSurfaceKHR surface_;
|
VkSurfaceKHR surface;
|
||||||
auto result = cast<vk::Result>(glfwCreateWindowSurface(cast<VkInstance>(_context->instance), window, nullptr, &surface_));
|
auto result =
|
||||||
|
cast<vk::Result>(glfwCreateWindowSurface(cast<VkInstance>(m_Context->m_Instance), m_Window, nullptr, &surface));
|
||||||
ERROR_IF(failed(result), "Failed to create Surface with {}", to_string(result))
|
ERROR_IF(failed(result), "Failed to create Surface with {}", to_string(result))
|
||||||
THEN_CRASH(result) ELSE_INFO("Surface Created");
|
THEN_ABORT(result)
|
||||||
surface = vk::SurfaceKHR(surface_);
|
ELSE_DEBUG("Surface {} Created", m_Name.c_str());
|
||||||
|
m_Surface = vk::SurfaceKHR(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(Window &&_other) noexcept :
|
Window::~Window()
|
||||||
parent_context{ std::move(_other.parent_context) }, window{ std::exchange(_other.window, nullptr) }, monitor{ _other.monitor }, surface{ std::exchange(_other.surface, nullptr) }, extent{ _other.extent }, name{ std::move(_other.name) }, full_screen{ _other.full_screen } {}
|
{
|
||||||
|
if (m_Context && m_Surface)
|
||||||
Window &Window::operator=(Window &&_other) noexcept {
|
{
|
||||||
if (this == &_other)
|
m_Context->m_Instance.destroy(m_Surface, nullptr);
|
||||||
return *this;
|
DEBUG("Surface Destroyed");
|
||||||
parent_context = std::move(_other.parent_context);
|
|
||||||
window = _other.window;
|
|
||||||
monitor = _other.monitor;
|
|
||||||
surface = std::exchange(_other.surface, nullptr);
|
|
||||||
extent = _other.extent;
|
|
||||||
name = std::move(_other.name);
|
|
||||||
full_screen = _other.full_screen;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
if (m_Window != nullptr)
|
||||||
if (parent_context && surface) {
|
{
|
||||||
parent_context->instance.destroy(surface);
|
glfwDestroyWindow(m_Window);
|
||||||
INFO("Surface Destroyed");
|
m_Window = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window != nullptr) {
|
DEBUG("Window '{}' Destroyed", m_Name.c_str());
|
||||||
glfwDestroyWindow(window);
|
|
||||||
window = nullptr;
|
|
||||||
}
|
|
||||||
monitor = nullptr;
|
|
||||||
|
|
||||||
INFO("Window '{}' Destroyed", name);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,45 +5,31 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include <EASTL/fixed_string.h>
|
||||||
|
|
||||||
struct Window final {
|
struct Window final
|
||||||
Window(const std::string_view &_title, Context *_context, vk::Extent2D _extent, b8 _full_screen = false);
|
{
|
||||||
|
|
||||||
Window(const Window &_other) = delete;
|
|
||||||
Window(Window &&_other) noexcept;
|
|
||||||
Window &operator=(const Window &_other) = delete;
|
|
||||||
Window &operator=(Window &&_other) noexcept;
|
|
||||||
|
|
||||||
~Window();
|
|
||||||
|
|
||||||
[[nodiscard]] bool should_close() const noexcept {
|
|
||||||
return glfwWindowShouldClose(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool poll() const noexcept {
|
|
||||||
glfwPollEvents();
|
|
||||||
return !glfwWindowShouldClose(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_window_size(const vk::Extent2D &_extent) noexcept {
|
|
||||||
extent = _extent;
|
|
||||||
glfwSetWindowSize(window, extent.width, extent.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_window_size(const u32 _width, const u32 _height) noexcept {
|
|
||||||
set_window_size({ _width, _height });
|
|
||||||
}
|
|
||||||
|
|
||||||
// fields
|
// fields
|
||||||
Context *parent_context{};
|
Context *m_Context{};
|
||||||
|
|
||||||
GLFWwindow *window{ nullptr };
|
GLFWwindow *m_Window = nullptr;
|
||||||
GLFWmonitor *monitor{ nullptr };
|
vk::SurfaceKHR m_Surface;
|
||||||
vk::SurfaceKHR surface;
|
eastl::fixed_string<char, 32> m_Name;
|
||||||
vk::Extent2D extent;
|
|
||||||
std::string name;
|
// Methods
|
||||||
b8 full_screen{ false };
|
[[nodiscard]] bool
|
||||||
|
Poll() const noexcept
|
||||||
|
{
|
||||||
|
glfwPollEvents();
|
||||||
|
return !glfwWindowShouldClose(m_Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWindowSize(const vk::Extent2D &extent) const noexcept;
|
||||||
|
void SetWindowSize(u32 width, u32 height) const noexcept;
|
||||||
|
|
||||||
|
// Ctor/Dtor
|
||||||
|
Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen = false);
|
||||||
|
~Window();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,59 +4,82 @@
|
||||||
#include "aster/physical_device.h"
|
#include "aster/physical_device.h"
|
||||||
#include "aster/window.h"
|
#include "aster/window.h"
|
||||||
|
|
||||||
constexpr QueueSupportFlags required_queue_support = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer;
|
#include "aster/global.h"
|
||||||
|
|
||||||
[[nodiscard]] bool is_suitable_device(const PhysicalDevice *_physical_device) {
|
constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics |
|
||||||
const bool all_required_queues = std::ranges::any_of(_physical_device->queue_families, [](const auto &_qfp) {
|
QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent |
|
||||||
return (_qfp.support & required_queue_support) == required_queue_support;
|
QueueSupportFlagBits::eTransfer;
|
||||||
|
|
||||||
|
[[nodiscard]] 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 device_type_check = _physical_device->properties.deviceType != vk::PhysicalDeviceType::eCpu;
|
const bool isNotCpu = physicalDevice->m_DeviceProperties.deviceType != vk::PhysicalDeviceType::eCpu;
|
||||||
|
|
||||||
const bool supported_present_mode = !_physical_device->present_modes.empty();
|
const bool hasPresentMode = !physicalDevice->m_PresentModes.empty();
|
||||||
|
|
||||||
const bool supported_format = !_physical_device->surface_formats.empty();
|
const bool hasSurfaceFormat = !physicalDevice->m_SurfaceFormats.empty();
|
||||||
|
|
||||||
return supported_format && supported_present_mode && device_type_check && all_required_queues;
|
return hasSurfaceFormat && hasPresentMode && isNotCpu && hasAllRequiredQueues;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDevice find_suitable_device(const PhysicalDevices &_physical_devices) {
|
PhysicalDevice
|
||||||
for (auto &_physical_device : _physical_devices) {
|
findSuitableDevice(const PhysicalDevices &physicalDevices)
|
||||||
if (is_suitable_device(&_physical_device)) {
|
{
|
||||||
return _physical_device;
|
for (auto &physicalDevice : physicalDevices)
|
||||||
|
{
|
||||||
|
if (isSuitableDevice(&physicalDevice))
|
||||||
|
{
|
||||||
|
return physicalDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw std::runtime_error("No suitable device found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueAllocation find_appropriate_queue_allocation(const PhysicalDevice* _physical_device) {
|
ERROR("No suitable GPU available on the system.")
|
||||||
for (auto &_queue_info: _physical_device->queue_families) {
|
THEN_ABORT(vk::Result::eErrorUnknown);
|
||||||
if ((_queue_info.support & required_queue_support) == required_queue_support) {
|
}
|
||||||
|
|
||||||
|
QueueAllocation
|
||||||
|
findAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
|
||||||
|
{
|
||||||
|
for (auto &queueFamilyInfo : physicalDevice->m_QueueFamilies)
|
||||||
|
{
|
||||||
|
if ((queueFamilyInfo.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT)
|
||||||
|
{
|
||||||
return {
|
return {
|
||||||
.family = _queue_info.index,
|
.m_Family = queueFamilyInfo.m_Index,
|
||||||
.count = _queue_info.count,
|
.m_Count = queueFamilyInfo.m_Count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw std::runtime_error("No suitable queue family.");
|
ERROR("No suitable queue family on the GPU.")
|
||||||
|
THEN_ABORT(vk::Result::eErrorUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int, char **) {
|
int
|
||||||
GlfwContext glfw_context = {};
|
main(int, char **)
|
||||||
|
{
|
||||||
|
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
||||||
|
|
||||||
|
GlfwContext glfwContext = {};
|
||||||
Context context = {"Aster", VERSION};
|
Context context = {"Aster", VERSION};
|
||||||
Window window = {"Aster1", &context, {640, 480}};
|
Window window = {"Aster1", &context, {640, 480}};
|
||||||
|
|
||||||
PhysicalDevices physical_devices = { &window, &context };
|
PhysicalDevices physicalDevices = {&window, &context};
|
||||||
PhysicalDevice device_to_use = find_suitable_device(physical_devices);
|
PhysicalDevice deviceToUse = findSuitableDevice(physicalDevices);
|
||||||
|
|
||||||
INFO("Using {} as the primary device.", device_to_use.properties.deviceName.data());
|
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
||||||
|
|
||||||
vk::PhysicalDeviceFeatures features = {};
|
vk::PhysicalDeviceFeatures features = {};
|
||||||
QueueAllocation queue_allocation = find_appropriate_queue_allocation(&device_to_use);
|
QueueAllocation queueAllocation = findAppropriateQueueAllocation(&deviceToUse);
|
||||||
|
|
||||||
Device device = { &context, std::move(device_to_use), &features, {queue_allocation}, "Primary Device" };
|
Device device = {&context, &deviceToUse, &features, {queueAllocation}, "Primary Device"};
|
||||||
|
|
||||||
while (window.poll()) {
|
while (window.Poll())
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
{
|
{
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
"fmt",
|
||||||
"glfw3",
|
"glfw3",
|
||||||
"glm",
|
"glm",
|
||||||
"scottt-debugbreak",
|
"scottt-debugbreak",
|
||||||
"vulkan-memory-allocator",
|
"vulkan-memory-allocator",
|
||||||
"fmt"
|
"eastl"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue