From 312ae2af9a36b1fcba2ebf2dc1cfc67303490b85 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Tue, 13 Apr 2021 23:09:16 +0200 Subject: [PATCH] 3700 FPS here we go --- .vscode/c_cpp_properties.json | 2 +- .vscode/launch.json | 21 +++- .vscode/settings.json | 5 +- CMakeLists.txt | 1 - cmake-variants.json | 2 + cmake/FindAssimp.cmake | 3 +- cmake/SuperBuild.cmake | 7 +- external/assimp | 2 +- src/Engine/Asset/Asset.h | 19 +++- src/Engine/Asset/AssetRegistry.cpp | 4 +- src/Engine/Asset/MeshAsset.cpp | 4 +- src/Engine/Asset/MeshAsset.h | 2 +- src/Engine/Asset/MeshLoader.cpp | 15 ++- src/Engine/Asset/MeshLoader.h | 2 +- src/Engine/Asset/TextureLoader.cpp | 6 +- src/Engine/Containers/Array.h | 71 +++++++----- src/Engine/Containers/List.h | 10 +- src/Engine/Containers/Map.h | 90 +++++++++++---- src/Engine/Graphics/GraphicsInitializer.h | 2 +- src/Engine/Graphics/GraphicsResources.cpp | 2 +- src/Engine/Graphics/GraphicsResources.h | 2 +- src/Engine/Graphics/Mesh.cpp | 1 + src/Engine/Graphics/RenderPass/BasePass.cpp | 14 +-- src/Engine/Graphics/RenderPass/BasePass.h | 1 - src/Engine/Graphics/Vulkan/CMakeLists.txt | 1 + .../Graphics/Vulkan/VulkanCommandBuffer.cpp | 51 ++++++--- .../Graphics/Vulkan/VulkanCommandBuffer.h | 7 +- .../Graphics/Vulkan/VulkanDescriptorSets.cpp | 77 ++++++++----- .../Graphics/Vulkan/VulkanDescriptorSets.h | 105 +++++++++--------- .../Graphics/Vulkan/VulkanInitializer.cpp | 11 +- src/Engine/Graphics/Vulkan/VulkanQueue.cpp | 71 ++++++------ src/Engine/Graphics/Vulkan/VulkanQueue.h | 1 + src/Engine/Material/Material.cpp | 3 +- src/Engine/MinimalEngine.h | 9 +- .../Scene/Components/PrimitiveComponent.h | 7 +- src/Engine/Window/RenderPath.cpp | 1 + 36 files changed, 401 insertions(+), 231 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 77107a0..2c29662 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,7 +11,7 @@ "UNICODE", "_UNICODE" ], - "intelliSenseMode": "clang-x64", + "intelliSenseMode": "msvc-x64", "configurationProvider": "ms-vscode.cmake-tools", "cppStandard": "c++20", "browse": { diff --git a/.vscode/launch.json b/.vscode/launch.json index b924ddd..67360e2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "Engine", + "name": "Engine Debug", "type": "cppvsdbg", "request": "launch", "program": "${workspaceRoot}/bin/Debug/SeeleEngine.exe", @@ -23,6 +23,25 @@ "traceResponse": true } }, + { + "name": "Engine Release", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceRoot}/bin/Release/SeeleEngine.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceRoot}/bin/Release", + "console": "internalConsole", + "environment": [], + "symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64", + "requireExactSource": false, + "logging": { + "moduleLoad": false, + "exceptions": true, + "trace": true, + "traceResponse": true + } + }, { "name": "Test", "type": "cppvsdbg", diff --git a/.vscode/settings.json b/.vscode/settings.json index 7fea7f4..766531d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -106,12 +106,13 @@ "scoped_allocator": "cpp", "stack": "cpp", "coroutine": "cpp", - "*.tcc": "cpp" + "*.tcc": "cpp", + "stop_token": "cpp" }, "cmake.skipConfigureIfCachePresent": false, "cmake.configureArgs": [ "-Wno-dev" ], "C_Cpp.default.cppStandard": "c++20", - "C_Cpp.default.intelliSenseMode": "gcc-x64" + "C_Cpp.default.intelliSenseMode": "msvc-x64" } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ec6f2c..30f5519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw) set(JSON_ROOT ${EXTERNAL_ROOT}/json) set(STB_ROOT ${EXTERNAL_ROOT}/stb) set(SPIRV_ROOT ${EXTERNAL_ROOT}/SPIRV-Cross) -set(Boost_DEBUG ON) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/) diff --git a/cmake-variants.json b/cmake-variants.json index 6bd2045..195bd88 100644 --- a/cmake-variants.json +++ b/cmake-variants.json @@ -6,6 +6,7 @@ "debug": { "short": "Debug", "long": "Enable debugging and validation", + "buildType": "Debug", "settings": { "CMAKE_DEBUG_POSTFIX": "d", "CMAKE_BUILD_TYPE": "Debug" @@ -14,6 +15,7 @@ "release": { "short": "Release", "long": "Optimize binary for speed", + "buildType": "Release", "settings": { "CMAKE_DEBUG_POSTFIX": "", "CMAKE_BUILD_TYPE": "Release" diff --git a/cmake/FindAssimp.cmake b/cmake/FindAssimp.cmake index fe0705d..a321eac 100644 --- a/cmake/FindAssimp.cmake +++ b/cmake/FindAssimp.cmake @@ -30,7 +30,8 @@ if (WIN32) PATHS $ENV{PROGRAMFILES}/lib ${ASSIMP_ROOT}/lib - ${ASSIMP_ROOT}/lib/${CMAKE_BUILD_TYPE}) + ${ASSIMP_ROOT}/code + PATH_SUFFIXES Debug Release) find_file( ASSIMP_BINARY diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 486f080..d4049ac 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -14,8 +14,11 @@ set(BUILD_SHARED_LIBS ON CACHE INTERNAL "") add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT}) target_compile_definitions(assimp PRIVATE _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) -target_compile_options(assimp PRIVATE -Wno-error) - +#if(WIN32) +# target_compile_options(assimp PRIVATE /WX-) +#else() +# target_compile_options(assimp PRIVATE -Wno-error) +#endif() #-------------BOOST---------------- list(APPEND DEPENDENCIES boost) if(WIN32) diff --git a/external/assimp b/external/assimp index 110f884..8f0c6b0 160000 --- a/external/assimp +++ b/external/assimp @@ -1 +1 @@ -Subproject commit 110f8845a2aa72f0712269dfbeeee91d4849590c +Subproject commit 8f0c6b04b2257a520aaab38421b2e090204b69df diff --git a/src/Engine/Asset/Asset.h b/src/Engine/Asset/Asset.h index 5fa86bb..e6da6e7 100644 --- a/src/Engine/Asset/Asset.h +++ b/src/Engine/Asset/Asset.h @@ -28,16 +28,31 @@ public: std::string getExtension() const; inline Status getStatus() { - std::scoped_lock lck(lock); + std::unique_lock lck(lock); return status; } inline void setStatus(Status status) { - std::scoped_lock lck(lock); + std::unique_lock lck(lock); this->status = status; + if(status == Status::Ready) + { + readyCV.notify_all(); + } } protected: + inline void waitReady() + { + std::unique_lock lck(lock); + if(status != Status::Ready) + { + std::cout << "Asset " << name.generic_string() << " not ready yet, waiting" << std::endl; + readyCV.wait(lck); + std::cout << "Asset " << name.generic_string() << " now ready, continuing" << std::endl; + } + } std::mutex lock; + std::condition_variable readyCV; std::ifstream& getReadStream(); std::ofstream& getWriteStream(); private: diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp index 4360ceb..125045f 100644 --- a/src/Engine/Asset/AssetRegistry.cpp +++ b/src/Engine/Asset/AssetRegistry.cpp @@ -43,7 +43,9 @@ void AssetRegistry::importFile(const std::string &filePath) PMeshAsset AssetRegistry::findMesh(const std::string &filePath) { - return get().meshes[filePath]; + auto it = get().meshes.find(filePath); + assert(it != get().meshes.end()); + return it->value; } PTextureAsset AssetRegistry::findTexture(const std::string &filePath) diff --git a/src/Engine/Asset/MeshAsset.cpp b/src/Engine/Asset/MeshAsset.cpp index 8b5a9ac..66d7109 100644 --- a/src/Engine/Asset/MeshAsset.cpp +++ b/src/Engine/Asset/MeshAsset.cpp @@ -1,5 +1,6 @@ #include "MeshAsset.h" #include "Graphics/Mesh.h" +#include "Graphics/VertexShaderInput.h" #include #include @@ -40,7 +41,8 @@ void MeshAsset::addMesh(PMesh mesh) referencedMaterials.add(mesh->referencedMaterial); } -const Array MeshAsset::getMeshes() const +const Array MeshAsset::getMeshes() { + waitReady(); return meshes; } \ No newline at end of file diff --git a/src/Engine/Asset/MeshAsset.h b/src/Engine/Asset/MeshAsset.h index e76c668..919fad4 100644 --- a/src/Engine/Asset/MeshAsset.h +++ b/src/Engine/Asset/MeshAsset.h @@ -15,7 +15,7 @@ public: virtual void save() override; virtual void load() override; void addMesh(PMesh mesh); - const Array getMeshes() const; + const Array getMeshes(); private: Array meshes; Array referencedMaterials; diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index 589d980..bbe841a 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -29,7 +29,11 @@ MeshLoader::~MeshLoader() void MeshLoader::importAsset(const std::filesystem::path &path) { - futures.add(std::async(std::launch::async, &MeshLoader::import, this, path)); + std::filesystem::path assetPath = path.filename(); + assetPath.replace_extension("asset"); + PMeshAsset meshAsset = new MeshAsset(assetPath.generic_string()); + AssetRegistry::get().registerMesh(meshAsset); + futures.add(std::async(std::launch::async, &MeshLoader::import, this, meshAsset, path)); } void MeshLoader::loadMaterials(const aiScene* scene, Array& globalMaterials, Gfx::PGraphics graphics) @@ -224,8 +228,9 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& AssetRegistry::importFile(texPngPath.string()); } } -void MeshLoader::import(const std::filesystem::path &path) +void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path) { + meshAsset->setStatus(Asset::Status::Loading); Assimp::Importer importer; importer.ReadFile(path.string().c_str(), aiProcess_FlipUVs | @@ -246,9 +251,7 @@ void MeshLoader::import(const std::filesystem::path &path) List meshNodes; findMeshRoots(scene->mRootNode, meshNodes); - std::filesystem::path filePath = path.filename(); - filePath.replace_extension("asset"); - PMeshAsset meshAsset = new MeshAsset(filePath.generic_string()); + for (auto meshNode : meshNodes) { for(uint32 i = 0; i < meshNode->mNumMeshes; ++i) @@ -256,6 +259,6 @@ void MeshLoader::import(const std::filesystem::path &path) meshAsset->addMesh(globalMeshes[meshNode->mMeshes[i]]); } } + meshAsset->setStatus(Asset::Status::Ready); meshAsset->save(); - AssetRegistry::get().registerMesh(meshAsset); } diff --git a/src/Engine/Asset/MeshLoader.h b/src/Engine/Asset/MeshLoader.h index e0cd3d7..0c4ebc7 100644 --- a/src/Engine/Asset/MeshLoader.h +++ b/src/Engine/Asset/MeshLoader.h @@ -25,7 +25,7 @@ private: void loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, const Array& materials, Gfx::PGraphics graphics); void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels); - void import(const std::filesystem::path& path); + void import(PMeshAsset meshAsset, const std::filesystem::path& path); List> futures; Gfx::PGraphics graphics; }; diff --git a/src/Engine/Asset/TextureLoader.cpp b/src/Engine/Asset/TextureLoader.cpp index 0eedb27..61d753e 100644 --- a/src/Engine/Asset/TextureLoader.cpp +++ b/src/Engine/Asset/TextureLoader.cpp @@ -28,12 +28,14 @@ void TextureLoader::importAsset(const std::filesystem::path& filePath) PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string()); asset->setStatus(Asset::Status::Loading); asset->setTexture(placeholderTexture); + std::cout << "Loading texture, placeholder" << std::endl; AssetRegistry::get().textures[asset->getFileName()] = asset; - //futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { + futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { Gfx::PTexture2D texture = import(filePath); asset->setTexture(texture); asset->setStatus(Asset::Status::Ready); - //})); + std::cout << "Finished loading texture" << std::endl; + })); } PTextureAsset TextureLoader::getPlaceholderTexture() diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 5c11eab..3dd591d 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -12,10 +12,14 @@ namespace Seele { + enum class Init_t { + NO_INIT + }; template struct Array { public: + Array() : arraySize(0) , allocated(DEFAULT_ALLOC_SIZE) @@ -23,7 +27,15 @@ namespace Seele _data = new T[DEFAULT_ALLOC_SIZE]; assert(_data != nullptr); //std::memset(_data, 0, sizeof(T) * DEFAULT_ALLOC_SIZE); - refreshIterators(); + markIteratorDirty(); + } + Array(Init_t) + : arraySize(0) + , allocated(0) + , _data(nullptr) + , beginIt(Iterator(nullptr)) + , endIt(Iterator(nullptr)) + { } Array(size_t size, T value = T()) : arraySize(size) @@ -36,7 +48,7 @@ namespace Seele assert(i < size); _data[i] = value; } - refreshIterators(); + markIteratorDirty(); } Array(std::initializer_list init) : arraySize(init.size()) @@ -49,7 +61,7 @@ namespace Seele assert(i < init.size()); _data[i] = *it; } - refreshIterators(); + markIteratorDirty(); } Array(const Array &other) : arraySize(other.arraySize) @@ -57,7 +69,7 @@ namespace Seele { _data = new T[other.allocated]; assert(_data != nullptr); - refreshIterators(); + markIteratorDirty(); std::copy(other.begin(), other.end(), beginIt); } Array(Array &&other) noexcept @@ -68,7 +80,7 @@ namespace Seele other._data = nullptr; other.allocated = 0; other.arraySize = 0; - refreshIterators(); + markIteratorDirty(); } Array &operator=(const Array &other) noexcept { @@ -76,12 +88,15 @@ namespace Seele { if (_data != nullptr) { - delete[] _data; + if(other.arraySize > allocated) + { + delete[] _data; + _data = new T[other.allocated]; + allocated = other.allocated; + } } - allocated = other.allocated; arraySize = other.arraySize; - _data = new T[other.allocated]; - refreshIterators(); + markIteratorDirty(); std::copy(other.begin(), other.end(), beginIt); } return *this; @@ -93,12 +108,13 @@ namespace Seele if (_data != nullptr) { delete[] _data; + _data = nullptr; } allocated = std::move(other.allocated); arraySize = std::move(other.arraySize); _data = other._data; other._data = nullptr; - refreshIterators(); + markIteratorDirty(); } return *this; } @@ -132,15 +148,15 @@ namespace Seele { return p; } - inline bool operator!=(const IteratorBase &other) + inline bool operator!=(const IteratorBase &other) const { return p != other.p; } - inline bool operator==(const IteratorBase &other) + inline bool operator==(const IteratorBase &other) const { return p == other.p; } - inline int operator-(const IteratorBase &other) + inline int operator-(const IteratorBase &other) const { return (int)(p - other.p); } @@ -238,7 +254,7 @@ namespace Seele _data = tempArray; } _data[arraySize++] = item; - refreshIterators(); + markIteratorDirty(); return _data[arraySize - 1]; } T &add(T&& item) @@ -257,7 +273,7 @@ namespace Seele _data = tempArray; } _data[arraySize++] = std::move(item); - refreshIterators(); + markIteratorDirty(); return _data[arraySize - 1]; } T &addUnique(const T &item = T()) @@ -286,7 +302,7 @@ namespace Seele _data = tempArray; } _data[arraySize++] = T(arguments...); - refreshIterators(); + markIteratorDirty(); return _data[arraySize - 1]; } void remove(Iterator it, bool keepOrder = true) @@ -314,7 +330,7 @@ namespace Seele _data = nullptr; arraySize = 0; allocated = 0; - refreshIterators(); + markIteratorDirty(); } void resize(size_t newSize) { @@ -335,7 +351,7 @@ namespace Seele delete _data; _data = newData; } - refreshIterators(); + markIteratorDirty(); } inline size_t indexOf(Iterator iterator) { @@ -369,21 +385,21 @@ namespace Seele { return _data; } - T &back() const + inline T &back() const { return _data[arraySize - 1]; } void pop() { arraySize--; - refreshIterators(); + markIteratorDirty(); } - T &operator[](size_t index) + constexpr inline T &operator[](size_t index) { assert(index < arraySize); return _data[index]; } - const T &operator[](size_t index) const + constexpr inline const T &operator[](size_t index) const { assert(index < arraySize); return _data[index]; @@ -407,7 +423,7 @@ namespace Seele return geometric; // geometric growth is sufficient } - void refreshIterators() + void markIteratorDirty() { beginIt = Iterator(_data); endIt = Iterator(_data + arraySize); @@ -416,18 +432,17 @@ namespace Seele template void serialize(Archive& ar, const unsigned int version) { - ar & version; ar & arraySize; resize(arraySize); for(size_t i = 0; i < arraySize; ++i) ar & _data[i]; - refreshIterators(); + markIteratorDirty(); } - size_t arraySize; - size_t allocated; + size_t arraySize = 0; + size_t allocated = 0; Iterator beginIt; Iterator endIt; - T *_data; + T *_data = nullptr; }; template diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 198dcea..1340ee2 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -203,7 +203,7 @@ public: tail->next = newTail; Iterator insertedElement(tail); tail = newTail; - refreshIterators(); + markIteratorDirty(); _size++; return insertedElement; } @@ -221,7 +221,7 @@ public: tail->next = newTail; Iterator insertedElement(tail); tail = newTail; - refreshIterators(); + markIteratorDirty(); _size++; return insertedElement; } @@ -247,7 +247,7 @@ public: next->prev = prev; } delete pos.node; - refreshIterators(); + markIteratorDirty(); return Iterator(next); } void popBack() @@ -270,7 +270,7 @@ public: root->prev = nullptr; tail->prev = root; tail->next = nullptr; - refreshIterators(); + markIteratorDirty(); return beginIt; } Node *tmp = pos.node->prev; @@ -319,7 +319,7 @@ public: } private: - void refreshIterators() + void markIteratorDirty() { beginIt = Iterator(root); endIt = Iterator(tail); diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 937b707..6ecc8d8 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -110,16 +110,22 @@ private: public: Map() - : root(nullptr), _size(0) + : root(nullptr) + , _size(0) + , iteratorsDirty(false) + , beginIt(nullptr) + , endIt(nullptr) { } Map(const Map& other) - : root(new Node(*other.root)), _size(other._size) + : root(new Node(*other.root)) + , _size(other._size) { refreshIterators(); } Map(Map&& other) - : root(std::move(other.root)), _size(other._size) + : root(std::move(other.root)) + , _size(other._size) { refreshIterators(); } @@ -137,7 +143,7 @@ public: } root = new Node(*other.root); _size = other.size; - refreshIterators(); + markIteratorDirty(); } return *this; } @@ -151,21 +157,21 @@ public: } root = new Node(std::move(*other.root)); _size = std::move(other._size); - refreshIterators(); + markIteratorDirty(); } return *this; } class Iterator { public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef Pair value_type; - typedef std::ptrdiff_t difference_type; - typedef Pair &reference; - typedef Pair *pointer; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = Pair; + using difference_type = std::ptrdiff_t; + using reference = Pair&; + using pointer = Pair*; Iterator(Node *x = nullptr) - : node(x) + : node(x), traversal(Init_t::NO_INIT) { } Iterator(Node *x, Array &&beginIt) @@ -261,31 +267,32 @@ public: Node *node; Array traversal; }; - V &operator[](const K& key) + inline V &operator[](const K& key) { root = splay(root, key); + markIteratorDirty(); if (root == nullptr || root->pair.key < key || key < root->pair.key) { root = insert(root, key); _size++; - refreshIterators(); } return root->pair.value; } - V &operator[](K&& key) + inline V &operator[](K&& key) { root = splay(root, std::forward(key)); + markIteratorDirty(); 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); + markIteratorDirty(); if (root == nullptr || root->pair.key != key) { return endIt; @@ -295,6 +302,7 @@ public: Iterator find(K&& key) { root = splay(root, std::move(key)); + markIteratorDirty(); if (root == nullptr || root->pair.key != key) { return endIt; @@ -304,13 +312,13 @@ public: Iterator erase(const K& key) { root = remove(root, key); - refreshIterators(); + markIteratorDirty(); return Iterator(root); } Iterator erase(K&& key) { root = remove(root, std::move(key)); - refreshIterators(); + markIteratorDirty(); return Iterator(root); } void clear() @@ -318,18 +326,42 @@ public: delete root; root = nullptr; _size = 0; - refreshIterators(); + markIteratorDirty(); } bool exists(K&& key) { return find(std::forward(key)) != endIt; } + Iterator begin() + { + if(iteratorsDirty) + { + refreshIterators(); + } + return beginIt; + } + Iterator end() + { + if(iteratorsDirty) + { + refreshIterators(); + } + return endIt; + } Iterator begin() const { + if(iteratorsDirty) + { + return calcBeginIterator(); + } return beginIt; } Iterator end() const { + if(iteratorsDirty) + { + return calcEndIterator(); + } return endIt; } bool empty() const @@ -342,12 +374,22 @@ public: } private: + void markIteratorDirty() + { + iteratorsDirty = true; + } void refreshIterators() + { + beginIt = calcBeginIterator(); + endIt = calcEndIterator(); + iteratorsDirty = false; + } + inline Iterator calcBeginIterator() const { Node *beginNode = root; if (root == nullptr) { - beginIt = Iterator(nullptr); + return Iterator(nullptr); } else { @@ -359,12 +401,15 @@ private: } beginNode = beginTraversal.back(); beginTraversal.pop(); - beginIt = Iterator(beginNode, std::move(beginTraversal)); + return Iterator(beginNode, std::move(beginTraversal)); } + } + inline Iterator calcEndIterator() const + { Node *endNode = root; if (root == nullptr) { - endIt = Iterator(nullptr); + return Iterator(nullptr); } else { @@ -374,12 +419,13 @@ private: endTraversal.add(endNode); endNode = endNode->rightChild; } - endIt = Iterator(endNode, std::move(endTraversal)); + return Iterator(endNode, std::move(endTraversal)); } } Node *root; Iterator beginIt; Iterator endIt; + bool iteratorsDirty; uint32 _size; Node *rotateRight(Node *node) { diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h index 60a5ae3..37f5c75 100644 --- a/src/Engine/Graphics/GraphicsInitializer.h +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -22,7 +22,7 @@ struct GraphicsInitializer GraphicsInitializer() : applicationName("SeeleEngine") , engineName("SeeleEngine") - , layers{"VK_LAYER_KHRONOS_validation"} + , layers{"VK_LAYER_KHRONOS_validation", "VK_LAYER_LUNARG_monitor"} , instanceExtensions{} , deviceExtensions{"VK_KHR_swapchain"} , windowHandle(nullptr) diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index 8ef5607..1ffcb7e 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -73,7 +73,7 @@ ShaderCollection& ShaderMap::createShaders( collection.fragmentShader = graphics->createFragmentShader(createInfo); } ShaderPermutation permutation; - std::string materialName = material->getFileName(); //Filename is fine, because it just has to be unique + std::string materialName = material->getName(); std::string vertexInputName = vertexInput->getName(); permutation.passType = renderPass; std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName)); diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index 89430b3..27faf8c 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -486,7 +486,7 @@ class RenderCommand public: RenderCommand(); virtual ~RenderCommand(); - virtual void begin() = 0; + virtual bool isReady() = 0; virtual void setViewport(Gfx::PViewport viewport) = 0; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0; virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0; diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index 339b6bc..a1d663b 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -1,4 +1,5 @@ #include "Mesh.h" +#include "VertexShaderInput.h" using namespace Seele; diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 02713fd..c442b16 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -42,18 +42,7 @@ void BasePassMeshProcessor::addMeshBatch( descriptorSet->writeChanges(); cachedPrimitiveSets.add(descriptorSet); } - Gfx::PRenderCommand renderCommand; - if (cachedCommandBuffers.size() > 0) - { - renderCommand = cachedCommandBuffers.back(); - cachedCommandBuffers.pop(); - renderCommand->begin(); - } - else - { - renderCommand = graphics->createRenderCommand(); - renderCommand->begin(); - } + Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); renderCommand->setViewport(target); for(uint32 i = 0; i < batch.elements.size(); ++i) { @@ -84,7 +73,6 @@ Array BasePassMeshProcessor::getRenderCommands() void BasePassMeshProcessor::clearCommands() { - cachedCommandBuffers = renderCommands; renderCommands.clear(); cachedPrimitiveSets.clear(); cachedPrimitiveIndex = 0; diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index df67666..229cfb0 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -22,7 +22,6 @@ public: void clearCommands(); private: Array renderCommands; - Array cachedCommandBuffers; Array cachedPrimitiveSets; Gfx::PViewport target; uint8 translucentBasePass; diff --git a/src/Engine/Graphics/Vulkan/CMakeLists.txt b/src/Engine/Graphics/Vulkan/CMakeLists.txt index b7a1784..cbe8ba1 100644 --- a/src/Engine/Graphics/Vulkan/CMakeLists.txt +++ b/src/Engine/Graphics/Vulkan/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(SeeleEngine VulkanGraphics.cpp VulkanGraphicsResources.h VulkanGraphicsResources.cpp + VulkanDescriptorSets.h VulkanDescriptorSets.cpp VulkanGraphicsEnums.h VulkanGraphicsEnums.cpp diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index eec2510..af6cb4e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -91,12 +91,15 @@ void CmdBuffer::executeCommands(Array commands) for (uint32 i = 0; i < commands.size(); ++i) { auto command = commands[i].cast(); + // Cache array and size to save on pointer access + DescriptorSet** boundDescriptors = command->boundDescriptors.data(); + size_t numDescriptors = command->boundDescriptors.size(); + for(size_t i = 0; i < numDescriptors; ++i) + { + boundDescriptors[i]->currentlyBound = true; + } command->end(); executingCommands.add(command); - for(PDescriptorSet set : command->boundDescriptors) - { - set->setCurrentlyBound(this); - } cmdBuffers[i] = command->getHandle(); } vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); @@ -114,14 +117,14 @@ void CmdBuffer::refreshFence() { if (fence->isSignaled()) { - state = State::ReadyBegin; vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + fence->reset(); for(auto command : executingCommands) { command->reset(); } executingCommands.clear(); - fence->reset(); + state = State::ReadyBegin; } } else @@ -142,6 +145,7 @@ PCommandBufferManager CmdBuffer::getManager() SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) : CmdBufferBase(graphics, cmdPool) + , ready(true) { VkCommandBufferAllocateInfo allocInfo = init::CommandBufferAllocateInfo(cmdPool, @@ -157,6 +161,7 @@ SecondaryCmdBuffer::~SecondaryCmdBuffer() void SecondaryCmdBuffer::begin(PCmdBuffer parent) { + ready = false; VkCommandBufferBeginInfo beginInfo = init::CommandBufferBeginInfo(); VkCommandBufferInheritanceInfo inheritanceInfo = @@ -176,15 +181,20 @@ void SecondaryCmdBuffer::end() void SecondaryCmdBuffer::reset() { - for(auto descriptor : boundDescriptors) + vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + size_t numBoundDescriptors = boundDescriptors.size(); + DescriptorSet** boundDescriptorSets = boundDescriptors.data(); + for(size_t i = 0; i < numBoundDescriptors; ++i) { - descriptor->releaseFromCmd(); + boundDescriptorSets[i]->currentlyBound = false; } + boundDescriptors.clear(); + ready = true; } -void SecondaryCmdBuffer::begin() +bool SecondaryCmdBuffer::isReady() { - begin(graphics->getGraphicsCommands()->getCommands()); + return ready; } void SecondaryCmdBuffer::setViewport(Gfx::PViewport viewport) @@ -203,7 +213,7 @@ void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { auto descriptor = descriptorSet.cast(); - boundDescriptors.add(descriptor); + boundDescriptors.add(descriptor.getHandle()); VkDescriptorSet setHandle = descriptor->getHandle(); vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); } @@ -213,7 +223,7 @@ void SecondaryCmdBuffer::bindDescriptor(const Array& descri for(uint32 i = 0; i < descriptorSets.size(); ++i) { auto descriptorSet = descriptorSets[i].cast(); - boundDescriptors.add(descriptorSet); + boundDescriptors.add(descriptorSet.getHandle()); sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); } vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); @@ -271,7 +281,20 @@ PCmdBuffer CommandBufferManager::getCommands() PSecondaryCmdBuffer CommandBufferManager::createSecondaryCmdBuffer() { - return new SecondaryCmdBuffer(graphics, commandPool); + std::scoped_lock lck(allocatedSecondBufferLock); + for (uint32 i = 0; i < allocatedSecondBuffers.size(); ++i) + { + PSecondaryCmdBuffer cmdBuffer = allocatedSecondBuffers[i]; + if (cmdBuffer->isReady()) + { + cmdBuffer->begin(activeCmdBuffer); + return cmdBuffer; + } + } + PSecondaryCmdBuffer result = new SecondaryCmdBuffer(graphics, commandPool); + allocatedSecondBuffers.add(result); + result->begin(activeCmdBuffer); + return result; } void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) @@ -293,7 +316,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) queue->submitCommandBuffer(activeCmdBuffer); } } - std::lock_guard lock(allocatedBufferLock); + std::scoped_lock lock(allocatedBufferLock); for (uint32 i = 0; i < allocatedBuffers.size(); ++i) { PCmdBuffer cmdBuffer = allocatedBuffers[i]; diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index c198ab8..ee55923 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -80,7 +80,7 @@ public: void begin(PCmdBuffer parent); void end(); void reset(); - virtual void begin() override; + virtual bool isReady() override; virtual void setViewport(Gfx::PViewport viewport) override; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override; virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override; @@ -91,7 +91,8 @@ public: private: PGraphicsPipeline pipeline; - Array boundDescriptors; + Array boundDescriptors; + bool ready; friend class CmdBuffer; }; DEFINE_REF(SecondaryCmdBuffer) @@ -118,6 +119,8 @@ private: PCmdBuffer activeCmdBuffer; std::mutex allocatedBufferLock; Array allocatedBuffers; + std::mutex allocatedSecondBufferLock; + Array allocatedSecondBuffers; }; DEFINE_REF(CommandBufferManager) } // namespace Vulkan diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index 73f6cf3..a3b0bdc 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -171,8 +171,10 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: TextureHandle* cachedTexture = reinterpret_cast(cachedData[Gfx::currentFrameIndex][binding]); if(vulkanTexture == cachedTexture) { + std::cout << "Cached texture is same as new one, skipping update" << std::endl; return; } + std::cout << "Texture changed, updating" << std::endl; //It is assumed that the image is in the correct layout VkDescriptorImageInfo imageInfo = init::DescriptorImageInfo( @@ -201,15 +203,16 @@ bool DescriptorSet::operator<(Gfx::PDescriptorSet other) return this < otherSet.getHandle(); } +uint32 DescriptorSet::getSetIndex() const +{ + return owner->getLayout().getSetIndex(); +} + void DescriptorSet::writeChanges() { if (writeDescriptors.size() > 0) { - if(currentlyBound != nullptr) - { - currentlyBound->getManager()->waitForCommands(currentlyBound); - currentlyBound = nullptr; - } + assert(!isCurrentlyBound()); vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); writeDescriptors.clear(); imageInfos.clear(); @@ -220,9 +223,11 @@ void DescriptorSet::writeChanges() DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout) : graphics(graphics) , layout(layout) - , currentCachedIndex(0) { - std::memset(&cachedHandles, 0, sizeof(cachedHandles)); + for(uint32 i = 0; i < cachedHandles.size(); ++i) + { + cachedHandles[i] = new DescriptorSet(graphics, this); + } uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM std::memset(perTypeSizes, 0, sizeof(perTypeSizes)); @@ -243,7 +248,7 @@ DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &l poolSizes.add(size); } } - VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo((uint32)poolSizes.size(), poolSizes.data(), maxSets); + VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo((uint32)poolSizes.size(), poolSizes.data(), maxSets * Gfx::numFramesBuffered); VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); } @@ -255,30 +260,48 @@ DescriptorAllocator::~DescriptorAllocator() void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet) { - descriptorSet = new DescriptorSet(graphics, this); - PDescriptorSet vulkanSet = descriptorSet.cast(); VkDescriptorSetLayout layoutHandle = layout.getHandle(); - VkDescriptorSetAllocateInfo allocInfo = - init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1); - for(uint32 i = 0; i < Gfx::numFramesBuffered; ++i) + VkDescriptorSetLayout layoutArray[Gfx::numFramesBuffered]; + for (uint32 i = 0; i < Gfx::numFramesBuffered; i++) { - if(cachedHandles[currentCachedIndex] != VK_NULL_HANDLE) - { - vulkanSet->setHandle[i] = cachedHandles[currentCachedIndex++]; - } - else - { - VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &vulkanSet->setHandle[i])); - cachedHandles[currentCachedIndex++] = vulkanSet->setHandle[i]; - } - - vulkanSet->cachedData[i].resize(layout.bindings.size()); - // Not really pretty, but this way the set knows which ones are valid - std::memset(vulkanSet->cachedData[i].data(), 0, sizeof(void*) * vulkanSet->cachedData[i].size()); + layoutArray[i] = layoutHandle; } + + VkDescriptorSetAllocateInfo allocInfo = + init::DescriptorSetAllocateInfo(poolHandle, layoutArray, Gfx::numFramesBuffered); + + for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) + { + if(cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse()) + { + // Currently in use, skip + continue; + } + if(cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) + { + //If it hasnt been initialized, allocate it + VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, cachedHandles[setIndex]->setHandle)); + } + cachedHandles[setIndex]->currentlyInUse = true; + descriptorSet = cachedHandles[setIndex]; + + PDescriptorSet vulkanSet = descriptorSet.cast(); + for(uint32 frameIndex = 0; frameIndex < Gfx::numFramesBuffered; ++frameIndex) + { + vulkanSet->cachedData[frameIndex].resize(layout.bindings.size()); + // Not really pretty, but this way the set knows which ones are valid + std::memset(vulkanSet->cachedData[frameIndex].data(), 0, sizeof(void*) * vulkanSet->cachedData[frameIndex].size()); + } + //Found set, stop searching + return; + } + throw std::logic_error("Out of descriptor sets"); } void DescriptorAllocator::reset() { - currentCachedIndex = 0; + for(uint32 i = 0; i < cachedHandles.size(); ++i) + { + cachedHandles[i]->free(); + } } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 5fbc84a..90962a4 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -54,6 +54,60 @@ private: }; DEFINE_REF(PipelineLayout) + +class DescriptorSet : public Gfx::DescriptorSet +{ +public: + DescriptorSet(PGraphics graphics, PDescriptorAllocator owner) + : graphics(graphics), owner(owner), currentlyInUse(false), currentlyBound(nullptr) + { + std::memset(setHandle, 0, sizeof(setHandle)); + } + virtual ~DescriptorSet(); + virtual void writeChanges(); + virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer); + virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer); + virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState); + virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState sampler = nullptr); + virtual bool operator<(Gfx::PDescriptorSet other); + + inline bool isCurrentlyBound() const + { + return currentlyBound; + } + inline bool isCurrentlyInUse() const + { + return currentlyInUse; + } + void free() + { + currentlyInUse = false; + } + inline VkDescriptorSet getHandle() const + { + return setHandle[Gfx::currentFrameIndex]; + } + virtual uint32 getSetIndex() const; + +private: + Array imageInfos; + Array bufferInfos; + Array writeDescriptors; + // contains the previously bound resources at every binding + // since the layout is fixed, trying to bind a texture to a buffer + // would not work anyways, so casts should be safe + Array cachedData[Gfx::numFramesBuffered]; + VkDescriptorSet setHandle[Gfx::numFramesBuffered]; + PGraphics graphics; + PDescriptorAllocator owner; + bool currentlyBound; + bool currentlyInUse; + friend class DescriptorAllocator; + friend class CmdBuffer; + friend class SecondaryCmdBuffer; +}; +DEFINE_REF(DescriptorSet) + class DescriptorAllocator : public Gfx::DescriptorAllocator { public: @@ -74,59 +128,10 @@ public: private: PGraphics graphics; DescriptorLayout &layout; - uint32 currentCachedIndex; const static int maxSets = 512; - VkDescriptorSet cachedHandles[maxSets]; + StaticArray cachedHandles; VkDescriptorPool poolHandle; }; DEFINE_REF(DescriptorAllocator) - -class DescriptorSet : public Gfx::DescriptorSet -{ -public: - DescriptorSet(PGraphics graphics, PDescriptorAllocator owner) - : graphics(graphics), owner(owner) - { - } - virtual ~DescriptorSet(); - virtual void writeChanges(); - virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer); - virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer); - virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState); - virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState sampler = nullptr); - virtual bool operator<(Gfx::PDescriptorSet other); - void setCurrentlyBound(PCmdBuffer boundBy) - { - currentlyBound = boundBy; - } - void releaseFromCmd() - { - currentlyBound = nullptr; - } - inline VkDescriptorSet getHandle() const - { - return setHandle[Gfx::currentFrameIndex]; - } - virtual uint32 getSetIndex() const - { - return owner->getLayout().getSetIndex(); - } - -private: - Array imageInfos; - Array bufferInfos; - Array writeDescriptors; - // contains the previously bound resources at every binding - // since the layout is fixed, trying to bind a texture to a buffer - // would not work anyways, so casts should be safe - Array cachedData[Gfx::numFramesBuffered]; - VkDescriptorSet setHandle[Gfx::numFramesBuffered]; - PGraphics graphics; - PDescriptorAllocator owner; - PCmdBuffer currentlyBound; - friend class DescriptorAllocator; -}; -DEFINE_REF(DescriptorSet) - } // namespace Vulkan } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp b/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp index fd23abd..53c5f91 100644 --- a/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp @@ -768,8 +768,15 @@ VkPipelineShaderStageCreateInfo init::PipelineShaderStageCreateInfo(VkShaderStag #pragma warning(disable : 4100) VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char *layerPrefix, const char *msg, void *userDataManager) { - std::cerr << layerPrefix << ": " << msg << std::endl; - return VK_FALSE; + if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) + { + return VK_FALSE; + } + else + { + std::cerr << layerPrefix << ": " << msg << std::endl; + return VK_FALSE; + } } #pragma warning(default : 4100) diff --git a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp index fa7a7eb..3080b80 100644 --- a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp @@ -22,43 +22,44 @@ Queue::~Queue() void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores) { - assert(cmdBuffer->state == CmdBuffer::State::Ended); - - PFence fence = cmdBuffer->fence; - assert(!fence->isSignaled()); - - const VkCommandBuffer cmdBuffers[] = {cmdBuffer->handle}; - - VkSubmitInfo submitInfo = - init::SubmitInfo(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = cmdBuffers; - submitInfo.signalSemaphoreCount = static_cast(numSignalSemaphores); - submitInfo.pSignalSemaphores = signalSemaphores; - - Array waitSemaphores; - if (cmdBuffer->waitSemaphores.size() > 0) { - for (PSemaphore semaphore : cmdBuffer->waitSemaphores) + std::scoped_lock lck(queueLock); + assert(cmdBuffer->state == CmdBuffer::State::Ended); + + PFence fence = cmdBuffer->fence; + assert(!fence->isSignaled()); + + const VkCommandBuffer cmdBuffers[] = {cmdBuffer->handle}; + + VkSubmitInfo submitInfo = + init::SubmitInfo(); + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = cmdBuffers; + submitInfo.signalSemaphoreCount = static_cast(numSignalSemaphores); + submitInfo.pSignalSemaphores = signalSemaphores; + + Array waitSemaphores; + if (cmdBuffer->waitSemaphores.size() > 0) { - waitSemaphores.add(semaphore->getHandle()); + for (PSemaphore semaphore : cmdBuffer->waitSemaphores) + { + waitSemaphores.add(semaphore->getHandle()); + } + submitInfo.waitSemaphoreCount = static_cast(cmdBuffer->waitSemaphores.size()); + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.pWaitDstStageMask = cmdBuffer->waitFlags.data(); } - submitInfo.waitSemaphoreCount = static_cast(cmdBuffer->waitSemaphores.size()); - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.pWaitDstStageMask = cmdBuffer->waitFlags.data(); + VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle())); + cmdBuffer->state = CmdBuffer::State::Submitted; + cmdBuffer->waitFlags.clear(); + cmdBuffer->waitSemaphores.clear(); + + if (Gfx::waitIdleOnSubmit) + { + fence->wait(200 * 1000ull); + } + + cmdBuffer->refreshFence(); + graphics->getStagingManager()->clearPending(); } - - VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle())); - - cmdBuffer->state = CmdBuffer::State::Submitted; - cmdBuffer->waitFlags.clear(); - cmdBuffer->waitSemaphores.clear(); - - if (Gfx::waitIdleOnSubmit) - { - fence->wait(200 * 1000ull); - } - - cmdBuffer->refreshFence(); - graphics->getStagingManager()->clearPending(); } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanQueue.h b/src/Engine/Graphics/Vulkan/VulkanQueue.h index a2f3049..3dda53b 100644 --- a/src/Engine/Graphics/Vulkan/VulkanQueue.h +++ b/src/Engine/Graphics/Vulkan/VulkanQueue.h @@ -27,6 +27,7 @@ public: } private: + std::mutex queueLock; PGraphics graphics; VkQueue queue; uint32 familyIndex; diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 16300a0..85d6a0c 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -42,6 +42,7 @@ void Material::load() void Material::compile() { + setStatus(Status::Loading); layout = WindowManager::getGraphics()->createDescriptorLayout(); auto& stream = getReadStream(); json j; @@ -142,13 +143,13 @@ void Material::compile() brdf->generateMaterialCode(codeStream, j["code"]); codeStream << "};"; codeStream.close(); + setStatus(Status::Ready); } const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const { Gfx::ShaderPermutation permutation; permutation.passType = renderPass; - std::string materialName = getFileName(); std::string vertexInputName = vertexInput->getName(); std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName)); std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName)); diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index ba8e739..42ec034 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -29,6 +29,8 @@ extern std::mutex registeredObjectsLock; namespace Seele { template +class RefPtr; +template class RefObject { public: @@ -98,13 +100,14 @@ public: delete this; } } - inline T *getHandle() const + T *getHandle() const { return handle; } private: T *handle; std::atomic_uint64_t refCount; + friend class RefPtr; }; template @@ -239,12 +242,12 @@ public: inline T *operator->() { assert(object != nullptr); - return object->getHandle(); + return object->handle; } inline const T *operator->() const { assert(object != nullptr); - return object->getHandle(); + return object->handle; } RefObject *getObject() const { diff --git a/src/Engine/Scene/Components/PrimitiveComponent.h b/src/Engine/Scene/Components/PrimitiveComponent.h index 3f05ce2..9a42ef2 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.h +++ b/src/Engine/Scene/Components/PrimitiveComponent.h @@ -16,11 +16,14 @@ public: ~PrimitiveComponent(); virtual void notifySceneAttach(PScene scene) override; Matrix4 getRenderMatrix(); - - Array staticMeshes; + const Array& getStaticMeshes() + { + return staticMeshes; + } private: Array materials; Gfx::PUniformBuffer uniformBuffer; + Array staticMeshes; friend class Scene; }; DEFINE_REF(PrimitiveComponent) diff --git a/src/Engine/Window/RenderPath.cpp b/src/Engine/Window/RenderPath.cpp index 787d68b..6d6de32 100644 --- a/src/Engine/Window/RenderPath.cpp +++ b/src/Engine/Window/RenderPath.cpp @@ -1,5 +1,6 @@ #include "RenderPath.h" #include "Graphics/GraphicsResources.h" +#include "Material/MaterialAsset.h" Seele::RenderPath::RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) : graphics(graphics), target(target)