Refactored for new coding scheme. No exceptions.
This commit is contained in:
parent
7bf87f5127
commit
f603bd5752
214
.clang-format
214
.clang-format
|
|
@ -3,197 +3,25 @@
|
|||
# chosen value in case the base style changes (last sync: Clang 14.0).
|
||||
---
|
||||
### General config, applies to all languages ###
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
# AlignArrayOfStructures: None
|
||||
# AlignConsecutiveMacros: None
|
||||
# AlignConsecutiveAssignments: None
|
||||
# AlignConsecutiveBitFields: None
|
||||
# AlignConsecutiveDeclarations: None
|
||||
# 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
|
||||
BasedOnStyle: Microsoft
|
||||
#AccessModifierOffset: -2
|
||||
AlwaysBreakAfterReturnType: AllDefinitions
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
#ColumnLimit: 0
|
||||
#ConstructorInitializerIndentWidth: 4
|
||||
#ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
# IndentCaseBlocks: false
|
||||
# IndentGotoLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentRequires: false
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# InsertTrailingCommas: None
|
||||
# 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
|
||||
# UseCRLF: false
|
||||
UseTab: Always
|
||||
# WhitespaceSensitiveMacros:
|
||||
# - STRINGIZE
|
||||
# - PP_STRINGIZE
|
||||
# - BOOST_PP_STRINGIZE
|
||||
# - NS_SWIFT_NAME
|
||||
# - CF_SWIFT_NAME
|
||||
---
|
||||
### C++ specific config ###
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
---
|
||||
### 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']
|
||||
...
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
#IndentCaseLabels: true
|
||||
IndentWidth: 4
|
||||
#KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
PenaltyReturnTypeOnItsOwnLine: 0
|
||||
TabWidth: 4
|
||||
Language: Cpp
|
||||
Standard: c++20
|
||||
76
.clang-tidy
76
.clang-tidy
|
|
@ -4,42 +4,42 @@ WarningsAsErrors: ''
|
|||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
CheckOptions:
|
||||
- key: cert-dcl16-c.NewSuffixes
|
||||
value: 'L;LL;LU;LLU'
|
||||
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||
value: '10'
|
||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||
value: '2'
|
||||
- key: modernize-loop-convert.MaxCopySize
|
||||
value: '16'
|
||||
- key: modernize-loop-convert.MinConfidence
|
||||
value: reasonable
|
||||
- key: modernize-loop-convert.NamingStyle
|
||||
value: CamelCase
|
||||
- key: modernize-pass-by-value.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-use-bool-literals.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '0'
|
||||
- key: cert-dcl16-c.NewSuffixes
|
||||
value: 'L;LL;LU;LLU'
|
||||
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||
value: '10'
|
||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||
value: '2'
|
||||
- key: modernize-loop-convert.MaxCopySize
|
||||
value: '16'
|
||||
- key: modernize-loop-convert.MinConfidence
|
||||
value: reasonable
|
||||
- key: modernize-loop-convert.NamingStyle
|
||||
value: CamelCase
|
||||
- key: modernize-pass-by-value.IncludeStyle
|
||||
value: microsoft
|
||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||
value: microsoft
|
||||
- key: modernize-use-bool-literals.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '0'
|
||||
...
|
||||
|
|
@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD 20)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_CXX_FLAGS -Wall)
|
||||
set(CMAKE_CXX_FLAGS "-Wall -fno-rtti -fno-exceptions")
|
||||
|
||||
add_subdirectory("aster")
|
||||
add_subdirectory("triangle")
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ find_package(glm CONFIG REQUIRED)
|
|||
find_package(glfw3 CONFIG REQUIRED)
|
||||
find_path(SCOTTT_DEBUGBREAK_INCLUDE_DIRS "debugbreak.h")
|
||||
find_package(Vulkan REQUIRED)
|
||||
# find_package( VulkanHeaders CONFIG REQUIRED )
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||
find_package(EASTL CONFIG REQUIRED)
|
||||
|
||||
set(HEADER_FILES
|
||||
constants.h
|
||||
|
|
@ -37,5 +37,6 @@ target_link_libraries(aster_core PUBLIC glm::glm-header-only)
|
|||
target_link_libraries(aster_core PRIVATE glfw)
|
||||
target_include_directories(aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS})
|
||||
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 VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
|
||||
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
|
||||
#define EASTL_NO_EXCEPTIONS 1
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
#define _HAS_EXCEPTIONS 0
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define USE_OPTICK (0)
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
|
@ -28,54 +28,70 @@ using b8 = bool;
|
|||
using b32 = u32;
|
||||
using usize = size_t;
|
||||
using p64 = intptr_t;
|
||||
using cstr = const char *;
|
||||
|
||||
constexpr usize strlen_c(const char *s) {
|
||||
usize len = 0;
|
||||
char c = '\0';
|
||||
do {
|
||||
c = s[len];
|
||||
len++;
|
||||
} while (c != '\0');
|
||||
return len;
|
||||
constexpr usize
|
||||
strlenC(const char *s)
|
||||
{
|
||||
usize len = 0;
|
||||
char c = '\0';
|
||||
do
|
||||
{
|
||||
c = s[len];
|
||||
len++;
|
||||
} while (c != '\0');
|
||||
return len;
|
||||
}
|
||||
|
||||
constexpr auto ANSI_Black = "\u001b[30m";
|
||||
constexpr auto ANSI_Red = "\u001b[31m";
|
||||
constexpr auto ANSI_Green = "\u001b[32m";
|
||||
constexpr auto ANSI_Yellow = "\u001b[33m";
|
||||
constexpr auto ANSI_Blue = "\u001b[34m";
|
||||
constexpr auto ANSI_Magenta = "\u001b[35m";
|
||||
constexpr auto ANSI_Cyan = "\u001b[36m";
|
||||
constexpr auto ANSI_White = "\u001b[37m";
|
||||
constexpr auto ANSI_Reset = "\u001b[0m";
|
||||
namespace ansi_color
|
||||
{
|
||||
constexpr auto Black = "\u001b[30m";
|
||||
constexpr auto Red = "\u001b[31m";
|
||||
constexpr auto Green = "\u001b[32m";
|
||||
constexpr auto Yellow = "\u001b[33m";
|
||||
constexpr auto Blue = "\u001b[34m";
|
||||
constexpr auto Magenta = "\u001b[35m";
|
||||
constexpr auto Cyan = "\u001b[36m";
|
||||
constexpr auto White = "\u001b[37m";
|
||||
constexpr auto Reset = "\u001b[0m";
|
||||
} // namespace ansi_color
|
||||
|
||||
template <typename T>
|
||||
using Option = std::optional<T>;
|
||||
|
||||
template <typename type_t, typename from_t>
|
||||
constexpr auto cast(from_t &&_in) {
|
||||
return static_cast<type_t>(std::forward<from_t>(_in));
|
||||
template <typename TypeT, typename FromT>
|
||||
constexpr auto
|
||||
cast(FromT &&in)
|
||||
{
|
||||
return static_cast<TypeT>(std::forward<FromT>(in));
|
||||
}
|
||||
|
||||
template <typename type_t, typename from_t>
|
||||
constexpr auto recast(from_t &&_in) {
|
||||
return reinterpret_cast<type_t>(std::forward<from_t>(_in));
|
||||
template <typename TypeT, typename FromT>
|
||||
constexpr auto
|
||||
recast(FromT &&in)
|
||||
{
|
||||
return reinterpret_cast<TypeT>(std::forward<FromT>(in));
|
||||
}
|
||||
|
||||
constexpr f32 operator""_deg(long double degrees) {
|
||||
return glm::radians<f32>(cast<f32>(degrees));
|
||||
constexpr f32
|
||||
operator""_deg(long double degrees)
|
||||
{
|
||||
return glm::radians<f32>(cast<f32>(degrees));
|
||||
}
|
||||
|
||||
constexpr f32 operator""_deg(unsigned long long int degrees) {
|
||||
return glm::radians<f32>(cast<f32>(degrees));
|
||||
constexpr f32
|
||||
operator""_deg(unsigned long long int degrees)
|
||||
{
|
||||
return glm::radians<f32>(cast<f32>(degrees));
|
||||
}
|
||||
|
||||
constexpr f32 operator""_rad(long double rads) {
|
||||
return cast<f32>(rads);
|
||||
constexpr f32
|
||||
operator""_rad(long double rads)
|
||||
{
|
||||
return cast<f32>(rads);
|
||||
}
|
||||
|
||||
constexpr f32 operator""_rad(unsigned long long int rads) {
|
||||
return cast<f32>(rads);
|
||||
constexpr f32
|
||||
operator""_rad(unsigned long long int rads)
|
||||
{
|
||||
return cast<f32>(rads);
|
||||
}
|
||||
|
||||
using glm::ivec2;
|
||||
|
|
@ -91,38 +107,45 @@ using glm::mat4;
|
|||
|
||||
constexpr auto *PROJECT_NAME = "Aster";
|
||||
|
||||
struct Version {
|
||||
u32 major;
|
||||
u32 minor;
|
||||
u32 patch;
|
||||
struct Version
|
||||
{
|
||||
u8 m_Major;
|
||||
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 = {
|
||||
.major = 0,
|
||||
.minor = 1,
|
||||
.patch = 0,
|
||||
.m_Major = 0,
|
||||
.m_Minor = 1,
|
||||
.m_Patch = 0,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr T max_value = std::numeric_limits<T>::max();
|
||||
constexpr T MaxValue = std::numeric_limits<T>::max();
|
||||
|
||||
template <typename T>
|
||||
constexpr T min_value = std::numeric_limits<T>::min();
|
||||
constexpr T MinValue = std::numeric_limits<T>::min();
|
||||
|
||||
template <typename T>
|
||||
constexpr T lowest_value = std::numeric_limits<T>::lowest();
|
||||
constexpr T LowestValue = std::numeric_limits<T>::lowest();
|
||||
|
||||
template <typename T>
|
||||
constexpr T err_epsilon = std::numeric_limits<T>::epsilon();
|
||||
constexpr T ErrEpsilon = std::numeric_limits<T>::epsilon();
|
||||
|
||||
template <typename T>
|
||||
constexpr T positive_inf = std::numeric_limits<T>::infinity();
|
||||
constexpr T PositiveInf = std::numeric_limits<T>::infinity();
|
||||
|
||||
template <typename T>
|
||||
constexpr T negative_inf = -std::numeric_limits<T>::infinity();
|
||||
constexpr T NegativeInf = -std::numeric_limits<T>::infinity();
|
||||
|
||||
template <typename T>
|
||||
constexpr T qnan = std::numeric_limits<T>::quiet_NaN();
|
||||
constexpr T Qnan = std::numeric_limits<T>::quiet_NaN();
|
||||
|
||||
template <typename T>
|
||||
constexpr T snan = std::numeric_limits<T>::signalling_NaN();
|
||||
constexpr T Snan = std::numeric_limits<T>::signalling_NaN();
|
||||
|
|
|
|||
|
|
@ -4,97 +4,108 @@
|
|||
// =============================================
|
||||
|
||||
#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) {
|
||||
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
|
||||
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
||||
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
|
||||
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
||||
constexpr eastl::array VALIDATION_LAYERS = {
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
};
|
||||
|
||||
const auto severity = Severity(_message_severity);
|
||||
const auto message_type = MessageType(_message_type);
|
||||
VKAPI_ATTR b32 VKAPI_CALL
|
||||
debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
|
||||
{
|
||||
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
|
||||
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
||||
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
|
||||
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
||||
|
||||
if (message_type & MessageTypeBits::eValidation) {
|
||||
if (severity & SeverityBits::eError)
|
||||
ERROR("{}", _callback_data->pMessage);
|
||||
if (severity & SeverityBits::eWarning)
|
||||
WARN("{}", _callback_data->pMessage);
|
||||
if (severity & SeverityBits::eInfo)
|
||||
INFO("{}", _callback_data->pMessage);
|
||||
if (severity & SeverityBits::eVerbose)
|
||||
VERBOSE("{}", _callback_data->pMessage);
|
||||
}
|
||||
const auto severity = Severity(messageSeverity);
|
||||
|
||||
return false;
|
||||
if (MessageType(messageType) & MessageTypeBits::eValidation)
|
||||
{
|
||||
if (severity & SeverityBits::eError)
|
||||
ERROR("{}", callbackData->pMessage);
|
||||
if (severity & SeverityBits::eWarning)
|
||||
WARN("{}", callbackData->pMessage);
|
||||
if (severity & SeverityBits::eInfo)
|
||||
INFO("{}", callbackData->pMessage);
|
||||
if (severity & SeverityBits::eVerbose)
|
||||
VERBOSE("{}", callbackData->pMessage);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Context::init(const std::string_view &_app_name, const Version &_app_version) {
|
||||
INFO_IF(enable_validation_layers, "Validation Layers enabled");
|
||||
Context::Context(cstr appName, Version version, bool enableValidation)
|
||||
{
|
||||
INFO_IF(enableValidation, "Validation Layers enabled");
|
||||
|
||||
// Creating Instance
|
||||
const vk::ApplicationInfo app_info = {
|
||||
.pApplicationName = _app_name.data(),
|
||||
.applicationVersion = VK_MAKE_VERSION(_app_version.major, _app_version.minor, _app_version.patch),
|
||||
.pEngineName = PROJECT_NAME,
|
||||
.engineVersion = VK_MAKE_VERSION(VERSION.major, VERSION.minor, VERSION.patch),
|
||||
.apiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
// Creating Instance
|
||||
const vk::ApplicationInfo appInfo = {
|
||||
.pApplicationName = appName,
|
||||
.applicationVersion = version.GetVkVersion(),
|
||||
.pEngineName = PROJECT_NAME,
|
||||
.engineVersion = version.GetVkVersion(),
|
||||
.apiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
|
||||
vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_create_info = {
|
||||
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo,
|
||||
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation,
|
||||
.pfnUserCallback = debug_callback,
|
||||
.pUserData = nullptr,
|
||||
};
|
||||
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfo = {
|
||||
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo,
|
||||
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation,
|
||||
.pfnUserCallback = debugCallback,
|
||||
.pUserData = nullptr,
|
||||
};
|
||||
|
||||
u32 glfw_extension_count = 0;
|
||||
const char **glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count);
|
||||
std::vector vulkan_extensions(glfw_extensions, glfw_extensions + glfw_extension_count);
|
||||
if (enable_validation_layers) {
|
||||
vulkan_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
u32 glfwExtensionCount = 0;
|
||||
cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
eastl::fixed_vector<cstr, 3> instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
|
||||
if (enableValidation)
|
||||
{
|
||||
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
const vk::DynamicLoader dl;
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
const vk::DynamicLoader dl;
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
|
||||
const auto instance_create_info = vk::InstanceCreateInfo{
|
||||
.pNext = enable_validation_layers ? &debug_messenger_create_info : nullptr,
|
||||
.pApplicationInfo = &app_info,
|
||||
.enabledLayerCount = enable_validation_layers ? cast<u32>(validation_layers.size()) : 0,
|
||||
.ppEnabledLayerNames = enable_validation_layers ? validation_layers.data() : nullptr,
|
||||
.enabledExtensionCount = cast<u32>(vulkan_extensions.size()),
|
||||
.ppEnabledExtensionNames = vulkan_extensions.data(),
|
||||
};
|
||||
const auto instanceCreateInfo = vk::InstanceCreateInfo{
|
||||
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
|
||||
.pApplicationInfo = &appInfo,
|
||||
.enabledLayerCount = enableValidation ? cast<u32>(VALIDATION_LAYERS.size()) : 0,
|
||||
.ppEnabledLayerNames = enableValidation ? VALIDATION_LAYERS.data() : nullptr,
|
||||
.enabledExtensionCount = cast<u32>(instanceExtensions.size()),
|
||||
.ppEnabledExtensionNames = instanceExtensions.data(),
|
||||
};
|
||||
|
||||
// May throw. Irrecoverable.
|
||||
instance = vk::createInstance(instance_create_info);
|
||||
INFO("Instance Created.");
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
|
||||
// May throw. Irrecoverable.
|
||||
vk::Result result = vk::createInstance(&instanceCreateInfo, nullptr, &m_Instance);
|
||||
ERROR_IF(result, "Instance creation failed. Cause: {}", to_string(result))
|
||||
THEN_ABORT(result)
|
||||
ELSE_DEBUG("Instance Created.");
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_Instance);
|
||||
|
||||
// Debug Messenger
|
||||
if (enable_validation_layers) {
|
||||
try {
|
||||
debug_messenger = instance.createDebugUtilsMessengerEXT(debug_messenger_create_info);
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Debug Messenger creation failed. Cause: {}", _err.what());
|
||||
// Non-critical. Continue.
|
||||
}
|
||||
INFO("Debug Messenger Created.");
|
||||
}
|
||||
// Debug Messenger
|
||||
if (enableValidation)
|
||||
{
|
||||
result = m_Instance.createDebugUtilsMessengerEXT(&debugUtilsMessengerCreateInfo, nullptr, &m_DebugMessenger);
|
||||
ERROR_IF(result, "Debug Messenger creation failed. Cause: {}", to_string(result)) // Non-critical. Continue.
|
||||
ELSE_DEBUG("Debug Messenger Created.");
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context() {
|
||||
if (instance) {
|
||||
if (enable_validation_layers && debug_messenger) {
|
||||
instance.destroyDebugUtilsMessengerEXT(debug_messenger);
|
||||
}
|
||||
instance.destroy();
|
||||
INFO("Context destroyed");
|
||||
}
|
||||
Context::~Context()
|
||||
{
|
||||
if (m_DebugMessenger)
|
||||
{
|
||||
m_Instance.destroy(m_DebugMessenger, nullptr);
|
||||
DEBUG("Debug Messenger destroyed");
|
||||
}
|
||||
m_Instance.destroy(nullptr);
|
||||
DEBUG("Instance destroyed");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "global.h"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @class Context
|
||||
|
|
@ -16,71 +14,13 @@
|
|||
*
|
||||
* Handles the required hardware interactions.
|
||||
*/
|
||||
class Context final {
|
||||
public:
|
||||
Context(const std::string_view &_app_name, const Version &_app_version, const b8 _enable_validation = true) :
|
||||
enable_validation_layers{ _enable_validation } {
|
||||
init(_app_name, _app_version);
|
||||
}
|
||||
struct Context final
|
||||
{
|
||||
// Members
|
||||
vk::Instance m_Instance = nullptr;
|
||||
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;
|
||||
}
|
||||
|
||||
~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);
|
||||
// Ctor/Dtor
|
||||
Context(cstr appName, Version version, bool enableValidation = true);
|
||||
~Context();
|
||||
};
|
||||
|
|
|
|||
128
aster/device.cpp
128
aster/device.cpp
|
|
@ -5,76 +5,80 @@
|
|||
|
||||
#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) :
|
||||
physical_device{ std::move(_physical_device) },
|
||||
name{ std::move(_name) } {
|
||||
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
|
||||
queue_create_infos.reserve(_queue_allocation.size());
|
||||
#include <EASTL/array.h>
|
||||
|
||||
u32 num_priorities = 0;
|
||||
for (auto [_, count] : _queue_allocation) {
|
||||
num_priorities = std::max(count, num_priorities);
|
||||
}
|
||||
std::vector priorities(num_priorities, 1.0f);
|
||||
constexpr eastl::array DEVICE_EXTENSIONS = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
|
||||
for (auto [family, count] : _queue_allocation) {
|
||||
queue_create_infos.push_back({
|
||||
.queueFamilyIndex = family,
|
||||
.queueCount = count,
|
||||
.pQueuePriorities = priorities.data(),
|
||||
});
|
||||
}
|
||||
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());
|
||||
|
||||
try {
|
||||
device = physical_device.device.createDevice({
|
||||
.queueCreateInfoCount = cast<u32>(queue_create_infos.size()),
|
||||
.pQueueCreateInfos = queue_create_infos.data(),
|
||||
.enabledLayerCount = _context->enable_validation_layers ? cast<u32>(_context->validation_layers.size()) : 0,
|
||||
.ppEnabledLayerNames = _context->enable_validation_layers ? _context->validation_layers.data() : nullptr,
|
||||
.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;
|
||||
}
|
||||
u32 numPriorities = 0;
|
||||
for (auto [_, count] : queueAllocations)
|
||||
{
|
||||
numPriorities = std::max(count, numPriorities);
|
||||
}
|
||||
// Shouldn't have more than 4 queues either.
|
||||
eastl::fixed_vector<f32, 4> priorities(numPriorities, 1.0f);
|
||||
|
||||
INFO("{} ({}) Initialized!", name.value_or(DEFAULT_DEVICE_NAME), physical_device.properties.deviceName.data());
|
||||
for (auto [family, count] : queueAllocations)
|
||||
{
|
||||
deviceQueueCreateInfos.push_back({
|
||||
.queueFamilyIndex = family,
|
||||
.queueCount = count,
|
||||
.pQueuePriorities = priorities.data(),
|
||||
});
|
||||
}
|
||||
|
||||
VmaVulkanFunctions vma_vulkan_functions = {
|
||||
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
||||
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
||||
};
|
||||
vk::DeviceCreateInfo deviceCreateInfo = {
|
||||
.queueCreateInfoCount = cast<u32>(deviceQueueCreateInfos.size()),
|
||||
.pQueueCreateInfos = deviceQueueCreateInfos.data(),
|
||||
.enabledExtensionCount = cast<u32>(DEVICE_EXTENSIONS.size()),
|
||||
.ppEnabledExtensionNames = DEVICE_EXTENSIONS.data(),
|
||||
.pEnabledFeatures = enabledFeatures,
|
||||
};
|
||||
|
||||
const VmaAllocatorCreateInfo vma_allocator_create_info = {
|
||||
.flags = 0,
|
||||
.physicalDevice = physical_device.device,
|
||||
.device = device,
|
||||
.pVulkanFunctions = &vma_vulkan_functions,
|
||||
.instance = _context->instance,
|
||||
.vulkanApiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
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());
|
||||
|
||||
const auto result = cast<vk::Result>(vmaCreateAllocator(&vma_allocator_create_info, &allocator));
|
||||
if (failed(result)) {
|
||||
device.destroy();
|
||||
auto _err = fmt::format("Memory allocator creation failed. Cause: {}", to_string(result));
|
||||
ERROR("{}", _err);
|
||||
throw std::runtime_error(_err);
|
||||
}
|
||||
VERBOSE("Memory Allocator Created");
|
||||
VmaVulkanFunctions vmaVulkanFunctions = {
|
||||
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
||||
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
||||
};
|
||||
|
||||
INFO("Created '{}' Successfully", name.value_or(DEFAULT_DEVICE_NAME));
|
||||
const VmaAllocatorCreateInfo allocatorCreateInfo = {
|
||||
.flags = 0,
|
||||
.physicalDevice = physicalDevice->m_PhysicalDevice,
|
||||
.device = m_Device,
|
||||
.pVulkanFunctions = &vmaVulkanFunctions,
|
||||
.instance = context->m_Instance,
|
||||
.vulkanApiVersion = ASTER_API_VERSION,
|
||||
};
|
||||
|
||||
result = cast<vk::Result>(vmaCreateAllocator(&allocatorCreateInfo, &m_Allocator));
|
||||
ERROR_IF(failed(result), "Memory allocator creation failed. Cause: {}", to_string(result))
|
||||
DO(m_Device.destroy(nullptr))
|
||||
THEN_ABORT(result)
|
||||
ELSE_VERBOSE("Memory Allocator Created");
|
||||
|
||||
DEBUG("Created '{}' Successfully", m_Name);
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
if (allocator) {
|
||||
vmaDestroyAllocator(allocator);
|
||||
allocator = nullptr;
|
||||
VERBOSE("Memory Allocator Destroyed");
|
||||
}
|
||||
device.destroy();
|
||||
INFO("Device '{}' Destroyed", name.value_or(DEFAULT_DEVICE_NAME));
|
||||
name = std::nullopt;
|
||||
Device::~Device()
|
||||
{
|
||||
if (m_Allocator)
|
||||
{
|
||||
vmaDestroyAllocator(m_Allocator);
|
||||
m_Allocator = nullptr;
|
||||
DEBUG("Memory Allocator Destroyed");
|
||||
}
|
||||
m_Device.destroy(nullptr);
|
||||
DEBUG("Device '{}' Destroyed", m_Name);
|
||||
}
|
||||
|
|
@ -8,20 +8,22 @@
|
|||
#include "global.h"
|
||||
#include "physical_device.h"
|
||||
|
||||
constexpr std::string DEFAULT_DEVICE_NAME = "<Unnamed GPU>";
|
||||
|
||||
struct QueueAllocation {
|
||||
u32 family;
|
||||
u32 count;
|
||||
struct QueueAllocation
|
||||
{
|
||||
u32 m_Family;
|
||||
u32 m_Count;
|
||||
};
|
||||
|
||||
struct Device final {
|
||||
vk::Device device;
|
||||
PhysicalDevice physical_device;
|
||||
VmaAllocator allocator{ nullptr };
|
||||
std::optional<std::string> name{ nullptr };
|
||||
struct Device final
|
||||
{
|
||||
using NameString = eastl::fixed_string<char, 32, false>;
|
||||
|
||||
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();
|
||||
Device(const Context *context, PhysicalDevice *physicalDevice, const vk::PhysicalDeviceFeatures *enabledFeatures,
|
||||
const eastl::vector<QueueAllocation> &queueAllocations, NameString name);
|
||||
|
||||
~Device();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,28 +7,36 @@
|
|||
|
||||
#include "global.h"
|
||||
|
||||
struct GlfwContext {
|
||||
static i32 post_error() noexcept {
|
||||
static const char *error_ = nullptr;
|
||||
const auto code = glfwGetError(&error_);
|
||||
ERROR("GLFW {}", error_);
|
||||
return code;
|
||||
}
|
||||
struct GlfwContext
|
||||
{
|
||||
|
||||
inline static u32 count = 0;
|
||||
static i32
|
||||
PostError() noexcept
|
||||
{
|
||||
static const char *error = nullptr;
|
||||
const auto code = glfwGetError(&error);
|
||||
ERROR("GLFW {}", error);
|
||||
return code;
|
||||
}
|
||||
|
||||
GlfwContext() {
|
||||
if (count++ > 0)
|
||||
return;
|
||||
if (glfwInit() == GLFW_FALSE) {
|
||||
CRASH(post_error());
|
||||
}
|
||||
}
|
||||
inline static u32 m_Count = 0;
|
||||
|
||||
~GlfwContext() {
|
||||
if (--count == 0) {
|
||||
glfwTerminate();
|
||||
}
|
||||
count = 0;
|
||||
}
|
||||
GlfwContext()
|
||||
{
|
||||
if (m_Count++ > 0)
|
||||
return;
|
||||
if (glfwInit() == GLFW_FALSE)
|
||||
{
|
||||
ABORT(PostError());
|
||||
}
|
||||
}
|
||||
|
||||
~GlfwContext()
|
||||
{
|
||||
if (--m_Count == 0)
|
||||
{
|
||||
glfwTerminate();
|
||||
}
|
||||
m_Count = 0;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,3 +13,16 @@
|
|||
|
||||
// NOTE: Vulkan Dispatch Loader Storage - Should only appear once.
|
||||
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];
|
||||
}
|
||||
142
aster/global.h
142
aster/global.h
|
|
@ -11,31 +11,53 @@
|
|||
|
||||
#include <GLFW/glfw3.h>
|
||||
#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")
|
||||
#include <EASTL/fixed_string.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
constexpr u32 ASTER_API_VERSION = vk::ApiVersion13;
|
||||
|
||||
#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>
|
||||
concept IsVkEnum = requires(T _t) {
|
||||
{ std::is_enum_v<T> };
|
||||
{ vk::to_string(_t) } -> std::same_as<std::string>;
|
||||
concept IsVkEnum = requires(T t) {
|
||||
{
|
||||
std::is_enum_v<T>
|
||||
};
|
||||
{
|
||||
vk::to_string(t)
|
||||
} -> std::same_as<std::string>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires IsVkEnum<T> [[nodiscard]] const char *to_cstr(const T &_val) {
|
||||
static std::string buffer;
|
||||
buffer = vk::to_string(_val);
|
||||
return buffer.c_str();
|
||||
requires IsVkEnum<T>
|
||||
[[nodiscard]] const char *
|
||||
toCstr(const T &val)
|
||||
{
|
||||
static std::string buffer;
|
||||
buffer = vk::to_string(val);
|
||||
return buffer.c_str();
|
||||
}
|
||||
|
||||
// TODO: Check why inline namespaces aren't working in MSVC 19.27.29110
|
||||
|
|
@ -43,49 +65,87 @@ using namespace std::literals::string_literals;
|
|||
using namespace std::literals::string_view_literals;
|
||||
|
||||
template <typename T>
|
||||
requires vk::isVulkanHandleType<T>::value [[nodiscard]] constexpr u64
|
||||
get_vk_handle(const T &_vk_handle) noexcept {
|
||||
return reinterpret_cast<u64>(cast<T::CType>(_vk_handle));
|
||||
requires vk::isVulkanHandleType<T>::value
|
||||
[[nodiscard]] constexpr u64
|
||||
getVkHandle(const T &vkHandle) noexcept
|
||||
{
|
||||
return reinterpret_cast<u64>(cast<T::CType>(vkHandle));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
struct std::hash<vk::Flags<F>> {
|
||||
[[nodiscard]] usize operator()(const vk::Flags<F> &_val) {
|
||||
return std::hash<u32>()(cast<u32>(_val));
|
||||
}
|
||||
struct std::hash<vk::Flags<F>>
|
||||
{
|
||||
[[nodiscard]] usize
|
||||
operator()(const vk::Flags<F> &val)
|
||||
{
|
||||
return std::hash<u32>()(cast<u32>(val));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] usize hash_any(const T &_val) {
|
||||
return std::hash<std::remove_cvref_t<T>>()(_val);
|
||||
[[nodiscard]] usize
|
||||
hashAny(const T &val)
|
||||
{
|
||||
return std::hash<std::remove_cvref_t<T>>()(val);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline usize hash_combine(const usize _hash0,
|
||||
const usize _hash1) {
|
||||
constexpr usize salt_value = 0x9e3779b9;
|
||||
return _hash0 ^ (_hash1 + salt_value + (_hash0 << 6) + (_hash0 >> 2));
|
||||
[[nodiscard]] inline usize
|
||||
hashCombine(const usize hash0, const usize hash1)
|
||||
{
|
||||
constexpr usize saltValue = 0x9e3779b9;
|
||||
return hash0 ^ (hash1 + saltValue + (hash0 << 6) + (hash0 >> 2));
|
||||
}
|
||||
|
||||
struct Time {
|
||||
static constexpr f64 max_delta = 0.1;
|
||||
struct Time
|
||||
{
|
||||
static constexpr f64 c_MaxDelta = 0.1;
|
||||
|
||||
inline static f64 elapsed{ qnan<f64> };
|
||||
inline static f64 delta{ qnan<f64> };
|
||||
inline static f64 m_Elapsed{Qnan<f64>};
|
||||
inline static f64 m_Delta{Qnan<f64>};
|
||||
|
||||
static void init() {
|
||||
WARN_IF(!std::isnan(elapsed), "Time already init.");
|
||||
elapsed = glfwGetTime();
|
||||
delta = 1.0 / 60.0;
|
||||
}
|
||||
static void
|
||||
Init()
|
||||
{
|
||||
WARN_IF(!std::isnan(m_Elapsed), "Time already init.");
|
||||
m_Elapsed = glfwGetTime();
|
||||
m_Delta = 1.0 / 60.0;
|
||||
}
|
||||
|
||||
static void update() {
|
||||
ERROR_IF(std::isnan(elapsed), "Time not init.");
|
||||
const auto new_elapsed = glfwGetTime();
|
||||
delta = std::clamp(new_elapsed - elapsed, 0.0, max_delta);
|
||||
elapsed = new_elapsed;
|
||||
}
|
||||
static void
|
||||
Update()
|
||||
{
|
||||
ERROR_IF(std::isnan(m_Elapsed), "Time not init.");
|
||||
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) {
|
||||
return _of * ((_val + _of - 1) / _of);
|
||||
[[nodiscard]] inline usize
|
||||
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"
|
||||
|
||||
Logger g_logger = Logger();
|
||||
Logger g_Logger = Logger();
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
|
||||
/* Credits to Const-me */
|
||||
//namespace eastl {
|
||||
// void __cdecl AssertionFailure(const char* af)
|
||||
// {
|
||||
// ERROR(af);
|
||||
// __debugbreak();
|
||||
// }
|
||||
//}
|
||||
namespace eastl
|
||||
{
|
||||
void
|
||||
AssertionFailure(const char *af)
|
||||
{
|
||||
ERROR("{}", af);
|
||||
debug_break();
|
||||
}
|
||||
} // namespace eastl
|
||||
|
|
|
|||
301
aster/logger.h
301
aster/logger.h
|
|
@ -9,175 +9,200 @@
|
|||
#include <debugbreak.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <string>
|
||||
struct Logger
|
||||
{
|
||||
enum class LogType : u32
|
||||
{
|
||||
eError,
|
||||
eWarning,
|
||||
eInfo,
|
||||
eDebug,
|
||||
eVerbose,
|
||||
};
|
||||
|
||||
struct Logger {
|
||||
enum class LogType : u32 {
|
||||
eError,
|
||||
eWarning,
|
||||
eInfo,
|
||||
eDebug,
|
||||
eVerbose,
|
||||
};
|
||||
u32 m_MinimumLoggingLevel{cast<u32>(LogType::eDebug)};
|
||||
|
||||
u32 minimum_logging_level{ cast<u32>(LogType::eDebug) };
|
||||
void
|
||||
SetMinimumLoggingLevel(LogType logType)
|
||||
{
|
||||
m_MinimumLoggingLevel = cast<u32>(logType);
|
||||
}
|
||||
|
||||
void set_minimum_logging_level(LogType _log_type) {
|
||||
minimum_logging_level = cast<u32>(_log_type);
|
||||
}
|
||||
template <LogType LogLevel>
|
||||
constexpr static const char *
|
||||
ToCstr()
|
||||
{
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
return "[ERROR]:";
|
||||
if constexpr (LogLevel == LogType::eWarning)
|
||||
return "[WARN]: ";
|
||||
if constexpr (LogLevel == LogType::eInfo)
|
||||
return "[INFO]: ";
|
||||
if constexpr (LogLevel == LogType::eDebug)
|
||||
return "[DEBUG]:";
|
||||
if constexpr (LogLevel == LogType::eVerbose)
|
||||
return "[VERB]: ";
|
||||
return "";
|
||||
}
|
||||
|
||||
template <LogType LogLevel>
|
||||
constexpr static const char *to_cstr() {
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
return "[ERROR]:";
|
||||
if constexpr (LogLevel == LogType::eWarning)
|
||||
return "[WARN]: ";
|
||||
if constexpr (LogLevel == LogType::eInfo)
|
||||
return "[INFO]: ";
|
||||
if constexpr (LogLevel == LogType::eDebug)
|
||||
return "[DEBUG]:";
|
||||
if constexpr (LogLevel == LogType::eVerbose)
|
||||
return "[VERB]: ";
|
||||
return "";
|
||||
}
|
||||
template <LogType LogLevel>
|
||||
constexpr static const char *
|
||||
ToColorCstr()
|
||||
{
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
return ansi_color::Red;
|
||||
if constexpr (LogLevel == LogType::eWarning)
|
||||
return ansi_color::Yellow;
|
||||
if constexpr (LogLevel == LogType::eInfo)
|
||||
return ansi_color::Green;
|
||||
if constexpr (LogLevel == LogType::eDebug)
|
||||
return ansi_color::White;
|
||||
if constexpr (LogLevel == LogType::eVerbose)
|
||||
return ansi_color::Blue;
|
||||
return ansi_color::White;
|
||||
}
|
||||
|
||||
template <LogType LogLevel>
|
||||
constexpr static const char *to_color_cstr() {
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
return ANSI_Red;
|
||||
if constexpr (LogLevel == LogType::eWarning)
|
||||
return ANSI_Yellow;
|
||||
if constexpr (LogLevel == LogType::eInfo)
|
||||
return ANSI_Green;
|
||||
if constexpr (LogLevel == LogType::eDebug)
|
||||
return ANSI_White;
|
||||
if constexpr (LogLevel == LogType::eVerbose)
|
||||
return ANSI_Blue;
|
||||
return ANSI_White;
|
||||
}
|
||||
|
||||
template <LogType LogLevel>
|
||||
void log(const std::string_view &_message, const char *_loc, u32 _line) const {
|
||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
||||
fmt::println("{}{} {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
}
|
||||
template <LogType LogLevel>
|
||||
void
|
||||
Log(const std::string_view &message, const char *loc, u32 line) const
|
||||
{
|
||||
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 constexpr (LogLevel == LogType::eError) {
|
||||
debug_break();
|
||||
}
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
{
|
||||
debug_break();
|
||||
}
|
||||
#endif // !defined(NDEBUG)
|
||||
}
|
||||
}
|
||||
|
||||
template <LogType LogLevel>
|
||||
void log_cond(const char *_expr_str, const std::string_view &_message, const char *_loc, u32 _line) const {
|
||||
if (cast<u32>(LogLevel) <= minimum_logging_level) {
|
||||
fmt::println("{}{} ({}) {} {} at {}:{}{}", to_color_cstr<LogLevel>(), to_cstr<LogLevel>(), _expr_str, _message.data(), ANSI_Black, _loc, _line, ANSI_Reset);
|
||||
}
|
||||
template <LogType LogLevel>
|
||||
void
|
||||
LogCond(const char *exprStr, const std::string_view &message, const char *loc, u32 line) const
|
||||
{
|
||||
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 constexpr (LogLevel == LogType::eError) {
|
||||
debug_break();
|
||||
}
|
||||
if constexpr (LogLevel == LogType::eError)
|
||||
{
|
||||
debug_break();
|
||||
}
|
||||
#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 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 INFO(...) g_logger.log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#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 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 ERROR_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) [[unlikely]] \
|
||||
g_logger.log_cond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define WARN_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) [[unlikely]] \
|
||||
g_logger.log_cond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define INFO_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_logger.log_cond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ERROR_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) [[unlikely]] \
|
||||
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define WARN_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) [[unlikely]] \
|
||||
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define INFO_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
#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__)
|
||||
#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__)
|
||||
#define ELSE_IF_INFO(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_ERROR(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) \
|
||||
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_WARN(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) \
|
||||
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_INFO(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
#define ELSE_ERROR(...) \
|
||||
; \
|
||||
else [[unlikely]] g_logger.log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_WARN(...) \
|
||||
; \
|
||||
else [[unlikely]] g_logger.log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_INFO(...) \
|
||||
; \
|
||||
else g_logger.log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_ERROR(...) \
|
||||
; \
|
||||
else [[unlikely]] g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_WARN(...) \
|
||||
; \
|
||||
else [[unlikely]] g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_INFO(...) \
|
||||
; \
|
||||
else g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
#if !defined(DEBUG_LOG_DISABLED) && !defined(NDEBUG)
|
||||
|
||||
#define DEBUG(...) g_logger.log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define DEBUG_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_logger.log_cond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_DEBUG(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_DEBUG(...) \
|
||||
; \
|
||||
else [[unlikely]] 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, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_DEBUG(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_DEBUG(...) \
|
||||
; \
|
||||
else g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
#else // !defined(DEBUG_LOG_DISABLED)
|
||||
|
||||
#define DEBUG(msg) \
|
||||
{}
|
||||
#define DEBUG_IF(expr, msg) \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_IF_DEBUG(expr, msg) \
|
||||
; \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_DEBUG(msg) \
|
||||
; \
|
||||
{}
|
||||
#define DEBUG(msg) \
|
||||
{ \
|
||||
}
|
||||
#define DEBUG_IF(expr, msg) \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_IF_DEBUG(expr, msg) \
|
||||
; \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_DEBUG(msg) \
|
||||
; \
|
||||
{ \
|
||||
}
|
||||
|
||||
#endif // !defined(DEBUG_LOG_DISABLED)
|
||||
|
||||
#if !defined(VERBOSE_LOG_DISABLED) && !defined(NDEBUG)
|
||||
|
||||
#define VERBOSE(...) g_logger.log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define VERBOSE_IF(expr, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_logger.log_cond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_VERBOSE(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) g_logger.log_cond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_VERBOSE(...) \
|
||||
; \
|
||||
else 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, ...) \
|
||||
if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_IF_VERBOSE(expr, ...) \
|
||||
; \
|
||||
else if (cast<bool>(expr)) \
|
||||
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
#define ELSE_VERBOSE(...) \
|
||||
; \
|
||||
else g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
#else // !defined(DEBUG_LOG_DISABLED)
|
||||
|
||||
#define VERBOSE(msg) \
|
||||
{}
|
||||
#define VERBOSE_IF(expr, msg) \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_IF_VERBOSE(expr, msg) \
|
||||
; \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_VERBOSE(msg) \
|
||||
; \
|
||||
{}
|
||||
#define VERBOSE(msg) \
|
||||
{ \
|
||||
}
|
||||
#define VERBOSE_IF(expr, msg) \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_IF_VERBOSE(expr, msg) \
|
||||
; \
|
||||
if (expr) \
|
||||
(void)msg
|
||||
#define ELSE_VERBOSE(msg) \
|
||||
; \
|
||||
{ \
|
||||
}
|
||||
|
||||
#endif // !defined(VERBOSE_LOG_DISABLED)
|
||||
|
||||
#define DO(code) , code
|
||||
#define CRASH(code) exit(cast<i32>(code))
|
||||
#define THEN_CRASH(code) , CRASH(code)
|
||||
#define ABORT(code) exit(cast<i32>(code))
|
||||
#define THEN_ABORT(code) , ABORT(code)
|
||||
|
|
|
|||
|
|
@ -5,95 +5,145 @@
|
|||
|
||||
#include "physical_device.h"
|
||||
|
||||
[[nodiscard]] std::vector<vk::SurfaceFormatKHR> get_surface_formats(const Window *_window, const vk::PhysicalDevice *_physical_device) {
|
||||
try {
|
||||
return _physical_device->getSurfaceFormatsKHR(_window->surface);
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Could not get surface formats. Cause: {}", _err.what());
|
||||
throw;
|
||||
}
|
||||
[[nodiscard]] eastl::vector<vk::SurfaceFormatKHR>
|
||||
getSurfaceFormats(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||
{
|
||||
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
|
||||
u32 count = 0;
|
||||
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) {
|
||||
try {
|
||||
return _physical_device->getSurfacePresentModesKHR(_window->surface);
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Could not get present modes. Cause: {}", _err.what());
|
||||
throw;
|
||||
}
|
||||
[[nodiscard]] eastl::vector<vk::PresentModeKHR>
|
||||
getSurfacePresentModes(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||
{
|
||||
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
|
||||
u32 count = 0;
|
||||
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) {
|
||||
try {
|
||||
return _device->getSurfaceSupportKHR(_family_index, _window->surface);
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Could not get queue family surface support. Cause: {}", _err.what());
|
||||
throw;
|
||||
}
|
||||
[[nodiscard]] bool
|
||||
getQueuePresentSupport(const u32 queueFamilyIndex, vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||
{
|
||||
b32 supported = false;
|
||||
const vk::Result result = physicalDevice.getSurfaceSupportKHR(queueFamilyIndex, surface, &supported);
|
||||
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) {
|
||||
auto queue_family_props = _device->getQueueFamilyProperties();
|
||||
[[nodiscard]] eastl::fixed_vector<vk::QueueFamilyProperties, 32>
|
||||
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;
|
||||
queue_family_infos.reserve(queue_family_props.size());
|
||||
eastl::fixed_vector<vk::QueueFamilyProperties, 32> queueFamilyProperties(count);
|
||||
physicalDevice.getQueueFamilyProperties(&count, queueFamilyProperties.data());
|
||||
|
||||
u32 family_index = 0;
|
||||
for (auto qfp : queue_family_props) {
|
||||
QueueSupportFlags support = {};
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eGraphics) {
|
||||
support |= QueueSupportFlagBits::eGraphics;
|
||||
}
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eTransfer) {
|
||||
support |= QueueSupportFlagBits::eTransfer;
|
||||
}
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eCompute) {
|
||||
support |= QueueSupportFlagBits::eCompute;
|
||||
}
|
||||
|
||||
if (get_present_support(family_index, _window, _device)) {
|
||||
support |= QueueSupportFlagBits::ePresent;
|
||||
}
|
||||
|
||||
queue_family_infos.push_back({
|
||||
.index = family_index,
|
||||
.count = qfp.queueCount,
|
||||
.support = support,
|
||||
});
|
||||
|
||||
family_index++;
|
||||
}
|
||||
|
||||
return queue_family_infos;
|
||||
return queueFamilyProperties;
|
||||
}
|
||||
|
||||
PhysicalDevice::PhysicalDevice(const Window *_window, vk::PhysicalDevice _physical_device) {
|
||||
_physical_device.getProperties(&properties);
|
||||
_physical_device.getFeatures(&features);
|
||||
// Size 384 return.
|
||||
[[nodiscard]] eastl::vector<QueueFamilyInfo>
|
||||
getQueueFamilies(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||
{
|
||||
|
||||
surface_formats = get_surface_formats(_window, &_physical_device);
|
||||
present_modes = get_present_modes(_window, &_physical_device);
|
||||
queue_families = get_queue_families(_window, &_physical_device);
|
||||
auto queueFamilyProperties = getQueueFamilyProperties(physicalDevice);
|
||||
|
||||
device = _physical_device;
|
||||
eastl::vector<QueueFamilyInfo> queueFamilyInfos;
|
||||
queueFamilyInfos.reserve(queueFamilyProperties.size());
|
||||
|
||||
u32 familyIndex = 0;
|
||||
for (auto qfp : queueFamilyProperties)
|
||||
{
|
||||
QueueSupportFlags support = {};
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eGraphics)
|
||||
{
|
||||
support |= QueueSupportFlagBits::eGraphics;
|
||||
}
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eTransfer)
|
||||
{
|
||||
support |= QueueSupportFlagBits::eTransfer;
|
||||
}
|
||||
|
||||
if (qfp.queueFlags | vk::QueueFlagBits::eCompute)
|
||||
{
|
||||
support |= QueueSupportFlagBits::eCompute;
|
||||
}
|
||||
|
||||
if (getQueuePresentSupport(familyIndex, surface, physicalDevice))
|
||||
{
|
||||
support |= QueueSupportFlagBits::ePresent;
|
||||
}
|
||||
|
||||
queueFamilyInfos.push_back({
|
||||
.m_Index = familyIndex,
|
||||
.m_Count = qfp.queueCount,
|
||||
.m_Support = support,
|
||||
});
|
||||
|
||||
familyIndex++;
|
||||
}
|
||||
|
||||
return queueFamilyInfos;
|
||||
}
|
||||
|
||||
std::vector<vk::PhysicalDevice> enumerate_physical_devices(const Context *_context) {
|
||||
try {
|
||||
return _context->instance.enumeratePhysicalDevices();
|
||||
} catch (const std::exception &_err) {
|
||||
ERROR("Could not fetch vulkan devices. Cause: {}", _err.what());
|
||||
throw;
|
||||
}
|
||||
PhysicalDevice::PhysicalDevice(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
|
||||
{
|
||||
physicalDevice.getProperties(&m_DeviceProperties);
|
||||
physicalDevice.getFeatures(&m_DeviceFeatures);
|
||||
|
||||
m_SurfaceFormats = getSurfaceFormats(surface, physicalDevice);
|
||||
m_PresentModes = getSurfacePresentModes(surface, physicalDevice);
|
||||
m_QueueFamilies = getQueueFamilies(surface, physicalDevice);
|
||||
|
||||
m_PhysicalDevice = physicalDevice;
|
||||
}
|
||||
|
||||
PhysicalDevices::PhysicalDevices(const Window *_window, const Context *_context) {
|
||||
auto physical_devices = enumerate_physical_devices(_context);
|
||||
this->reserve(physical_devices.size());
|
||||
for (auto physical_device : physical_devices) {
|
||||
this->emplace_back(_window, physical_device);
|
||||
}
|
||||
eastl::fixed_vector<vk::PhysicalDevice, 8>
|
||||
enumeratePhysicalDevices(const vk::Instance instance)
|
||||
{
|
||||
u32 count = 0;
|
||||
vk::Result result = instance.enumeratePhysicalDevices(&count, nullptr);
|
||||
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)
|
||||
{
|
||||
auto surface = window->m_Surface;
|
||||
auto physicalDevices = enumeratePhysicalDevices(context->m_Instance);
|
||||
for (auto physicalDevice : physicalDevices)
|
||||
{
|
||||
this->emplace_back(surface, physicalDevice);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,34 +7,39 @@
|
|||
|
||||
#include "global.h"
|
||||
#include "window.h"
|
||||
#include <EASTL/fixed_vector.h>
|
||||
|
||||
enum class QueueSupportFlagBits {
|
||||
eGraphics = 0b0001,
|
||||
eTransfer = 0b0010,
|
||||
eCompute = 0b0100,
|
||||
ePresent = 0b1000,
|
||||
enum class QueueSupportFlagBits
|
||||
{
|
||||
eGraphics = 0b0001,
|
||||
eTransfer = 0b0010,
|
||||
eCompute = 0b0100,
|
||||
ePresent = 0b1000,
|
||||
};
|
||||
|
||||
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
||||
|
||||
struct QueueFamilyInfo {
|
||||
u32 index;
|
||||
u32 count;
|
||||
QueueSupportFlags support;
|
||||
struct QueueFamilyInfo
|
||||
{
|
||||
u32 m_Index;
|
||||
u32 m_Count;
|
||||
QueueSupportFlags m_Support;
|
||||
};
|
||||
|
||||
struct PhysicalDevice {
|
||||
vk::PhysicalDevice device;
|
||||
vk::PhysicalDeviceProperties properties;
|
||||
vk::PhysicalDeviceFeatures features;
|
||||
std::vector<vk::SurfaceFormatKHR> surface_formats;
|
||||
std::vector<vk::PresentModeKHR> present_modes;
|
||||
std::vector<QueueFamilyInfo> queue_families;
|
||||
struct PhysicalDevice
|
||||
{
|
||||
vk::PhysicalDevice m_PhysicalDevice;
|
||||
vk::PhysicalDeviceProperties m_DeviceProperties;
|
||||
vk::PhysicalDeviceFeatures m_DeviceFeatures;
|
||||
eastl::vector<vk::SurfaceFormatKHR> m_SurfaceFormats;
|
||||
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> {
|
||||
public:
|
||||
PhysicalDevices(const Window *_window, const Context *_context);
|
||||
class PhysicalDevices : public eastl::fixed_vector<PhysicalDevice, 4>
|
||||
{
|
||||
public:
|
||||
PhysicalDevices(const Window *window, const Context *context);
|
||||
};
|
||||
117
aster/window.cpp
117
aster/window.cpp
|
|
@ -8,65 +8,72 @@
|
|||
#include "glfw_context.h"
|
||||
#include "logger.h"
|
||||
|
||||
Window::Window(const std::string_view &_title, Context *_context, vk::Extent2D _extent, b8 _full_screen) :
|
||||
parent_context{ std::move(_context) }, extent{ _extent }, name{ _title }, full_screen{ _full_screen } {
|
||||
monitor = glfwGetPrimaryMonitor();
|
||||
ERROR_IF(monitor == nullptr, "No monitor found");
|
||||
|
||||
i32 x_, y_, w_, h_;
|
||||
glfwGetMonitorWorkarea(monitor, &x_, &y_, &w_, &h_);
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
|
||||
|
||||
window = glfwCreateWindow(extent.width, extent.height, name.data(), full_screen ? monitor : nullptr, nullptr);
|
||||
ERROR_IF(window == nullptr, "Window creation failed")
|
||||
ELSE_INFO("Window '{}' created with resolution '{}x{}'", name, extent.width, extent.height);
|
||||
if (window == nullptr) {
|
||||
auto code = GlfwContext::post_error();
|
||||
glfwTerminate();
|
||||
CRASH(code);
|
||||
}
|
||||
|
||||
if (full_screen == false) {
|
||||
glfwSetWindowPos(window, (w_ - extent.width) / 2, (h_ - extent.height) / 2);
|
||||
}
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
|
||||
VkSurfaceKHR surface_;
|
||||
auto result = cast<vk::Result>(glfwCreateWindowSurface(cast<VkInstance>(_context->instance), window, nullptr, &surface_));
|
||||
ERROR_IF(failed(result), "Failed to create Surface with {}", to_string(result))
|
||||
THEN_CRASH(result) ELSE_INFO("Surface Created");
|
||||
surface = vk::SurfaceKHR(surface_);
|
||||
void
|
||||
Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
|
||||
{
|
||||
SetWindowSize(extent.width, extent.height);
|
||||
}
|
||||
|
||||
Window::Window(Window &&_other) noexcept :
|
||||
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 } {}
|
||||
|
||||
Window &Window::operator=(Window &&_other) noexcept {
|
||||
if (this == &_other)
|
||||
return *this;
|
||||
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;
|
||||
void
|
||||
Window::SetWindowSize(const u32 width, const u32 height) const noexcept
|
||||
{
|
||||
glfwSetWindowSize(m_Window, cast<i32>(width), cast<i32>(height));
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
if (parent_context && surface) {
|
||||
parent_context->instance.destroy(surface);
|
||||
INFO("Surface Destroyed");
|
||||
}
|
||||
Window::Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen)
|
||||
{
|
||||
m_Context = context;
|
||||
m_Name = title;
|
||||
|
||||
if (window != nullptr) {
|
||||
glfwDestroyWindow(window);
|
||||
window = nullptr;
|
||||
}
|
||||
monitor = nullptr;
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
ERROR_IF(!monitor, "No monitor found");
|
||||
|
||||
INFO("Window '{}' Destroyed", name);
|
||||
i32 windowX, windowY, windowWidth, windowHeight;
|
||||
glfwGetMonitorWorkarea(monitor, &windowX, &windowY, &windowWidth, &windowHeight);
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
|
||||
|
||||
m_Window = glfwCreateWindow(cast<i32>(extent.width), cast<i32>(extent.height), m_Name.c_str(),
|
||||
isFullScreen ? monitor : nullptr, nullptr);
|
||||
ERROR_IF(m_Window == nullptr, "Window creation failed")
|
||||
ELSE_DEBUG("Window '{}' created with resolution '{}x{}'", m_Name.c_str(), extent.width, extent.height);
|
||||
if (m_Window == nullptr)
|
||||
{
|
||||
auto code = GlfwContext::PostError();
|
||||
glfwTerminate();
|
||||
ABORT(code);
|
||||
}
|
||||
|
||||
if (isFullScreen == false)
|
||||
{
|
||||
glfwSetWindowPos(m_Window, cast<i32>(windowWidth - extent.width) / 2,
|
||||
cast<i32>(windowHeight - extent.height) / 2);
|
||||
}
|
||||
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
|
||||
VkSurfaceKHR 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))
|
||||
THEN_ABORT(result)
|
||||
ELSE_DEBUG("Surface {} Created", m_Name.c_str());
|
||||
m_Surface = vk::SurfaceKHR(surface);
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
if (m_Context && m_Surface)
|
||||
{
|
||||
m_Context->m_Instance.destroy(m_Surface, nullptr);
|
||||
DEBUG("Surface Destroyed");
|
||||
}
|
||||
|
||||
if (m_Window != nullptr)
|
||||
{
|
||||
glfwDestroyWindow(m_Window);
|
||||
m_Window = nullptr;
|
||||
}
|
||||
|
||||
DEBUG("Window '{}' Destroyed", m_Name.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,45 +5,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "global.h"
|
||||
#include <EASTL/fixed_string.h>
|
||||
|
||||
struct Window final {
|
||||
Window(const std::string_view &_title, Context *_context, vk::Extent2D _extent, b8 _full_screen = false);
|
||||
struct Window final
|
||||
{
|
||||
// fields
|
||||
Context *m_Context{};
|
||||
|
||||
Window(const Window &_other) = delete;
|
||||
Window(Window &&_other) noexcept;
|
||||
Window &operator=(const Window &_other) = delete;
|
||||
Window &operator=(Window &&_other) noexcept;
|
||||
GLFWwindow *m_Window = nullptr;
|
||||
vk::SurfaceKHR m_Surface;
|
||||
eastl::fixed_string<char, 32> m_Name;
|
||||
|
||||
~Window();
|
||||
// Methods
|
||||
[[nodiscard]] bool
|
||||
Poll() const noexcept
|
||||
{
|
||||
glfwPollEvents();
|
||||
return !glfwWindowShouldClose(m_Window);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool should_close() const noexcept {
|
||||
return glfwWindowShouldClose(window);
|
||||
}
|
||||
void SetWindowSize(const vk::Extent2D &extent) const noexcept;
|
||||
void SetWindowSize(u32 width, u32 height) const noexcept;
|
||||
|
||||
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
|
||||
Context *parent_context{};
|
||||
|
||||
GLFWwindow *window{ nullptr };
|
||||
GLFWmonitor *monitor{ nullptr };
|
||||
vk::SurfaceKHR surface;
|
||||
vk::Extent2D extent;
|
||||
std::string name;
|
||||
b8 full_screen{ false };
|
||||
// Ctor/Dtor
|
||||
Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen = false);
|
||||
~Window();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,60 +4,83 @@
|
|||
#include "aster/physical_device.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) {
|
||||
const bool all_required_queues = std::ranges::any_of(_physical_device->queue_families, [](const auto &_qfp) {
|
||||
return (_qfp.support & required_queue_support) == required_queue_support;
|
||||
});
|
||||
constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics |
|
||||
QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent |
|
||||
QueueSupportFlagBits::eTransfer;
|
||||
|
||||
const bool device_type_check = _physical_device->properties.deviceType != vk::PhysicalDeviceType::eCpu;
|
||||
[[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 supported_present_mode = !_physical_device->present_modes.empty();
|
||||
const bool isNotCpu = physicalDevice->m_DeviceProperties.deviceType != vk::PhysicalDeviceType::eCpu;
|
||||
|
||||
const bool supported_format = !_physical_device->surface_formats.empty();
|
||||
const bool hasPresentMode = !physicalDevice->m_PresentModes.empty();
|
||||
|
||||
return supported_format && supported_present_mode && device_type_check && all_required_queues;
|
||||
const bool hasSurfaceFormat = !physicalDevice->m_SurfaceFormats.empty();
|
||||
|
||||
return hasSurfaceFormat && hasPresentMode && isNotCpu && hasAllRequiredQueues;
|
||||
}
|
||||
|
||||
PhysicalDevice find_suitable_device(const PhysicalDevices &_physical_devices) {
|
||||
for (auto &_physical_device : _physical_devices) {
|
||||
if (is_suitable_device(&_physical_device)) {
|
||||
return _physical_device;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("No suitable device found.");
|
||||
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 find_appropriate_queue_allocation(const PhysicalDevice* _physical_device) {
|
||||
for (auto &_queue_info: _physical_device->queue_families) {
|
||||
if ((_queue_info.support & required_queue_support) == required_queue_support) {
|
||||
return {
|
||||
.family = _queue_info.index,
|
||||
.count = _queue_info.count,
|
||||
};
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("No suitable queue family.");
|
||||
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);
|
||||
}
|
||||
|
||||
int main(int, char **) {
|
||||
GlfwContext glfw_context = {};
|
||||
Context context = {"Aster", VERSION};
|
||||
Window window = {"Aster1", &context, { 640, 480 }};
|
||||
int
|
||||
main(int, char **)
|
||||
{
|
||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
||||
|
||||
PhysicalDevices physical_devices = { &window, &context };
|
||||
PhysicalDevice device_to_use = find_suitable_device(physical_devices);
|
||||
GlfwContext glfwContext = {};
|
||||
Context context = {"Aster", VERSION};
|
||||
Window window = {"Aster1", &context, {640, 480}};
|
||||
|
||||
INFO("Using {} as the primary device.", device_to_use.properties.deviceName.data());
|
||||
PhysicalDevices physicalDevices = {&window, &context};
|
||||
PhysicalDevice deviceToUse = findSuitableDevice(physicalDevices);
|
||||
|
||||
vk::PhysicalDeviceFeatures features = {};
|
||||
QueueAllocation queue_allocation = find_appropriate_queue_allocation(&device_to_use);
|
||||
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
||||
|
||||
Device device = { &context, std::move(device_to_use), &features, {queue_allocation}, "Primary Device" };
|
||||
vk::PhysicalDeviceFeatures features = {};
|
||||
QueueAllocation queueAllocation = findAppropriateQueueAllocation(&deviceToUse);
|
||||
|
||||
while (window.poll()) {
|
||||
}
|
||||
Device device = {&context, &deviceToUse, &features, {queueAllocation}, "Primary Device"};
|
||||
|
||||
return 0;
|
||||
while (window.Poll())
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"dependencies": [
|
||||
"fmt",
|
||||
"glfw3",
|
||||
"glm",
|
||||
"scottt-debugbreak",
|
||||
"vulkan-memory-allocator",
|
||||
"fmt"
|
||||
"eastl"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue