diff --git a/.clang-format b/.clang-format
index 849cdca54..24420da65 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,31 +4,31 @@ BasedOnStyle: LLVM
Language: Cpp
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
-AlignConsecutiveAssignments: 'true'
-AlignConsecutiveDeclarations: 'true'
+AlignConsecutiveAssignments: "true"
+AlignConsecutiveDeclarations: "true"
AlignEscapedNewlines: Left
AlignOperands: Align
-AlignTrailingComments: 'true'
-AllowAllParametersOfDeclarationOnNextLine: 'false'
-AllowAllArgumentsOnNextLine: 'false'
-AllowShortBlocksOnASingleLine: 'true'
-AllowShortCaseLabelsOnASingleLine: 'true'
+AlignTrailingComments: "true"
+AllowAllParametersOfDeclarationOnNextLine: "false"
+AllowAllArgumentsOnNextLine: "false"
+AllowShortBlocksOnASingleLine: "true"
+AllowShortCaseLabelsOnASingleLine: "true"
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Always
-AllowShortLoopsOnASingleLine: 'true'
-AllowShortLambdasOnASingleLine: 'true'
-AllowShortEnumsOnASingleLine: 'false'
+AllowShortLoopsOnASingleLine: "true"
+AllowShortLambdasOnASingleLine: "true"
+AllowShortEnumsOnASingleLine: "false"
AlignConsecutiveMacros: Consecutive
BitFieldColonSpacing: After
-BreakBeforeConceptDeclarations: 'true'
+BreakBeforeConceptDeclarations: "true"
BreakBinaryOperations: RespectPrecedence
EmptyLineBeforeAccessModifier: LogicalBlock
EnumTrailingComma: Insert
-FixNamespaceComments: 'true'
+FixNamespaceComments: "true"
IndentExternBlock: Indent
-IndentGotoLabels: 'false'
-IndentRequiresClause: 'true'
-InsertBraces: 'false'
+IndentGotoLabels: "false"
+IndentRequiresClause: "true"
+InsertBraces: "false"
InsertTrailingCommas: Wrapped
LambdaBodyIndentation: Signature
PPIndentWidth: 4
@@ -36,20 +36,29 @@ PenaltyBreakAssignment: 1000
PenaltyReturnTypeOnItsOwnLine: 1000
PenaltyBreakBeforeFirstCallParameter: 1000
PenaltyBreakOpenParenthesis: 1000
-PenaltyBreakBeforeMemberAccess: 10
-PenaltyIndentedWhitespace: 1
+PenaltyBreakBeforeMemberAccess: 1000
+PenaltyIndentedWhitespace: 2
ContinuationIndentWidth: 2
ReferenceAlignment: Left
# RemoveBracesLLVM: 'true'
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Always
-SpaceAfterLogicalNot: 'false'
+SpaceAfterLogicalNot: "false"
SpaceAroundPointerQualifiers: After
-SpaceBeforeCaseColon: 'false'
+SpaceBeforeCaseColon: "false"
AlwaysBreakAfterDefinitionReturnType: None
-SpaceBeforeSquareBrackets: 'false'
-SpaceInEmptyBlock: 'false'
-AttributeMacros: [STORMKIT_FORCE_INLINE, STORMKIT_API, STORMKIT_PRIVATE, STORMKIT_PUBLIC, STORMKIT_CONST, STORMKIT_PURE, STORMKIT_INTRINSIC]
+SpaceBeforeSquareBrackets: "false"
+SpaceInEmptyBlock: "false"
+AttributeMacros:
+ [
+ STORMKIT_FORCE_INLINE,
+ STORMKIT_API,
+ STORMKIT_PRIVATE,
+ STORMKIT_PUBLIC,
+ STORMKIT_CONST,
+ STORMKIT_PURE,
+ STORMKIT_INTRINSIC,
+ ]
IfMacros: [CASE_DO, CASE_DO_RETURN, CASE, CASE_ARGS_DO]
BreakAfterAttributes: Always
Macros:
@@ -60,120 +69,122 @@ Macros:
- STORMKIT_CONST=[[maybe_unused]]
- STORMKIT_PURE=[[maybe_unused]]
- STORMKIT_INTRINSIC=[[maybe_unused]]
-
+
QualifierAlignment: Custom
QualifierOrder: [static, inline, volatile, restrict, constexpr, const, type]
SpacesInLineCommentPrefix:
- Minimum: '1'
- Maximum: '4'
+ Minimum: "1"
+ Maximum: "4"
AlwaysBreakAfterReturnType: None
-AlwaysBreakBeforeMultilineStrings: 'false'
-AlwaysBreakTemplateDeclarations: 'Yes'
-BinPackArguments: 'false'
-BinPackParameters: 'false'
+AlwaysBreakBeforeMultilineStrings: "false"
+AlwaysBreakTemplateDeclarations: "Yes"
+BinPackArguments: "false"
+BinPackParameters: "false"
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Attach
BreakConstructorInitializers: BeforeColon
+BreakBeforeCloseBracketBracedList: "true"
BreakInheritanceList: BeforeColon
-BreakStringLiterals: 'true'
-ColumnLimit: '130'
-CompactNamespaces: 'true'
-ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
-ConstructorInitializerIndentWidth: '4'
+BreakStringLiterals: "true"
+ColumnLimit: "130"
+CompactNamespaces: "true"
+ConstructorInitializerAllOnOneLineOrOnePerLine: "true"
+ConstructorInitializerIndentWidth: "4"
IncludeBlocks: Preserve
-IndentCaseLabels: 'true'
-IndentWidth: '4'
-IndentWrappedFunctionNames: 'true'
+IndentCaseLabels: "true"
+IndentWidth: "4"
+IndentWrappedFunctionNames: "true"
IndentPPDirectives: BeforeHash
-KeepEmptyLinesAtTheStartOfBlocks: 'false'
-Cpp11BracedListStyle: 'false'
-MaxEmptyLinesToKeep: '1'
+KeepEmptyLinesAtTheStartOfBlocks: "false"
+Cpp11BracedListStyle: "Block"
+MaxEmptyLinesToKeep: "1"
NamespaceIndentation: All
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PointerAlignment: Left
-SortIncludes: 'true'
-SortUsingDeclarations: 'true'
-SpaceAfterTemplateKeyword: 'false'
-SpaceBeforeAssignmentOperators: 'true'
-SpaceBeforeCpp11BracedList: 'true'
-SpaceBeforeCtorInitializerColon: 'true'
-SpaceBeforeInheritanceColon: 'false'
-SpaceBeforeRangeBasedForLoopColon: 'true'
-SpaceInEmptyParentheses: 'false'
-SpacesInAngles: 'false'
+SortIncludes: "true"
+SortUsingDeclarations: "true"
+SpaceAfterTemplateKeyword: "false"
+SpaceBeforeAssignmentOperators: "true"
+SpaceBeforeCpp11BracedList: "true"
+SpaceBeforeCtorInitializerColon: "true"
+SpaceBeforeInheritanceColon: "false"
+SpaceBeforeRangeBasedForLoopColon: "true"
+SpaceInEmptyParentheses: "false"
+SpacesInAngles: "false"
Standard: c++20
-TabWidth: '4'
+TabWidth: "4"
UseTab: Never
---
Language: ObjC
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
-AlignConsecutiveAssignments: 'true'
-AlignConsecutiveDeclarations: 'false'
+AlignConsecutiveAssignments: "true"
+AlignConsecutiveDeclarations: "false"
AlignEscapedNewlines: Left
AlignOperands: Align
-AlignTrailingComments: 'true'
-AllowAllParametersOfDeclarationOnNextLine: 'false'
-AllowAllArgumentsOnNextLine: 'false'
-AllowShortBlocksOnASingleLine: 'true'
-AllowShortCaseLabelsOnASingleLine: 'true'
+AlignTrailingComments: "true"
+AllowAllParametersOfDeclarationOnNextLine: "false"
+AllowAllArgumentsOnNextLine: "false"
+AllowShortBlocksOnASingleLine: "true"
+AllowShortCaseLabelsOnASingleLine: "true"
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Always
-AllowShortLoopsOnASingleLine: 'true'
-AllowShortLambdasOnASingleLine: 'true'
+AllowShortLoopsOnASingleLine: "true"
+AllowShortLambdasOnASingleLine: "true"
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
-AlwaysBreakBeforeMultilineStrings: 'false'
-AlwaysBreakTemplateDeclarations: 'Yes'
-BinPackArguments: 'false'
-BinPackParameters: 'false'
+AlwaysBreakBeforeMultilineStrings: "false"
+AlwaysBreakTemplateDeclarations: "Yes"
+BinPackArguments: "false"
+BinPackParameters: "false"
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Attach
BreakBinaryOperations: OnePerLine
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
-BreakStringLiterals: 'true'
-ColumnLimit: '130'
-CompactNamespaces: 'true'
-ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
-ConstructorInitializerIndentWidth: '4'
-ContinuationIndentWidth: '4'
+BreakStringLiterals: "true"
+ColumnLimit: "130"
+CompactNamespaces: "true"
+ConstructorInitializerAllOnOneLineOrOnePerLine: "false"
+ConstructorInitializerIndentWidth: "4"
+ContinuationIndentWidth: "4"
IncludeBlocks: Preserve
-IndentCaseLabels: 'true'
-IndentWidth: '4'
-IndentWrappedFunctionNames: 'true'
+IndentCaseLabels: "true"
+IndentWidth: "4"
+IndentWrappedFunctionNames: "true"
IndentPPDirectives: BeforeHash
-KeepEmptyLinesAtTheStartOfBlocks: 'false'
-Cpp11BracedListStyle: 'false'
-MaxEmptyLinesToKeep: '1'
+KeepEmptyLinesAtTheStartOfBlocks: "false"
+Cpp11BracedListStyle: "false"
+MaxEmptyLinesToKeep: "1"
NamespaceIndentation: All
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PointerAlignment: Right
-PenaltyBreakAssignment: 1000
-PenaltyReturnTypeOnItsOwnLine: 1000
-PenaltyBreakBeforeFirstCallParameter: 1000
-PenaltyBreakOpenParenthesis: 1000
-PenaltyBreakBeforeMemberAccess: 10
-SortIncludes: 'true'
-SortUsingDeclarations: 'true'
-SpaceAfterTemplateKeyword: 'false'
-SpaceBeforeAssignmentOperators: 'true'
-SpaceBeforeCpp11BracedList: 'true'
-SpaceBeforeCtorInitializerColon: 'true'
-SpaceBeforeInheritanceColon: 'false'
-SpaceBeforeRangeBasedForLoopColon: 'true'
-SpaceInEmptyParentheses: 'false'
-SpacesInAngles: 'false'
+PenaltyBreakAssignment: 300
+PenaltyReturnTypeOnItsOwnLine: 100
+PenaltyBreakBeforeFirstCallParameter: 500
+PenaltyBreakOpenParenthesis: 700
+PenaltyBreakBeforeMemberAccess: 700
+SortIncludes: "true"
+SortUsingDeclarations: "true"
+SpaceAfterTemplateKeyword: "false"
+SpaceBeforeAssignmentOperators: "true"
+SpaceBeforeCpp11BracedList: "true"
+SpaceBeforeCtorInitializerColon: "true"
+SpaceBeforeInheritanceColon: "false"
+SpaceBeforeRangeBasedForLoopColon: "true"
+SpaceInEmptyParentheses: "false"
+SpacesInAngles: "false"
Standard: c++20
-TabWidth: '4'
+TabWidth: "4"
UseTab: Never
-PenaltyIndentedWhitespace: '1'
+PenaltyIndentedWhitespace: "1"
QualifierAlignment: Custom
QualifierOrder: [static, inline, volatile, restrict, constexpr, const, type]
-AttributeMacros: [STORMKIT_FORCE_INLINE, STORMKIT_API, STORMKIT_PRIVATE, STORMKIT_PUBLIC]
+AttributeMacros:
+ [STORMKIT_FORCE_INLINE, STORMKIT_API, STORMKIT_PRIVATE, STORMKIT_PUBLIC]
IfMacros: [CASE_DO, CASE_DO_RETURN, CASE, CASE_ARGS_DO]
BreakAfterAttributes: Always
diff --git a/examples/wsi/events/win32/manifest.manifest b/examples/common/Windows/manifest.manifest
similarity index 100%
rename from examples/wsi/events/win32/manifest.manifest
rename to examples/common/Windows/manifest.manifest
diff --git a/examples/log/file-logger/iOS/info.plist b/examples/common/macOS/info.plist
similarity index 97%
rename from examples/log/file-logger/iOS/info.plist
rename to examples/common/macOS/info.plist
index 83e13e582..6e96e13c8 100644
--- a/examples/log/file-logger/iOS/info.plist
+++ b/examples/common/macOS/info.plist
@@ -1,44 +1,44 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- LSRequiresIPhoneOS
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
-
-
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${MACOSX_BUNDLE_EXECUTABLE_NAME}
+ CFBundleGetInfoString
+ ${MACOSX_BUNDLE_INFO_STRING}
+ CFBundleIconFile
+ ${MACOSX_BUNDLE_ICON_FILE}
+ CFBundleIdentifier
+ ${MACOSX_BUNDLE_GUI_IDENTIFIER}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleLongVersionString
+ ${MACOSX_BUNDLE_LONG_VERSION_STRING}
+ CFBundleName
+ ${MACOSX_BUNDLE_BUNDLE_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ ${MACOSX_BUNDLE_BUNDLE_VERSION}
+ LSRequiresIPhoneOS
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ NSHumanReadableCopyright
+ ${MACOSX_BUNDLE_COPYRIGHT}
+
+
diff --git a/examples/entities/gameoflife/src/App.cpp b/examples/entities/gameoflife/src/App.cpp
index 97f47c4b6..d1545f474 100644
--- a/examples/entities/gameoflife/src/App.cpp
+++ b/examples/entities/gameoflife/src/App.cpp
@@ -25,7 +25,7 @@ App::~App() {
ilog("Cleaning");
}
-auto App::run([[maybe_unused]] const int argc, [[maybe_unused]] CZString argv[]) -> i32 {
+auto App::run([[maybe_unused]] const int argc, [[maybe_unused]] czstring argv[]) -> i32 {
using Clock = std::chrono::high_resolution_clock;
using namespace stormkit::literals;
@@ -83,7 +83,7 @@ auto App::run([[maybe_unused]] const int argc, [[maybe_unused]] CZString argv[])
auto App::do_initWindow() -> void {
const auto window_style = wsi::WindowStyle::ALL;
- m_window = allocate(WINDOW_TITLE, math::ExtentU { 800u, 600u }, window_style);
+ m_window = allocate(WINDOW_TITLE, math::uextent2 { 800u, 600u }, window_style);
m_renderer = allocate(*m_window);
}
@@ -124,8 +124,8 @@ auto App::handleKeyboard(const stormkit::wsi::KeyReleasedEventData& event) -> vo
m_is_on_edit_mode = !m_is_on_edit_mode;
m_update_system->setEditModeEnabled(m_is_on_edit_mode);
break;
- case wsi::Key::ADD: m_update_system->incrementDelta(Secondf { 0.01f }); break;
- case wsi::Key::SUBSTRACT: m_update_system->incrementDelta(Secondf { -0.01f }); break;
+ case wsi::Key::ADD: m_update_system->incrementDelta(fsecond { 0.01f }); break;
+ case wsi::Key::SUBSTRACT: m_update_system->incrementDelta(fsecond { -0.01f }); break;
default: break;
}
}
@@ -135,11 +135,11 @@ auto App::handleMouse(const stormkit::wsi::MouseButtonPushedEventData& event) ->
return;
if (event.button != wsi::MouseButton::LEFT) return;
- const auto cell_width = as(m_window->size().width) / as(BOARD_SIZE);
- const auto cell_height = as(m_window->size().height) / as(BOARD_SIZE);
+ const auto cell_width = as(m_window->size().width) / as(BOARD_SIZE);
+ const auto cell_height = as(m_window->size().height) / as(BOARD_SIZE);
- const auto x = glm::floor(as(event.position.x) / cell_width);
- const auto y = glm::floor(as(event.position.y) / cell_height);
+ const auto x = glm::floor(as(event.position.x) / cell_width);
+ const auto y = glm::floor(as(event.position.y) / cell_height);
const auto cells = m_entities.entities_with_component();
const auto it = std::ranges::find_if(cells, [&](const auto e) {
diff --git a/examples/entities/gameoflife/src/App.mpp b/examples/entities/gameoflife/src/App.cppm
similarity index 90%
rename from examples/entities/gameoflife/src/App.mpp
rename to examples/entities/gameoflife/src/App.cppm
index 0c76586fc..ef52d2ecd 100644
--- a/examples/entities/gameoflife/src/App.mpp
+++ b/examples/entities/gameoflife/src/App.cppm
@@ -1,59 +1,59 @@
-
-
-#ifdef STORMKIT_BUILD_MODULES
-export module App;
-
-import std;
-
-import stormkit.core;
-import stormkit.image;
-import stormkit.wsi;
-import stormkit.entities;
-
-import Renderer;
-
-export {
-#else
- #include
-
- #include
- #include
- #include
- #include
-
- #include "Renderer.mpp"
-#endif
-
- class UpdateBoardSystem;
-
- class App: public stormkit::App {
- public:
- App();
- ~App() override;
-
- auto run(const int argc, CZString argv[]) -> stormkit::i32 override;
-
- private:
- auto do_initWindow() -> void;
-
- auto handleKeyboard(const stormkit::wsi::KeyReleasedEventData& event) -> void;
- auto handleMouse(const stormkit::wsi::MouseButtonPushedEventData& event) -> void;
- auto createCell(stormkit::u32 x, stormkit::u32 y) -> void;
-
- std::unique_ptr m_window;
-
- bool m_fullscreen_enabled = false;
- bool m_is_on_edit_mode = true;
-
- std::unique_ptr m_renderer;
-
- stormkit::entities::EntityManager m_entities;
-
- stormkit::image::Image m_board;
-
- UpdateBoardSystem* m_update_system = nullptr;
- };
-
-#ifdef STORMKIT_BUILD_MODULES
-}
-#endif
+
+
+#ifdef STORMKIT_BUILD_MODULES
+export module App;
+
+import std;
+
+import stormkit.core;
+import stormkit.image;
+import stormkit.wsi;
+import stormkit.entities;
+
+import Renderer;
+
+export {
+#else
+ #include
+
+ #include
+ #include
+ #include
+ #include
+
+ #include "Renderer.mpp"
+#endif
+
+ class UpdateBoardSystem;
+
+ class App: public stormkit::App {
+ public:
+ App();
+ ~App() override;
+
+ auto run(const int argc, czstring argv[]) -> stormkit::i32 override;
+
+ private:
+ auto do_initWindow() -> void;
+
+ auto handleKeyboard(const stormkit::wsi::KeyReleasedEventData& event) -> void;
+ auto handleMouse(const stormkit::wsi::MouseButtonPushedEventData& event) -> void;
+ auto createCell(stormkit::u32 x, stormkit::u32 y) -> void;
+
+ std::unique_ptr m_window;
+
+ bool m_fullscreen_enabled = false;
+ bool m_is_on_edit_mode = true;
+
+ std::unique_ptr m_renderer;
+
+ stormkit::entities::EntityManager m_entities;
+
+ stormkit::image::Image m_board;
+
+ UpdateBoardSystem* m_update_system = nullptr;
+ };
+
+#ifdef STORMKIT_BUILD_MODULES
+}
+#endif
diff --git a/examples/entities/gameoflife/src/Components.mpp b/examples/entities/gameoflife/src/Components.cppm
similarity index 77%
rename from examples/entities/gameoflife/src/Components.mpp
rename to examples/entities/gameoflife/src/Components.cppm
index 290615e1f..cfd9c7265 100644
--- a/examples/entities/gameoflife/src/Components.mpp
+++ b/examples/entities/gameoflife/src/Components.cppm
@@ -1,28 +1,28 @@
-
-
-#ifdef STORMKIT_BUILD_MODULES
-export module Components;
-
-import std;
-
-import stormkit.core;
-import stormkit.entities;
-
-export {
-#else
- #include
-
- #include
- #include
-#endif
-
- struct PositionComponent: public stormkit::entities::Component {
- stormkit::u32 x;
- stormkit::u32 y;
-
- static constexpr Type TYPE = stormkit::entities::component_hash("PositionComponent");
- };
-
-#ifdef STORMKIT_BUILD_MODULES
-}
-#endif
+
+
+#ifdef STORMKIT_BUILD_MODULES
+export module Components;
+
+import std;
+
+import stormkit.core;
+import stormkit.entities;
+
+export {
+#else
+ #include
+
+ #include
+ #include
+#endif
+
+ struct PositionComponent: public stormkit::entities::Component {
+ stormkit::u32 x;
+ stormkit::u32 y;
+
+ static constexpr Type TYPE = stormkit::hash("PositionComponent");
+ };
+
+#ifdef STORMKIT_BUILD_MODULES
+}
+#endif
diff --git a/examples/entities/gameoflife/src/Constants.mpp b/examples/entities/gameoflife/src/Constants.cppm
similarity index 82%
rename from examples/entities/gameoflife/src/Constants.mpp
rename to examples/entities/gameoflife/src/Constants.cppm
index 1b5a5fad4..ca6ac6433 100644
--- a/examples/entities/gameoflife/src/Constants.mpp
+++ b/examples/entities/gameoflife/src/Constants.cppm
@@ -1,54 +1,54 @@
-// Copyright (C) 2024 Arthur LAURENT
-// This file is subject to the license terms in the LICENSE file
-// found in the top-level of this distribution
-
-#ifdef STORMKIT_BUILD_MODULES
-export module Constants;
-
-import std;
-
-import stormkit.core;
-import stormkit.log;
-import stormkit.gpu;
-
-export {
-#else
- #include
-
- #include
- #include
- #include
-#endif
-
- inline constexpr auto VERTEX_SIZE
- = sizeof(stormkit::math::vec2f) + sizeof(stormkit::vec3f);
- inline constexpr auto WINDOW_TITLE = "StormKit GameOfLife Example";
- inline constexpr auto MESH_VERTEX_BUFFER_SIZE = VERTEX_SIZE * 3;
- inline constexpr auto MESH_VERTEX_BINDING_DESCRIPTIONS = std::array {
- stormkit::gpu::VertexBindingDescription { .binding = 0, .stride = VERTEX_SIZE }
- };
- inline constexpr auto MESH_VERTEX_ATTRIBUTE_DESCRIPTIONS = std::array {
- stormkit::gpu::VertexInputAttributeDescription { .location = 0,
- .binding = 0,
- .format = stormkit::gpu::format::f322,
- .offset = 0 },
- stormkit::gpu::VertexInputAttributeDescription { .location = 1,
- .binding = 0,
- .format = stormkit::gpu::format::f322,
- .offset
- = sizeof(stormkit::math::vec2f) }
- };
-
- inline constexpr auto BOARD_SIZE = 100u;
- inline constexpr auto BOARD_BUFFERING_COUNT = 3u;
- inline constexpr auto REFRESH_BOARD_DELTA = stormkit::Secondf { 1 };
-
- inline constexpr auto SHADER_DATA = stormkit::as_bytes(
-#include
- );
-
- IN_MODULE_LOGGER("StormKit.GameOfLife");
-
-#ifdef STORMKIT_BUILD_MODULES
-}
-#endif
+// Copyright (C) 2024 Arthur LAURENT
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level of this distribution
+
+#ifdef STORMKIT_BUILD_MODULES
+export module Constants;
+
+import std;
+
+import stormkit.core;
+import stormkit.log;
+import stormkit.gpu;
+
+export {
+#else
+ #include
+
+ #include
+ #include
+ #include
+#endif
+
+ inline constexpr auto VERTEX_SIZE
+ = sizeof(stormkit::math::fvec2) + sizeof(stormkit::fvec3);
+ inline constexpr auto WINDOW_TITLE = "StormKit GameOfLife Example";
+ inline constexpr auto MESH_VERTEX_BUFFER_SIZE = VERTEX_SIZE * 3;
+ inline constexpr auto MESH_VERTEX_BINDING_DESCRIPTIONS = array {
+ stormkit::gpu::VertexBindingDescription { .binding = 0, .stride = VERTEX_SIZE }
+ };
+ inline constexpr auto MESH_VERTEX_ATTRIBUTE_DESCRIPTIONS = array {
+ stormkit::gpu::VertexInputAttributeDescription { .location = 0,
+ .binding = 0,
+ .format = stormkit::gpu::format::f322,
+ .offset = 0 },
+ stormkit::gpu::VertexInputAttributeDescription { .location = 1,
+ .binding = 0,
+ .format = stormkit::gpu::format::f322,
+ .offset
+ = sizeof(stormkit::math::fvec2) }
+ };
+
+ inline constexpr auto BOARD_SIZE = 100u;
+ inline constexpr auto BOARD_BUFFERING_COUNT = 3u;
+ inline constexpr auto REFRESH_BOARD_DELTA = stormkit::fsecond { 1 };
+
+ inline constexpr auto SHADER_DATA = stormkit::as_bytes(
+#include
+ );
+
+ IN_MODULE_LOGGER("StormKit.GameOfLife");
+
+#ifdef STORMKIT_BUILD_MODULES
+}
+#endif
diff --git a/examples/entities/gameoflife/src/Renderer.cpp b/examples/entities/gameoflife/src/Renderer.cpp
index 27b849145..cc93afd5c 100644
--- a/examples/entities/gameoflife/src/Renderer.cpp
+++ b/examples/entities/gameoflife/src/Renderer.cpp
@@ -28,7 +28,7 @@ auto Renderer::operator=(Renderer&&) noexcept -> Renderer& = default;
auto Renderer::renderFrame() -> void {
const auto& surface_extent = m_surface->extent();
- const auto surface_extentf = math::ExtentF { surface_extent };
+ const auto surface_extentf = math::fextent2 { surface_extent };
if (m_surface->needRecreate()) {
m_surface->recreate();
@@ -36,17 +36,17 @@ auto Renderer::renderFrame() -> void {
}
const auto viewports = [&] {
- auto v = std::vector {};
+ auto v = dyn_array {};
v.emplace_back(gpu::Viewport {
- .extent = surface_extentf,
- .depth = { 0, 1 }
+ .extent = surface_extentf,
+ .depth = { 0, 1 }
});
return v;
}();
const auto scissors = [&] {
- auto s = std::vector {};
+ auto s = dyn_array {};
s.emplace_back(gpu::Scissor { .extent = surface_extent });
return s;
@@ -88,14 +88,12 @@ auto Renderer::updateBoard(const stormkit::image::Image& board) -> void {
if (m_current_fence) m_current_fence->wait();
- const auto descriptors = into_array(gpu::Descriptor {
- gpu::ImageDescriptor { .type = gpu::DescriptorType::Combined_Image_Sampler,
- .binding = 0,
- .layout = gpu::ImageLayout::Shader_Read_Only_Optimal,
- .image_view
- = makeConstObserver(m_board.image_views[m_board.current_image]),
- .sampler = makeConstObserver(m_board.sampler) }
- });
+ const auto descriptors = into_array_of(gpu::ImageDescriptor {
+ .type = gpu::DescriptorType::Combined_Image_Sampler,
+ .binding = 0,
+ .layout = gpu::ImageLayout::Shader_Read_Only_Optimal,
+ .image_view = makeConstObserver(m_board.image_views[m_board.current_image]),
+ .sampler = makeConstObserver(m_board.sampler) });
m_board.descriptor_set->update(descriptors);
}
@@ -122,9 +120,7 @@ auto Renderer::do_initBaseRenderObjects() -> void {
const auto& physical_device_info = physical_device.info();
- ilog("Using physical device {} ({:#06x})",
- physical_device_info.device_name,
- physical_device_info.device_id);
+ ilog("Using physical device {} ({:#06x})", physical_device_info.device_name, physical_device_info.device_id);
m_device = physical_device.allocateLogicalDevice();
@@ -136,49 +132,46 @@ auto Renderer::do_initBaseRenderObjects() -> void {
auto Renderer::do_initMeshRenderObjects() -> void {
const auto& surface_extent = m_surface->extent();
- const auto surface_extentf = math::ExtentF { surface_extent };
+ const auto surface_extentf = math::fextent2 { surface_extent };
m_board.vertex_shader = m_device->allocateShader(SHADER_DATA, gpu::ShaderStageFlag::Vertex);
m_board.fragment_shader = m_device->allocateShader(SHADER_DATA, gpu::ShaderStageFlag::Fragment);
- const auto description
- = gpu::RenderPassDescription { .attachments = { { .format = m_surface->pixelFormat() } },
- .subpasses
- = { { .bind_point = gpu::PipelineBindPoint::Graphics,
- .attachment_refs = { { .attachment_id = 0u } } } } };
+ const auto description = gpu::RenderPassDescription {
+ .attachments = { { .format = m_surface->pixelFormat() } },
+ .subpasses = { { .bind_point = gpu::PipelineBindPoint::Graphics, .attachment_refs = { { .attachment_id = 0u } } } }
+ };
m_descriptor_set_layout = m_device->allocateDescriptorSetLayout();
- m_descriptor_set_layout->addBinding({ .binding = 0,
- .type = gpu::DescriptorType::Combined_Image_Sampler,
- .stages = gpu::ShaderStageFlag::Fragment,
- .descriptor_count = 1 });
+ m_descriptor_set_layout
+ ->addBinding({ .binding = 0,
+ .type = gpu::DescriptorType::Combined_Image_Sampler,
+ .stages = gpu::ShaderStageFlag::Fragment,
+ .descriptor_count = 1 });
m_descriptor_set_layout->bake();
m_descriptor_pool = m_device->allocateDescriptorPool(
- std::array {
- gpu::DescriptorPool::Size { gpu::DescriptorType::Combined_Image_Sampler, 1 }
+ array {
+ gpu::DescriptorPool::Size { gpu::DescriptorType::Combined_Image_Sampler, 1 }
},
- 1);
+ 1);
m_render_pass = m_device->allocateRenderPass(description);
m_board.pipeline = m_device->allocateRasterPipeline();
const auto state = gpu::RasterPipelineState {
.input_assembly_state = { .topology = gpu::PrimitiveTopology::Triangle_Strip },
- .viewport_state
- = { .viewports = { gpu::Viewport { .position = { 0.f, 0.f },
- .extent = surface_extentf,
- .depth = { 0.f, 1.f } } },
+ .viewport_state = { .viewports = { gpu::Viewport { .position = { 0.f, 0.f },
+ .extent = surface_extentf,
+ .depth = { 0.f, 1.f } } },
.scissors = { gpu::Scissor { .offset = { 0, 0 }, .extent = surface_extent } } },
- .color_blend_state
- = { .attachments = { { .blend_enable = true,
- .src_color_blend_factor = gpu::BlendFactor::Src_Alpha,
- .dst_color_blend_factor = gpu::BlendFactor::One_Minus_Src_Alpha,
- .src_alpha_blend_factor = gpu::BlendFactor::Src_Alpha,
- .dst_alpha_blend_factor = gpu::BlendFactor::One_Minus_Src_Alpha,
- .alpha_blend_operation = gpu::BlendOperation::Add } } },
- .dynamic_state = { { gpu::DynamicState::Viewport, gpu::DynamicState::Scissor } },
- .shader_state
- = { .shaders = makeConstObserverArray(m_board.vertex_shader, m_board.fragment_shader) },
+ .color_blend_state = { .attachments = { { .blend_enable = true,
+ .src_color_blend_factor = gpu::BlendFactor::Src_Alpha,
+ .dst_color_blend_factor = gpu::BlendFactor::One_Minus_Src_Alpha,
+ .src_alpha_blend_factor = gpu::BlendFactor::Src_Alpha,
+ .dst_alpha_blend_factor = gpu::BlendFactor::One_Minus_Src_Alpha,
+ .alpha_blend_operation = gpu::BlendOperation::Add } } },
+ .dynamic_state = { { gpu::DynamicState::Viewport, gpu::DynamicState::Scissor } },
+ .shader_state = { .shaders = makeConstObserverArray(m_board.vertex_shader, m_board.fragment_shader) },
/*.vertex_input_state = { .binding_descriptions =
to_dyn_array(MESH_VERTEX_BINDING_DESCRIPTIONS),
.input_attribute_descriptions =
@@ -193,17 +186,17 @@ auto Renderer::do_initMeshRenderObjects() -> void {
for (auto i : range(BOARD_BUFFERING_COUNT)) {
auto& img = m_board.images.emplace_back(*m_device,
gpu::Image::CreateInfo {
- .extent = { BOARD_SIZE, BOARD_SIZE }
+ .extent = { BOARD_SIZE, BOARD_SIZE }
});
m_board.image_views.emplace_back(img.createView());
}
- m_board.sampler = m_device->allocateSampler(
- gpu::Sampler::Settings { .mag_filter = gpu::Filter::Nearest,
- .min_filter = gpu::Filter::Nearest,
- .address_mode_u = gpu::SamplerAddressMode::Clamp_To_Edge,
- .address_mode_v = gpu::SamplerAddressMode::Clamp_To_Edge });
+ m_board.sampler = m_device->allocateSampler(gpu::Sampler::Settings {
+ .mag_filter = gpu::Filter::Nearest,
+ .min_filter = gpu::Filter::Nearest,
+ .address_mode_u = gpu::SamplerAddressMode::Clamp_To_Edge,
+ .address_mode_v = gpu::SamplerAddressMode::Clamp_To_Edge });
m_board.descriptor_set = m_descriptor_pool->allocateDescriptorSet(*m_descriptor_set_layout);
@@ -212,7 +205,7 @@ auto Renderer::do_initMeshRenderObjects() -> void {
auto Renderer::do_initPerFrameObjects() -> void {
const auto& surface_extent = m_surface->extent();
- const auto surface_extentf = math::ExtentF { surface_extent };
+ const auto surface_extentf = math::fextent2 { surface_extent };
const auto buffering_count = m_surface->bufferingCount();
m_surface_views.clear();
diff --git a/examples/entities/gameoflife/src/Renderer.mpp b/examples/entities/gameoflife/src/Renderer.cppm
similarity index 83%
rename from examples/entities/gameoflife/src/Renderer.mpp
rename to examples/entities/gameoflife/src/Renderer.cppm
index 63f6aa419..a45a6437c 100644
--- a/examples/entities/gameoflife/src/Renderer.mpp
+++ b/examples/entities/gameoflife/src/Renderer.cppm
@@ -1,77 +1,77 @@
-
-
-#ifdef STORMKIT_BUILD_MODULES
-export module Renderer;
-
-import std;
-
-import stormkit.core;
-import stormkit.wsi;
-import stormkit.gpu;
-
-export {
-#else
- #include
-
- #include
- #include
- #include
-#endif
-
- class Renderer {
- public:
- Renderer(const stormkit::wsi::Window& window);
- ~Renderer();
-
- Renderer(const Renderer&) = delete;
- auto operator=(const Renderer&) -> Renderer& = delete;
-
- Renderer(Renderer&&) noexcept;
- auto operator=(Renderer&&) noexcept -> Renderer&;
-
- auto renderFrame() -> void;
-
- auto updateBoard(const stormkit::image::Image& board) -> void;
-
- private:
- auto do_initBaseRenderObjects() -> void;
- auto do_initMeshRenderObjects() -> void;
- auto do_initPerFrameObjects() -> void;
-
- const stormkit::wsi::Window* m_window = nullptr;
-
- std::unique_ptr m_instance;
- std::unique_ptr m_device;
- std::unique_ptr m_surface;
- stormkit::gpu::Fence* m_current_fence = nullptr;
-
- const stormkit::gpu::Queue* m_queue = nullptr;
- std::vector m_surface_views;
-
- std::unique_ptr m_descriptor_set_layout;
- std::unique_ptr m_descriptor_pool;
-
- std::unique_ptr m_render_pass;
-
- struct Board {
- std::vector images;
- std::vector image_views;
- std::unique_ptr sampler;
-
- stormkit::u32 current_image = 0;
-
- std::unique_ptr vertex_shader;
- std::unique_ptr fragment_shader;
-
- std::unique_ptr pipeline;
-
- std::unique_ptr descriptor_set;
- } m_board;
-
- std::vector m_command_buffers;
- std::vector m_framebuffers;
- };
-
-#ifdef STORMKIT_BUILD_MODULES
-}
-#endif
+
+
+#ifdef STORMKIT_BUILD_MODULES
+export module Renderer;
+
+import std;
+
+import stormkit.core;
+import stormkit.wsi;
+import stormkit.gpu;
+
+export {
+#else
+ #include
+
+ #include
+ #include
+ #include
+#endif
+
+ class Renderer {
+ public:
+ Renderer(const stormkit::wsi::Window& window);
+ ~Renderer();
+
+ Renderer(const Renderer&) = delete;
+ auto operator=(const Renderer&) -> Renderer& = delete;
+
+ Renderer(Renderer&&) noexcept;
+ auto operator=(Renderer&&) noexcept -> Renderer&;
+
+ auto renderFrame() -> void;
+
+ auto updateBoard(const stormkit::image::Image& board) -> void;
+
+ private:
+ auto do_initBaseRenderObjects() -> void;
+ auto do_initMeshRenderObjects() -> void;
+ auto do_initPerFrameObjects() -> void;
+
+ const stormkit::wsi::Window* m_window = nullptr;
+
+ std::unique_ptr m_instance;
+ std::unique_ptr m_device;
+ std::unique_ptr m_surface;
+ stormkit::gpu::Fence* m_current_fence = nullptr;
+
+ const stormkit::gpu::Queue* m_queue = nullptr;
+ dyn_array m_surface_views;
+
+ std::unique_ptr m_descriptor_set_layout;
+ std::unique_ptr m_descriptor_pool;
+
+ std::unique_ptr m_render_pass;
+
+ struct Board {
+ dyn_array images;
+ dyn_array image_views;
+ std::unique_ptr sampler;
+
+ stormkit::u32 current_image = 0;
+
+ std::unique_ptr vertex_shader;
+ std::unique_ptr fragment_shader;
+
+ std::unique_ptr pipeline;
+
+ std::unique_ptr descriptor_set;
+ } m_board;
+
+ dyn_array m_command_buffers;
+ dyn_array m_framebuffers;
+ };
+
+#ifdef STORMKIT_BUILD_MODULES
+}
+#endif
diff --git a/examples/entities/gameoflife/src/Systems.cpp b/examples/entities/gameoflife/src/Systems.cpp
index 8f621fd99..4f0fce0d4 100644
--- a/examples/entities/gameoflife/src/Systems.cpp
+++ b/examples/entities/gameoflife/src/Systems.cpp
@@ -24,7 +24,7 @@ UpdateBoardSystem::~UpdateBoardSystem()
UpdateBoardSystem::UpdateBoardSystem(UpdateBoardSystem&&) noexcept = default;
auto UpdateBoardSystem::operator=(UpdateBoardSystem&&) noexcept -> UpdateBoardSystem& = default;
-auto UpdateBoardSystem::update(stormkit::Secondf delta) -> void {
+auto UpdateBoardSystem::update(stormkit::fsecond delta) -> void {
const auto now = Clock::now();
if (m_is_on_edit_mode) [[unlikely]] {
diff --git a/examples/entities/gameoflife/src/Systems.mpp b/examples/entities/gameoflife/src/Systems.cppm
similarity index 85%
rename from examples/entities/gameoflife/src/Systems.mpp
rename to examples/entities/gameoflife/src/Systems.cppm
index 279e12c7e..e7c4d5cf6 100644
--- a/examples/entities/gameoflife/src/Systems.mpp
+++ b/examples/entities/gameoflife/src/Systems.cppm
@@ -1,62 +1,62 @@
-
-
-#ifdef STORMKIT_BUILD_MODULES
-export module Systems;
-
-import std;
-
-import stormkit.core;
-import stormkit.image;
-import stormkit.entities;
-
-import Constants;
-import Renderer;
-
-export {
-#else
- #include
-
- #include
- #include
- #include
-
- #include "Constants.mpp"
- #include "Renderer.mpp"
-#endif
-
- class UpdateBoardSystem final: public stormkit::entities::System {
- public:
- UpdateBoardSystem(stormkit::image::Image& board,
- Renderer& renderer,
- stormkit::entities::EntityManager& manager);
- ~UpdateBoardSystem() override;
-
- UpdateBoardSystem(UpdateBoardSystem&&) noexcept;
- auto operator=(UpdateBoardSystem&&) noexcept -> UpdateBoardSystem&;
-
- auto update(stormkit::Secondf delta) -> void override;
- auto post_update() -> void override;
-
- auto setEditModeEnabled(bool enabled) noexcept { m_is_on_edit_mode = enabled; }
-
- auto incrementDelta(stormkit::Secondf delta) { m_refresh_board_delta += delta; }
-
- private:
- using Clock = std::chrono::high_resolution_clock;
-
- auto on_message_received(const stormkit::entities::Message& message) -> void override {};
-
- bool m_is_on_edit_mode = true;
- stormkit::image::Image* m_board = nullptr;
- Renderer* m_renderer = nullptr;
-
- Clock::time_point m_last_update;
-
- bool m_updated = true;
-
- stormkit::Secondf m_refresh_board_delta = REFRESH_BOARD_DELTA;
- };
-
-#ifdef STORMKIT_BUILD_MODULES
-}
-#endif
+
+
+#ifdef STORMKIT_BUILD_MODULES
+export module Systems;
+
+import std;
+
+import stormkit.core;
+import stormkit.image;
+import stormkit.entities;
+
+import Constants;
+import Renderer;
+
+export {
+#else
+ #include
+
+ #include
+ #include
+ #include
+
+ #include "Constants.mpp"
+ #include "Renderer.mpp"
+#endif
+
+ class UpdateBoardSystem final: public stormkit::entities::System {
+ public:
+ UpdateBoardSystem(stormkit::image::Image& board,
+ Renderer& renderer,
+ stormkit::entities::EntityManager& manager);
+ ~UpdateBoardSystem() override;
+
+ UpdateBoardSystem(UpdateBoardSystem&&) noexcept;
+ auto operator=(UpdateBoardSystem&&) noexcept -> UpdateBoardSystem&;
+
+ auto update(stormkit::fsecond delta) -> void override;
+ auto post_update() -> void override;
+
+ auto setEditModeEnabled(bool enabled) noexcept { m_is_on_edit_mode = enabled; }
+
+ auto incrementDelta(stormkit::fsecond delta) { m_refresh_board_delta += delta; }
+
+ private:
+ using Clock = std::chrono::high_resolution_clock;
+
+ auto on_message_received(const stormkit::entities::Message& message) -> void override {};
+
+ bool m_is_on_edit_mode = true;
+ stormkit::image::Image* m_board = nullptr;
+ Renderer* m_renderer = nullptr;
+
+ Clock::time_point m_last_update;
+
+ bool m_updated = true;
+
+ stormkit::fsecond m_refresh_board_delta = REFRESH_BOARD_DELTA;
+ };
+
+#ifdef STORMKIT_BUILD_MODULES
+}
+#endif
diff --git a/examples/entities/gameoflife/src/main.cpp b/examples/entities/gameoflife/src/main.cpp
index 13eee9992..4be3cea29 100644
--- a/examples/entities/gameoflife/src/main.cpp
+++ b/examples/entities/gameoflife/src/main.cpp
@@ -14,7 +14,7 @@ import App;
#include "App.mpp"
#endif
-auto main([[maybe_unused]] std::span args) -> int {
+auto main([[maybe_unused]] array_view args) -> int {
using namespace stormkit;
setup_signal_handler();
diff --git a/examples/entities/gameoflife/xmake.lua b/examples/entities/gameoflife/xmake.lua
index 9e96e6baf..221d097be 100644
--- a/examples/entities/gameoflife/xmake.lua
+++ b/examples/entities/gameoflife/xmake.lua
@@ -1,29 +1,29 @@
-if has_config("enable_gpu") and has_config("enable_wsi") and has_config("enable-image") then
- target("game_of_life")
- do
- set_kind("binary")
- set_languages("cxxlatest", "clatest")
+-- if has_config("enable_gpu") and has_config("enable_wsi") and has_config("enable-image") then
+-- target("game_of_life")
+-- do
+-- set_kind("binary")
+-- set_languages("cxxlatest", "clatest")
- add_packages("nzsl")
- add_deps("core", "main", "log", "wsi", "gpu", "image")
+-- add_packages("nzsl")
+-- add_deps("core", "main", "log", "wsi", "gpu", "image")
- add_rules("stormkit.utils.nzsl2spv")
+-- add_rules("stormkit.utils.nzsl2spv")
- if is_mode("debug") then
- add_defines("STORMKIT_BUILD_DEBUG")
- add_defines("STORMKIT_ASSERT=1")
- set_suffixname("-d")
- else
- add_defines("STORMKIT_ASSERT=0")
- end
+-- if is_mode("debug") then
+-- add_defines("STORMKIT_BUILD_DEBUG")
+-- add_defines("STORMKIT_ASSERT=1")
+-- set_suffixname("-d")
+-- else
+-- add_defines("STORMKIT_ASSERT=0")
+-- end
- add_files("src/*.cpp")
- add_files("src/*.mpp")
- add_files("shaders/*.nzsl")
- if is_plat("windows") then add_files("win32/*.manifest") end
+-- add_files("src/*.cpp")
+-- add_files("src/*.cppm")
+-- add_files("shaders/*.nzsl")
+-- if is_plat("windows") then add_files("win32/*.manifest") end
- add_rules("platform.windows.subsystem.windows")
+-- add_rules("platform.windows.subsystem.windows")
- set_group("examples/stormkit-entities")
- end
-end
+-- set_group("examples/stormkit-entities")
+-- end
+-- end
diff --git a/src/wsi/linux/mouse.mpp b/examples/entities/xmake.lua
similarity index 100%
rename from src/wsi/linux/mouse.mpp
rename to examples/entities/xmake.lua
diff --git a/examples/gpu/common/app.cppm b/examples/gpu/common/app.cppm
new file mode 100644
index 000000000..9fe4d8c3c
--- /dev/null
+++ b/examples/gpu/common/app.cppm
@@ -0,0 +1,150 @@
+// Copyright (C) 2024 Arthur LAURENT
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level of this distribution
+
+module;
+
+#include
+#include
+
+#include
+
+#include
+
+export module gpu_app;
+
+import std;
+import stormkit;
+
+export import :logger;
+
+using namespace stormkit;
+
+namespace stdr = std::ranges;
+namespace stdv = std::views;
+
+NAMED_LOGGER(vulkan_logger, "vulkan")
+
+extern "C" auto debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT,
+ const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
+ void*) noexcept -> u32 {
+ EXPECTS(callback_data);
+ auto message = std::format("{}", callback_data->pMessage);
+
+ if (check_flag_bit(severity, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)) vulkan_logger.ilog("{}", message);
+ else if (check_flag_bit(severity, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT))
+ vulkan_logger.dlog("{}", message);
+ else if (check_flag_bit(severity, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT))
+ vulkan_logger.elog("{}", message);
+ else if (check_flag_bit(severity, VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT))
+ vulkan_logger.wlog("{}", message);
+
+ return 0;
+}
+
+static constexpr auto ENABLE_VALIDATION_LAYERS = false;
+
+export namespace base {
+ class Application {
+ public:
+ auto run(this auto& self, array_view args) {
+ wsi::parse_args(args);
+ log::parse_args(args);
+
+ const auto example_name = self.example_name();
+
+ auto logger_singleton = log::Logger::create_logger_instance();
+
+ self.init_window(example_name);
+ self.init_gpu(example_name);
+
+ self.init_example();
+
+ self.m_window->event_loop([&self] noexcept { self.run_example(); });
+
+ TryDiscardAssert(self.m_raster_queue->wait_idle(), "Failed to wait for raster queue");
+ self.m_device->wait_idle();
+
+ if constexpr (requires { self.deinit(); }) self.deinit();
+ }
+
+ protected:
+ DeferInit m_window;
+ DeferInit m_instance;
+ DeferInit m_debug_callback;
+ DeferInit m_surface;
+ DeferInit m_physical_device;
+ DeferInit m_device;
+ DeferInit m_swapchain;
+ DeferInit m_raster_queue;
+ DeferInit m_command_pool;
+
+ private:
+ auto init_window(string_view example_name) noexcept -> void {
+ m_window = wsi::Window::open(std::format("Stormkit GPU {} example", example_name),
+ { 800_u32, 600_u32 },
+ wsi::WindowFlag::DEFAULT | wsi::WindowFlag::EXTERNAL_CONTEXT);
+ m_window->on([this](u8 /*id*/, wsi::Key key, char /*c*/) mutable noexcept {
+ if (key == wsi::Key::ESCAPE) m_window->close();
+ });
+ }
+
+ auto init_gpu(string_view example_name) noexcept -> void {
+ // initialize gpu backend (vulkan or webgpu depending the platform)
+ TryDiscardAssert(gpu::initialize_backend(), "Failed to initialize gpu backend");
+
+ // create gpu instance and attach surface to window
+ m_instance = TryAssert(gpu::Instance::create({ .application_name = string { example_name },
+ .enable_validation_layers = ENABLE_VALIDATION_LAYERS }),
+ "Failed to initialize gpu instance");
+
+ if (ENABLE_VALIDATION_LAYERS) {
+ m_debug_callback = TryAssert(gpu::DebugCallback::create(m_instance, { .messenger_closure = debug_callback }),
+ "Failed to initialize gpu instance");
+ }
+
+ m_surface = TryAssert(gpu::Surface::create_from_window(m_instance, m_window),
+ "Failed to initialize window gpu surface");
+
+ // pick the best physical device
+ const auto& physical_devices = m_instance->physical_devices();
+ if (stdr::empty(physical_devices)) {
+ elog("No render physical device found!");
+ return;
+ }
+ ilog("Physical devices: {}", physical_devices);
+
+ m_physical_device = physical_devices.front();
+ auto score = gpu::score_physical_device(*m_physical_device);
+ for (auto i : range(1_u32, stdr::size(physical_devices))) {
+ const auto& d = physical_devices[i];
+ const auto d_score = gpu::score_physical_device(d);
+ if (d_score > score) {
+ m_physical_device = d;
+ score = d_score;
+ }
+ }
+
+ ilog("Picked gpu: {}", *m_physical_device);
+
+ // create gpu device
+ m_device = TryAssert(gpu::Device::create(m_physical_device, {}), "Failed to initialize gpu device");
+
+ // create swapchain
+ const auto window_extent = m_window->extent();
+ m_swapchain = TryAssert(gpu::SwapChain::create(m_device, { gpu::as_view(m_surface), window_extent }),
+ "Failed to create swapchain");
+
+ const auto queue_entries = m_device->queue_entries();
+ const auto it = stdr::find_if(queue_entries, gpu::monadic::find_queue());
+ ensures(it != stdr::cend(queue_entries), "No raster queue found!");
+
+ m_raster_queue = gpu::Queue::create(m_device, *it);
+
+ m_command_pool = TryAssert(gpu::CommandPool::create(m_device, { .queue = m_raster_queue }),
+ "Failed to create command pool "
+ "command pool");
+ }
+ };
+} // namespace base
diff --git a/examples/gpu/common/app.mpp b/examples/gpu/common/app.mpp
deleted file mode 100644
index caec4ac2a..000000000
--- a/examples/gpu/common/app.mpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (C) 2024 Arthur LAURENT
-// This file is subject to the license terms in the LICENSE file
-// found in the top-level of this distribution
-
-export module gpu_app;
-
-import std;
-import stormkit;
-
-using namespace stormkit;
-
-namespace stdr = std::ranges;
-namespace stdv = std::views;
-
-export namespace base {
- class Application {
- public:
- auto run(this auto& self, std::span args) {
- const auto example_name = self.example_name();
-
- auto logger_singleton = log::Logger::create_logger_instance();
-
- wsi::parse_args(args);
-
- self.init_window(example_name);
- self.init_gpu(example_name);
-
- self.init_example();
-
- self.m_window->event_loop([&self] noexcept { self.run_example(); });
-
- self.m_raster_queue->wait_idle();
- self.m_device->wait_idle();
-
- if constexpr (requires { self.deinit(); }) self.deinit();
- }
-
- protected:
- DeferInit m_window;
- DeferInit m_instance;
- DeferInit m_surface;
- OptionalRef m_physical_device;
- DeferInit m_device;
- DeferInit m_swapchain;
- DeferInit m_raster_queue;
- DeferInit m_command_pool;
-
- private:
- auto init_window(std::string_view example_name) noexcept -> void {
- m_window = wsi::Window::open(std::format("Stormkit GPU {} example", example_name),
- { 800_u32, 600_u32 },
- wsi::WindowFlag::DEFAULT
- | wsi::WindowFlag::EXTERNAL_CONTEXT);
- m_window->on([this](u8 /*id*/,
- wsi::Key key,
- char /*c*/) mutable noexcept {
- if (key == wsi::Key::ESCAPE) m_window->close();
- });
- }
-
- auto init_gpu(std::string_view example_name) noexcept -> void {
- // initialize gpu backend (vulkan or webgpu depending the platform)
- *gpu::initialize_backend()
- .transform_error(monadic::assert("Failed to initialize gpu backend"));
-
- // create gpu instance and attach surface to window
- m_instance = gpu::Instance::create(std::string { example_name })
- .transform_error(monadic::assert("Failed to initialize gpu instance"))
- .value();
-
- m_surface = gpu::Surface::create_from_window(m_instance, m_window)
- .transform_error(monadic::
- assert("Failed to initialize window gpu surface"))
- .value();
- // pick the best physical device
- const auto& physical_devices = m_instance->physical_devices();
- if (stdr::empty(physical_devices)) {
- log::Logger::elog("No render physical device found!");
- return;
- }
- log::Logger::ilog("Physical devices: {}", physical_devices);
-
- m_physical_device = as_opt_ref(physical_devices.front());
- auto score = gpu::score_physical_device(*m_physical_device);
- for (auto i = 1u; i < stdr::size(physical_devices); ++i) {
- const auto& d = physical_devices[i];
- const auto d_score = gpu::score_physical_device(d);
- if (d_score > score) {
- m_physical_device = as_opt_ref(d);
- score = d_score;
- }
- }
-
- log::Logger::ilog("Picked gpu: {}", *m_physical_device);
-
- // create gpu device
- m_device = gpu::Device::create(*m_physical_device, m_instance)
- .transform_error(monadic::assert("Failed to initialize gpu device"))
- .value();
-
- // create swapchain
- const auto window_extent = m_window->extent();
- m_swapchain = gpu::SwapChain::create(m_device, m_surface, window_extent)
- .transform_error(monadic::assert("Failed to create swapchain"))
- .value();
-
- m_raster_queue = gpu::Queue::create(m_device, m_device->raster_queue_entry());
-
- m_command_pool = gpu::CommandPool::create(m_device)
- .transform_error(monadic::assert("Failed to create raster queue "
- "command pool"))
- .value();
- }
- };
-} // namespace base
diff --git a/examples/gpu/imgui/iOS/Info.plist b/examples/gpu/imgui/iOS/Info.plist
deleted file mode 100644
index a62a3592d..000000000
--- a/examples/gpu/imgui/iOS/Info.plist
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
-
-
diff --git a/examples/gpu/imgui/iOS/LaunchScreen.storyboard b/examples/gpu/imgui/iOS/LaunchScreen.storyboard
deleted file mode 100644
index 436820912..000000000
--- a/examples/gpu/imgui/iOS/LaunchScreen.storyboard
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/gpu/imgui/macOS/Info.plist b/examples/gpu/imgui/macOS/Info.plist
deleted file mode 100644
index f68f66070..000000000
--- a/examples/gpu/imgui/macOS/Info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
-
-
-
diff --git a/examples/gpu/imgui/src/logger.cppm b/examples/gpu/imgui/src/logger.cppm
new file mode 100644
index 000000000..ca004b433
--- /dev/null
+++ b/examples/gpu/imgui/src/logger.cppm
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 Arthur LAURENT
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level of this distribution
+
+module;
+
+#include
+
+export module gpu_app:logger;
+
+import std;
+
+import stormkit.log;
+
+export { IN_MODULE_LOGGER("Imgui"); }
diff --git a/examples/gpu/imgui/src/main.cpp b/examples/gpu/imgui/src/main.cpp
index ba751c442..018321dc2 100644
--- a/examples/gpu/imgui/src/main.cpp
+++ b/examples/gpu/imgui/src/main.cpp
@@ -7,6 +7,7 @@ import std;
import stormkit;
import gpu_app;
+#include
#include
#include
#include
@@ -16,8 +17,6 @@ import gpu_app;
#include
#undef assert
-LOGGER("stormkit.examples.gpu.imgui");
-
namespace stdr = std::ranges;
namespace stdfs = std::filesystem;
@@ -31,13 +30,17 @@ struct SubmissionResource {
};
struct SwapchainImageResource {
- Ref image;
- gpu::ImageView view;
- gpu::FrameBuffer framebuffer;
- gpu::Semaphore render_finished;
+ gpu::view::Image image;
+ gpu::ImageView view;
+ gpu::Semaphore render_finished;
};
-static constexpr auto BUFFERING_COUNT = 2;
+namespace {
+ constexpr auto BUFFERING_COUNT = 2_u32;
+ constexpr auto POOL_SIZES = array {
+ gpu::DescriptorPool::Size { .type = gpu::DescriptorType::COMBINED_IMAGE_SAMPLER, .descriptor_count = BUFFERING_COUNT }
+ };
+} // namespace
class Application: public base::Application {
public:
@@ -48,44 +51,23 @@ class Application: public base::Application {
auto init_resources() -> void {
// initialilze descriptor pool
- static constexpr auto POOL_SIZES = std::array {
- gpu::DescriptorPool::Size { .type = gpu::DescriptorType::COMBINED_IMAGE_SAMPLER,
- .descriptor_count = BUFFERING_COUNT }
- };
- m_descriptor_pool = gpu::DescriptorPool::create(m_device, POOL_SIZES, BUFFERING_COUNT)
- .transform_error(monadic::assert("Failed to create descriptor pool"))
- .value();
-
- // initialize render pass
- m_render_pass
- = gpu::RenderPass::
- create(m_device,
- { .attachments = { { .format = m_swapchain->pixel_format() } },
- .subpasses = { { .bind_point = gpu::PipelineBindPoint::GRAPHICS,
- .color_attachment_refs = { { .attachment_id = 0u } } } } })
- .transform_error(monadic::assert("Failed to create render pass"))
- .value();
-
- const auto window_extent = m_window->extent();
+ m_descriptor_pool = TryAssert(gpu::DescriptorPool::create(m_device, POOL_SIZES, BUFFERING_COUNT),
+ "Failed to create descriptor pool!");
// create present engine resources
- m_submission_resources = init_by>([&](auto& out) noexcept {
+ m_submission_resources = init_by>([&](auto& out) noexcept {
out.reserve(BUFFERING_COUNT);
for (auto _ : range(BUFFERING_COUNT)) {
out.push_back({
- .in_flight = gpu::Fence::create_signaled(m_device)
- .transform_error(monadic::
- assert("Failed to create swapchain image "
- "in flight fence"))
- .value(),
- .image_available = gpu::Semaphore::create(m_device)
- .transform_error(monadic::assert("Failed to create "
- "present wait semaphore"))
- .value(),
- .render_cmb = m_command_pool->create_command_buffer()
- .transform_error(monadic::assert("Failed to create transition "
- "command buffers"))
- .value(),
+ .in_flight = TryAssert(gpu::Fence::create_signaled(m_device),
+ "Failed to create swapchain image "
+ "in flight fence!"),
+ .image_available = TryAssert(gpu::Semaphore::create(m_device),
+ "Failed to create "
+ "present wait semaphore!"),
+ .render_cmb = TryAssert(m_command_pool->create_command_buffer(),
+ "Failed to create transition "
+ "command buffers!"),
});
}
});
@@ -93,64 +75,43 @@ class Application: public base::Application {
// transition swapchain image to present image
const auto& images = m_swapchain->images();
- const auto image_count = stdr::size(images);
- auto transition_cmbs
- = m_command_pool->create_command_buffers(image_count)
- .transform_error(monadic::assert("Failed to create transition command buffers"))
- .value();
+ const auto image_count = stdr::size(images);
+ auto transition_cmbs = TryAssert(m_command_pool->create_command_buffers(image_count),
+ "Failed to create transition command buffers!");
m_image_resources.reserve(stdr::size(images));
auto image_index = 0u;
for (const auto& swap_image : images) {
- auto view = gpu::ImageView::create(m_device, swap_image)
- .transform_error(core::monadic::
- assert("Failed to create swapchain image view"))
- .value();
- auto framebuffer = m_render_pass
- ->create_frame_buffer(m_device, window_extent, to_refs(view))
- .transform_error(core::monadic::assert(
- std::format("Failed to create framebuffer for image {}",
- image_index)))
- .value();
-
- m_image_resources.push_back({
- .image = as_ref(swap_image),
- .view = std::move(view),
- .framebuffer = std::move(framebuffer),
- .render_finished = gpu::Semaphore::create(m_device)
- .transform_error(core::monadic::assert("Failed to create render "
- "signal semaphore"))
- .value(),
- });
+ auto view = TryAssert(gpu::ImageView::create(m_device, { swap_image }), "Failed to create swapchain image view!");
+
+ m_image_resources.push_back({ .image = swap_image,
+ .view = std::move(view),
+ .render_finished = TryAssert(gpu::Semaphore::create(m_device),
+ "Failed to create render "
+ "signal semaphore!") });
auto& transition_cmb = transition_cmbs[image_index];
- *transition_cmb.begin(true)
- .transform_error(monadic::
- assert("Failed to begin texture transition command buffer"))
- .value()
- ->begin_debug_region(std::format("transition image {}", image_index))
- .transition_image_layout(swap_image,
- gpu::ImageLayout::UNDEFINED,
- gpu::ImageLayout::PRESENT_SRC)
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to begin texture transition command "
- "buffer"));
+ TryDiscardAssert((transition_cmb.record([&](auto cmb) noexcept {
+ cmb.begin_debug_region(std::format("Transition image {}", image_index))
+ .transition_image_layout(swap_image,
+ gpu::ImageLayout::UNDEFINED,
+ gpu::ImageLayout::PRESENT_SRC)
+ .end_debug_region();
+ })),
+ std::format("Failed to record transition cmb {}!", image_index));
++image_index;
}
- const auto fence = gpu::Fence::create(m_device)
- .transform_error(monadic::assert("Failed to create transition fence"))
- .value();
- const auto cmbs = to_refs(transition_cmbs);
+ const auto fence = TryAssert(gpu::Fence::create(m_device), "Failed to create transition fence!");
- m_raster_queue->submit({ .command_buffers = cmbs }, as_ref(fence))
- .transform_error(monadic::assert("Failed to submit texture transition command buffers"))
- .value();
+ const auto cmbs = to_views(transition_cmbs);
+
+ TryAssert(m_raster_queue->submit({ .command_buffers = cmbs }, fence),
+ "Failed to submit texture transition command buffers!");
// wait for transition to be done
- fence.wait().transform_error(monadic::assert());
+ TryAssert(fence.wait(), "");
}
auto init_imgui() -> void {
@@ -160,70 +121,81 @@ class Application: public base::Application {
io.DisplaySize.x = m_window->extent().to().width;
io.DisplaySize.y = m_window->extent().to().height;
+ const auto format = gpu::vk::to_vk(m_swapchain->pixel_format());
/*const*/ auto init_info = ImGui_ImplVulkan_InitInfo {
- .ApiVersion = VK_API_VERSION_1_1,
+ .ApiVersion = VK_API_VERSION_1_3,
.Instance = m_instance->native_handle(),
.PhysicalDevice = m_physical_device->native_handle(),
.Device = m_device->native_handle(),
.QueueFamily = 0,
.Queue = m_raster_queue->native_handle(),
.DescriptorPool = m_descriptor_pool->native_handle(),
- .RenderPass = m_render_pass->native_handle(),
+ .DescriptorPoolSize = 0,
.MinImageCount = BUFFERING_COUNT,
.ImageCount = BUFFERING_COUNT,
- .MSAASamples = VK_SAMPLE_COUNT_1_BIT,
.PipelineCache = nullptr,
- .Subpass = 0,
- .DescriptorPoolSize = 0,
- .UseDynamicRendering = false,
- .PipelineRenderingCreateInfo = {},
+ .PipelineInfoMain = {
+ .RenderPass = nullptr,
+ .Subpass = {},
+ .MSAASamples = {},
+ .PipelineRenderingCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
+ .pNext = nullptr,
+ .viewMask = 0,
+ .colorAttachmentCount = 1,
+ .pColorAttachmentFormats = &format,
+ .depthAttachmentFormat = {},
+ .stencilAttachmentFormat = {}
+
+ },
+ },
+ .UseDynamicRendering = true,
.Allocator = nullptr,
.CheckVkResultFn =
[](auto result) static noexcept {
- if (result != VK_SUCCESS) elog("{}", gpu::from_vk(result));
+ if (result != VK_SUCCESS) elog("{}", gpu::vk::from_vk(result));
},
.MinAllocationSize = 1024 * 1024,
+ .CustomShaderVertCreateInfo = {},
+ .CustomShaderFragCreateInfo = {},
};
- ImGui_ImplVulkan_LoadFunctions(VK_API_VERSION_1_1, gpu::imgui_vk_loader, &*m_device);
+ ImGui_ImplVulkan_LoadFunctions(VK_API_VERSION_1_1, gpu::vk::imgui_vk_loader, &*m_device);
ImGui_ImplVulkan_Init(&init_info);
- m_window
- ->on(wsi::KeyDownEventFunc { [this,
- &io](u8 /*id*/, wsi::Key key, char c) mutable noexcept {
- if (key == wsi::Key::ESCAPE) m_window->close();
- io.AddInputCharactersUTF8(&c);
- } },
- wsi::MouseMovedEventFunc {
- [&io](u8 /*id*/, const math::vec2i& position) mutable noexcept {
- const auto _position = position.to();
-
- io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
- io.AddMousePosEvent(_position.x, _position.y);
- } },
- wsi::MouseButtonDownEventFunc {
- [&io](u8 /*id*/, wsi::MouseButton button, const math::vec2i&) mutable noexcept {
- auto mouse_button = -1;
- if (button == wsi::MouseButton::LEFT) mouse_button = 0;
- if (button == wsi::MouseButton::RIGHT) mouse_button = 1;
- if (button == wsi::MouseButton::MIDDLE) mouse_button = 2;
- if (button == wsi::MouseButton::BUTTON_1) mouse_button = 3;
- if (button == wsi::MouseButton::BUTTON_2) mouse_button = 4;
- if (mouse_button == -1) return;
- io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
- io.AddMouseButtonEvent(mouse_button, true);
- } },
- wsi::MouseButtonUpEventFunc {
- [&io](u8 /*id*/, wsi::MouseButton button, const math::vec2i&) mutable noexcept {
- auto mouse_button = -1;
- if (button == wsi::MouseButton::LEFT) mouse_button = 0;
- if (button == wsi::MouseButton::RIGHT) mouse_button = 1;
- if (button == wsi::MouseButton::MIDDLE) mouse_button = 2;
- if (button == wsi::MouseButton::BUTTON_1) mouse_button = 3;
- if (button == wsi::MouseButton::BUTTON_2) mouse_button = 4;
- if (mouse_button == -1) return;
- io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
- io.AddMouseButtonEvent(mouse_button, false);
- } });
+ m_window->on(wsi::KeyDownEventFunc { [this, &io](u8 /*id*/, wsi::Key key, char c) mutable noexcept {
+ if (key == wsi::Key::ESCAPE) m_window->close();
+ io.AddInputCharactersUTF8(&c);
+ } },
+ wsi::MouseMovedEventFunc { [&io](u8 /*id*/, const math::ivec2& position) mutable noexcept {
+ const auto _position = position.to();
+
+ io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
+ io.AddMousePosEvent(_position.x, _position.y);
+ } },
+ wsi::MouseButtonDownEventFunc {
+ [&io](u8 /*id*/, wsi::MouseButton button, const math::ivec2&) mutable noexcept {
+ auto mouse_button = -1;
+ if (button == wsi::MouseButton::LEFT) mouse_button = 0;
+ if (button == wsi::MouseButton::RIGHT) mouse_button = 1;
+ if (button == wsi::MouseButton::MIDDLE) mouse_button = 2;
+ if (button == wsi::MouseButton::BUTTON_1) mouse_button = 3;
+ if (button == wsi::MouseButton::BUTTON_2) mouse_button = 4;
+ if (mouse_button == -1) return;
+ io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
+ io.AddMouseButtonEvent(mouse_button, true);
+ } },
+ wsi::MouseButtonUpEventFunc {
+ [&io](u8 /*id*/, wsi::MouseButton button, const math::ivec2&) mutable noexcept {
+ auto mouse_button = -1;
+ if (button == wsi::MouseButton::LEFT) mouse_button = 0;
+ if (button == wsi::MouseButton::RIGHT) mouse_button = 1;
+ if (button == wsi::MouseButton::MIDDLE) mouse_button = 2;
+ if (button == wsi::MouseButton::BUTTON_1) mouse_button = 3;
+ if (button == wsi::MouseButton::BUTTON_2) mouse_button = 4;
+ if (mouse_button == -1) return;
+ io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
+ io.AddMouseButtonEvent(mouse_button, false);
+ } });
}
auto run_example() {
@@ -240,64 +212,55 @@ class Application: public base::Application {
const auto& wait = submission_resource.image_available;
auto& in_flight = submission_resource.in_flight;
- const auto acquire_next_image = bind_front(&gpu::SwapChain::acquire_next_image,
- &*m_swapchain,
- 100ms,
- std::cref(wait));
- const auto extract_index = [](auto&& _result) static noexcept {
- auto&& [result, _image_index] = _result;
- return _image_index;
- };
+ TryAssert(in_flight.wait(), "Failed to wait in_flight fence!");
+ TryAssert(in_flight.reset(), "Failed to reset in_flight fence!");
- const auto image_index
- = in_flight.wait()
- .transform([&in_flight](auto&&) mutable noexcept { in_flight.reset(); })
- .and_then(acquire_next_image)
- .transform(extract_index)
- .transform_error(monadic::assert("Failed to acquire next swapchain image"))
- .value();
+ const auto&& [_, image_index] = TryAssert(m_swapchain->acquire_next_image(100ms, wait),
+ "Failed to acquire next swapchain image!");
const auto& swapchain_image_resource = m_image_resources[image_index];
- const auto& framebuffer = swapchain_image_resource.framebuffer;
const auto& signal = swapchain_image_resource.render_finished;
- static constexpr auto PIPELINE_FLAGS = std::array {
- gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT
+ static constexpr auto PIPELINE_FLAGS = array { gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT };
+
+ const auto window_extent = m_window->extent().to();
+ const auto rendering_info = gpu::RenderingInfo {
+ .render_area = { .x = 0, .y = 0, .width = window_extent.width, .height = window_extent.height },
+ .color_attachments = { { .image_view = swapchain_image_resource.view,
+ .layout = gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ .clear_value = gpu::ClearColor { .color = colors::SILVER } } }
};
// render in it
auto& render_cmb = submission_resource.render_cmb;
- render_cmb.reset()
- .transform_error(monadic::assert("Failed to reset render command buffer"))
- .value()
- ->begin()
- .transform_error(monadic::assert("Failed to begin render command buffer"))
- .value()
- ->begin_debug_region("Render imgui")
- .begin_render_pass(m_render_pass, framebuffer);
-
- ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), render_cmb.native_handle());
-
- *render_cmb.end_render_pass()
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to end render command buffer"))
- .value()
- ->submit(m_raster_queue,
- as_refs(wait),
- PIPELINE_FLAGS,
- as_refs(signal),
- as_ref(in_flight))
- .transform_error(monadic::assert("Failed to submit render command buffer"));
+ TryAssert(render_cmb.reset(), std::format("Failed to reset render cmb {}!", image_index));
+ TryDiscardAssert((render_cmb.record([&](auto cmb) noexcept {
+ cmb
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::PRESENT_SRC,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL)
+ .begin_debug_region("Render imgui")
+ .begin_rendering(rendering_info);
+
+ ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmb);
+
+ cmb
+ .end_rendering() //
+ .end_debug_region()
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ gpu::ImageLayout::PRESENT_SRC);
+ })),
+ std::format("Failed to record render cmb {}!", image_index));
+
+ TryDiscardAssert(render_cmb.submit(m_raster_queue, gpu::as_views(wait), PIPELINE_FLAGS, gpu::as_views(signal), in_flight),
+ "Failed to submit render command buffer");
// present it
- auto update_current_frame = [this](auto&&) mutable noexcept {
- if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
- };
+ TryDiscardAssert(m_raster_queue->present(gpu::as_views(m_swapchain), gpu::as_views(signal), as_view(image_index)),
+ "Failed to present swapchain image");
- m_raster_queue->present(as_refs(m_swapchain), as_refs(signal), as_view(image_index))
- .transform(update_current_frame)
- .transform_error(monadic::assert("Failed to present swapchain image"));
+ if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
}
auto deinit() {
@@ -305,17 +268,16 @@ class Application: public base::Application {
ImGui::DestroyContext();
}
- constexpr auto example_name() const noexcept -> std::string_view { return "Imgui"; }
+ constexpr auto example_name() const noexcept -> string_view { return "Imgui"; }
private:
- DeferInit m_render_pass;
- DeferInit m_descriptor_pool;
- std::vector m_submission_resources;
- std::vector m_image_resources;
- usize m_current_frame = 0_usize;
+ DeferInit m_descriptor_pool;
+ dyn_array m_submission_resources;
+ dyn_array m_image_resources;
+ usize m_current_frame = 0_usize;
};
-auto main(std::span args) -> int {
+auto main(array_view args) -> int {
auto app = Application {};
app.run(args);
return 0;
diff --git a/examples/gpu/imgui/win32/manifest.manifest b/examples/gpu/imgui/win32/manifest.manifest
deleted file mode 100644
index 4a9b5f6a6..000000000
--- a/examples/gpu/imgui/win32/manifest.manifest
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- true
- PerMonitorV2
-
-
-
diff --git a/examples/gpu/imgui/xmake.lua b/examples/gpu/imgui/xmake.lua
index b7cfa0a5b..7eca49909 100644
--- a/examples/gpu/imgui/xmake.lua
+++ b/examples/gpu/imgui/xmake.lua
@@ -3,31 +3,21 @@ add_requires("imgui", {
system = false,
debug = true,
})
-target("imgui", function()
- set_kind("binary")
- set_languages("cxxlatest", "clatest")
-
- add_rules("stormkit.flags")
- -- add_rules("platform.windows.subsystem.windows")
- add_rules("platform.windows.subsystem.console")
- add_deps("core", "main", "log", "wsi", "gpu", "stormkit")
+target("imgui", function()
+ add_rules("stormkit::example")
- add_packages("imgui")
+ add_files("src/*.cpp", "src/*.cppm", "../common/app.cppm")
- if is_mode("debug") then
- add_defines("STORMKIT_BUILD_DEBUG")
- add_defines("STORMKIT_ASSERT=1")
- set_suffixname("-d")
- else
- add_defines("STORMKIT_ASSERT=0")
+ if get_config("devmode") then
+ add_defines(format('RESOURCE_DIR="%s"', path.unix(path.join(os.projectdir(), "gpu/imgui"))))
+ add_defines(format('SHADER_DIR="%s"', path.unix("$(builddir)/shader")))
end
-
- add_files("../common/app.mpp")
- add_files("src/*.cpp")
- if is_plat("windows") then add_files("win32/*.manifest") end
+ add_embeddirs("$(builddir)/shaders")
if get_config("devmode") then set_rundir("$(projectdir)") end
+ add_packages("imgui", "volk", "vulkan-headers")
+
set_group("examples/stormkit-gpu")
end)
diff --git a/examples/gpu/textured_cube/iOS/Info.plist b/examples/gpu/textured_cube/iOS/Info.plist
deleted file mode 100644
index a62a3592d..000000000
--- a/examples/gpu/textured_cube/iOS/Info.plist
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
-
-
diff --git a/examples/gpu/textured_cube/iOS/LaunchScreen.storyboard b/examples/gpu/textured_cube/iOS/LaunchScreen.storyboard
deleted file mode 100644
index 436820912..000000000
--- a/examples/gpu/textured_cube/iOS/LaunchScreen.storyboard
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/gpu/textured_cube/macOS/Info.plist b/examples/gpu/textured_cube/macOS/Info.plist
deleted file mode 100644
index f68f66070..000000000
--- a/examples/gpu/textured_cube/macOS/Info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
-
-
-
diff --git a/examples/gpu/textured_cube/shaders/textured_cube.nzsl b/examples/gpu/textured_cube/shaders/textured_cube.nzsl
index 8580764db..0c3dd2ac1 100644
--- a/examples/gpu/textured_cube/shaders/textured_cube.nzsl
+++ b/examples/gpu/textured_cube/shaders/textured_cube.nzsl
@@ -29,7 +29,7 @@ external {
}
[entry(vert)]
-fn main(input: VertIn) -> VertOut {
+fn vert_main(input: VertIn) -> VertOut {
let output: VertOut;
output.position = viewer.proj * viewer.view * viewer.model * vec4[f32](input.position, 1.);
@@ -49,7 +49,7 @@ external {
}
[entry(frag)]
-fn main(input: VertOut) -> FragOut {
+fn frag_main(input: VertOut) -> FragOut {
let output: FragOut;
output.color = texture.Sample(input.uv);
diff --git a/examples/gpu/textured_cube/src/logger.cppm b/examples/gpu/textured_cube/src/logger.cppm
new file mode 100644
index 000000000..30e39ca8f
--- /dev/null
+++ b/examples/gpu/textured_cube/src/logger.cppm
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 Arthur LAURENT
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level of this distribution
+
+module;
+
+#include
+
+export module gpu_app:logger;
+
+import std;
+
+import stormkit.log;
+
+export { IN_MODULE_LOGGER("Textured Cube"); }
diff --git a/examples/gpu/textured_cube/src/main.cpp b/examples/gpu/textured_cube/src/main.cpp
index 7b2566504..1f868809e 100644
--- a/examples/gpu/textured_cube/src/main.cpp
+++ b/examples/gpu/textured_cube/src/main.cpp
@@ -10,21 +10,21 @@ import stormkit;
import gpu_app;
#include
+#include
#include
#include
-LOGGER("stormkit.examples.gpu.textured_cube");
-
#ifndef SHADER_DIR
- #define SHADER_DIR "../share/shaders"
+static constexpr auto SHADER_DIR "../share/stormkit/shaders/"
#endif
-#ifndef TEXTURE_DIR
- #define TEXTURE_DIR "../share/textures"
+#ifndef RESOURCE_DIR
+ static constexpr auto RESOURCE_DIR "../share/stormkit/"
#endif
-namespace stdc = std::chrono;
-namespace stdr = std::ranges;
+ namespace stdc = std::chrono;
+namespace stdr = std::ranges;
+namespace stdfs = std::filesystem;
using clock = stdc::high_resolution_clock;
@@ -41,151 +41,145 @@ struct SubmissionResource {
};
struct SwapchainImageResource {
- Ref image;
- gpu::ImageView view;
- gpu::Image depth_image;
- gpu::ImageView depth_view;
- gpu::FrameBuffer framebuffer;
- gpu::Semaphore render_finished;
+ gpu::view::Image image;
+ gpu::ImageView view;
+ gpu::Image depth_image;
+ gpu::ImageView depth_view;
+ gpu::Semaphore render_finished;
};
struct Vertex {
- math::vec3f position;
- math::vec2f uv;
-
- static constexpr auto attribute_descriptions() noexcept
- -> std::array {
- return {
- gpu::VertexInputAttributeDescription {
- 0, 0,
- gpu::PixelFormat::RGB32F,
- offsetof(Vertex, position) },
- gpu::VertexInputAttributeDescription {
- 1, 0,
- gpu::PixelFormat::RG32F,
- offsetof(Vertex, uv) },
- };
+ math::fvec3 position;
+ math::fvec2 uv;
+
+ static constexpr auto attribute_descriptions() noexcept -> array {
+ return to_array({
+ { .location = 0, .binding = 0, .format = gpu::PixelFormat::RGB32F, .offset = offsetof(Vertex, position) },
+ { .location = 1, .binding = 0, .format = gpu::PixelFormat::RG32F, .offset = offsetof(Vertex, uv) }
+ });
}
static constexpr auto binding_description() noexcept -> gpu::VertexBindingDescription {
- return { 0, sizeof(Vertex), gpu::VertexInputRate::VERTEX };
+ return { .binding = 0, .stride = sizeof(Vertex), .input_rate = gpu::VertexInputRate::VERTEX };
}
};
-static constexpr auto VERTICES = std::array {
- Vertex { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } }, // -X side
- { { -1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
- { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f } },
- { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f } },
- { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f } },
- { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } },
-
- { { -1.f, -1.f, -1.f }, { 1.f / 3.f, 2.f / 4.f } }, // -Z side
- { { 1.f, 1.f, -1.f }, { 0.f, 1.f / 4.f } },
- { { 1.f, -1.f, -1.f }, { 0.f, 2.f / 4.f } },
- { { -1.f, -1.f, -1.f }, { 1.f / 3.f, 2.f / 4.f } },
- { { -1.f, 1.f, -1.f }, { 1.f / 3.f, 1.f / 4.f } },
- { { 1.f, 1.f, -1.f }, { 0.f, 1.f / 4.f } },
-
- { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } }, // -Y side
- { { 1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } },
- { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
- { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } },
- { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
- { { -1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
-
- { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 0.f } }, // +Y side
- { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 0.f } },
- { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
- { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 0.f } },
- { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
- { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } },
-
- { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } }, // +X side
- { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
- { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
- { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
- { { 1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } },
- { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } },
-
- { { -1.f, 1.f, 1.f }, { 2.f / 3.f, 1.f / 4.f } }, // +Z side
- { { -1.f, -1.f, 1.f }, { 2.f / 3.f, 2.f / 4.f } },
- { { 1.f, 1.f, 1.f }, { 1.f, 1.f / 4.f } },
- { { -1.f, -1.f, 1.f }, { 2.f / 3.f, 2.f / 4.f } },
- { { 1.f, -1.f, 1.f }, { 1.f, 2.f / 4.f } },
- { { 1.f, 1.f, 1.f }, { 1.f, 1.f / 4.f } },
-};
-
struct ViewerData {
- math::mat4f proj;
- math::mat4f view;
- math::mat4f model;
+ math::fmat4 proj;
+ math::fmat4 view;
+ math::fmat4 model;
static constexpr auto layout_binding() -> gpu::DescriptorSetLayoutBinding {
- return { 0, gpu::DescriptorType::UNIFORM_BUFFER, gpu::ShaderStageFlag::VERTEX, 1 };
+ return { .binding = 0,
+ .type = gpu::DescriptorType::UNIFORM_BUFFER,
+ .stages = gpu::ShaderStageFlag::VERTEX,
+ .descriptor_count = 1 };
}
};
-static constexpr auto VERTICES_SIZE = sizeof(Vertex) * stdr::size(VERTICES);
+namespace {
+ const auto SHADER = stdfs::path { SHADER_DIR } / "textured_cube.spv";
+ const auto TEXTURE = stdfs::path { RESOURCE_DIR } / "textures/cube.png";
+ constexpr auto VERTICES = array {
+ Vertex { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } }, // -X side
+ { { -1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
+ { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f } },
+ { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f } },
+ { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f } },
+ { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } },
+
+ { { -1.f, -1.f, -1.f }, { 1.f / 3.f, 2.f / 4.f } }, // -Z side
+ { { 1.f, 1.f, -1.f }, { 0.f, 1.f / 4.f } },
+ { { 1.f, -1.f, -1.f }, { 0.f, 2.f / 4.f } },
+ { { -1.f, -1.f, -1.f }, { 1.f / 3.f, 2.f / 4.f } },
+ { { -1.f, 1.f, -1.f }, { 1.f / 3.f, 1.f / 4.f } },
+ { { 1.f, 1.f, -1.f }, { 0.f, 1.f / 4.f } },
+
+ { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } }, // -Y side
+ { { 1.f, -1.f, -1.f }, { 2.f / 3.f, 3.f / 4.f } },
+ { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
+ { { -1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } },
+ { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 3.f / 4.f } },
+ { { -1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
+
+ { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 0.f } }, // +Y side
+ { { -1.f, 1.f, 1.f }, { 1.f / 3.f, 0.f } },
+ { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
+ { { -1.f, 1.f, -1.f }, { 2.f / 3.f, 0.f } },
+ { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
+ { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } },
+
+ { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } }, // +X side
+ { { 1.f, 1.f, 1.f }, { 1.f / 3.f, 1.f / 4.f } },
+ { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
+ { { 1.f, -1.f, 1.f }, { 1.f / 3.f, 2.f / 4.f } },
+ { { 1.f, -1.f, -1.f }, { 2.f / 3.f, 2.f / 4.f } },
+ { { 1.f, 1.f, -1.f }, { 2.f / 3.f, 1.f / 4.f } },
+
+ { { -1.f, 1.f, 1.f }, { 2.f / 3.f, 1.f / 4.f } }, // +Z side
+ { { -1.f, -1.f, 1.f }, { 2.f / 3.f, 2.f / 4.f } },
+ { { 1.f, 1.f, 1.f }, { 1.f, 1.f / 4.f } },
+ { { -1.f, -1.f, 1.f }, { 2.f / 3.f, 2.f / 4.f } },
+ { { 1.f, -1.f, 1.f }, { 1.f, 2.f / 4.f } },
+ { { 1.f, 1.f, 1.f }, { 1.f, 1.f / 4.f } },
+ };
-static constexpr auto BUFFERING_COUNT = 2;
+ constexpr auto VERTICES_SIZE = sizeof(Vertex) * stdr::size(VERTICES);
+ constexpr auto BUFFERING_COUNT = 2_u32;
+ constexpr auto POOL_SIZES = to_array({
+ {
+ .type = gpu::DescriptorType::UNIFORM_BUFFER,
+ .descriptor_count = BUFFERING_COUNT,
+ },
+ {
+ .type = gpu::DescriptorType::COMBINED_IMAGE_SAMPLER,
+ .descriptor_count = BUFFERING_COUNT,
+ }
+ });
+
+ constexpr auto OFFSETS = array { 0_u64 };
+ constexpr auto PIPELINE_FLAGS = array { gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT };
+} // namespace
class Application: public base::Application {
public:
auto init_example() {
- static constexpr auto POOL_SIZES = std::array {
- gpu::DescriptorPool::Size {
- .type = gpu::DescriptorType::UNIFORM_BUFFER,
- .descriptor_count = BUFFERING_COUNT,
- },
- gpu::DescriptorPool::Size { .type = gpu::DescriptorType::COMBINED_IMAGE_SAMPLER,
- .descriptor_count = BUFFERING_COUNT }
- };
- m_descriptor_pool = gpu::DescriptorPool::create(m_device, POOL_SIZES, BUFFERING_COUNT * 2)
- .transform_error(monadic::assert("Failed to create descriptor pool"))
- .value();
+ m_descriptor_pool = TryAssert(gpu::DescriptorPool::create(m_device, POOL_SIZES, BUFFERING_COUNT * 2),
+ "Failed to create descriptor pool!");
// load shaders
- m_vertex_shader = gpu::Shader::load_from_file(m_device,
- SHADER_DIR "/textured_cube.spv",
- gpu::ShaderStageFlag::VERTEX)
- .transform_error(monadic::assert("Failed to load vertex shader"))
- .value();
-
- m_fragment_shader = gpu::Shader::load_from_file(m_device,
- SHADER_DIR "/textured_cube.spv",
- gpu::ShaderStageFlag::FRAGMENT)
- .transform_error(monadic::assert("Failed to load fragment shader"))
- .value();
-
- m_descriptor_set_layout
- = gpu::DescriptorSetLayout::
- create(m_device,
- into_dyn_array(ViewerData::layout_binding(),
- gpu::DescriptorSetLayoutBinding {
- 1,
- gpu::DescriptorType::COMBINED_IMAGE_SAMPLER,
- gpu::ShaderStageFlag::FRAGMENT,
- 1 }))
- .transform_error(monadic::assert("Failed to create descriptor set layout"))
- .value();
- m_pipeline_layout = gpu::PipelineLayout::create(
- m_device,
- { .descriptor_set_layouts = to_refs(m_descriptor_set_layout) })
- .transform_error(monadic::assert("Failed to create pipeline layout"))
- .value();
+ m_vertex_shader = TryAssert(gpu::Shader::load_from_file(m_device, SHADER, gpu::ShaderStageFlag::VERTEX),
+ std::format("Failed to load vertex shader {}!", SHADER.string()));
+
+ m_fragment_shader = TryAssert(gpu::Shader::load_from_file(m_device, SHADER, gpu::ShaderStageFlag::FRAGMENT),
+ std::format("Failed to load fragment shader {}!", SHADER.string()));
+
+ m_descriptor_set_layout = TryAssert(gpu::DescriptorSetLayout::
+ create(m_device,
+ into_dyn_array(ViewerData::layout_binding(),
+ gpu::DescriptorSetLayoutBinding {
+ 1,
+ gpu::DescriptorType::COMBINED_IMAGE_SAMPLER,
+ gpu::ShaderStageFlag::FRAGMENT,
+ 1 })),
+ "Failed to create descriptor set layout!");
+
+ m_pipeline_layout = TryAssert(gpu::PipelineLayout::
+ create(m_device,
+ gpu::RasterPipelineLayout {
+ .descriptor_set_layouts = gpu::to_views(m_descriptor_set_layout) }),
+ "Failed to create pipeline layout!");
// initialize render pass
const auto depth_format = [this] {
const auto formats_properties = m_physical_device->formats_properties();
- const auto candidates = std::array { gpu::PixelFormat::DEPTH32F,
- gpu::PixelFormat::DEPTH32F_STENCIL8U,
- gpu::PixelFormat::DEPTH24_UNORM_STENCIL8U };
+ const auto candidates = array { gpu::PixelFormat::DEPTH32F,
+ gpu::PixelFormat::DEPTH32F_STENCIL8U,
+ gpu::PixelFormat::DEPTH24_UNORM_STENCIL8U };
for (const auto format : candidates) {
- const auto properties = stdr::find_if(formats_properties,
- [format](const auto& pair) {
- return pair.first == format;
- });
+ const auto properties = stdr::find_if(formats_properties, [format](const auto& pair) {
+ return pair.first == format;
+ });
ENSURES(properties != stdr::cend(formats_properties));
if (check_flag_bit(properties->second.optimal_tiling_features,
gpu::FormatFeatureFlag::DEPTH_STENCIL_ATTACHMENT)) {
@@ -193,7 +187,7 @@ class Application: public base::Application {
}
}
- ensures(false, "No supported depth format found !");
+ ensures(false, "No supported depth format found!");
std::unreachable();
}();
@@ -203,20 +197,6 @@ class Application: public base::Application {
return flag;
}();
- m_render_pass
- = gpu::RenderPass::
- create(m_device,
- { .attachments = { {
- .format = m_swapchain->pixel_format(),
- }, {
- .format = depth_format,
- .destination_layout = gpu::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
- }},
- .subpasses = { gpu::Subpass{ .bind_point = gpu::PipelineBindPoint::GRAPHICS,
- .color_attachment_refs = { { .attachment_id = 0u }, }, .depth_attachment_ref = gpu::Subpass::Ref{.attachment_id = 1u, .layout = gpu::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL, }, }, }, })
- .transform_error(monadic::assert("Failed to create render pass"))
- .value();
-
// initialize render pipeline
const auto window_extent = m_window->extent();
const auto window_viewport = gpu::Viewport {
@@ -230,159 +210,125 @@ class Application: public base::Application {
};
const auto state = gpu::RasterPipelineState {
- .input_assembly_state = { .topology = gpu::PrimitiveTopology::TRIANGLE_LIST, },
- .viewport_state = { .viewports = { window_viewport },
- .scissors = { scissor }, },
- .rasterization_state = {
- .cull_mode = gpu::CullModeFlag::BACK,
- .front_face = gpu::FrontFace::CLOCKWISE,
- },
- .color_blend_state
- = { .attachments = { { .blend_enable = true,
- .src_color_blend_factor = gpu::BlendFactor::SRC_ALPHA,
- .dst_color_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
- .src_alpha_blend_factor = gpu::BlendFactor::SRC_ALPHA,
- .dst_alpha_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
- .alpha_blend_operation = gpu::BlendOperation::ADD, }, }, },
- .shader_state = to_refs(m_vertex_shader, m_fragment_shader),
- .vertex_input_state = {
- .binding_descriptions = into_dyn_array(Vertex::binding_description()),
- .input_attribute_descriptions = to_dyn_array(Vertex::attribute_descriptions()),
- },
- .depth_stencil_state = {
- .depth_test_enable = true,
- .depth_write_enable = true
- },
- };
+ .input_assembly_state = { .topology = gpu::PrimitiveTopology::TRIANGLE_LIST, },
+ .viewport_state = { .viewports = { window_viewport },
+ .scissors = { scissor }, },
+ .rasterization_state = {
+ .cull_mode = gpu::CullModeFlag::BACK,
+ .front_face = gpu::FrontFace::CLOCKWISE,
+ },
+ .color_blend_state
+ = { .attachments = { { .blend_enable = true,
+ .src_color_blend_factor = gpu::BlendFactor::SRC_ALPHA,
+ .dst_color_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
+ .src_alpha_blend_factor = gpu::BlendFactor::SRC_ALPHA,
+ .dst_alpha_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
+ .alpha_blend_operation = gpu::BlendOperation::ADD, }, }, },
+ .shader_state = to_views(m_vertex_shader, m_fragment_shader),
+ .vertex_input_state = {
+ .binding_descriptions = into_dyn_array(Vertex::binding_description()),
+ .input_attribute_descriptions = to_dyn_array(Vertex::attribute_descriptions()),
+ },
+ .depth_stencil_state = {
+ .depth_test_enable = true,
+ .depth_write_enable = true
+ },
+ };
+
+ const auto rendering_info = gpu::RasterPipelineRenderingInfo {
+ .color_attachment_formats = { m_swapchain->pixel_format() },
+ .depth_attachment_format = depth_format,
+ };
- m_pipeline = gpu::Pipeline::create(m_device, state, m_pipeline_layout, m_render_pass)
- .transform_error(monadic::assert("Failed to create raster pipeline"))
- .value();
+ m_pipeline = TryAssert(gpu::Pipeline::create(m_device,
+ gpu::Pipeline::RasterizationCreateInfo { .state = as_ref(state),
+ .layout = m_pipeline_layout,
+ .rendering_info = rendering_info }),
+ "Failed to create raster pipeline!");
// load texture
auto image = image::Image {};
- image.load_from_file(TEXTURE_DIR "/cube.png").transform_error(monadic::assert()).value();
+ TryAssert(image.load_from_file(TEXTURE), std::format("Failed to load texture file {}!", TEXTURE.string()));
- m_texture = gpu::Image::create(m_device,
- { .extent = image.extent(),
- .format = gpu::PixelFormat::RGBA8_UNORM,
- .usages = gpu::ImageUsageFlag::SAMPLED
- | gpu::ImageUsageFlag::TRANSFER_DST,
- .property = gpu::MemoryPropertyFlag::DEVICE_LOCAL })
- .transform_error(monadic::assert("Failed to allocate texture"))
- .value();
+ m_texture = TryAssert(gpu::Image::create(m_device,
+ { .extent = image.extent(),
+ .format = gpu::PixelFormat::RGBA8_UNORM,
+ .usages = gpu::ImageUsageFlag::SAMPLED | gpu::ImageUsageFlag::TRANSFER_DST,
+ .properties = gpu::MemoryPropertyFlag::DEVICE_LOCAL }),
+ "Failed to allocate texture!");
{
- auto staging_buffer
- = gpu::Buffer::create(m_device,
- { .usages = gpu::BufferUsageFlag::TRANSFER_SRC,
- .size = image.size() })
- .transform_error(monadic::assert("Failed to allocate gpu texture staging buffer"))
- .value();
-
- staging_buffer.upload(image.data())
- .transform_error(monadic::assert("Failed to upload texture data to staging buffer"))
- .value();
-
- auto
- cpy_fence = gpu::Fence::create(m_device)
- .transform_error(monadic::
- assert("Failed to create copy texture buffer fence"))
- .value();
-
- const auto copy = {
- gpu::BufferImageCopy {
- .buffer_offset = 0,
- .buffer_row_length = 0,
- .buffer_image_height = 0,
- .subresource_layers = {},
- .offset = {},
- .extent = image.extent() }
- };
- auto copy_cmb = m_command_pool->create_command_buffer()
- .transform_error(monadic::
- assert("Failed to allocate copy texture buffer "
- "commandbuffer"))
- .value();
-
- copy_cmb.begin()
- .transform_error(monadic::assert("Failed to begin texture upload command buffer"))
- .value()
- ->begin_debug_region("Upload texture data")
- .transition_image_layout(m_texture,
- gpu::ImageLayout::UNDEFINED,
- gpu::ImageLayout::TRANSFER_DST_OPTIMAL)
- .copy_buffer_to_image(staging_buffer, m_texture, as_view(copy))
- .transition_image_layout(m_texture,
- gpu::ImageLayout::TRANSFER_DST_OPTIMAL,
- gpu::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to end texture upload command buffer"))
- .value()
- ->submit(m_raster_queue, {}, {}, {}, as_ref(cpy_fence))
- .transform_error(monadic::assert("Failed to submit texture upload command buffer"))
- .value();
-
- *cpy_fence.wait().transform_error(monadic::assert());
+ auto cpy_fence = TryAssert(gpu::Fence::create(m_device), "Failed to create copy texture buffer fence!");
+ auto staging_buffer = TryAssert(gpu::Buffer::create(m_device,
+ { .usages = gpu::BufferUsageFlag::TRANSFER_SRC,
+ .size = image.size() }),
+ "Failed to allocate gpu texture staging buffer!");
+ TryAssert(staging_buffer.upload(image.data()), "Failed to upload texture data to staging buffer!");
+
+ auto copy_cmb = TryAssert(m_command_pool->create_command_buffer(), "Failed to allocate copy texture buffer");
+ TryDiscardAssert((copy_cmb.record([&](auto cmb) noexcept {
+ const auto copy = array {
+ gpu::BufferImageCopy {
+ .buffer_offset = 0,
+ .buffer_row_length = 0,
+ .buffer_image_height = 0,
+ .subresource_layers = {},
+ .offset = {},
+ .extent = image.extent() }
+ };
+
+ cmb.begin_debug_region("Upload texture data")
+ .transition_image_layout(m_texture,
+ gpu::ImageLayout::UNDEFINED,
+ gpu::ImageLayout::TRANSFER_DST_OPTIMAL)
+ .copy_buffer_to_image(staging_buffer, m_texture, copy)
+ .end_debug_region()
+ .begin_debug_region("Transition texture data")
+ .transition_image_layout(m_texture,
+ gpu::ImageLayout::TRANSFER_DST_OPTIMAL,
+ gpu::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
+ .end_debug_region();
+ })),
+ "Failed to record texture upload and transition cmb!");
+
+ TryDiscardAssert(copy_cmb.submit(m_raster_queue, {}, {}, {}, cpy_fence),
+ "Failed to submit texture upload command buffer!");
+
+ TryDiscardAssert(cpy_fence.wait(), "Failed to create texture view!");
}
- m_texture_view = gpu::ImageView::create(m_device, m_texture)
- .transform_error(monadic::assert("Failed to create texture view"))
- .value();
-
- m_sampler = gpu::Sampler::create(m_device, {})
- .transform_error(monadic::assert("Failed to create sampler"))
- .value();
-
- // create present engine resources
- m_submission_resources = std::vector {};
+ m_texture_view = TryAssert(gpu::ImageView::create(m_device, { m_texture }), "Failed to create texture view!");
+ m_sampler = TryAssert(gpu::Sampler::create(m_device, {}), "Failed to create sampler!");
+ m_submission_resources = dyn_array {};
m_submission_resources.reserve(BUFFERING_COUNT);
for (auto _ : range(BUFFERING_COUNT)) {
- m_submission_resources.push_back({
- .in_flight = gpu::Fence::create_signaled(m_device)
- .transform_error(core::monadic::
- assert("Failed to create swapchain image "
- "in flight fence"))
- .value(),
- .image_available = gpu::Semaphore::create(m_device)
- .transform_error(core::monadic::
- assert("Failed to create present "
- "wait semaphore"))
- .value(),
- .render_cmb = m_command_pool->create_command_buffer()
- .transform_error(monadic::assert("Failed to create "
- "transition command "
- "buffers"))
- .value(),
- .viewer_buffer = gpu::Buffer::create(m_device,
- {
- .usages = gpu::BufferUsageFlag::UNIFORM,
- .size = sizeof(ViewerData),
- },
- true)
- .transform_error(monadic::
- assert("Failed to allocate gpu viewer buffer"))
- .value(),
- .descriptor_set = m_descriptor_pool->create_descriptor_set(m_descriptor_set_layout)
- .transform_error(monadic::
- assert("Failed to create descriptor set"))
- .value(),
- });
+ m_submission_resources.push_back(
+ { .in_flight = TryAssert(gpu::Fence::create_signaled(m_device), "Failed to create swapchain image!"),
+ .image_available = TryAssert(gpu::Semaphore::create(m_device), "Failed to create present image!"),
+ .render_cmb = TryAssert(m_command_pool->create_command_buffer(), "Failed to create buffers!"),
+ .viewer_buffer = TryAssert(gpu::Buffer::create(m_device,
+ {
+ .usages = gpu::BufferUsageFlag::UNIFORM,
+ .size = sizeof(ViewerData),
+ .persistently_mapped = true,
+ }),
+ "Failed to allocate gpu viewer buffer!"),
+ .descriptor_set = TryAssert(m_descriptor_pool->create_descriptor_set(m_descriptor_set_layout),
+ "Failed to create descriptor set!") });
auto& res = m_submission_resources.back();
- const auto sets = std::array {
+ const auto sets = array {
gpu::BufferDescriptor {
.binding = 0,
- .buffer = as_ref(res.viewer_buffer),
+ .buffer = res.viewer_buffer,
.range = sizeof(ViewerData),
.offset = 0,
},
gpu::ImageDescriptor {
.binding = 1,
.layout = gpu::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
- .image_view = as_ref(m_texture_view),
- .sampler = as_ref(m_sampler),
+ .image_view = m_texture_view,
+ .sampler = m_sampler,
}
};
res.descriptor_set.update(sets);
@@ -390,163 +336,112 @@ class Application: public base::Application {
const auto& images = m_swapchain->images();
- const auto image_count = stdr::size(images);
- auto transition_cmbs
- = m_command_pool->create_command_buffers(image_count)
- .transform_error(monadic::assert("Failed to create transition command buffers"))
- .value();
+ const auto image_count = stdr::size(images);
+ auto transition_cmbs = TryAssert(m_command_pool->create_command_buffers(image_count),
+ "Failed to create transition command buffers!");
- m_image_resources = std::vector {};
+ m_image_resources = dyn_array {};
m_image_resources.reserve(stdr::size(images));
auto image_index = 0u;
for (const auto& swap_image : images) {
- auto view = gpu::ImageView::create(m_device, swap_image)
- .transform_error(core::monadic::
- assert("Failed to create swapchain image view"))
- .value();
-
- auto depth_image
- = gpu::Image::create(m_device,
- gpu::Image::CreateInfo {
- .extent = swap_image.extent(),
- .format = depth_format,
- .usages = gpu::ImageUsageFlag::DEPTH_STENCIL_ATTACHMENT,
- .property = gpu::MemoryPropertyFlag::DEVICE_LOCAL })
- .transform_error(core::monadic::assert("Failed to create depth image"))
- .value();
-
- auto depth_view = gpu::ImageView::create(m_device,
- depth_image,
- gpu::ImageViewType::T2D,
- { .aspect_mask = depth_aspect_flag })
- .transform_error(core::monadic::
- assert("Failed to create depth image view"))
- .value();
-
- auto framebuffer = m_render_pass
- ->create_frame_buffer(m_device,
- window_extent,
- to_refs(view, depth_view))
- .transform_error(core::monadic::assert(
- std::format("Failed to create framebuffer for image {}",
- image_index)))
- .value();
-
- m_image_resources.push_back({
- .image = as_ref(swap_image),
- .view = std::move(view),
- .depth_image = std::move(depth_image),
- .depth_view = std::move(depth_view),
- .framebuffer = std::move(framebuffer),
- .render_finished = gpu::Semaphore::create(m_device)
- .transform_error(core::monadic::assert("Failed to create render "
- "signal semaphore"))
- .value(),
- });
+ auto view = TryAssert(gpu::ImageView::create(m_device, { swap_image }), "Failed to create swapchain image view!");
+ auto depth_image = TryAssert(gpu::Image::create(m_device,
+ { .extent = swap_image.extent(),
+ .format = depth_format,
+ .usages = gpu::ImageUsageFlag::DEPTH_STENCIL_ATTACHMENT,
+ .properties = gpu::MemoryPropertyFlag::DEVICE_LOCAL }),
+ "Failed to create depth image!");
+
+ auto depth_view = TryAssert(gpu::ImageView::create(m_device,
+ { .image = depth_image,
+ .subresource_range = gpu::
+ ImageSubresourceRange { .aspect_mask = depth_aspect_flag } }),
+ "Failed to create depth image view!");
+
+ m_image_resources.push_back({ .image = swap_image,
+ .view = std::move(view),
+ .depth_image = std::move(depth_image),
+ .depth_view = std::move(depth_view),
+ .render_finished = TryAssert(gpu::Semaphore::create(m_device),
+ "Failed to create render!") });
const auto& resources = m_image_resources.back();
auto& transition_cmb = transition_cmbs[image_index];
- *transition_cmb.begin(true)
- .transform_error(monadic::
- assert("Failed to begin texture transition command buffer"))
- .value()
- ->begin_debug_region(std::format("transition image {}", image_index))
- .transition_image_layout(swap_image,
- gpu::ImageLayout::UNDEFINED,
- gpu::ImageLayout::PRESENT_SRC)
- .transition_image_layout(resources.depth_image,
- gpu::ImageLayout::UNDEFINED,
- gpu::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- { .aspect_mask = depth_aspect_flag })
- .end_debug_region()
- .end()
- .transform_error(monadic::
- assert("Failed to begin texture transition command buffer"))
- .transform(monadic::discard());
+ TryDiscardAssert((transition_cmb.record([&](auto cmb) noexcept {
+ cmb.begin_debug_region(std::format("Transition image {}", image_index))
+ .transition_image_layout(swap_image,
+ gpu::ImageLayout::UNDEFINED,
+ gpu::ImageLayout::PRESENT_SRC)
+ .end_debug_region()
+ .begin_debug_region(std::format("Transition depth image {}", image_index))
+ .transition_image_layout(resources.depth_image,
+ gpu::ImageLayout::UNDEFINED,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ { .aspect_mask = depth_aspect_flag })
+ .end_debug_region();
+ })),
+ std::format("Failed to record transition cmb {}!", image_index));
++image_index;
}
- const auto fence = gpu::Fence::create(m_device)
- .transform_error(monadic::assert("Failed to create transition fence"))
- .value();
+ const auto fence = TryAssert(gpu::Fence::create(m_device), "Failed to create transition fence!");
- const auto cmbs = to_refs(transition_cmbs);
- m_raster_queue->submit({ .command_buffers = cmbs }, as_ref(fence))
- .transform_error(monadic::assert("Failed to submit texture transition command buffers"))
- .value();
+ const auto cmbs = to_views(transition_cmbs);
+ TryDiscardAssert(m_raster_queue->submit({ .command_buffers = cmbs }, fence),
+ "Failed to submit texture transition command buffers!");
// setup vertex buffer
- m_vertex_buffer = gpu::Buffer::create(m_device,
- { .usages = gpu::BufferUsageFlag::VERTEX
- | gpu::BufferUsageFlag::TRANSFER_DST,
- .size = VERTICES_SIZE,
- .property = gpu::MemoryPropertyFlag::DEVICE_LOCAL })
- .transform_error(monadic::
- assert("Failed to allocate gpu vertex buffer"))
- .value();
+ m_vertex_buffer = TryAssert(gpu::Buffer::create(m_device,
+ { .usages = gpu::BufferUsageFlag::VERTEX
+ | gpu::BufferUsageFlag::TRANSFER_DST,
+ .size = VERTICES_SIZE,
+ .properties = gpu::MemoryPropertyFlag::DEVICE_LOCAL }),
+ "Failed to allocate gpu vertex buffer!");
{
- auto staging_buffer
- = gpu::Buffer::create(m_device,
- { .usages = gpu::BufferUsageFlag::TRANSFER_SRC,
- .size = VERTICES_SIZE })
- .transform_error(monadic::assert("Failed to allocate gpu vertex staging buffer"))
- .value();
-
- staging_buffer.upload(VERTICES)
- .transform_error(monadic::assert("Failed to upload vertex data to staging buffer"))
- .value();
-
- auto
- cpy_fence = gpu::Fence::create(m_device)
- .transform_error(monadic::
- assert("Failed to create copy vertex buffer fence"))
- .value();
-
- auto
- copy_cmb = m_command_pool->create_command_buffer()
- .transform_error(monadic::assert("Failed to allocate copy vertex buffer "
- "commandbuffer"))
- .value();
-
- copy_cmb.begin()
- .transform_error(monadic::assert("Failed to begin vertices upload command buffer"))
- .value()
- ->begin_debug_region("Upload vertex data to vertex buffer")
+ auto staging_buffer = TryAssert(gpu::Buffer::create(m_device,
+ { .usages = gpu::BufferUsageFlag::TRANSFER_SRC,
+ .size = VERTICES_SIZE }),
+ "Failed to allocate gpu vertex staging buffer!");
+
+ TryAssert(staging_buffer.upload(VERTICES), "Failed to upload vertex data to staging buffer!");
+
+ auto cpy_fence = TryAssert(gpu::Fence::create(m_device), "Failed to create copy vertex buffer fence!");
+
+ auto copy_cmb = TryAssert(m_command_pool->create_command_buffer(), "Failed to allocate copy vertex buffer");
+ TryAssert(copy_cmb.begin(), "Failed to begin vertices upload command buffer");
+
+ copy_cmb.begin_debug_region("Upload vertex data to vertex buffer")
.copy_buffer(staging_buffer, m_vertex_buffer, VERTICES_SIZE)
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to begin vertices upload command buffer"))
- .value()
- ->submit(m_raster_queue, {}, {}, {}, as_ref(cpy_fence));
+ .end_debug_region();
- cpy_fence.wait().transform_error(monadic::assert());
+ TryDiscardAssert(copy_cmb.end(), "Failed to begin vertices upload command buffer");
+ TryDiscardAssert(copy_cmb.submit(m_raster_queue, {}, {}, {}, cpy_fence),
+ "Failed to submit vertices upload command buffer!");
+ TryAssert(cpy_fence.wait(), "Failed to acquire next swapchain image!");
}
- // wait for transition to be done
- fence.wait().transform_error(monadic::assert());
+ TryAssert(fence.wait(), "");
}
auto run_example() {
- using SecondF = stdc::duration;
+ LOG_MODULE.flush();
+
+ const auto current_time = clock::now();
+
const auto window_extent = m_window->extent();
const auto window_extent_f32 = window_extent.to();
auto viewer_data = ViewerData {
- .proj = math::perspective(math::radians(45.f),
+ .proj = math::perspective(math::angle::radians(45.f),
window_extent_f32.width / window_extent_f32.height,
0.1f,
100.f),
- .view = math::look_at(math::vec3f { 0.f, 3.f, 5.f },
- { 0.f, 0.f, 0.f },
- { 0.f, 1.f, 0.f }),
- .model = math::mat4f::identity(),
+ .view = math::look_at(math::fvec3 { 0.f, 3.f, 5.f }, { 0.f, 0.f, 0.f }, { 0.f, 1.f, 0.f }),
+ .model = math::fmat4::identity(),
};
- LOG_MODULE.flush();
-
- const auto current_time = clock::now();
// get next swapchain image
auto& submission_resource = m_submission_resources[m_current_frame];
@@ -554,89 +449,68 @@ class Application: public base::Application {
const auto& wait = submission_resource.image_available;
auto& in_flight = submission_resource.in_flight;
- const auto acquire_next_image = bind_front(&gpu::SwapChain::acquire_next_image,
- &*m_swapchain,
- 100ms,
- std::cref(wait));
- const auto extract_index = [](auto&& _result) static noexcept {
- auto&& [result, _image_index] = _result;
- return _image_index;
- };
+ TryAssert(in_flight.wait(), "Failed to wait in_flight fence!");
+ TryAssert(in_flight.reset(), "Failed to reset in_flight fence!");
- const auto
- image_index = in_flight.wait()
- .transform([&in_flight](auto&&) noexcept { in_flight.reset(); })
- .and_then(acquire_next_image)
- .transform(extract_index)
- .transform_error(monadic::
- assert("Failed to acquire next swapchain image"))
- .value();
+ const auto&& [_, image_index] = TryAssert(m_swapchain->acquire_next_image(100ms, wait),
+ "Failed to acquire next swapchain image!");
const auto& swapchain_image_resource = m_image_resources[image_index];
- const auto& framebuffer = swapchain_image_resource.framebuffer;
const auto& signal = swapchain_image_resource.render_finished;
// update viewer data and upload
- const auto time = stdc::duration_cast(current_time - m_start_time).count();
- viewer_data.model = math::rotate(math::mat4f::identity(),
- time * math::radians(90.f),
- math::vec3f { 0.f, 1.f, 0.f });
+ const auto time = stdc::duration_cast(current_time - m_start_time).count();
+ viewer_data.model = math::transpose(math::rotate(math::fmat4::identity(),
+ time * math::angle::radians(90.f),
+ math::fvec3 { 0.f, 1.f, 0.f }));
auto& viewer_buffer = submission_resource.viewer_buffer;
- viewer_buffer.upload(viewer_data);
+ TryAssert(viewer_buffer.upload(viewer_data), "Failed to upload texture to gpu!");
+
+ const auto rendering_info = gpu::RenderingInfo {
+ .render_area = { .x = 0, .y = 0, .width = window_extent.to().width, .height = window_extent.to().height },
+ .color_attachments = { { .image_view = swapchain_image_resource.view,
+ .layout = gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ .clear_value = gpu::ClearColor { .color = colors::SILVER } } },
+ .depth_attachment = { { .image_view = swapchain_image_resource.depth_view,
+ .layout = gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ .clear_value = gpu::ClearDepthStencil {} } }
+ };
// render in it
auto& render_cmb = submission_resource.render_cmb;
const auto& descriptor_set = submission_resource.descriptor_set;
- static constexpr auto CLEAR_VALUES = std::array {
- gpu::ClearColor { .color = RGBColorDef::SILVER },
- gpu::ClearDepthStencil {}
- };
- static constexpr auto OFFSETS = std::array { 0_u64 };
- static constexpr auto PIPELINE_FLAGS = std::array {
- gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT
- };
-
- render_cmb.reset()
- .transform_error(monadic::assert("Failed to reset render command buffer"))
- .value()
- ->begin()
- .transform_error(monadic::assert("Failed to begin render command buffer"))
- .value()
- ->begin_debug_region("Render textured cube")
- .begin_render_pass(m_render_pass, framebuffer, CLEAR_VALUES)
- .bind_pipeline(m_pipeline)
- .bind_vertex_buffers(to_refs(m_vertex_buffer), OFFSETS)
- .bind_descriptor_sets(m_pipeline, m_pipeline_layout, as_refs(descriptor_set), {})
- .draw(stdr::size(VERTICES))
- .end_render_pass()
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to end render command buffer"))
- .value()
- ->submit(m_raster_queue,
- as_refs(wait),
- PIPELINE_FLAGS,
- as_refs(signal),
- as_ref(in_flight))
- .transform_error(monadic::assert("Failed to submit render command buffer"))
- .value();
+ TryAssert(render_cmb.reset(), std::format("Failed to reset render cmb {}!", image_index));
+ TryDiscardAssert((render_cmb.record([&](auto cmb) noexcept {
+ cmb
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::PRESENT_SRC,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL)
+ .begin_debug_region("Render cube")
+ .begin_rendering(rendering_info)
+ .bind_pipeline(m_pipeline)
+ .bind_vertex_buffers(gpu::as_views(m_vertex_buffer), OFFSETS)
+ .bind_descriptor_sets(m_pipeline, m_pipeline_layout, gpu::as_views(descriptor_set), {})
+ .draw(stdr::size(VERTICES))
+ .end_rendering()
+ .end_debug_region()
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ gpu::ImageLayout::PRESENT_SRC);
+ })),
+ std::format("Failed to record render cmb {}!", image_index));
+ TryDiscardAssert(render_cmb.submit(m_raster_queue, gpu::as_views(wait), PIPELINE_FLAGS, gpu::as_views(signal), in_flight),
+ "Failed to submit render command buffer!");
// present it
- auto update_current_frame = [this](auto&&) mutable noexcept {
- if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
- };
-
- m_raster_queue->present(as_refs(m_swapchain), as_refs(signal), as_view(image_index))
- .transform(update_current_frame)
- .transform_error(monadic::assert("Failed to present swapchain image"));
+ TryAssert(m_raster_queue->present(gpu::as_views(m_swapchain), gpu::as_views(signal), as_view(image_index)),
+ "Failed to present swapchain image!");
- m_raster_queue->wait_idle();
- m_device->wait_idle();
+ if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
}
- constexpr auto example_name() const noexcept -> std::string_view { return "Textured Cube"; }
+ constexpr auto example_name() const noexcept -> string_view { return "Textured Cube"; }
private:
DeferInit m_descriptor_pool;
@@ -645,19 +519,18 @@ class Application: public base::Application {
DeferInit m_fragment_shader;
DeferInit m_descriptor_set_layout;
DeferInit m_pipeline_layout;
- DeferInit m_render_pass;
DeferInit m_pipeline;
DeferInit m_texture;
DeferInit m_texture_view;
DeferInit m_sampler;
- std::vector m_submission_resources;
- std::vector m_image_resources;
+ dyn_array m_submission_resources;
+ dyn_array m_image_resources;
DeferInit m_vertex_buffer;
usize m_current_frame = 0_usize;
decltype(clock::now()) m_start_time = clock::now();
};
-auto main(std::span args) -> int {
+auto main(array_view args) -> int {
auto app = Application {};
app.run(args);
return 0;
diff --git a/examples/gpu/textured_cube/win32/manifest.manifest b/examples/gpu/textured_cube/win32/manifest.manifest
deleted file mode 100644
index 4a9b5f6a6..000000000
--- a/examples/gpu/textured_cube/win32/manifest.manifest
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- true
- PerMonitorV2
-
-
-
diff --git a/examples/gpu/textured_cube/xmake.lua b/examples/gpu/textured_cube/xmake.lua
index f16e33fd1..748a76f2e 100644
--- a/examples/gpu/textured_cube/xmake.lua
+++ b/examples/gpu/textured_cube/xmake.lua
@@ -1,47 +1,28 @@
-if is_plat("linux") then
- add_requires(
- "nzsl",
- { configs = { toolchains = "gcc", runtimes = "stdc++_shared", fs_watcher = false, link = {} } }
- )
-elseif is_plat("windows") then
- add_requires("nzsl", { configs = { toolchains = "msvc", runtimes = "MD", fs_watcher = false, links = {} } })
-else
- add_requires("nzsl", { configs = { fs_watcher = false, links = {} } })
+local runtimes
+local toolchain
+if is_plat("windows") then
+ runtimes = "MD"
+ toolchain = "msvc"
+elseif is_plat("linux") then
+ runtimes = "stdc++_shared"
+ toolchain = "gcc"
end
+add_requires("nzsl", { configs = { fs_watcher = false, kind = "binary", toolchains = toolchain, runtimes = runtimes } })
target("textured_cube", function()
- set_kind("binary")
- set_languages("cxxlatest", "clatest")
+ add_rules("stormkit::example", "compile.shaders")
- add_rules("stormkit.flags")
- add_rules("platform.windows.subsystem.console")
- -- add_rules("platform.windows.subsystem.windows")
-
- add_rules("compile.shaders")
- add_deps("core", "main", "log", "wsi", "gpu", "stormkit")
-
- if is_mode("debug") then
- add_defines("STORMKIT_BUILD_DEBUG")
- add_defines("STORMKIT_ASSERT=1")
- set_suffixname("-d")
- else
- add_defines("STORMKIT_ASSERT=0")
- end
-
- add_files("src/*.cpp", "../common/app.mpp")
- add_files("shaders/*.nzsl")
- if is_plat("windows") then add_files("win32/*.manifest") end
-
- add_includedirs("$(builddir)/shaders")
+ add_files("src/*.cpp", "src/*.cppm", "../common/app.cppm", "shaders/*.nzsl")
if get_config("devmode") then
- add_defines('SHADER_DIR="$(builddir)/shaders"')
- add_defines('TEXTURE_DIR="$(builddir)/textures"')
- set_rundir("$(projectdir)")
+ add_defines(format('RESOURCE_DIR="%s"', path.unix(path.join(os.projectdir(), "examples/gpu/textured_cube"))))
+ add_defines(format('SHADER_DIR="%s"', path.unix("$(builddir)/shaders")))
end
+ add_embeddirs("$(builddir)/shaders")
+
+ if get_config("devmode") then set_rundir("$(projectdir)") end
- -- add_cxflags("--embed-dir=$(builddir)/shaders", {tools = {"clang", "clangxx", "clang-cl", "gcc", "gxx"}})
- after_build(function(target) os.cp("examples/gpu/textured_cube/textures/", "$(builddir)") end)
+ add_packages("nzsl")
set_group("examples/stormkit-gpu")
end)
diff --git a/examples/gpu/triangle/iOS/Info.plist b/examples/gpu/triangle/iOS/Info.plist
deleted file mode 100644
index a62a3592d..000000000
--- a/examples/gpu/triangle/iOS/Info.plist
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
-
-
diff --git a/examples/gpu/triangle/iOS/LaunchScreen.storyboard b/examples/gpu/triangle/iOS/LaunchScreen.storyboard
deleted file mode 100644
index 436820912..000000000
--- a/examples/gpu/triangle/iOS/LaunchScreen.storyboard
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/gpu/triangle/macOS/Info.plist b/examples/gpu/triangle/macOS/Info.plist
deleted file mode 100644
index f68f66070..000000000
--- a/examples/gpu/triangle/macOS/Info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
-
-
-
diff --git a/examples/gpu/triangle/shaders/triangle.nzsl b/examples/gpu/triangle/shaders/triangle.nzsl
index 5f88feefe..e6b6d6b57 100644
--- a/examples/gpu/triangle/shaders/triangle.nzsl
+++ b/examples/gpu/triangle/shaders/triangle.nzsl
@@ -15,7 +15,7 @@ struct VertOut {
}
[entry(vert)]
-fn main(input: VertIn) -> VertOut {
+fn vert_main(input: VertIn) -> VertOut {
let output: VertOut;
let position: vec2[f32];
@@ -44,7 +44,7 @@ struct FragOut {
}
[entry(frag)]
-fn main(input: VertOut) -> FragOut {
+fn frag_main(input: VertOut) -> FragOut {
let output: FragOut;
output.color = vec4[f32](input.color, 1.);
diff --git a/examples/gpu/triangle/src/logger.cppm b/examples/gpu/triangle/src/logger.cppm
new file mode 100644
index 000000000..7aa06a6b7
--- /dev/null
+++ b/examples/gpu/triangle/src/logger.cppm
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 Arthur LAURENT
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level of this distribution
+
+module;
+
+#include
+
+export module gpu_app:logger;
+
+import std;
+
+import stormkit.log;
+
+export { IN_MODULE_LOGGER("Triangle"); }
diff --git a/examples/gpu/triangle/src/main.cpp b/examples/gpu/triangle/src/main.cpp
index 4f8bdfac8..a1716f214 100644
--- a/examples/gpu/triangle/src/main.cpp
+++ b/examples/gpu/triangle/src/main.cpp
@@ -2,22 +2,22 @@
// This file is subject to the license terms in the LICENSE file
// found in the top-level of this distribution
+#include
+
import std;
import stormkit;
import gpu_app;
-#include
+#include
#include
-LOGGER("stormkit.examples.gpu.triangle");
-
#ifndef SHADER_DIR
- #define SHADER_DIR "../share/shaders"
+static constexpr auto SHADER_DIR "../share/stormkit/shaders/"
#endif
-namespace stdr = std::ranges;
-namespace stdfs = std::filesystem;
+ namespace stdr = std::ranges;
+namespace stdfs = std::filesystem;
using namespace std::literals;
using namespace stormkit;
@@ -29,43 +29,28 @@ struct SubmissionResource {
};
struct SwapchainImageResource {
- Ref image;
- gpu::ImageView view;
- gpu::FrameBuffer framebuffer;
- gpu::Semaphore render_finished;
+ gpu::view::Image image;
+ gpu::ImageView view;
+ gpu::Semaphore render_finished;
};
-static constexpr auto BUFFERING_COUNT = 2;
+namespace {
+ constexpr auto BUFFERING_COUNT = 2_u32;
+ const auto SHADER = stdfs::path { SHADER_DIR } / "triangle.spv";
+} // namespace
class Application: public base::Application {
public:
auto init_example() {
// load shaders
- m_vertex_shader = gpu::Shader::load_from_file(m_device,
- SHADER_DIR "/triangle.spv",
- gpu::ShaderStageFlag::VERTEX)
- .transform_error(monadic::assert("Failed to load vertex shader"))
- .value();
-
- m_fragment_shader = gpu::Shader::load_from_file(m_device,
- SHADER_DIR "/triangle.spv",
- gpu::ShaderStageFlag::FRAGMENT)
- .transform_error(monadic::assert("Failed to load fragment shader"))
- .value();
-
- m_pipeline_layout = gpu::PipelineLayout::create(m_device, {})
- .transform_error(monadic::assert("Failed to create pipeline layout"))
- .value();
-
- // initialize render pass
- m_render_pass
- = gpu::RenderPass::
- create(m_device,
- { .attachments = { { .format = m_swapchain->pixel_format() } },
- .subpasses = { { .bind_point = gpu::PipelineBindPoint::GRAPHICS,
- .color_attachment_refs = { { .attachment_id = 0u } } } } })
- .transform_error(monadic::assert("Failed to create render pass"))
- .value();
+ m_vertex_shader = TryAssert(gpu::Shader::load_from_file(m_device, SHADER, gpu::ShaderStageFlag::VERTEX),
+ std::format("Failed to load vertex shader {}!", SHADER.string()));
+
+ m_fragment_shader = TryAssert(gpu::Shader::load_from_file(m_device, SHADER, gpu::ShaderStageFlag::FRAGMENT),
+ std::format("Failed to load fragment shader {}!", SHADER.string()));
+
+ m_pipeline_layout = TryAssert(gpu::PipelineLayout::create(m_device, gpu::RasterPipelineLayout {}),
+ "Failed to create pipeline layoutu!");
const auto window_extent = m_window->extent();
@@ -81,41 +66,43 @@ class Application: public base::Application {
};
const auto state = gpu::RasterPipelineState {
- .input_assembly_state = { .topology = gpu::PrimitiveTopology::TRIANGLE_LIST, },
- .viewport_state = { .viewports = { window_viewport },
- .scissors = { scissor }, },
- .color_blend_state
- = { .attachments = { { .blend_enable = true,
- .src_color_blend_factor = gpu::BlendFactor::SRC_ALPHA,
- .dst_color_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
- .src_alpha_blend_factor = gpu::BlendFactor::SRC_ALPHA,
- .dst_alpha_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
- .alpha_blend_operation = gpu::BlendOperation::ADD, }, }, },
- .shader_state = to_refs(m_vertex_shader, m_fragment_shader),
- };
-
- m_pipeline = gpu::Pipeline::create(m_device, state, m_pipeline_layout, m_render_pass)
- .transform_error(monadic::assert("Failed to create raster pipeline"))
- .value();
+ .input_assembly_state = { .topology = gpu::PrimitiveTopology::TRIANGLE_LIST, },
+ .viewport_state = { .viewports = { window_viewport },
+ .scissors = { scissor }, },
+ .color_blend_state
+ = { .attachments = { { .blend_enable = true,
+ .src_color_blend_factor = gpu::BlendFactor::SRC_ALPHA,
+ .dst_color_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
+ .src_alpha_blend_factor = gpu::BlendFactor::SRC_ALPHA,
+ .dst_alpha_blend_factor = gpu::BlendFactor::ONE_MINUS_SRC_ALPHA,
+ .alpha_blend_operation = gpu::BlendOperation::ADD, }, }, },
+ .shader_state = gpu::to_views(m_vertex_shader, m_fragment_shader),
+ };
+
+ const auto rendering_info = gpu::RasterPipelineRenderingInfo {
+ .color_attachment_formats = { m_swapchain->pixel_format() }
+ };
+
+ m_pipeline = TryAssert(gpu::Pipeline::create(m_device,
+ gpu::Pipeline::RasterizationCreateInfo { .state = as_ref(state),
+ .layout = m_pipeline_layout,
+ .rendering_info = rendering_info }),
+ "Failed to create raster pipeline!");
// create present engine resources
- m_submission_resources = init_by>([&](auto& out) noexcept {
+ m_submission_resources = init_by>([&](auto& out) noexcept {
out.reserve(BUFFERING_COUNT);
for (auto _ : range(BUFFERING_COUNT)) {
out.push_back({
- .in_flight = gpu::Fence::create_signaled(m_device)
- .transform_error(monadic::
- assert("Failed to create swapchain image "
- "in flight fence"))
- .value(),
- .image_available = gpu::Semaphore::create(m_device)
- .transform_error(monadic::assert("Failed to create "
- "present wait semaphore"))
- .value(),
- .render_cmb = m_command_pool->create_command_buffer()
- .transform_error(monadic::assert("Failed to create transition "
- "command buffers"))
- .value(),
+ .in_flight = TryAssert(gpu::Fence::create_signaled(m_device),
+ "Failed to create swapchain image "
+ "in flight fence!"),
+ .image_available = TryAssert(gpu::Semaphore::create(m_device),
+ "Failed to create "
+ "present wait semaphore!"),
+ .render_cmb = TryAssert(m_command_pool->create_command_buffer(),
+ "Failed to create transition "
+ "command buffers!"),
});
}
});
@@ -123,65 +110,43 @@ class Application: public base::Application {
// transition swapchain image to present image
const auto& images = m_swapchain->images();
- const auto image_count = stdr::size(images);
- auto transition_cmbs
- = m_command_pool->create_command_buffers(image_count)
- .transform_error(monadic::assert("Failed to create transition command buffers"))
- .value();
+ const auto image_count = stdr::size(images);
+ auto transition_cmbs = TryAssert(m_command_pool->create_command_buffers(image_count),
+ "Failed to create transition command buffers!");
m_image_resources.reserve(stdr::size(images));
auto image_index = 0u;
for (const auto& swap_image : images) {
- auto view = gpu::ImageView::create(m_device, swap_image)
- .transform_error(core::monadic::
- assert("Failed to create swapchain image view"))
- .value();
- auto framebuffer = m_render_pass
- ->create_frame_buffer(m_device, window_extent, to_refs(view))
- .transform_error(core::monadic::assert(
- std::format("Failed to create framebuffer for image {}",
- image_index)))
- .value();
-
- m_image_resources.push_back({
- .image = as_ref(swap_image),
- .view = std::move(view),
- .framebuffer = std::move(framebuffer),
- .render_finished = gpu::Semaphore::create(m_device)
- .transform_error(core::monadic::assert("Failed to create render "
- "signal semaphore"))
- .value(),
- });
+ auto view = TryAssert(gpu::ImageView::create(m_device, { swap_image }), "Failed to create swapchain image view!");
+
+ m_image_resources.push_back({ .image = swap_image,
+ .view = std::move(view),
+ .render_finished = TryAssert(gpu::Semaphore::create(m_device),
+ "Failed to create render "
+ "signal semaphore!") });
auto& transition_cmb = transition_cmbs[image_index];
- *transition_cmb.begin(true)
- .transform_error(monadic::
- assert("Failed to begin texture transition command buffer"))
- .value()
- ->begin_debug_region(std::format("transition image {}", image_index))
- .transition_image_layout(swap_image,
- gpu::ImageLayout::UNDEFINED,
- gpu::ImageLayout::PRESENT_SRC)
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to begin texture transition command "
- "buffer"));
+ TryDiscardAssert((transition_cmb.record([&](auto cmb) noexcept {
+ cmb.begin_debug_region(std::format("Transition image {}", image_index))
+ .transition_image_layout(swap_image,
+ gpu::ImageLayout::UNDEFINED,
+ gpu::ImageLayout::PRESENT_SRC)
+ .end_debug_region();
+ })),
+ std::format("Failed to record transition cmb {}!", image_index));
++image_index;
}
- const auto fence = gpu::Fence::create(m_device)
- .transform_error(monadic::assert("Failed to create transition fence"))
- .value();
+ const auto fence = TryAssert(gpu::Fence::create(m_device), "Failed to create transition fence!");
- const auto cmbs = to_refs(transition_cmbs);
+ const auto cmbs = gpu::to_views(transition_cmbs);
- m_raster_queue->submit({ .command_buffers = cmbs }, as_ref(fence))
- .transform_error(monadic::assert("Failed to submit texture transition command buffers"))
- .value();
+ TryAssert(m_raster_queue->submit({ .command_buffers = cmbs }, fence),
+ "Failed to submit texture transition command buffers!");
// wait for transition to be done
- fence.wait().transform_error(monadic::assert());
+ TryAssert(fence.wait(), "");
}
auto run_example() {
@@ -193,80 +158,69 @@ class Application: public base::Application {
const auto& wait = submission_resource.image_available;
auto& in_flight = submission_resource.in_flight;
- const auto acquire_next_image = bind_front(&gpu::SwapChain::acquire_next_image,
- &*m_swapchain,
- 100ms,
- std::cref(wait));
- const auto extract_index = [](auto&& _result) static noexcept {
- auto&& [result, _image_index] = _result;
- return _image_index;
- };
+ TryAssert(in_flight.wait(), "Failed to wait in_flight fence!");
+ TryAssert(in_flight.reset(), "Failed to reset in_flight fence!");
- const auto
- image_index = in_flight.wait()
- .transform([&in_flight](auto&&) mutable noexcept { in_flight.reset(); })
- .and_then(acquire_next_image)
- .transform(extract_index)
- .transform_error(monadic::
- assert("Failed to acquire next swapchain image"))
- .value();
+ const auto&& [_, image_index] = TryAssert(m_swapchain->acquire_next_image(100ms, wait),
+ "Failed to acquire next swapchain image!");
const auto& swapchain_image_resource = m_image_resources[image_index];
- const auto& framebuffer = swapchain_image_resource.framebuffer;
const auto& signal = swapchain_image_resource.render_finished;
- static constexpr auto PIPELINE_FLAGS = std::array {
- gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT
+ static constexpr auto PIPELINE_FLAGS = array { gpu::PipelineStageFlag::COLOR_ATTACHMENT_OUTPUT };
+
+ const auto window_extent = m_window->extent().to();
+ const auto rendering_info = gpu::RenderingInfo {
+ .render_area = { .x = 0, .y = 0, .width = window_extent.width, .height = window_extent.height },
+ .color_attachments = { { .image_view = swapchain_image_resource.view,
+ .layout = gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ .clear_value = gpu::ClearColor { .color = colors::SILVER } } }
};
// render in it
auto& render_cmb = submission_resource.render_cmb;
- *render_cmb.reset()
- .transform_error(monadic::assert("Failed to reset render command buffer"))
- .value()
- ->begin()
- .transform_error(monadic::assert("Failed to begin render command buffer"))
- .value()
- ->begin_debug_region("Render triangle")
- .begin_render_pass(m_render_pass, framebuffer)
- .bind_pipeline(m_pipeline)
- .draw(3)
- .end_render_pass()
- .end_debug_region()
- .end()
- .transform_error(monadic::assert("Failed to end render command buffer"))
- .value()
- ->submit(m_raster_queue,
- as_refs(wait),
- PIPELINE_FLAGS,
- as_refs(signal),
- as_ref(in_flight))
- .transform_error(monadic::assert("Failed to submit render command buffer"));
+ TryAssert(render_cmb.reset(), std::format("Failed to reset render cmb {}!", image_index));
+ TryDiscardAssert((render_cmb.record([&](auto cmb) noexcept {
+ cmb
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::PRESENT_SRC,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL)
+ .begin_debug_region("Render triangle")
+ .begin_rendering(rendering_info)
+ .bind_pipeline(m_pipeline)
+ .draw(3)
+ .end_rendering()
+ .end_debug_region()
+ .transition_image_layout(swapchain_image_resource.image,
+ gpu::ImageLayout::ATTACHMENT_OPTIMAL,
+ gpu::ImageLayout::PRESENT_SRC);
+ })),
+ std::format("Failed to record render cmb {}!", image_index));
+
+ TryDiscardAssert(render_cmb.submit(m_raster_queue, gpu::as_views(wait), PIPELINE_FLAGS, gpu::as_views(signal), in_flight),
+ "Failed to submit render command buffer");
// present it
- auto update_current_frame = [this](auto&&) mutable noexcept {
- if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
- };
+ TryDiscardAssert(m_raster_queue->present(gpu::as_views(m_swapchain), gpu::as_views(signal), as_view(image_index)),
+ "Failed to present swapchain image!");
- m_raster_queue->present(as_refs(m_swapchain), as_refs(signal), as_view(image_index))
- .transform(update_current_frame)
- .transform_error(monadic::assert("Failed to present swapchain image"));
+ if (++m_current_frame >= BUFFERING_COUNT) m_current_frame = 0;
}
- constexpr auto example_name() const noexcept -> std::string_view { return "Triangle"; }
+ constexpr auto example_name() const noexcept -> string_view { return "Triangle"; }
private:
- DeferInit m_vertex_shader;
- DeferInit m_fragment_shader;
- DeferInit m_pipeline_layout;
- DeferInit m_render_pass;
- DeferInit m_pipeline;
- std::vector m_submission_resources;
- std::vector m_image_resources;
- usize m_current_frame = 0_usize;
+ DeferInit m_vertex_shader;
+ DeferInit m_fragment_shader;
+ DeferInit m_pipeline_layout;
+ DeferInit m_render_pass;
+ DeferInit m_pipeline;
+ dyn_array m_submission_resources;
+ dyn_array m_image_resources;
+ usize m_current_frame = 0_usize;
};
-auto main(std::span args) -> int {
+auto main(array_view args) -> int {
auto app = Application {};
app.run(args);
return 0;
diff --git a/examples/gpu/triangle/win32/manifest.manifest b/examples/gpu/triangle/win32/manifest.manifest
deleted file mode 100644
index 4a9b5f6a6..000000000
--- a/examples/gpu/triangle/win32/manifest.manifest
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- true
- PerMonitorV2
-
-
-
diff --git a/examples/gpu/triangle/xmake.lua b/examples/gpu/triangle/xmake.lua
index 7069fe24b..762d686d0 100644
--- a/examples/gpu/triangle/xmake.lua
+++ b/examples/gpu/triangle/xmake.lua
@@ -1,46 +1,28 @@
-if is_plat("linux") then
- add_requires(
- "nzsl",
- { configs = { toolchains = "gcc", runtimes = "stdc++_shared", fs_watcher = false, link = {} } }
- )
-elseif is_plat("windows") then
- add_requires("nzsl", { configs = { toolchains = "msvc", runtimes = "MD", fs_watcher = false, links = {} } })
-else
- add_requires("nzsl", { configs = { fs_watcher = false, links = {} } })
+local runtimes
+local toolchain
+if is_plat("windows") then
+ runtimes = "MD"
+ toolchain = "msvc"
+elseif is_plat("linux") then
+ runtimes = "stdc++_shared"
+ toolchain = "gcc"
end
+add_requires("nzsl", { configs = { fs_watcher = false, kind = "binary", toolchains = toolchain, runtimes = runtimes } })
target("triangle", function()
- set_kind("binary")
- set_languages("cxxlatest", "clatest")
+ add_rules("stormkit::example", "compile.shaders")
- add_rules("stormkit.flags")
- -- add_rules("platform.windows.subsystem.windows")
- add_rules("platform.windows.subsystem.console")
-
- add_rules("compile.shaders")
- add_deps("core", "main", "log", "wsi", "gpu", "stormkit")
-
- if is_mode("debug") then
- add_defines("STORMKIT_BUILD_DEBUG")
- add_defines("STORMKIT_ASSERT=1")
- set_suffixname("-d")
- else
- add_defines("STORMKIT_ASSERT=0")
- end
-
- add_files("../common/app.mpp")
- add_files("src/*.cpp")
- add_files("shaders/*.nzsl")
- if is_plat("windows") then add_files("win32/*.manifest") end
-
- add_includedirs("$(builddir)/shaders")
+ add_files("src/*.cpp", "src/*.cppm", "../common/app.cppm", "shaders/*.nzsl")
if get_config("devmode") then
- add_defines('SHADER_DIR="$(builddir)/shaders"')
- set_rundir("$(projectdir)")
+ add_defines(format('RESOURCE_DIR="%s"', path.unix(path.join(os.projectdir(), "gpu/triangle"))))
+ add_defines(format('SHADER_DIR="%s"', path.unix("$(builddir)/shaders")))
end
-
add_embeddirs("$(builddir)/shaders")
+ if get_config("devmode") then set_rundir("$(projectdir)") end
+
+ add_packages("nzsl")
+
set_group("examples/stormkit-gpu")
end)
diff --git a/examples/log/console-logger/iOS/info.plist b/examples/log/console-logger/iOS/info.plist
deleted file mode 100644
index 83e13e582..000000000
--- a/examples/log/console-logger/iOS/info.plist
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- LSRequiresIPhoneOS
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
-
-
diff --git a/examples/log/console-logger/macOS/info.plist b/examples/log/console-logger/macOS/info.plist
deleted file mode 100644
index f68f66070..000000000
--- a/examples/log/console-logger/macOS/info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
-
-
-
diff --git a/examples/log/console-logger/src/main.cpp b/examples/log/console-logger/src/main.cpp
index 869b4f17f..f1a8be34f 100644
--- a/examples/log/console-logger/src/main.cpp
+++ b/examples/log/console-logger/src/main.cpp
@@ -4,15 +4,14 @@
import std;
-import stormkit.core;
-import stormkit.log;
+import stormkit;
#include
using namespace stormkit;
struct Bar {
- std::string d = "FooBar";
+ string d = "FooBar";
};
template
@@ -20,30 +19,35 @@ struct std::formatter: std::formatter, Char
template
auto format(const Bar& data, FormatContext& ctx) const -> decltype(ctx.out()) {
auto&& out = ctx.out();
- return format_to(out, "[Bar: d = {}]", data.d);
+ return format_to(out, "[Bar d: {}]", data.d);
}
};
struct Foo {
- u32 a = 0u;
- float b = 2.3f;
- Bar c = Bar {};
+ u32 a = 0u;
+ f32 b = 2.3f;
+ Bar c = Bar {};
};
-template
-struct std::formatter: std::formatter, CharT> {
- template
- auto format(const Foo& data, FormatContext& ctx) const -> decltype(ctx.out()) {
- auto&& out = ctx.out();
- return format_to(out, "[Foo: a = {}, b = {}, c = {}]", data.a, data.b, data.c);
- }
-};
+template
+auto format_as(const Foo& data, FormatContext& ctx) -> decltype(ctx.out()) {
+ return std::format_to(ctx.out(), "[Foo a: {}, b: {}, c: {}]", data.a, data.b, data.c);
+}
+
+namespace stdr = std::ranges;
+namespace stdv = std::views;
////////////////////////////////////////
////////////////////////////////////////
-auto main(std::span) -> int {
+auto main(array_view args) -> int {
using log::operator""_module;
+ // force debug
+ auto args2 = dyn_array { std::from_range, args };
+ args2.emplace_back("--debug");
+
+ log::parse_args(args2);
+
auto logger = log::Logger::create_logger_instance();
log::Logger::ilog("This is an information");
diff --git a/examples/log/console-logger/xmake.lua b/examples/log/console-logger/xmake.lua
index c7a024340..91bc43c2e 100644
--- a/examples/log/console-logger/xmake.lua
+++ b/examples/log/console-logger/xmake.lua
@@ -1,22 +1,7 @@
-target("console-logger")
-do
- set_kind("binary")
- set_languages("cxxlatest", "clatest")
+target("console-logger", function()
+ add_rules("stormkit::example")
- add_rules("stormkit.flags")
- add_rules("platform.windows.subsystem.console")
-
- add_deps("core", "main", "log")
-
- if is_mode("debug") then
- add_defines("STORMKIT_BUILD_DEBUG")
- add_defines("STORMKIT_ASSERT=1")
- set_suffixname("-d")
- else
- add_defines("STORMKIT_ASSERT=0")
- end
-
- add_files("src/main.cpp")
+ add_files("src/*.cpp")
set_group("examples/stormkit-log")
-end
+end)
diff --git a/examples/log/file-logger/macOS/info.plist b/examples/log/file-logger/macOS/info.plist
deleted file mode 100644
index f68f66070..000000000
--- a/examples/log/file-logger/macOS/info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleExecutable
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
- CFBundleGetInfoString
- ${MACOSX_BUNDLE_INFO_STRING}
- CFBundleIconFile
- ${MACOSX_BUNDLE_ICON_FILE}
- CFBundleIdentifier
- ${MACOSX_BUNDLE_GUI_IDENTIFIER}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleLongVersionString
- ${MACOSX_BUNDLE_LONG_VERSION_STRING}
- CFBundleName
- ${MACOSX_BUNDLE_BUNDLE_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
- CFBundleSignature
- ????
- CFBundleVersion
- ${MACOSX_BUNDLE_BUNDLE_VERSION}
- CSResourcesFileMapped
-
- NSHumanReadableCopyright
- ${MACOSX_BUNDLE_COPYRIGHT}
- NSHighResolutionCapable
-
-
-
diff --git a/examples/log/file-logger/src/main.cpp b/examples/log/file-logger/src/main.cpp
index 79586a346..7b033ab0c 100644
--- a/examples/log/file-logger/src/main.cpp
+++ b/examples/log/file-logger/src/main.cpp
@@ -4,8 +4,7 @@
import std;
-import stormkit.core;
-import stormkit.log;
+import stormkit;
#include
@@ -14,32 +13,27 @@ import stormkit.log;
using namespace stormkit;
struct Bar {
- std::string d = "FooBar";
+ string d = "FooBar";
};
template
struct std::formatter: std::formatter, CharT> {
template
auto format(const Bar& data, FormatContext& ctx) const -> decltype(ctx.out()) {
- auto&& out = ctx.out();
- return format_to(out, "[Bar: d = {}]", data.d);
+ return format_to(ctx.out(), "[Bar d: {}]", data.d);
}
};
struct Foo {
stormkit::u32 a = 0u;
- float b = 2.3f;
+ f32 b = 2.3f;
Bar c = Bar {};
};
-template
-struct std::formatter: std::formatter, CharT> {
- template