From 28f0f88c03f4489181623a7e88e6253ebfd5cf62 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 31 Mar 2021 12:18:16 +0200 Subject: [PATCH] Provisional multithreading framework --- .vscode/launch.json | 4 +- CMakeLists.txt | 11 +- cmake-variants.json | 8 +- cmake/FindAssimp.cmake | 3 +- cmake/SuperBuild.cmake | 19 +- res/shaders/generated/Placeholder.txt | 1 + src/Engine/Arch/CMakeLists.txt | 1 + src/Engine/Asset/MeshLoader.cpp | 9 +- src/Engine/CMakeLists.txt | 2 + src/Engine/Containers/Array.h | 226 ++++++++++-------- src/Engine/Containers/List.h | 8 + src/Engine/Containers/Map.h | 82 +++++-- src/Engine/Fibers/CMakeLists.txt | 6 + src/Engine/Fibers/Fibers.cpp | 36 +++ src/Engine/Fibers/Fibers.h | 205 ++++++++++++++++ src/Engine/Fibers/JobQueue.cpp | 134 +++++++++++ src/Engine/Fibers/JobQueue.h | 56 +++++ src/Engine/Graphics/Mesh.h | 2 +- src/Engine/Graphics/VertexShaderInput.cpp | 4 +- .../Graphics/Vulkan/VulkanCommandBuffer.cpp | 8 +- .../Graphics/Vulkan/VulkanDescriptorSets.cpp | 12 +- .../Graphics/Vulkan/VulkanFramebuffer.cpp | 2 +- .../Graphics/Vulkan/VulkanPipelineCache.cpp | 6 +- .../Graphics/Vulkan/VulkanRenderPass.cpp | 6 +- src/Engine/Graphics/Vulkan/VulkanRenderPass.h | 2 +- src/Engine/Graphics/Vulkan/VulkanShader.cpp | 2 +- src/Engine/Material/Material.cpp | 14 +- src/Engine/Math/Transform.h | 2 +- src/Engine/MinimalEngine.h | 2 +- src/Engine/Scene/Scene.cpp | 2 +- src/Engine/main.cpp | 4 + test/Engine/CMakeLists.txt | 1 + test/Engine/Containers/Map.cpp | 2 +- test/Engine/EngineTest.cpp | 2 +- test/Engine/EngineTest.h | 24 +- test/Engine/Fibers/CMakeLists.txt | 5 + test/Engine/Fibers/Fibers.cpp | 61 +++++ 37 files changed, 788 insertions(+), 186 deletions(-) create mode 100644 res/shaders/generated/Placeholder.txt create mode 100644 src/Engine/Arch/CMakeLists.txt create mode 100644 src/Engine/Fibers/CMakeLists.txt create mode 100644 src/Engine/Fibers/Fibers.cpp create mode 100644 src/Engine/Fibers/Fibers.h create mode 100644 src/Engine/Fibers/JobQueue.cpp create mode 100644 src/Engine/Fibers/JobQueue.h create mode 100644 test/Engine/Fibers/CMakeLists.txt create mode 100644 test/Engine/Fibers/Fibers.cpp diff --git a/.vscode/launch.json b/.vscode/launch.json index b530dec..b924ddd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,8 +12,8 @@ "args": [], "stopAtEntry": false, "cwd": "${workspaceRoot}/bin/Debug", + "console": "internalConsole", "environment": [], - "externalConsole": false, "symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64", "requireExactSource": false, "logging": { @@ -30,9 +30,9 @@ "program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe", "args": [], "stopAtEntry": false, + "console": "internalConsole", "cwd": "${workspaceRoot}/bin/Debug", "environment": [], - "externalConsole": false }, ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a5a091d..076fc8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) # Handle superbuild first option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON) @@ -27,6 +27,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/bin/Release) +add_compile_options($<$:/MP>) + if (USE_SUPERBUILD) project (SUPERBUILD NONE) # execute the superbuild (this script will be invoked again without the @@ -52,13 +54,12 @@ find_package(SLang REQUIRED) include_directories(${GLM_INCLUDE_DIRS}) include_directories(${STB_INCLUDE_DIRS}) include_directories(${Vulkan_INCLUDE_DIR}) -include_directories(${SPIRV_INCLUDE_DIRS}) +#include_directories(${SPIRV_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${GLFW_INCLUDE_DIRS}) include_directories(${SLANG_INCLUDE_DIRS}) include_directories(${ASSIMP_INCLUDE_DIRS}) include_directories(${JSON_INCLUDE_DIRS}) -include_directories(${SPIRV_INCLUDE_DIRS}) include_directories(${ENGINE_ROOT}) include_directories(src/Engine) add_definitions(${Vulkan_DEFINITIONS}) @@ -77,7 +78,7 @@ target_link_libraries(SeeleEngine ${GLFW_LIBRARIES}) target_link_libraries(SeeleEngine ${SLANG_LIBRARIES}) target_link_libraries(SeeleEngine ${ASSIMP_LIBRARIES}) target_link_libraries(SeeleEngine ${JSON_LIBRARY}) -target_link_libraries(SeeleEngine ${SPIRV_LIBRARIES}) +#target_link_libraries(SeeleEngine ${SPIRV_LIBRARIES}) #target_precompile_headers(SeeleEngine # PRIVATE diff --git a/cmake-variants.json b/cmake-variants.json index 32d3500..6bd2045 100644 --- a/cmake-variants.json +++ b/cmake-variants.json @@ -6,17 +6,17 @@ "debug": { "short": "Debug", "long": "Enable debugging and validation", - "buildType": "Debug", "settings": { - "CMAKE_DEBUG_POSTFIX": "d" + "CMAKE_DEBUG_POSTFIX": "d", + "CMAKE_BUILD_TYPE": "Debug" } }, "release": { "short": "Release", "long": "Optimize binary for speed", - "buildType": "Release", "settings": { - "CMAKE_DEBUG_POSTFIX": "" + "CMAKE_DEBUG_POSTFIX": "", + "CMAKE_BUILD_TYPE": "Release" } } } diff --git a/cmake/FindAssimp.cmake b/cmake/FindAssimp.cmake index 537ae50..b987e3a 100644 --- a/cmake/FindAssimp.cmake +++ b/cmake/FindAssimp.cmake @@ -29,7 +29,8 @@ if (WIN32) NAMES assimp-vc${MSVC_TOOLSET_VERSION}-mt${CMAKE_DEBUG_POSTFIX}.lib PATHS $ENV{PROGRAMFILES}/lib - ${ASSIMP_ROOT}/lib/) + ${ASSIMP_ROOT}/lib + ${ASSIMP_ROOT}/lib/${CMAKE_BUILD_TYPE}) find_file( ASSIMP_BINARY diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 3f0cb29..04cb460 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -5,8 +5,11 @@ set(EXTRA_CMAKE_ARGS) #------------ASSIMP--------------- list(APPEND DEPENDENCIES assimp) set(ASSIMP_BUILD_TESTS OFF CACHE INTERNAL "") +set(ASSIMP_BUILD_SAMPLES OFF CACHE INTERNAL "") +set(ASSIMP_BUILD_OVERALLS OFF CACHE INTERNAL "") set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "") set(ASSIMP_INSTALL OFF CACHE INTERNAL "") +set(ASSIMP_BUILD_ZLIB OFF CACHE INTERNAL "") set(BUILD_SHARED_LIBS ON CACHE INTERNAL "") add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT}) @@ -74,14 +77,14 @@ ExternalProject_Add(slang endif() #----------------SPIR-V-CROSS-------------------- -list(APPEND DEPENDENCIES spirv-cross-reflect) -set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "") -set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "") -set(SPIRV_CROSS_CLI OFF CACHE BOOL "") -set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "") -set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE BOOL "") -set(SPIRV_CROSS_SKIP_INSTALL ON CACHE BOOL "") -add_subdirectory(${SPIRV_ROOT}) +# list(APPEND DEPENDENCIES spirv-cross-reflect) +# set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "") +# set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "") +# set(SPIRV_CROSS_CLI OFF CACHE BOOL "") +# set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "") +# set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE BOOL "") +# set(SPIRV_CROSS_SKIP_INSTALL ON CACHE BOOL "") +# add_subdirectory(${SPIRV_ROOT}) #-----------------SeeleEngine-------------------- diff --git a/res/shaders/generated/Placeholder.txt b/res/shaders/generated/Placeholder.txt new file mode 100644 index 0000000..e751b3f --- /dev/null +++ b/res/shaders/generated/Placeholder.txt @@ -0,0 +1 @@ +This file needs to be here because otherwise git will delete the folder and the engine can't automatically generate it \ No newline at end of file diff --git a/src/Engine/Arch/CMakeLists.txt b/src/Engine/Arch/CMakeLists.txt new file mode 100644 index 0000000..d44f6af --- /dev/null +++ b/src/Engine/Arch/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(x64/) \ No newline at end of file diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index 12f98f4..f46cc2d 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -29,8 +29,7 @@ MeshLoader::~MeshLoader() void MeshLoader::importAsset(const std::filesystem::path &path) { - //futures.add(std::async(std::launch::async, &MeshLoader::import, this, path)); - import(path); + futures.add(std::async(std::launch::async, &MeshLoader::import, this, path)); } void MeshLoader::loadMaterials(const aiScene* scene, Array& globalMaterials, Gfx::PGraphics graphics) @@ -118,7 +117,7 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gf vbInfo.vertexSize = sizeof(Vector); vbInfo.resourceData.data = (uint8 *)buffer.data(); vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - vbInfo.resourceData.size = sizeof(Vector) * buffer.size(); + vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size(); return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT); } VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics) @@ -133,7 +132,7 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gf vbInfo.vertexSize = sizeof(Vector2); vbInfo.resourceData.data = (uint8 *)buffer.data(); vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - vbInfo.resourceData.size = sizeof(Vector2) * buffer.size(); + vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size(); return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT); } void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, const Array& materials, Gfx::PGraphics graphics) @@ -180,7 +179,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array& globalMesh idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32; idxInfo.resourceData.data = (uint8 *)indices.data(); idxInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - idxInfo.resourceData.size = sizeof(uint32) * indices.size(); + idxInfo.resourceData.size = sizeof(uint32) * (uint32)indices.size(); Gfx::PIndexBuffer indexBuffer = graphics->createIndexBuffer(idxInfo); indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index 8aee034..9702511 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -5,7 +5,9 @@ target_sources(SeeleEngine main.cpp) add_subdirectory(Asset/) +add_subdirectory(Arch/) add_subdirectory(Containers/) +add_subdirectory(Fibers/) add_subdirectory(Graphics/) add_subdirectory(Material/) add_subdirectory(Math/) diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 2e5ccca..3a83e19 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -25,12 +25,12 @@ namespace Seele //std::memset(_data, 0, sizeof(T) * DEFAULT_ALLOC_SIZE); refreshIterators(); } - Array(uint32 size, T value = T()) + Array(size_t size, T value = T()) : allocated(size), arraySize(size) { _data = new T[size]; assert(_data != nullptr); - for (uint32 i = 0; i < size; ++i) + for (size_t i = 0; i < size; ++i) { assert(i < size); _data[i] = value; @@ -38,7 +38,7 @@ namespace Seele refreshIterators(); } Array(std::initializer_list init) - : allocated((uint32)init.size()), arraySize((uint32)init.size()) + : allocated(init.size()), arraySize(init.size()) { _data = new T[init.size()]; auto it = init.begin(); @@ -194,6 +194,17 @@ namespace Seele } return endIt; } + Iterator find(T&& item) + { + for (uint32 i = 0; i < arraySize; ++i) + { + if (_data[i] == item) + { + return Iterator(&_data[i]); + } + } + return endIt; + } Iterator begin() const { return beginIt; @@ -215,11 +226,11 @@ namespace Seele { if (arraySize == allocated) { - uint32 newSize = arraySize + 1; + size_t newSize = arraySize + 1; allocated = calculateGrowth(newSize); T *tempArray = new T[allocated]; assert(tempArray != nullptr); - for (uint32 i = 0; i < arraySize; ++i) + for (size_t i = 0; i < arraySize; ++i) { tempArray[i] = _data[i]; } @@ -230,6 +241,25 @@ namespace Seele refreshIterators(); return _data[arraySize - 1]; } + T &add(T&& item) + { + if (arraySize == allocated) + { + size_t newSize = arraySize + 1; + allocated = calculateGrowth(newSize); + T *tempArray = new T[allocated]; + assert(tempArray != nullptr); + for (size_t i = 0; i < arraySize; ++i) + { + tempArray[i] = std::move(_data[i]); + } + delete[] _data; + _data = tempArray; + } + _data[arraySize++] = std::move(item); + refreshIterators(); + return _data[arraySize - 1]; + } T &addUnique(const T &item = T()) { Iterator it; @@ -240,22 +270,22 @@ namespace Seele return add(item); } template - T &emplace(args...) + T &emplace(args... arguments) { if (arraySize == allocated) { - uint32 newSize = arraySize + 1; + size_t newSize = arraySize + 1; allocated = calculateGrowth(newSize); T *tempArray = new T[allocated]; assert(tempArray != nullptr); - for (uint32 i = 0; i < arraySize; ++i) + for (size_t i = 0; i < arraySize; ++i) { tempArray[i] = _data[i]; } delete[] _data; _data = tempArray; } - _data[arraySize++] = T(args...); + _data[arraySize++] = T(arguments...); refreshIterators(); return _data[arraySize - 1]; } @@ -271,7 +301,7 @@ namespace Seele } else { - _data[index] = _data[arraySize - 1]; + _data[index] = std::move(_data[arraySize - 1]); } arraySize--; } @@ -283,7 +313,7 @@ namespace Seele allocated = 0; refreshIterators(); } - void resize(uint32 newSize) + void resize(size_t newSize) { if (newSize < allocated) { @@ -301,27 +331,31 @@ namespace Seele } refreshIterators(); } - inline uint32 indexOf(Iterator iterator) + inline size_t indexOf(Iterator iterator) { return iterator - beginIt; } - inline uint32 indexOf(ConstIterator iterator) const + inline size_t indexOf(ConstIterator iterator) const { return iterator.p - beginIt.p; } - inline uint32 indexOf(T& t) + inline size_t indexOf(T& t) { return indexOf(find(t)); } - inline uint32 indexOf(const T& t) const + inline size_t indexOf(const T& t) const { return indexOf(find(t)); } - inline uint32 size() const + inline size_t size() const { return arraySize; } - inline uint32 capacity() const + inline size_t empty() const + { + return arraySize == 0; + } + inline size_t capacity() const { return allocated; } @@ -338,44 +372,27 @@ namespace Seele arraySize--; refreshIterators(); } - T &operator[](uint32 index) + T &operator[](size_t index) { assert(index < arraySize); return _data[index]; } - inline T &operator[](size_t index) - { - return this->operator[]((uint32)index); - } - inline T &operator[](int32 index) - { - return this->operator[]((uint32)index); - } - const T &operator[](uint32 index) const + const T &operator[](size_t index) const { assert(index < arraySize); return _data[index]; } - inline const T &operator[](size_t index) const - { - return this->operator[]((uint32)index); - } - inline const T &operator[](int32 index) const - { - return this->operator[]((uint32)index); - } - private: - uint32 calculateGrowth(uint32 newSize) const + size_t calculateGrowth(size_t newSize) const { - const uint32 oldCapacity = capacity(); + const size_t oldCapacity = capacity(); - if (oldCapacity > UINT32_MAX - oldCapacity / 2) + if (oldCapacity > SIZE_MAX - oldCapacity / 2) { return newSize; // geometric growth would overflow } - const uint32 geometric = oldCapacity + oldCapacity / 2; + const size_t geometric = oldCapacity + oldCapacity / 2; if (geometric < newSize) { @@ -395,71 +412,30 @@ namespace Seele { ar & arraySize; ar & allocated; - for(uint32 i = 0; i < arraySize; ++i) + for(size_t i = 0; i < arraySize; ++i) ar & _data[i]; refreshIterators(); } - uint32 arraySize; - uint32 allocated; + size_t arraySize; + size_t allocated; Iterator beginIt; Iterator endIt; T *_data; }; - template + template struct StaticArray { - public: - StaticArray() - { - beginIt = Iterator(_data); - endIt = Iterator(_data + N); - } - StaticArray(T value) - { - for (int i = 0; i < N; ++i) - { - _data[i] = value; - } - beginIt = Iterator(_data); - endIt = Iterator(_data + N); - } - ~StaticArray() - { - } - - inline uint32 size() const - { - return N; - } - inline T *data() - { - return _data; - } - inline const T *data() const - { - return _data; - } - T &operator[](int index) - { - assert(index >= 0 && index < N); - return _data[index]; - } - const T &operator[](int index) const - { - assert(index >= 0 && index < N); - return _data[index]; - } - + public: template class IteratorBase { public: - typedef std::forward_iterator_tag iterator_category; - typedef X value_type; - typedef std::ptrdiff_t difference_type; - typedef X &reference; - typedef X *pointer; + using iterator_category = std::forward_iterator_tag; + using value_type = X; + using difference_type = std::ptrdiff_t; + using reference = X&; + using pointer = X*; IteratorBase(X *x = nullptr) : p(x) @@ -500,36 +476,86 @@ namespace Seele private: X *p; }; - typedef IteratorBase Iterator; - typedef IteratorBase ConstIterator; + using value_type = T; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; - Iterator begin() + using iterator = IteratorBase; + using const_iterator = IteratorBase; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + StaticArray() + { + beginIt = iterator(_data); + endIt = iterator(_data + N); + } + StaticArray(T value) + { + for (int i = 0; i < N; ++i) + { + _data[i] = value; + } + beginIt = iterator(_data); + endIt = iterator(_data + N); + } + ~StaticArray() + { + } + + inline size_type size() const + { + return N; + } + inline pointer data() + { + return _data; + } + inline const_pointer data() const + { + return _data; + } + constexpr reference operator[](size_type index) noexcept + { + assert(index >= 0 && index < N); + return _data[index]; + } + constexpr const_reference operator[](size_type index) const noexcept + { + assert(index >= 0 && index < N); + return _data[index]; + } + iterator begin() { return beginIt; } - Iterator end() + iterator end() { return endIt; } - ConstIterator begin() const + const_iterator begin() const { return beginIt; } - ConstIterator end() const + const_iterator end() const { return beginIt; } private: T _data[N]; - Iterator beginIt; - Iterator endIt; + iterator beginIt; + iterator endIt; friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int version) { ar & N; ar & _data; - refreshIterators(); } }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 8d7ce8d..198dcea 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -250,6 +250,14 @@ public: refreshIterators(); return Iterator(next); } + void popBack() + { + remove(Iterator(tail->prev)); + } + void popFront() + { + remove(Iterator(root)); + } Iterator insert(Iterator pos, const T &value) { _size++; diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 470bb0a..3ee75e2 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Array.h" namespace Seele @@ -9,12 +10,15 @@ struct Pair public: Pair() : key(K()), value(V()) - { - } - Pair(K key, V value) - : key(key), value(value) - { - } + {} + template + explicit Pair(KeyType&& key) + : key(key), value(V()) + {} + template + explicit Pair(KeyType&& key, ValueType&& value) + : key(std::move(key)), value(std::move(value)) + {} K key; V value; }; @@ -28,11 +32,12 @@ private: Node *leftChild; Node *rightChild; Node() - : leftChild(nullptr), rightChild(nullptr), pair(K(), V()) + : leftChild(nullptr), rightChild(nullptr), pair() { } - Node(const K &key) - : leftChild(nullptr), rightChild(nullptr), pair(key, V()) + template + explicit Node(KeyType&& key, ValueType&& value) + : leftChild(nullptr), rightChild(nullptr), pair(key, value) { } Node(const Node& other) @@ -242,7 +247,7 @@ public: Iterator operator--(int) { Iterator tmp(*this); - ++*this; + --*this; return tmp; } Iterator operator++(int) @@ -256,8 +261,7 @@ public: Node *node; Array traversal; }; - - V &operator[](const K &key) + V &operator[](const K& key) { root = splay(root, key); if (root == nullptr || root->pair.key < key || key < root->pair.key) @@ -268,7 +272,18 @@ public: } return root->pair.value; } - Iterator find(const K &key) + V &operator[](K&& key) + { + root = splay(root, std::forward(key)); + if (root == nullptr || root->pair.key < key || key < root->pair.key) + { + root = insert(root, std::forward(key)); + _size++; + refreshIterators(); + } + return root->pair.value; + } + Iterator find(const K& key) { root = splay(root, key); if (root == nullptr || root->pair.key != key) @@ -277,10 +292,25 @@ public: } return Iterator(root); } - Iterator erase(const K &key) + Iterator find(K&& key) + { + root = splay(root, std::move(key)); + if (root == nullptr || root->pair.key != key) + { + return endIt; + } + return Iterator(root); + } + Iterator erase(const K& key) { root = remove(root, key); refreshIterators(); + return Iterator(root); + } + Iterator erase(K&& key) + { + root = remove(root, std::move(key)); + refreshIterators(); return Iterator(root); } void clear() @@ -290,9 +320,9 @@ public: _size = 0; refreshIterators(); } - bool exists(const K &key) + bool exists(K&& key) { - return find(key) != endIt; + return find(std::forward(key)) != endIt; } Iterator begin() const { @@ -365,21 +395,19 @@ private: y->leftChild = node; return y; } - Node *makeNode(const K &key) - { - return new Node(key); - } - Node *insert(Node *r, const K &key) + template + Node *insert(Node *r, KeyType&& key) { if (r == nullptr) - return makeNode(key); - + { + return new Node(std::forward(key), V()); + } r = splay(r, key); if (!(r->pair.key < key || key < r->pair.key)) return r; - Node *newNode = makeNode(key); + Node *newNode = new Node(std::forward(key), V()); if (key < r->pair.key) { @@ -395,7 +423,8 @@ private: } return newNode; } - Node *remove(Node *r, const K &key) + template + Node *remove(Node *r, KeyType&& key) { Node *temp; if (!r) @@ -424,7 +453,8 @@ private: delete temp; return r; } - Node *splay(Node *r, const K &key) + template + Node *splay(Node *r, KeyType&& key) { if (r == nullptr || !(r->pair.key < key || key < r->pair.key)) { diff --git a/src/Engine/Fibers/CMakeLists.txt b/src/Engine/Fibers/CMakeLists.txt new file mode 100644 index 0000000..5fcd8d5 --- /dev/null +++ b/src/Engine/Fibers/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(SeeleEngine + PRIVATE + Fibers.h + Fibers.cpp + JobQueue.h + JobQueue.cpp) \ No newline at end of file diff --git a/src/Engine/Fibers/Fibers.cpp b/src/Engine/Fibers/Fibers.cpp new file mode 100644 index 0000000..d7e181a --- /dev/null +++ b/src/Engine/Fibers/Fibers.cpp @@ -0,0 +1,36 @@ +#include "Fibers.h" + +using namespace Seele; +using namespace Seele::Fibers; + +std::atomic_uint64_t FiberJob::jobIDGenerator; + +Counter::Counter() +{ + count.store(0); +} + +Counter::Counter(uint64 initialValue) +{ + count.store(initialValue); +} + +Counter::~Counter() +{ +} + +AwaitCounter&& FiberTask::promise_type::await_transform(AwaitCounter&& awaitCounter) +{ + counter = awaitCounter.counter; + target = awaitCounter.target; + priority = awaitCounter.priority; + return std::move(awaitCounter); +} + +FiberJob::FiberJob() +{ +} + +FiberJob::~FiberJob() +{ +} diff --git a/src/Engine/Fibers/Fibers.h b/src/Engine/Fibers/Fibers.h new file mode 100644 index 0000000..f96d74d --- /dev/null +++ b/src/Engine/Fibers/Fibers.h @@ -0,0 +1,205 @@ +#pragma once +#include "MinimalEngine.h" +#include "JobQueue.h" +#include +#include + +namespace Seele +{ +namespace Fibers +{ +class Counter +{ +public: + Counter(); + Counter(uint64 initialValue); + ~Counter(); + inline void increment() + { + count++; + } + inline void decrement() + { + count--; + } + inline void setValue(uint64 value) + { + count.store(value); + } + inline uint64 getValue() + { + return count.load(); + } + inline bool greaterEqual(uint64 target) + { + return count.load() >= target; + } + inline bool greaterThan(uint64 target) + { + return count.load() > target; + } + inline bool lessEqual(uint64 target) + { + return count.load() <= target; + } + inline bool lessThan(uint64 target) + { + return count.load() < target; + } + inline bool equals(uint64 target) + { + return count.load() == target; + } + friend std::strong_ordering operator<=>(const Counter& counter, uint64 other) + { + return counter.count.load() <=> other; + } + friend std::ostream& operator<<(std::ostream& stream, const Counter* counter) + { + stream << counter->count; + return stream; + } + friend std::ostream& operator<<(std::ostream& stream, PCounter counter) + { + stream << counter->count; + return stream; + } +private: + std::atomic_uint64_t count; +}; +DEFINE_REF(Counter); +struct AwaitCounter +{ + PCounter counter; + uint64 target; + JobPriority priority = JobPriority::MEDIUM; + bool await_ready() { return counter->greaterEqual(target); } + void await_suspend(std::coroutine_handle<> h) { + } + void await_resume() {} +}; +struct AwaitCounter; +class FiberTask +{ +public: + struct promise_type; + using handle_type = std::coroutine_handle; +private: + promise_type* promise; +public: + FiberTask() = default; + explicit FiberTask(promise_type* promise) + : promise(promise) {} + FiberTask(const FiberTask& other) + : promise(other.promise) {} + FiberTask(FiberTask&& other) + : promise(std::move(other.promise)) {} + FiberTask& operator=(const FiberTask& other) + { + promise = other.promise; + return *this; + } + FiberTask& operator=(FiberTask&& other) + { + promise = std::move(other.promise); + return *this; + } + inline void resume() { promise->resume(); } + inline void destroy() { promise->destroy(); } + inline bool done() { return promise->done(); } + inline PCounter getCounter() const { return promise->counter; } + inline uint64 getTarget() const { return promise->target; } + inline JobPriority getPriority() const { return promise->priority; } + struct promise_type + { + promise_type() + { + handle = handle_type::from_promise(*this); + } + ~promise_type() = default; + promise_type(const promise_type&) = delete; + promise_type(promise_type&&) = delete; + promise_type &operator=(const promise_type&) = delete; + promise_type &operator=(promise_type&&) = delete; + FiberTask get_return_object() + { + return FiberTask(this); + } + auto initial_suspend() { return std::suspend_never{}; } + auto final_suspend() noexcept { return std::suspend_always{}; } + auto return_void() {} + void unhandled_exception() { std::exit(1); } + AwaitCounter&& await_transform(AwaitCounter&& awaitCounter); + inline void resume() { handle.resume(); } + inline void destroy() { handle.destroy(); } + inline bool done() { return handle.done(); } + private: + handle_type handle; + PCounter counter; + uint64 target; + JobPriority priority; + friend class FiberTask; + }; +}; +class FiberJob +{ +public: + FiberJob(); + template + FiberJob(PCounter counter, func function, args... arg) + : counter(counter), function(std::bind(function, arg...)) + { + jobID = jobIDGenerator.fetch_add(1); + } + template + FiberJob(PCounter counter, JobPriority priority, func function, args... arg) + : counter(counter), priority(priority), function(std::bind(function, arg...)) + { + } + FiberJob(const FiberJob& other) = delete; + FiberJob(FiberJob&& other) + : counter(std::move(other.counter)) + , jobID(std::move(other.jobID)) + , priority(std::move(other.priority)) + , function(std::move(other.function)) + { + } + ~FiberJob(); + FiberJob& operator=(const FiberJob& other) = delete; + FiberJob& operator=(FiberJob&& other) + { + if(this != &other) + { + counter = std::move(other.counter); + jobID = std::move(other.jobID); + priority = std::move(other.priority); + function = std::move(other.function); + } + return *this; + } + void operator()() + { + FiberTask task = function(); + if(!task.done()) + { + JobQueue::suspendJob(std::move(task)); + } + else + { + counter->increment(); + task.destroy(); + } + } + inline JobPriority getPriority() + { + return priority; + } +private: + PCounter counter; + uint64 jobID; + static std::atomic_uint64_t jobIDGenerator; + JobPriority priority = JobPriority::MEDIUM; + std::function function; +}; +} // namespace Fibers +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Fibers/JobQueue.cpp b/src/Engine/Fibers/JobQueue.cpp new file mode 100644 index 0000000..06d4fe7 --- /dev/null +++ b/src/Engine/Fibers/JobQueue.cpp @@ -0,0 +1,134 @@ +#include "JobQueue.h" +#include "Fibers.h" +#include +#include + +using namespace Seele; +using namespace Seele::Fibers; + +std::wstring toString(JobPriority priority) +{ + switch (priority) + { + case JobPriority::HIGH: + return L"HIGH"; + case JobPriority::MEDIUM: + return L"MEDIUM"; + case JobPriority::LOW: + return L"LOW"; + case JobPriority::IO: + return L"IO"; + default: + return L"Illegal Priority"; + } +} + +Array JobQueue::workers; +StaticArray JobQueue::priorityQueues; + +JobQueue::JobQueue(JobPriority priority) + : priority(priority) +{ + threadHandle = std::thread(&JobQueue::work, this); + SetThreadDescription(threadHandle.native_handle(), toString(priority).c_str()); +} + +JobQueue::~JobQueue() +{ + running = false; + threadHandle.join(); +} + +void JobQueue::initJobQueues() +{ + // TODO: make this dependent on actual cores + JobPriority priorities[16] = { + JobPriority::IO, JobPriority::IO, + JobPriority::LOW, JobPriority::LOW, JobPriority::LOW, JobPriority::LOW, + JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM, + JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH}; + + for(uint32 i = 0; i < 16; ++i) + { + workers.add(new JobQueue(priorities[i])); + } +} +void JobQueue::cleanupJobQueues() +{ + for(auto worker : workers) + { + delete worker; + } +} + +void JobQueue::runJobs(FiberJob* jobs, uint32 numJobs) +{ + for(uint32 i = 0; i < numJobs; ++i) + { + JobPriorityInfo& info = priorityQueues[(size_t)jobs[i].getPriority()]; + std::unique_lock lock(info.jobQueueLock); + info.jobQueue.add(std::move(jobs[i])); + //info.jobQueueCV.notify_one(); + } +} + +void JobQueue::waitForCounter(PCounter counter, uint32 waitFor) +{ + while(counter->lessThan(waitFor)) + std::this_thread::yield(); +} + +void JobQueue::suspendJob(FiberTask&& task) +{ + JobPriorityInfo& info = priorityQueues[(size_t)task.getPriority()]; + std::unique_lock lock(info.jobQueueLock); + info.waiterQueue[task.getCounter()].add(task); +} +void JobQueue::refreshWaiterQueue() +{ + JobPriorityInfo& info = priorityQueues[(size_t)priority]; + //shortcut to avoid iterator creation + if(info.waiterQueue.empty()) + return; + for(auto it : info.waiterQueue) + { + auto& entries = info.waiterQueue[it.key]; + for(uint32 i = 0; i < entries.size(); ++i) + { + if(it.key->greaterEqual(entries[i].getTarget())) + { + info.resumableTasks.add(std::move(entries[i])); + entries.remove(i); + i--; + } + } + } +} + +void JobQueue::work() +{ + JobPriorityInfo& targetInfo = priorityQueues[(size_t)priority]; + auto& jobQueue = targetInfo.jobQueue; + auto& resumableTasks = targetInfo.resumableTasks; + while(running) + { + std::unique_lock lock(targetInfo.jobQueueLock); + refreshWaiterQueue(); + if(resumableTasks.size() > 0) + { + FiberTask task = std::move(resumableTasks.front()); + resumableTasks.popFront(); + lock.unlock(); + task.resume(); + lock.lock(); + } + if(jobQueue.size() > 0) + { + FiberJob job = std::move(jobQueue.front()); + jobQueue.popFront(); + lock.unlock(); + job(); + lock.lock(); + } + } +} \ No newline at end of file diff --git a/src/Engine/Fibers/JobQueue.h b/src/Engine/Fibers/JobQueue.h new file mode 100644 index 0000000..9e0130a --- /dev/null +++ b/src/Engine/Fibers/JobQueue.h @@ -0,0 +1,56 @@ +#pragma once +#include "MinimalEngine.h" +#include "Containers/List.h" +#include +namespace Seele +{ +namespace Fibers +{ +class FiberJob; +DECLARE_REF(Counter); +enum class JobPriority : size_t +{ + HIGH = 0, + MEDIUM, + LOW, + IO, + NUM_PRIORITIES +}; +struct AtomicJobQueue +{ +}; +class FiberTask; +struct JobPriorityInfo +{ + List jobQueue; + Map> waiterQueue; + List resumableTasks; + std::mutex jobQueueLock; +}; +class JobQueue +{ +public: + JobQueue(JobPriority priority); + JobQueue(const JobQueue& other) = delete; + JobQueue(JobQueue&& other) = delete; + JobQueue& operator=(const JobQueue& other) = delete; + JobQueue& operator=(JobQueue&& other) = delete; + ~JobQueue(); + static void initJobQueues(); + static void cleanupJobQueues(); + static void runJobs(FiberJob* jobs, uint32 numJobs); + //This does in fact not do any coroutine stuff, but is a simple busy wait + //For coroutine waits, you have to be in a coroutine, and + static void waitForCounter(PCounter counter, uint32 waitFor); + static void suspendJob(FiberTask&& task); + void refreshWaiterQueue(); +private: + void work(); + static Array workers; + static StaticArray priorityQueues; + std::thread threadHandle; + JobPriority priority; + bool running = true; +}; +} // namespace Fibers +} // namespace Seele diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index 291bc09..44a2720 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -57,7 +57,7 @@ private: template void serialize(Archive& ar, const unsigned int version) { - ar & referencedMaterial->getFullPath(); + //ar & referencedMaterial->getFullPath(); //TODO: } }; diff --git a/src/Engine/Graphics/VertexShaderInput.cpp b/src/Engine/Graphics/VertexShaderInput.cpp index 8fc7d28..7d8dbb7 100644 --- a/src/Engine/Graphics/VertexShaderInput.cpp +++ b/src/Engine/Graphics/VertexShaderInput.cpp @@ -91,7 +91,7 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo vertexStream.stride = component.stride; vertexStream.offset = component.offset; - return Gfx::VertexElement(streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride); + return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride); } Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const VertexStreamComponent& component, uint8 attributeIndex) @@ -101,7 +101,7 @@ Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const Vertex vertexStream.stride = component.stride; vertexStream.offset = component.offset; - return Gfx::VertexElement(streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride); + return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride); } void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array& elements) diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index bf2f32f..42a2768 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -65,7 +65,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame VkRenderPassBeginInfo beginInfo = init::RenderPassBeginInfo(); - beginInfo.clearValueCount = renderPass->getClearValueCount(); + beginInfo.clearValueCount = (uint32)renderPass->getClearValueCount(); beginInfo.pClearValues = renderPass->getClearValues(); beginInfo.renderArea = renderPass->getRenderArea(); beginInfo.renderPass = renderPass->getHandle(); @@ -95,7 +95,7 @@ void CmdBuffer::executeCommands(Array commands) } cmdBuffers[i] = command->getHandle(); } - vkCmdExecuteCommands(handle, cmdBuffers.size(), cmdBuffers.data()); + vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); } void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore) @@ -212,7 +212,7 @@ void SecondaryCmdBuffer::bindDescriptor(const Array& descri boundDescriptors.add(descriptorSet); sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); } - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, descriptorSets.size(), sets, 0, nullptr); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); delete[] sets; } void SecondaryCmdBuffer::bindVertexBuffer(const Array& streams) @@ -225,7 +225,7 @@ void SecondaryCmdBuffer::bindVertexBuffer(const Array& stream buffers[i] = buf->getHandle(); offsets[i] = streams[i].offset; }; - vkCmdBindVertexBuffers(handle, 0, streams.size(), buffers.data(), offsets.data()); + vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data()); } void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) { diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index d55d7e3..15a677d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -39,7 +39,7 @@ void DescriptorLayout::create() binding.pImmutableSamplers = nullptr; } VkDescriptorSetLayoutCreateInfo createInfo = - init::DescriptorSetLayoutCreateInfo(bindings.data(), bindings.size()); + init::DescriptorSetLayoutCreateInfo(bindings.data(), (uint32)bindings.size()); VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); allocator = new DescriptorAllocator(graphics, *this); @@ -75,7 +75,7 @@ void PipelineLayout::create() } VkPipelineLayoutCreateInfo createInfo = - init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), vulkanDescriptorLayouts.size()); + init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), (uint32)vulkanDescriptorLayouts.size()); Array vkPushConstants(pushConstants.size()); for (size_t i = 0; i < pushConstants.size(); i++) { @@ -83,7 +83,7 @@ void PipelineLayout::create() vkPushConstants[i].size = pushConstants[i].size; vkPushConstants[i].stageFlags = cast((VkShaderStageFlagBits)pushConstants[i].stageFlags); } - createInfo.pushConstantRangeCount = vkPushConstants.size(); + createInfo.pushConstantRangeCount = (uint32)vkPushConstants.size(); createInfo.pPushConstantRanges = vkPushConstants.data(); boost::crc_32_type result; @@ -198,7 +198,7 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: bool DescriptorSet::operator<(Gfx::PDescriptorSet other) { PDescriptorSet otherSet = other.cast(); - return setHandle < otherSet->setHandle; + return this < otherSet.getHandle(); } void DescriptorSet::writeChanges() @@ -210,7 +210,7 @@ void DescriptorSet::writeChanges() currentlyBound->getManager()->waitForCommands(currentlyBound); currentlyBound = nullptr; } - vkUpdateDescriptorSets(graphics->getDevice(), writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); + vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); writeDescriptors.clear(); imageInfos.clear(); bufferInfos.clear(); @@ -241,7 +241,7 @@ DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &l poolSizes.add(size); } } - VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), maxSets); + VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo((uint32)poolSizes.size(), poolSizes.data(), maxSets); VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); } diff --git a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp index a255e51..e360dda 100644 --- a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp @@ -34,7 +34,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRende VkFramebufferCreateInfo createInfo = init::FramebufferCreateInfo( renderPass->getHandle(), - attachments.size(), + (uint32)attachments.size(), attachments.data(), renderPass->getRenderArea().extent.width, renderPass->getRenderArea().extent.height, diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp index da27c45..ff71ade 100644 --- a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp @@ -215,9 +215,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo std::memcpy(hashStruct.attribs, attributes.data(), attributes.size() * sizeof(VkVertexInputAttributeDescription)); vertexInput.pVertexBindingDescriptions = bindings.data(); - vertexInput.vertexBindingDescriptionCount = bindings.size(); + vertexInput.vertexBindingDescriptionCount = (uint32)bindings.size(); vertexInput.pVertexAttributeDescriptions = attributes.data(); - vertexInput.vertexAttributeDescriptionCount = attributes.size(); + vertexInput.vertexAttributeDescriptionCount = (uint32)attributes.size(); VkPipelineInputAssemblyStateCreateInfo assemblyInfo = init::PipelineInputAssemblyStateCreateInfo( @@ -291,7 +291,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo } VkPipelineColorBlendStateCreateInfo blendState = init::PipelineColorBlendStateCreateInfo( - blendAttachments.size(), + (uint32)blendAttachments.size(), blendAttachments.data() ); blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable; diff --git a/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp b/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp index 649cf0c..86dc697 100644 --- a/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp @@ -91,10 +91,10 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout) VkSubpassDescription subPassDesc = init::SubpassDescription( VK_PIPELINE_BIND_POINT_GRAPHICS, - colorRefs.size(), + (uint32)colorRefs.size(), colorRefs.data(), &depthRef, - inputRefs.size(), + (uint32)inputRefs.size(), inputRefs.data()); VkSubpassDependency dependency = {}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; @@ -108,7 +108,7 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout) VkRenderPassCreateInfo info = init::RenderPassCreateInfo( - attachments.size(), + (uint32)attachments.size(), attachments.data(), 1, &subPassDesc, diff --git a/src/Engine/Graphics/Vulkan/VulkanRenderPass.h b/src/Engine/Graphics/Vulkan/VulkanRenderPass.h index 761e95c..47bd40e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanRenderPass.h +++ b/src/Engine/Graphics/Vulkan/VulkanRenderPass.h @@ -15,7 +15,7 @@ public: { return renderPass; } - inline uint32 getClearValueCount() const + inline size_t getClearValueCount() const { return clearValues.size(); } diff --git a/src/Engine/Graphics/Vulkan/VulkanShader.cpp b/src/Engine/Graphics/Vulkan/VulkanShader.cpp index 3207163..ec64d01 100644 --- a/src/Engine/Graphics/Vulkan/VulkanShader.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanShader.cpp @@ -113,7 +113,7 @@ void Shader::create(const ShaderCreateInfo& createInfo) spAddSearchPath(request, "shaders/lib/"); spAddSearchPath(request, "shaders/generated/"); - spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data()); + spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data()); int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type)); if(spCompile(request)) diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index c6cc5a0..16300a0 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -65,7 +65,7 @@ void Material::compile() for(auto param : j["params"].items()) { std::string type = param.value()["type"].get(); - auto default = param.value().find("default"); + auto defaultValue = param.value().find("default"); if(type.compare("float") == 0) { PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0); @@ -76,9 +76,9 @@ void Material::compile() uniformBinding = bindingCounter++; } uniformBufferOffset += 4; - if(default != param.value().end()) + if(defaultValue != param.value().end()) { - p->data = std::stof(default.value().get()); + p->data = std::stof(defaultValue.value().get()); } parameters.add(p); } @@ -92,9 +92,9 @@ void Material::compile() uniformBinding = bindingCounter++; } uniformBufferOffset += 12; - if(default != param.value().end()) + if(defaultValue != param.value().end()) { - p->data = parseVector(default.value().get().c_str()); + p->data = parseVector(defaultValue.value().get().c_str()); } parameters.add(p); } @@ -102,9 +102,9 @@ void Material::compile() { PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter); layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE); - if(default != param.value().end()) + if(defaultValue != param.value().end()) { - p->data = AssetRegistry::findTexture(default.value().get()); + p->data = AssetRegistry::findTexture(defaultValue.value().get()); } else { diff --git a/src/Engine/Math/Transform.h b/src/Engine/Math/Transform.h index 35174a4..d35351c 100644 --- a/src/Engine/Math/Transform.h +++ b/src/Engine/Math/Transform.h @@ -10,7 +10,7 @@ public: Transform(); Transform(const Transform &other); Transform(Transform &&other); - Transform(Vector position); + explicit Transform(Vector position); Transform(Vector position, Quaternion rotation); Transform(Vector position, Quaternion rotation, Vector scale); Transform(Quaternion rotation, Vector scale); diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index aebc2a8..60faa45 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -108,7 +108,7 @@ public: private: T *handle; - uint64 refCount; + std::atomic_uint64_t refCount; }; template diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index 8fdc082..63fcbd4 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -15,7 +15,7 @@ Scene::Scene(Gfx::PGraphics graphics) lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1); lightEnv.numDirectionalLights = 1; lightEnv.numPointLights = 0; - srand(time(NULL)); + srand((unsigned int)time(NULL)); } Scene::~Scene() diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index cc3aaee..f2da2e4 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -1,7 +1,11 @@ #include "Graphics/RenderCore.h" #include "Window/SceneView.h" #include "Asset/AssetRegistry.h" +#include "Fibers/Fibers.h" +#include + using namespace Seele; + int main() { RenderCore core; diff --git a/test/Engine/CMakeLists.txt b/test/Engine/CMakeLists.txt index 86f8b74..36ee31c 100644 --- a/test/Engine/CMakeLists.txt +++ b/test/Engine/CMakeLists.txt @@ -5,5 +5,6 @@ target_sources(Seele_unit_tests EngineTest.cpp) target_include_directories(Seele_unit_tests PUBLIC ./) add_subdirectory(Containers/) +add_subdirectory(Fibers/) add_subdirectory(Graphics/) add_subdirectory(Math/) \ No newline at end of file diff --git a/test/Engine/Containers/Map.cpp b/test/Engine/Containers/Map.cpp index 531fbda..f235b4d 100644 --- a/test/Engine/Containers/Map.cpp +++ b/test/Engine/Containers/Map.cpp @@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(for_each) map[6] = 4; map[4] = 7; int count = 0; - for(auto it = map.begin(); it != map.end(); ++it) + for(auto it : map) { count++; } diff --git a/test/Engine/EngineTest.cpp b/test/Engine/EngineTest.cpp index ddd2712..fefd4c6 100644 --- a/test/Engine/EngineTest.cpp +++ b/test/Engine/EngineTest.cpp @@ -3,7 +3,7 @@ #include using namespace Seele; - +BOOST_TEST_GLOBAL_FIXTURE(GlobalFixture); BOOST_AUTO_TEST_SUITE(RefPtr) struct TestStruct diff --git a/test/Engine/EngineTest.h b/test/Engine/EngineTest.h index 7b9637e..a3d7ec7 100644 --- a/test/Engine/EngineTest.h +++ b/test/Engine/EngineTest.h @@ -1 +1,23 @@ -#pragma once \ No newline at end of file +#pragma once +#include "Fibers/JobQueue.h" + +namespace Seele +{ + struct GlobalFixture + { + GlobalFixture() + { + } + ~GlobalFixture() + { + } + void setup() + { + Fibers::JobQueue::initJobQueues(); + } + void teardown() + { + Fibers::JobQueue::cleanupJobQueues(); + } + }; +}; \ No newline at end of file diff --git a/test/Engine/Fibers/CMakeLists.txt b/test/Engine/Fibers/CMakeLists.txt new file mode 100644 index 0000000..7a89398 --- /dev/null +++ b/test/Engine/Fibers/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(Seele_unit_tests + PRIVATE + ../../../src/Engine/Fibers/JobQueue.cpp + ../../../src/Engine/Fibers/Fibers.cpp + Fibers.cpp) \ No newline at end of file diff --git a/test/Engine/Fibers/Fibers.cpp b/test/Engine/Fibers/Fibers.cpp new file mode 100644 index 0000000..ea290ec --- /dev/null +++ b/test/Engine/Fibers/Fibers.cpp @@ -0,0 +1,61 @@ +#include "EngineTest.h" +#include "MinimalEngine.h" +#include "Fibers/Fibers.h" +#include +#include + +using namespace Seele; +using namespace Seele::Fibers; + +BOOST_AUTO_TEST_SUITE(Fibers_Suite) + +FiberTask basicFiberSync1(PCounter syncCounter) +{ + syncCounter->increment(); + std::cout << "basicFiberSync1 start" << std::endl; + co_await AwaitCounter{syncCounter, 2}; + std::cout << "basicFiberSync1 has resumed, counter is " << syncCounter << std::endl; + co_return; +} + +FiberTask basicFiberSync2(PCounter syncCounter) +{ + syncCounter->increment(); + std::cout << "basicFiberSync2 start" << std::endl; + co_await AwaitCounter(syncCounter, 3); + std::cout << "basicFiberSync2 has resumed, counter is " << syncCounter << std::endl; + co_return; +} +BOOST_AUTO_TEST_CASE(basicFiberSync) +{ + PCounter syncCounter = new Counter(1); + PCounter counter1 = new Counter(); + FiberJob job1 = FiberJob(counter1, &basicFiberSync1, syncCounter); + JobQueue::runJobs(&job1, 1); + FiberJob job2 = FiberJob(counter1, &basicFiberSync2, syncCounter); + JobQueue::runJobs(&job2, 1); + while(counter1->lessThan(2)) + std::this_thread::yield(); + BOOST_CHECK_EQUAL(syncCounter->getValue(), 3); +} +FiberTask incrementJob(PCounter localCounter) +{ + localCounter->increment(); + co_return; +} +BOOST_AUTO_TEST_CASE(jobBatch) +{ + PCounter localCounter = new Counter(); + PCounter jobCounter = new Counter(); + FiberJob jobs[256]; + for(int i = 0; i < 256; ++i) + { + jobs[i] = FiberJob(jobCounter, JobPriority::HIGH, &incrementJob, localCounter); + } + JobQueue::runJobs(jobs, 256); + while(jobCounter->lessThan(256)) + std::this_thread::yield(); + BOOST_CHECK_EQUAL(localCounter->getValue(), 256); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file