diff --git a/.vscode_Linux/c_cpp_properties.json b/.vscode_Linux/c_cpp_properties.json index b276fdc7..96885f73 100644 --- a/.vscode_Linux/c_cpp_properties.json +++ b/.vscode_Linux/c_cpp_properties.json @@ -32,7 +32,9 @@ "vendor/tracy/include" ], "defines": [ - "ZoneScopedNC(x,y)" + "ZoneScopedNC(x,y)", + "ZoneScopedN(x)", + "ZoneTransientN(x, y, z)" ], "cStandard": "c17", "cppStandard": "c++20", diff --git a/.vscode_MacOS/c_cpp_properties.json b/.vscode_MacOS/c_cpp_properties.json index 2b4fdd76..e0c91e15 100644 --- a/.vscode_MacOS/c_cpp_properties.json +++ b/.vscode_MacOS/c_cpp_properties.json @@ -37,7 +37,9 @@ "defines": [ "MACOSX", "PROFILING", - "ZoneScopedNC(x,y)" + "ZoneScopedNC(x,y)", + "ZoneScopedN(x)", + "ZoneTransientN(x, y, z)" ], "cStandard": "c17", "cppStandard": "c++20" diff --git a/application/lucre/UI/imgui.cpp b/application/lucre/UI/imgui.cpp index 885cbb38..6bfa3b27 100644 --- a/application/lucre/UI/imgui.cpp +++ b/application/lucre/UI/imgui.cpp @@ -301,7 +301,7 @@ namespace LucreApp m_CurrentItem = nullptr; m_VisibleModels.clear(); - TreeNode& rootNode = scene->GetTreeNode(SceneGraph::ROOT_NODE); + auto& rootNode = scene->GetTreeNode(SceneGraph::ROOT_NODE); { // insert root auto& label = rootNode.GetName(); @@ -313,7 +313,7 @@ namespace LucreApp // insert gltf files for (uint nodeIndex : rootNode.GetChildren()) { - TreeNode& node = scene->GetTreeNode(nodeIndex); + auto& node = scene->GetTreeNode(nodeIndex); auto& label = node.GetName(); auto entity = node.GetGameObject(); @@ -332,7 +332,7 @@ namespace LucreApp { if (depth < maxDepth) { - TreeNode& node = scene.GetTreeNode(nodeIndex); + auto& node = scene.GetTreeNode(nodeIndex); int gameObject = static_cast(node.GetGameObject()); ImGui::PushID(gameObject); std::string label = "entity " + std::to_string(gameObject) + " " + node.GetName(); diff --git a/application/lucre/gameState.cpp b/application/lucre/gameState.cpp index e6d9c9d3..3191f68a 100644 --- a/application/lucre/gameState.cpp +++ b/application/lucre/gameState.cpp @@ -58,7 +58,11 @@ namespace LucreApp SetNextState(State::TERRAIN); } - void GameState::Stop() { GetScene()->Stop(); } + void GameState::Stop() + { + GetScene()->Stop(); + DestroyScene(m_State); + } std::string GameState::StateToString(State state) const { @@ -249,7 +253,7 @@ namespace LucreApp void GameState::Load(GameState::State state) { - ASSERT(!IsLoaded(state)); + CORE_ASSERT(!IsLoaded(state), "!IsLoaded(state)"); if (m_LoadingState != State::NULL_STATE) { return; @@ -449,8 +453,10 @@ namespace LucreApp void GameState::DestroyScene(const State state) { std::lock_guard lock(m_Mutex); + Engine::m_Engine->WaitIdle(); m_StateLoaded[static_cast(state)] = false; m_Scenes[static_cast(state)] = nullptr; m_DeleteScene = State::NULL_STATE; + Engine::m_Engine->ResetDescriptorPools(); } } // namespace LucreApp diff --git a/application/lucre/lucre.cpp b/application/lucre/lucre.cpp index f905c74c..38b87075 100644 --- a/application/lucre/lucre.cpp +++ b/application/lucre/lucre.cpp @@ -20,6 +20,8 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ +#include +#include #include #include "engine.h" @@ -73,11 +75,63 @@ namespace LucreApp auto position = glm::vec3(0.0f, 0.0f, 1.0f); auto direction = glm::vec3(0.0f, 0.0f, -1.0f); camera.SetViewDirection(position, direction); +#define STRESS_TEST +#ifdef STRESS_TEST + { // stress test scene changing + std::srand(std::time(nullptr)); + auto stressTest = []() + { + const uint numberOfScenes = + static_cast(GameState::State::MAX_STATES) - static_cast(GameState::State::MAIN); + uint loopCounter{0}; + uint previousRandomNumber{0}; + while (Engine::m_Engine->IsRunning()) + { + std::this_thread::sleep_for(100ms); + if (!Engine::m_Engine->IsRunning()) + { + break; + } + // skip + if (Engine::m_Engine->IsPaused() || (Lucre::m_Application->GetState() == GameState::State::SPLASH)) + { + continue; + } + + if (Lucre::m_Application->GetState() != GameState::State::CUTSCENE) + { + std::this_thread::sleep_for(2000ms); + if (!Engine::m_Engine->IsRunning()) + { + break; + } + uint randomNumber; + do + { + randomNumber = 1 + std::rand() / ((RAND_MAX + 1u) / numberOfScenes); + } while (randomNumber == previousRandomNumber); + previousRandomNumber = randomNumber; + uint sceneNumber = randomNumber + static_cast(GameState::State::MAIN) - 1; + LOG_APP_INFO("stress test: random number = {0}, sceneNumber = {1}, loop counter = {2}", randomNumber, + sceneNumber, ++loopCounter); + SceneChangedEvent event(static_cast(sceneNumber)); + Lucre::m_Application->OnAppEvent(event); + } + } + return true; + }; + m_StressTestFuture = Engine::m_Engine->m_PoolPrimary.SubmitTask(stressTest); + } +#endif return true; } - void Lucre::Shutdown() { m_GameState.Stop(); } + void Lucre::Shutdown() + { + m_GameState.Stop(); + m_StressTestFuture.get(); + } void Lucre::OnUpdate(const Timestep& timestep) { @@ -103,7 +157,7 @@ namespace LucreApp void Lucre::OnResize() { - ASSERT(m_CurrentScene); + CORE_ASSERT(m_CurrentScene, "m_CurrentScene is null"); m_CurrentScene->OnResize(); m_UIControllerIcon->Init(); m_UI->OnResize(); diff --git a/application/lucre/lucre.h b/application/lucre/lucre.h index 8c6359a4..dd285513 100644 --- a/application/lucre/lucre.h +++ b/application/lucre/lucre.h @@ -90,5 +90,7 @@ namespace LucreApp SpriteSheet m_Atlas; bool m_InGameGuiIsRunning; bool m_DebugWindowIsRunning; + + std::future m_StressTestFuture; }; } // namespace LucreApp diff --git a/application/lucre/sceneDescriptions/island2.json b/application/lucre/sceneDescriptions/island2.json index d5bbd5c9..4b921d7e 100644 --- a/application/lucre/sceneDescriptions/island2.json +++ b/application/lucre/sceneDescriptions/island2.json @@ -615,13 +615,30 @@ ], "rotation": [ - 0, -0, 0 + 0, 0, 0 ], "translation": [ 3.03369, 2.09252, 3.85279 ] } + }, + { + "transform": + { + "scale": + [ + 0.41, 0.41, 0.41 + ], + "rotation": + [ + 0, 0, 0 + ], + "translation": + [ + 0.473659, 2.09252, 4.48397 + ] + } } ] }, @@ -1409,31 +1426,5 @@ } ] } - ], - "ufbx files": - [ - { - "filename": "application/lucre/models/dancing/fbx/Dancing Michelle.fbx", - "instances": - [ - { - "transform": - { - "scale": - [ - 0.41, 0.41, 0.41 - ], - "rotation": - [ - 0, -0, 0 - ], - "translation": - [ - 0.473659, 2.09252, 4.48397 - ] - } - } - ] - } ] } diff --git a/application/lucre/sceneDescriptions/night.json b/application/lucre/sceneDescriptions/night.json index 2aa8b87e..b2b38d8d 100644 --- a/application/lucre/sceneDescriptions/night.json +++ b/application/lucre/sceneDescriptions/night.json @@ -1116,16 +1116,7 @@ 2.116, 1.529, -1.377 ] } - } - ] - } - ], - "ufbx files": - [ - { - "filename": "application/lucre/models/external_3D_files/Wooden Crate/Wooden Crate.fbx", - "instances": - [ + }, { "transform": { diff --git a/application/lucre/scenes/beachScene.cpp b/application/lucre/scenes/beachScene.cpp index 836757c5..94228c06 100644 --- a/application/lucre/scenes/beachScene.cpp +++ b/application/lucre/scenes/beachScene.cpp @@ -64,8 +64,8 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); + ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/cutScene.h b/application/lucre/scenes/cutScene.h index 868055e0..fa9848fe 100644 --- a/application/lucre/scenes/cutScene.h +++ b/application/lucre/scenes/cutScene.h @@ -52,7 +52,7 @@ namespace LucreApp virtual void ResetTimer() override; private: - static constexpr std::chrono::duration MIN_TIME_IN_CUTSCENE = 1s; + static constexpr std::chrono::duration MIN_TIME_IN_CUTSCENE = 0.7ms; void Init(); void MoveClouds(const Timestep& timestep); void Draw(); diff --git a/application/lucre/scenes/dessertScene.cpp b/application/lucre/scenes/dessertScene.cpp index 594c3da9..116bc807 100644 --- a/application/lucre/scenes/dessertScene.cpp +++ b/application/lucre/scenes/dessertScene.cpp @@ -67,9 +67,8 @@ namespace LucreApp m_Camera[CameraTypes::DefaultCamera] = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera[CameraTypes::DefaultCamera], cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera[CameraTypes::DefaultCamera], "defaultCamera", "defaultCamera", - m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera[CameraTypes::DefaultCamera], "defaultCamera", + m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/island2Scene.cpp b/application/lucre/scenes/island2Scene.cpp index 43ad7243..15f3c91b 100644 --- a/application/lucre/scenes/island2Scene.cpp +++ b/application/lucre/scenes/island2Scene.cpp @@ -67,9 +67,8 @@ namespace LucreApp m_Camera[CameraTypes::DefaultCamera] = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera[CameraTypes::DefaultCamera], cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera[CameraTypes::DefaultCamera], "defaultCamera", "defaultCamera", - m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera[CameraTypes::DefaultCamera], "defaultCamera", + m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; @@ -196,7 +195,7 @@ namespace LucreApp } m_NonPlayableCharacters[NPC::Character4] = - m_Dictionary.Retrieve("SL::application/lucre/models/dancing/fbx/Dancing Michelle.fbx::0::Michelle"); + m_Dictionary.Retrieve("SL::application/lucre/models/dancing/gltf/Dancing Michelle.glb::1::Scene::Michelle"); if (m_NonPlayableCharacters[NPC::Character4] != entt::null) { auto& mesh = m_Registry.get(m_NonPlayableCharacters[NPC::Character4]); diff --git a/application/lucre/scenes/mainScene.cpp b/application/lucre/scenes/mainScene.cpp index 2120f6d4..1bc4b32c 100644 --- a/application/lucre/scenes/mainScene.cpp +++ b/application/lucre/scenes/mainScene.cpp @@ -64,8 +64,7 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/mainSceneModels.cpp b/application/lucre/scenes/mainSceneModels.cpp index 0cc69b9f..81689b19 100644 --- a/application/lucre/scenes/mainSceneModels.cpp +++ b/application/lucre/scenes/mainSceneModels.cpp @@ -80,7 +80,6 @@ namespace LucreApp FastgltfBuilder builder("application/lucre/models/external_3D_files/banana/banana.gltf", *this); builder.SetDictionaryPrefix("mainScene"); builder.Load(MAX_B /*instance(s)*/); - auto model = Engine::m_Engine->LoadModel(builder); for (uint i = 0; i < MAX_B; i++) { diff --git a/application/lucre/scenes/nightScene.cpp b/application/lucre/scenes/nightScene.cpp index b7be8257..bee153d3 100644 --- a/application/lucre/scenes/nightScene.cpp +++ b/application/lucre/scenes/nightScene.cpp @@ -65,8 +65,7 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/reserved0Scene.cpp b/application/lucre/scenes/reserved0Scene.cpp index 44e4b3e3..5ca4a8c4 100644 --- a/application/lucre/scenes/reserved0Scene.cpp +++ b/application/lucre/scenes/reserved0Scene.cpp @@ -66,8 +66,7 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/terrainScene.cpp b/application/lucre/scenes/terrainScene.cpp index 95c7ee8c..c3415d02 100644 --- a/application/lucre/scenes/terrainScene.cpp +++ b/application/lucre/scenes/terrainScene.cpp @@ -66,8 +66,7 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/application/lucre/scenes/volcanoScene.cpp b/application/lucre/scenes/volcanoScene.cpp index 77f011dc..48ac7e15 100644 --- a/application/lucre/scenes/volcanoScene.cpp +++ b/application/lucre/scenes/volcanoScene.cpp @@ -66,8 +66,7 @@ namespace LucreApp m_Camera = m_Registry.Create(); TransformComponent cameraTransform{}; m_Registry.emplace(m_Camera, cameraTransform); - uint cameraNode = m_SceneGraph.CreateNode(m_Camera, "defaultCamera", "defaultCamera", m_Dictionary); - m_SceneGraph.GetRoot().AddChild(cameraNode); + m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, m_Camera, "defaultCamera", m_Dictionary); ResetScene(); KeyboardInputControllerSpec keyboardInputControllerSpec{}; diff --git a/engine/auxiliary/queue.h b/engine/auxiliary/queue.h new file mode 100644 index 00000000..329a45a9 --- /dev/null +++ b/engine/auxiliary/queue.h @@ -0,0 +1,107 @@ +/* Engine Copyright (c) 2024 Engine Development Team + https://github.com/beaumanvienna/vulkan + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#pragma once + +#include +#include +#include + +namespace GfxRenderEngine +{ + namespace Atomic + { + template class Queue + { + public: + Queue() = default; // default + Queue(Queue const& other) = delete; // copy + Queue(Queue&& other) = delete; // move + ~Queue() {} + + void Emplace(T&& value) // constructs element in-place at the end via move + { + std::lock_guard lock(m_Mutex); + m_Queue.emplace(std::move(value)); + } + + void EmplaceBack(T&& value) // constructs element in-place at the end via move + { + std::lock_guard lock(m_Mutex); + m_Queue.emplace(std::move(value)); + } + + void Pop() // removes the first element + { + std::lock_guard lock(m_Mutex); + m_Queue.pop(); + } + + auto& Front() + { + std::lock_guard lock(m_Mutex); + return m_Queue.front(); + } + + auto& Back() + { + std::lock_guard lock(m_Mutex); + return m_Queue.back(); + } + + auto Empty() + { + std::lock_guard lock(m_Mutex); + return m_Queue.empty(); + } + + auto Size() + { + std::lock_guard lock(m_Mutex); + return m_Queue.size(); + } + + void Clear() + { + std::lock_guard lock(m_Mutex); + for (; !m_Queue.empty(); m_Queue.pop()) + { + } + } + + void Reset() { Clear(); } + + void DoAll(std::function function) + { + for (; !Empty(); Pop()) + { + function(std::move(Front())); + } + } + + private: + std::queue m_Queue; + std::mutex m_Mutex; + }; + + } // namespace Atomic +} // namespace GfxRenderEngine diff --git a/engine/core.cpp b/engine/core.cpp index 665e95a7..6bccbd55 100644 --- a/engine/core.cpp +++ b/engine/core.cpp @@ -349,8 +349,25 @@ namespace GfxRenderEngine } log.push_back(static_cast(entity)); LOG_CORE_WARN("no script loaded for game object {0}, '{1}'", static_cast(entity), - currentScene->GetDictionary().GetLongName(entity)); + currentScene->GetDictionary().GetName(entity)); } } } + + void Engine::WaitIdle() const { m_GraphicsContext->WaitIdle(); } + void Engine::ResetDescriptorPools() + { + m_GraphicsContext->ResetDescriptorPool(m_PoolPrimary); + m_GraphicsContext->ResetDescriptorPool(m_PoolSecondary); + } + + std::shared_ptr Engine::LoadModel(const Builder& builder) { return m_GraphicsContext->LoadModel(builder); } + std::shared_ptr Engine::LoadModel(const TerrainBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } + std::shared_ptr Engine::LoadModel(const GltfBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } + std::shared_ptr Engine::LoadModel(const Model::ModelData& modelData) + { + return m_GraphicsContext->LoadModel(modelData); + } + std::shared_ptr Engine::LoadModel(const FbxBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } + std::shared_ptr Engine::LoadModel(const UFbxBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } } // namespace GfxRenderEngine diff --git a/engine/core.h b/engine/core.h index 12343a44..8dfa28d9 100644 --- a/engine/core.h +++ b/engine/core.h @@ -55,10 +55,12 @@ namespace GfxRenderEngine bool Start(); void WaitInitialized(); + void WaitIdle() const; void OnUpdate(); void OnEvent(Event& event); void PostRender(); void QueueEvent(std::unique_ptr& event); + void ResetDescriptorPools(); void Shutdown(bool switchOffComputer = false); void Quit(); @@ -85,12 +87,12 @@ namespace GfxRenderEngine float GetDesktopWidth() const { return static_cast(m_Window->GetDesktopWidth()); } float GetDesktopHeight() const { return static_cast(m_Window->GetDesktopHeight()); } - std::shared_ptr LoadModel(const Builder& builder) { return m_GraphicsContext->LoadModel(builder); } - std::shared_ptr LoadModel(const TerrainBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } - std::shared_ptr LoadModel(const GltfBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } - std::shared_ptr LoadModel(const FastgltfBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } - std::shared_ptr LoadModel(const FbxBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } - std::shared_ptr LoadModel(const UFbxBuilder& builder) { return m_GraphicsContext->LoadModel(builder); } + std::shared_ptr LoadModel(const Builder&); + std::shared_ptr LoadModel(const TerrainBuilder&); + std::shared_ptr LoadModel(const GltfBuilder&); + std::shared_ptr LoadModel(const Model::ModelData&); + std::shared_ptr LoadModel(const FbxBuilder&); + std::shared_ptr LoadModel(const UFbxBuilder&); bool IsFullscreen() const { return m_Window->IsFullscreen(); } void EnableMousePointer() { m_Window->EnableMousePointer(); } diff --git a/engine/engine.h b/engine/engine.h index 9c2bc1e4..6deddce3 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -58,10 +58,6 @@ int engine(int argc, char* argv[]); #undef CreateDirectory #undef CreateWindow -#define ASSERT(x) \ - if (!(x)) \ - std::cout << " (ASSERT on line number " << __LINE__ << " in file " << __FILE__ << ")" << std::endl; - #define MEMBER_SIZE(type, member) sizeof(type::member) #define BIT(x) (1 << (x)) diff --git a/engine/platform/Vulkan/VKbuffer.cpp b/engine/platform/Vulkan/VKbuffer.cpp index 45c12e3e..837fee67 100644 --- a/engine/platform/Vulkan/VKbuffer.cpp +++ b/engine/platform/Vulkan/VKbuffer.cpp @@ -99,8 +99,11 @@ namespace GfxRenderEngine VK_Buffer::~VK_Buffer() { Unmap(); - vkDestroyBuffer(m_Device->Device(), m_Buffer, nullptr); - vkFreeMemory(m_Device->Device(), m_Memory, nullptr); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkDestroyBuffer(m_Device->Device(), m_Buffer, nullptr); + vkFreeMemory(m_Device->Device(), m_Memory, nullptr); + } } /** @@ -114,9 +117,18 @@ namespace GfxRenderEngine */ VkResult VK_Buffer::Map(VkDeviceSize size, VkDeviceSize offset) { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); if (!(m_Buffer && m_Memory)) + { LOG_CORE_CRITICAL("VkResult VK_Buffer::Map(...): Called map on buffer before create"); - return vkMapMemory(m_Device->Device(), m_Memory, offset, size, 0, &m_Mapped); + } + auto result = vkMapMemory(m_Device->Device(), m_Memory, offset, size, 0, &m_Mapped); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + CORE_HARD_STOP("VK_Buffer::Map"); + } + return result; } void VK_Buffer::MapBuffer() { Map(); } @@ -130,7 +142,10 @@ namespace GfxRenderEngine { if (m_Mapped) { - vkUnmapMemory(m_Device->Device(), m_Memory); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkUnmapMemory(m_Device->Device(), m_Memory); + } m_Mapped = nullptr; } } @@ -179,7 +194,11 @@ namespace GfxRenderEngine mappedRange.memory = m_Memory; mappedRange.offset = offset; mappedRange.size = size; - VkResult result = vkFlushMappedMemoryRanges(m_Device->Device(), 1, &mappedRange); + VkResult result; + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + result = vkFlushMappedMemoryRanges(m_Device->Device(), 1, &mappedRange); + } return result; } diff --git a/engine/platform/Vulkan/VKbuffer.h b/engine/platform/Vulkan/VKbuffer.h index fddc0a88..228c6248 100644 --- a/engine/platform/Vulkan/VKbuffer.h +++ b/engine/platform/Vulkan/VKbuffer.h @@ -62,7 +62,7 @@ namespace GfxRenderEngine VkResult Flush(VkDeviceSize size, VkDeviceSize offset); virtual bool Flush() override { - VkResult result = Flush(VK_WHOLE_SIZE /*VkDeviceSize size*/, 0 /*VkDeviceSize offset*/); + auto result = Flush(VK_WHOLE_SIZE /*VkDeviceSize size*/, 0 /*VkDeviceSize offset*/); return result == VkResult::VK_SUCCESS; } VkDescriptorBufferInfo DescriptorInfo(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0); diff --git a/engine/platform/Vulkan/VKcubemap.cpp b/engine/platform/Vulkan/VKcubemap.cpp index 2230f5fd..2eeec026 100644 --- a/engine/platform/Vulkan/VKcubemap.cpp +++ b/engine/platform/Vulkan/VKcubemap.cpp @@ -128,6 +128,7 @@ namespace GfxRenderEngine auto result = vkCreateImage(device, &imageInfo, nullptr, &m_CubemapImage); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create image!"); } } @@ -144,6 +145,7 @@ namespace GfxRenderEngine auto result = vkAllocateMemory(device, &allocInfo, nullptr, &m_CubemapImageMemory); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate image memory in 'void VK_Cubemap::CreateImage'"); } } @@ -162,9 +164,13 @@ namespace GfxRenderEngine bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create buffer!"); + auto result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + CORE_HARD_STOP("failed to create buffer!"); + } } VkMemoryRequirements memRequirements; @@ -179,6 +185,7 @@ namespace GfxRenderEngine auto result = vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate buffer memory!"); } } @@ -280,6 +287,7 @@ namespace GfxRenderEngine auto result = vkCreateSampler(device, &samplerCreateInfo, nullptr, &m_Sampler); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create sampler!"); } } @@ -311,6 +319,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(device, &view, nullptr, &m_ImageView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create image view!"); } } diff --git a/engine/platform/Vulkan/VKdescriptor.cpp b/engine/platform/Vulkan/VKdescriptor.cpp index bf7bea68..6d5f63db 100644 --- a/engine/platform/Vulkan/VKdescriptor.cpp +++ b/engine/platform/Vulkan/VKdescriptor.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -36,7 +36,7 @@ namespace GfxRenderEngine VkDescriptorType descriptorType, VkShaderStageFlags stageFlags, uint count) { - ASSERT(m_Bindings.count(binding) == 0); // binding already in use + CORE_ASSERT(m_Bindings.count(binding) == 0, "binding already in use"); VkDescriptorSetLayoutBinding layoutBinding{}; layoutBinding.binding = binding; layoutBinding.descriptorType = descriptorType; @@ -67,16 +67,21 @@ namespace GfxRenderEngine descriptorSetLayoutInfo.bindingCount = static_cast(setLayoutBindings.size()); descriptorSetLayoutInfo.pBindings = setLayoutBindings.data(); - auto result = vkCreateDescriptorSetLayout(VK_Core::m_Device->Device(), &descriptorSetLayoutInfo, nullptr, - &m_DescriptorSetLayout); - if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create descriptor set layout!"); + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + auto result = vkCreateDescriptorSetLayout(VK_Core::m_Device->Device(), &descriptorSetLayoutInfo, nullptr, + &m_DescriptorSetLayout); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create descriptor set layout!"); + } } } VK_DescriptorSetLayout::~VK_DescriptorSetLayout() { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); vkDestroyDescriptorSetLayout(VK_Core::m_Device->Device(), m_DescriptorSetLayout, nullptr); } @@ -85,7 +90,7 @@ namespace GfxRenderEngine VK_DescriptorPool::Builder& VK_DescriptorPool::Builder::AddPoolSize(VkDescriptorType descriptorType, uint count) { - CORE_ASSERT(!m_MaxSetsCalled, "SetMaxSets() is optionally. It must be the final call b4 build()."); + CORE_ASSERT(!m_MaxSetsCalled, "SetMaxSets() is optionally. It must be the final call before build()."); m_MaxSets += count; m_PoolSizes.push_back({descriptorType, count}); return *this; @@ -122,17 +127,24 @@ namespace GfxRenderEngine descriptorPoolInfo.maxSets = maxSets; descriptorPoolInfo.flags = poolFlags; - auto result = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &m_DescriptorPool); - if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create descriptor pool!"); + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + auto result = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &m_DescriptorPool); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create descriptor pool!"); + } } } VK_DescriptorPool::~VK_DescriptorPool() { VK_Core::m_Device->WaitIdle(); - vkDestroyDescriptorPool(m_Device, m_DescriptorPool, nullptr); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkDestroyDescriptorPool(m_Device, m_DescriptorPool, nullptr); + } } bool VK_DescriptorPool::AllocateDescriptorSet(const VkDescriptorSetLayout descriptorSetLayout, @@ -144,23 +156,32 @@ namespace GfxRenderEngine allocInfo.pSetLayouts = &descriptorSetLayout; allocInfo.descriptorSetCount = 1; - auto result = vkAllocateDescriptorSets(VK_Core::m_Device->Device(), &allocInfo, &descriptor); - CORE_ASSERT(result == VK_SUCCESS, "vkAllocateDescriptorSets failed"); - if (result != VK_SUCCESS) { - CORE_HARD_STOP("AllocateDescriptorSet"); - return false; + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + auto result = vkAllocateDescriptorSets(VK_Core::m_Device->Device(), &allocInfo, &descriptor); + CORE_ASSERT(result == VK_SUCCESS, "vkAllocateDescriptorSets failed"); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + CORE_HARD_STOP("AllocateDescriptorSet failed"); + return false; + } } return true; } void VK_DescriptorPool::FreeDescriptors(std::vector& descriptors) const { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); vkFreeDescriptorSets(VK_Core::m_Device->Device(), m_DescriptorPool, static_cast(descriptors.size()), descriptors.data()); } - void VK_DescriptorPool::ResetPool() { vkResetDescriptorPool(VK_Core::m_Device->Device(), m_DescriptorPool, 0); } + void VK_DescriptorPool::ResetPool() + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkResetDescriptorPool(VK_Core::m_Device->Device(), m_DescriptorPool, 0); + } // *************** Descriptor Writer ********************* VK_DescriptorWriter::VK_DescriptorWriter(VK_DescriptorSetLayout& setLayout) @@ -170,11 +191,11 @@ namespace GfxRenderEngine VK_DescriptorWriter& VK_DescriptorWriter::WriteBuffer(uint binding, const VkDescriptorBufferInfo& bufferInfo) { - ASSERT(m_SetLayout.m_Bindings.count(binding) == 1); // layout does not contain specified binding + CORE_ASSERT(m_SetLayout.m_Bindings.count(binding) == 1, "layout does not contain specified binding"); auto& bindingDescription = m_SetLayout.m_Bindings[binding]; - ASSERT(bindingDescription.descriptorCount == 1); // binding single descriptor info, but binding expects multiple + CORE_ASSERT(bindingDescription.descriptorCount == 1, "binding single descriptor info, but binding expects multiple"); VkWriteDescriptorSet write{}; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -253,6 +274,9 @@ namespace GfxRenderEngine { write.dstSet = set; } - vkUpdateDescriptorSets(VK_Core::m_Device->Device(), m_Writes.size(), m_Writes.data(), 0, nullptr); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkUpdateDescriptorSets(VK_Core::m_Device->Device(), m_Writes.size(), m_Writes.data(), 0, nullptr); + } } } // namespace GfxRenderEngine diff --git a/engine/platform/Vulkan/VKdevice.cpp b/engine/platform/Vulkan/VKdevice.cpp index c7447519..f7a4df76 100644 --- a/engine/platform/Vulkan/VKdevice.cpp +++ b/engine/platform/Vulkan/VKdevice.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -74,8 +74,7 @@ namespace GfxRenderEngine } } - VK_Device::VK_Device(VK_Window* window, ThreadPool& threadPoolPrimary, ThreadPool& threadPoolSecondary) - : m_Window{window} + VK_Device::VK_Device(VK_Window* window) : m_Window{window} { CreateInstance(); SetupDebugMessenger(); @@ -83,7 +82,6 @@ namespace GfxRenderEngine PickPhysicalDevice(); CreateLogicalDevice(); CreateCommandPool(); - m_LoadPool = std::make_unique(m_Device, m_QueueFamilyIndices, threadPoolPrimary, threadPoolSecondary); } VK_Device::~VK_Device() @@ -101,8 +99,16 @@ namespace GfxRenderEngine vkDestroyInstance(m_Instance, nullptr); } + void VK_Device::LoadPool(ThreadPool& threadPoolPrimary, ThreadPool& threadPoolSecondary) + { + m_LoadPool = std::make_unique(m_Device, m_QueueFamilyIndices, threadPoolPrimary, threadPoolSecondary); + } + + void VK_Device::ResetPool(ThreadPool& threadPool) { m_LoadPool->ResetDescriptorPools(threadPool); } + void VK_Device::Shutdown() { + std::lock_guard guard(m_DeviceAccessMutex); vkQueueWaitIdle(m_GraphicsQueue); vkQueueWaitIdle(m_PresentQueue); } @@ -148,11 +154,12 @@ namespace GfxRenderEngine createInfo.pNext = nullptr; } - if (vkCreateInstance(&createInfo, nullptr, &m_Instance) != VK_SUCCESS) + auto result = vkCreateInstance(&createInfo, nullptr, &m_Instance); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); CORE_HARD_STOP("failed to create instance"); } - if (HasGflwRequiredInstanceExtensions() != VK_SUCCESS) { CORE_HARD_STOP("required glfw extensions missing"); @@ -269,11 +276,12 @@ namespace GfxRenderEngine createInfo.enabledLayerCount = 0; } - if (vkCreateDevice(m_PhysicalDevice, &createInfo, nullptr, &m_Device) != VK_SUCCESS) + auto result = vkCreateDevice(m_PhysicalDevice, &createInfo, nullptr, &m_Device); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create logical device!"); } - vkGetDeviceQueue(m_Device, indices.m_GraphicsFamily, indices.m_QueueIndices[QueueTypes::GRAPHICS], &m_GraphicsQueue); vkGetDeviceQueue(m_Device, indices.m_PresentFamily, indices.m_QueueIndices[QueueTypes::PRESENT], &m_PresentQueue); // PrintAllSupportedFormats(); @@ -286,8 +294,10 @@ namespace GfxRenderEngine poolInfo.queueFamilyIndex = m_QueueFamilyIndices.m_GraphicsFamily; poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - if (vkCreateCommandPool(m_Device, &poolInfo, nullptr, &m_GraphicsCommandPool) != VK_SUCCESS) + auto result = vkCreateCommandPool(m_Device, &poolInfo, nullptr, &m_GraphicsCommandPool); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create graphics command pool!"); } } @@ -392,6 +402,7 @@ namespace GfxRenderEngine auto result = CreateDebugUtilsMessengerEXT(m_Instance, &createInfo, nullptr, &m_DebugMessenger); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to set up debug messenger!"); } } @@ -448,7 +459,7 @@ namespace GfxRenderEngine VkResult VK_Device::HasGflwRequiredInstanceExtensions() { - VkResult result = VK_SUCCESS; + auto result = VK_SUCCESS; uint extensionCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); std::vector extensions(extensionCount); @@ -651,14 +662,17 @@ namespace GfxRenderEngine void VK_Device::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) { + // no guard needed; none of the below are externally synchronized VkBufferCreateInfo bufferInfo{}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = size; bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(m_Device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) + auto result = vkCreateBuffer(m_Device, &bufferInfo, nullptr, &buffer); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create vertex buffer!"); } @@ -670,12 +684,17 @@ namespace GfxRenderEngine allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(m_Device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) + result = vkAllocateMemory(m_Device, &allocInfo, nullptr, &bufferMemory); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate vertex buffer memory!"); } - vkBindBufferMemory(m_Device, buffer, bufferMemory, 0); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkBindBufferMemory(m_Device, buffer, bufferMemory, 0); + } } VkCommandBuffer VK_Device::BeginSingleTimeCommands() @@ -688,20 +707,29 @@ namespace GfxRenderEngine allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(m_Device, &allocInfo, &commandBuffer); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkAllocateCommandBuffers(m_Device, &allocInfo, &commandBuffer); + } VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(commandBuffer, &beginInfo); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkBeginCommandBuffer(commandBuffer, &beginInfo); + } return commandBuffer; } void VK_Device::EndSingleTimeCommands(VkCommandBuffer commandBuffer) { - vkEndCommandBuffer(commandBuffer); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkEndCommandBuffer(commandBuffer); + } uint64_t& signalTimelineValue = m_LoadPool->GetSignalValue(); ++signalTimelineValue; VkTimelineSemaphoreSubmitInfo timelineSemaphoreSubmitInfo{}; @@ -719,7 +747,7 @@ namespace GfxRenderEngine submitInfo.pSignalSemaphores = &signalSemaphore; { ZoneScopedN("ESTC vkQueueSubmit"); // ESTC = end single time commands - std::lock_guard guard(m_QueueAccessMutex); + std::lock_guard guard(m_DeviceAccessMutex); vkQueueSubmit(GraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE); } @@ -735,14 +763,14 @@ namespace GfxRenderEngine { ZoneScopedN("ESTC wait sema"); { - std::lock_guard guard(m_QueueAccessMutex); if (vkWaitSemaphores(m_Device, &waitInfo, 0 /* no timeout, return immediately*/) == VK_SUCCESS) { + std::lock_guard guard(m_DeviceAccessMutex); vkFreeCommandBuffers(m_Device, m_LoadPool->GetCommandPool(), 1, &commandBuffer); break; } } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(1ms); } } } @@ -755,7 +783,10 @@ namespace GfxRenderEngine copyRegion.srcOffset = 0; // Optional copyRegion.dstOffset = 0; // Optional copyRegion.size = size; - vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); + } EndSingleTimeCommands(commandBuffer); } @@ -778,16 +809,23 @@ namespace GfxRenderEngine region.imageOffset = {0, 0, 0}; region.imageExtent = {width, height, 1}; - vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + { + std::lock_guard guard(m_DeviceAccessMutex); + vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } EndSingleTimeCommands(commandBuffer); } void VK_Device::CreateImageWithInfo(const VkImageCreateInfo& imageInfo, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) { - if (vkCreateImage(m_Device, &imageInfo, nullptr, &image) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create image!"); + auto result = vkCreateImage(m_Device, &imageInfo, nullptr, &image); + if (result != VK_SUCCESS) + { + PrintError(result); + LOG_CORE_CRITICAL("failed to create image!"); + } } VkMemoryRequirements memRequirements; @@ -798,14 +836,23 @@ namespace GfxRenderEngine allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(m_Device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to allocate image memory! in 'void VK_Device::CreateImageWithInfo'"); + auto result = vkAllocateMemory(m_Device, &allocInfo, nullptr, &imageMemory); + if (result != VK_SUCCESS) + { + PrintError(result); + LOG_CORE_CRITICAL("failed to allocate image memory! in 'void VK_Device::CreateImageWithInfo'"); + } } - - if (vkBindImageMemory(m_Device, image, imageMemory, 0) != VK_SUCCESS) + // only vkBindImageMemory is externally synchronized in this function { - LOG_CORE_CRITICAL("failed to bind image memory!"); + std::lock_guard guard(m_DeviceAccessMutex); + auto result = vkBindImageMemory(m_Device, image, imageMemory, 0); + if (result != VK_SUCCESS) + { + PrintError(result); + LOG_CORE_CRITICAL("failed to bind image memory!"); + } } } @@ -854,10 +901,151 @@ namespace GfxRenderEngine void VK_Device::WaitIdle() { ZoneScopedN("WaitIdle"); - std::lock_guard guard(m_QueueAccessMutex); vkDeviceWaitIdle(m_Device); } + void VK_Device::PrintError(VkResult result) + { + switch (result) + { + case VK_NOT_READY: + { + LOG_CORE_CRITICAL("VK_NOT_READY"); + break; + } + case VK_TIMEOUT: + { + LOG_CORE_CRITICAL("VK_TIMEOUT"); + break; + } + case VK_INCOMPLETE: + { + LOG_CORE_CRITICAL("VK_INCOMPLETE"); + break; + } + case VK_ERROR_OUT_OF_HOST_MEMORY: + { + LOG_CORE_CRITICAL("VK_ERROR_OUT_OF_HOST_MEMORY"); + break; + } + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + { + LOG_CORE_CRITICAL("VK_ERROR_OUT_OF_DEVICE_MEMORY"); + break; + } + case VK_ERROR_INITIALIZATION_FAILED: + { + LOG_CORE_CRITICAL("VK_ERROR_INITIALIZATION_FAILED"); + break; + } + case VK_ERROR_DEVICE_LOST: + { + LOG_CORE_CRITICAL("VK_ERROR_DEVICE_LOST"); + break; + } + case VK_ERROR_MEMORY_MAP_FAILED: + { + LOG_CORE_CRITICAL("VK_ERROR_MEMORY_MAP_FAILED"); + break; + } + case VK_ERROR_EXTENSION_NOT_PRESENT: + { + LOG_CORE_CRITICAL("VK_ERROR_EXTENSION_NOT_PRESENT"); + break; + } + case VK_ERROR_FEATURE_NOT_PRESENT: + { + LOG_CORE_CRITICAL("VK_ERROR_FEATURE_NOT_PRESENT"); + break; + } + case VK_ERROR_INCOMPATIBLE_DRIVER: + { + LOG_CORE_CRITICAL("VK_ERROR_INCOMPATIBLE_DRIVER"); + break; + } + case VK_ERROR_TOO_MANY_OBJECTS: + { + LOG_CORE_CRITICAL("VK_ERROR_TOO_MANY_OBJECTS"); + break; + } + case VK_ERROR_FORMAT_NOT_SUPPORTED: + { + LOG_CORE_CRITICAL("VK_ERROR_FORMAT_NOT_SUPPORTED"); + break; + } + case VK_ERROR_FRAGMENTED_POOL: + { + LOG_CORE_CRITICAL("VK_ERROR_FRAGMENTED_POOL"); + break; + } + case VK_ERROR_UNKNOWN: + { + LOG_CORE_CRITICAL("VK_ERROR_UNKNOWN"); + break; + } + case VK_ERROR_OUT_OF_POOL_MEMORY: + { + LOG_CORE_CRITICAL("VK_ERROR_OUT_OF_POOL_MEMORY"); + break; + } + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + { + LOG_CORE_CRITICAL("VK_ERROR_INVALID_EXTERNAL_HANDLE"); + break; + } + case VK_ERROR_FRAGMENTATION: + { + LOG_CORE_CRITICAL("VK_ERROR_FRAGMENTATION"); + break; + } + case VK_PIPELINE_COMPILE_REQUIRED: + { + LOG_CORE_CRITICAL("VK_PIPELINE_COMPILE_REQUIRED"); + break; + } + case VK_ERROR_SURFACE_LOST_KHR: + { + LOG_CORE_CRITICAL("VK_ERROR_SURFACE_LOST_KHR"); + break; + } + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + { + LOG_CORE_CRITICAL("VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"); + break; + } + case VK_ERROR_OUT_OF_DATE_KHR: + { + LOG_CORE_CRITICAL("VK_ERROR_OUT_OF_DATE_KHR"); + break; + } + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + { + LOG_CORE_CRITICAL("VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"); + break; + } + case VK_ERROR_VALIDATION_FAILED_EXT: + { + LOG_CORE_CRITICAL("VK_ERROR_VALIDATION_FAILED_EXT"); + break; + } + case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: + { + LOG_CORE_CRITICAL("VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR"); + break; + } + case VK_SUCCESS: + { + LOG_CORE_INFO("VK_SUCCES"); + break; + } + default: + { + LOG_CORE_CRITICAL("VK_Device::PrintError: error not in list"); + break; + } + } + } + void VK_Device::PrintAllSupportedFormats() { // clang-format off diff --git a/engine/platform/Vulkan/VKdevice.h b/engine/platform/Vulkan/VKdevice.h index e69fef12..563d37a0 100644 --- a/engine/platform/Vulkan/VKdevice.h +++ b/engine/platform/Vulkan/VKdevice.h @@ -43,7 +43,7 @@ namespace GfxRenderEngine const bool m_EnableValidationLayers = true; #endif - VK_Device(VK_Window* window, ThreadPool& threadPoolPrimary, ThreadPool& threadPoolSecondary); + VK_Device(VK_Window* window); ~VK_Device(); // Not copyable or movable @@ -88,9 +88,12 @@ namespace GfxRenderEngine VkInstance GetInstance() const { return m_Instance; } bool MultiThreadingSupport() const { return true; } - std::mutex m_QueueAccessMutex; + std::mutex m_DeviceAccessMutex; VK_Pool* GetLoadPool() { return m_LoadPool.get(); } + void LoadPool(ThreadPool& threadPoolPrimary, ThreadPool& threadPoolSecondary); + void ResetPool(ThreadPool& threadPool); void WaitIdle(); + void PrintError(VkResult result); private: static constexpr int NO_ASSIGNED = -1; diff --git a/engine/platform/Vulkan/VKgraphicsContext.cpp b/engine/platform/Vulkan/VKgraphicsContext.cpp index 3fea60f4..710e1111 100644 --- a/engine/platform/Vulkan/VKgraphicsContext.cpp +++ b/engine/platform/Vulkan/VKgraphicsContext.cpp @@ -36,8 +36,9 @@ namespace GfxRenderEngine : m_Window{window}, m_Initialized{false} { // create a device - m_Device = std::make_unique(window, threadPoolPrimary, threadPoolSecondary); + m_Device = std::make_unique(window); VK_Core::m_Device = m_Device.get(); + m_Device->LoadPool(threadPoolPrimary, threadPoolSecondary); m_Renderer = std::make_unique(m_Window); m_Initialized = m_Renderer->Init(); } @@ -76,45 +77,48 @@ namespace GfxRenderEngine std::shared_ptr VK_Context::LoadModel(const Builder& builder) { - ASSERT(VK_Core::m_Device != nullptr); + CORE_ASSERT(VK_Core::m_Device != nullptr, "device is null"); auto model = std::make_shared(VK_Core::m_Device, builder); return model; } std::shared_ptr VK_Context::LoadModel(const TerrainBuilder& builder) { - ASSERT(VK_Core::m_Device != nullptr); + CORE_ASSERT(VK_Core::m_Device != nullptr, "device is null"); auto model = std::make_shared(VK_Core::m_Device, builder); return model; } std::shared_ptr VK_Context::LoadModel(const GltfBuilder& builder) { - ASSERT(VK_Core::m_Device != nullptr); + CORE_ASSERT(VK_Core::m_Device != nullptr, "device is null"); auto model = std::make_shared(VK_Core::m_Device, builder); return model; } - std::shared_ptr VK_Context::LoadModel(const FastgltfBuilder& builder) + std::shared_ptr VK_Context::LoadModel(const Model::ModelData& modelData) { - ASSERT(VK_Core::m_Device != nullptr); - auto model = std::make_shared(VK_Core::m_Device, builder); + auto model = std::make_shared(modelData); return model; } std::shared_ptr VK_Context::LoadModel(const FbxBuilder& builder) { - ASSERT(VK_Core::m_Device != nullptr); + CORE_ASSERT(VK_Core::m_Device != nullptr, "device is null"); auto model = std::make_shared(VK_Core::m_Device, builder); return model; } std::shared_ptr VK_Context::LoadModel(const UFbxBuilder& builder) { - ASSERT(VK_Core::m_Device != nullptr); + CORE_ASSERT(VK_Core::m_Device != nullptr, "device is null"); auto model = std::make_shared(VK_Core::m_Device, builder); return model; } bool VK_Context::MultiThreadingSupport() const { return VK_Core::m_Device->MultiThreadingSupport(); } + + void VK_Context::WaitIdle() const { VK_Core::m_Device->WaitIdle(); }; + + void VK_Context::ResetDescriptorPool(ThreadPool& threadPool) { VK_Core::m_Device->ResetPool(threadPool); }; } // namespace GfxRenderEngine diff --git a/engine/platform/Vulkan/VKgraphicsContext.h b/engine/platform/Vulkan/VKgraphicsContext.h index 7a53e667..a5898488 100644 --- a/engine/platform/Vulkan/VKgraphicsContext.h +++ b/engine/platform/Vulkan/VKgraphicsContext.h @@ -49,7 +49,7 @@ namespace GfxRenderEngine virtual std::shared_ptr LoadModel(const Builder& builder) override; virtual std::shared_ptr LoadModel(const TerrainBuilder& builder) override; virtual std::shared_ptr LoadModel(const GltfBuilder& builder) override; - virtual std::shared_ptr LoadModel(const FastgltfBuilder& builder) override; + virtual std::shared_ptr LoadModel(const Model::ModelData& modelData) override; virtual std::shared_ptr LoadModel(const FbxBuilder& builder) override; virtual std::shared_ptr LoadModel(const UFbxBuilder& builder) override; virtual void ToggleDebugWindow(const GenericCallback& callback = nullptr) override @@ -60,6 +60,8 @@ namespace GfxRenderEngine virtual uint GetContextWidth() const override { return m_Renderer->GetContextWidth(); } virtual uint GetContextHeight() const override { return m_Renderer->GetContextHeight(); } virtual bool MultiThreadingSupport() const override; + virtual void WaitIdle() const override; + virtual void ResetDescriptorPool(ThreadPool& threadPool) override; private: bool m_Initialized; diff --git a/engine/platform/Vulkan/VKmodel.cpp b/engine/platform/Vulkan/VKmodel.cpp index d347e61d..5ff874b1 100644 --- a/engine/platform/Vulkan/VKmodel.cpp +++ b/engine/platform/Vulkan/VKmodel.cpp @@ -70,10 +70,16 @@ namespace GfxRenderEngine m_Animations = std::move(builder.m_Animations); \ m_ShaderDataUbo = builder.m_ShaderData; - VK_Model::VK_Model(VK_Device* device, const FastgltfBuilder& builder) : m_Device(device) + VK_Model::VK_Model(const Model::ModelData& modelData) : m_Device(VK_Core::m_Device) { ZoneScopedNC("VK_Model(FastgltfBuilder)", 0x00ffff); - INIT_GLTF_AND_FBX_MODEL(); + + CopySubmeshes(modelData.m_Submeshes); + CreateVertexBuffer(std::move(modelData.m_Vertices)); + CreateIndexBuffer(std::move(modelData.m_Indices)); + m_Skeleton = std::move(modelData.m_Skeleton); + m_Animations = std::move(modelData.m_Animations); + m_ShaderDataUbo = std::move(modelData.m_ShaderData); } VK_Model::VK_Model(VK_Device* device, const UFbxBuilder& builder) : m_Device(device) { INIT_GLTF_AND_FBX_MODEL(); } VK_Model::VK_Model(VK_Device* device, const GltfBuilder& builder) : m_Device(device) { INIT_GLTF_AND_FBX_MODEL(); } diff --git a/engine/platform/Vulkan/VKmodel.h b/engine/platform/Vulkan/VKmodel.h index a26db3ad..5295bcf4 100644 --- a/engine/platform/Vulkan/VKmodel.h +++ b/engine/platform/Vulkan/VKmodel.h @@ -88,7 +88,7 @@ namespace GfxRenderEngine public: VK_Model(VK_Device* device, const Builder& builder); VK_Model(VK_Device* device, const GltfBuilder& builder); - VK_Model(VK_Device* device, const FastgltfBuilder& builder); + VK_Model(const Model::ModelData&); VK_Model(VK_Device* device, const FbxBuilder& builder); VK_Model(VK_Device* device, const UFbxBuilder& builder); VK_Model(VK_Device* device, const TerrainBuilder& builder); diff --git a/engine/platform/Vulkan/VKpipeline.cpp b/engine/platform/Vulkan/VKpipeline.cpp index 4749532f..90840590 100644 --- a/engine/platform/Vulkan/VKpipeline.cpp +++ b/engine/platform/Vulkan/VKpipeline.cpp @@ -66,8 +66,8 @@ namespace GfxRenderEngine const std::string& filePathFragmentShader_SPV, const PipelineConfigInfo& configInfo) { - ASSERT(configInfo.pipelineLayout != nullptr); - ASSERT(configInfo.renderPass != nullptr); + CORE_ASSERT(configInfo.pipelineLayout != nullptr, "configInfo.pipelineLayout is null"); + CORE_ASSERT(configInfo.renderPass != nullptr, "configInfo.renderPass"); auto vertCode = readFile(filePathVertexShader_SPV); auto fragCode = readFile(filePathFragmentShader_SPV); @@ -130,10 +130,14 @@ namespace GfxRenderEngine pipelineInfo.basePipelineIndex = -1; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - if (vkCreateGraphicsPipelines(m_Device->Device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_GraphicsPipeline) != - VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create graphics pipeline"); + auto result = vkCreateGraphicsPipelines(m_Device->Device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, + &m_GraphicsPipeline); + if (result != VK_SUCCESS) + { + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create graphics pipeline"); + } } } void VK_Pipeline::CreateShaderModule(const std::vector& code, VkShaderModule* shaderModule) @@ -144,8 +148,10 @@ namespace GfxRenderEngine createInfo.codeSize = code.size(); createInfo.pCode = reinterpret_cast(code.data()); - if (vkCreateShaderModule(m_Device->Device(), &createInfo, nullptr, shaderModule) != VK_SUCCESS) + auto result = vkCreateShaderModule(m_Device->Device(), &createInfo, nullptr, shaderModule); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create shader module"); } } diff --git a/engine/platform/Vulkan/VKpool.cpp b/engine/platform/Vulkan/VKpool.cpp index 5ccf58b3..3fbd1e2c 100644 --- a/engine/platform/Vulkan/VKpool.cpp +++ b/engine/platform/Vulkan/VKpool.cpp @@ -22,6 +22,7 @@ #include +#include "VKcore.h" #include "VKpool.h" #include "VKswapChain.h" @@ -40,9 +41,13 @@ namespace GfxRenderEngine poolInfo.queueFamilyIndex = m_QueueFamilyIndices.m_GraphicsFamily; poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; VkCommandPool commandPool; - if (vkCreateCommandPool(m_Device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create graphics command pool!"); + auto result = vkCreateCommandPool(m_Device, &poolInfo, nullptr, &commandPool); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create graphics command pool!"); + } } return commandPool; }; @@ -72,8 +77,10 @@ namespace GfxRenderEngine semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.pNext = &timelineCreateInfo; { - if (vkCreateSemaphore(m_Device, &semaphoreInfo, nullptr, &uploadSemaphore) != VK_SUCCESS) + auto result = vkCreateSemaphore(m_Device, &semaphoreInfo, nullptr, &uploadSemaphore); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); CORE_HARD_STOP("failed to create synchronization objects in VK_Pool::CreateSyncObjects()!"); } } diff --git a/engine/platform/Vulkan/VKrenderPass.cpp b/engine/platform/Vulkan/VKrenderPass.cpp index 87d7862a..aa3751c8 100644 --- a/engine/platform/Vulkan/VKrenderPass.cpp +++ b/engine/platform/Vulkan/VKrenderPass.cpp @@ -124,8 +124,10 @@ namespace GfxRenderEngine viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_ColorAttachmentView) != VK_SUCCESS) + auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_ColorAttachmentView); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -164,8 +166,10 @@ namespace GfxRenderEngine viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_DepthImageView) != VK_SUCCESS) + auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_DepthImageView); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -188,9 +192,11 @@ namespace GfxRenderEngine framebufferInfo.height = m_RenderPassExtent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_3DFramebuffers[i]) != VK_SUCCESS) + auto result = vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_3DFramebuffers[i]); + if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create framebuffer!"); + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create framebuffer! Create3DFramebuffers()"); } } } @@ -212,10 +218,12 @@ namespace GfxRenderEngine framebufferInfo.height = m_RenderPassExtent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_PostProcessingFramebuffers[i]) != - VK_SUCCESS) + auto result = + vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_PostProcessingFramebuffers[i]); + if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create framebuffer!"); + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create framebuffer! CreatePostProcessingFramebuffers()"); } } } @@ -237,9 +245,11 @@ namespace GfxRenderEngine framebufferInfo.height = m_RenderPassExtent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_GUIFramebuffers[i]) != VK_SUCCESS) + auto result = vkCreateFramebuffer(m_Device->Device(), &framebufferInfo, nullptr, &m_GUIFramebuffers[i]); + if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create framebuffer!"); + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create framebuffer! CreateGUIFramebuffers()"); } } } @@ -372,6 +382,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_GBufferPositionView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -393,6 +404,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_GBufferNormalView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -414,6 +426,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_GBufferColorView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -435,6 +448,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_GBufferMaterialView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -456,6 +470,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_GBufferEmissionView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -695,8 +710,10 @@ namespace GfxRenderEngine renderPassInfo.dependencyCount = NUMBER_OF_DEPENDENCIES; renderPassInfo.pDependencies = dependencies.data(); - if (vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_3DRenderPass) != VK_SUCCESS) + auto result = vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_3DRenderPass); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create render pass!"); } } @@ -800,8 +817,10 @@ namespace GfxRenderEngine renderPassInfo.dependencyCount = NUMBER_OF_DEPENDENCIES; renderPassInfo.pDependencies = dependencies.data(); - if (vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_PostProcessingRenderPass) != VK_SUCCESS) + auto result = vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_PostProcessingRenderPass); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create render pass!"); } } @@ -869,9 +888,11 @@ namespace GfxRenderEngine renderPassInfo.dependencyCount = NUMBER_OF_DEPENDENCIES; renderPassInfo.pDependencies = dependencies.data(); - if (vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_GUIRenderPass) != VK_SUCCESS) + auto result = vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_GUIRenderPass); + if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create render pass!"); + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create render pass! CreateGUIRenderPass()"); } } diff --git a/engine/platform/Vulkan/VKrenderer.cpp b/engine/platform/Vulkan/VKrenderer.cpp index 5eeb4b5a..a7d8641d 100644 --- a/engine/platform/Vulkan/VKrenderer.cpp +++ b/engine/platform/Vulkan/VKrenderer.cpp @@ -439,8 +439,10 @@ namespace GfxRenderEngine allocateInfo.commandPool = m_Device->GetCommandPool(); allocateInfo.commandBufferCount = static_cast(m_CommandBuffers.size()); - if (vkAllocateCommandBuffers(m_Device->Device(), &allocateInfo, m_CommandBuffers.data()) != VK_SUCCESS) + auto result = vkAllocateCommandBuffers(m_Device->Device(), &allocateInfo, m_CommandBuffers.data()); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate command buffers"); } } @@ -454,26 +456,28 @@ namespace GfxRenderEngine VkCommandBuffer VK_Renderer::GetCurrentCommandBuffer() const { - ASSERT(m_FrameInProgress); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); return m_CommandBuffers[m_CurrentFrameIndex]; } VkCommandBuffer VK_Renderer::BeginFrame() { ZoneScopedN("VK_Renderer::BeginFrame()"); - ASSERT(!m_FrameInProgress); + CORE_ASSERT(!m_FrameInProgress, "frame must not be in progress"); - auto result = m_SwapChain->AcquireNextImage(&m_CurrentImageIndex); - - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - Recreate(); - return nullptr; - } + auto result = m_SwapChain->AcquireNextImage(&m_CurrentImageIndex); - if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) - { - LOG_CORE_CRITICAL("failed to acquire next swap chain image"); + if (result == VK_ERROR_OUT_OF_DATE_KHR) + { + Recreate(); + return nullptr; + } + + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) + { + LOG_CORE_CRITICAL("failed to acquire next swap chain image"); + } } m_FrameInProgress = true; @@ -483,11 +487,14 @@ namespace GfxRenderEngine VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to begin recording command buffer!"); + auto result = vkBeginCommandBuffer(commandBuffer, &beginInfo); + if (result != VK_SUCCESS) + { + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to allocate command buffers"); + } } - return commandBuffer; } @@ -496,13 +503,15 @@ namespace GfxRenderEngine { ZoneScopedNS("VK_Renderer::EndFrame()", 10); } - ASSERT(m_FrameInProgress); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); auto commandBuffer = GetCurrentCommandBuffer(); { ZoneScopedN("vkEndCommandBuffer"); - if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) + auto result = vkEndCommandBuffer(commandBuffer); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("recording of command buffer failed"); } } @@ -515,7 +524,8 @@ namespace GfxRenderEngine } else if (result != VK_SUCCESS) { - LOG_CORE_WARN("failed to present swap chain image"); + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to present swap chain image"); } m_FrameInProgress = false; m_CurrentFrameIndex = (m_CurrentFrameIndex + 1) % VK_SwapChain::MAX_FRAMES_IN_FLIGHT; @@ -532,8 +542,8 @@ namespace GfxRenderEngine void VK_Renderer::BeginShadowRenderPass0(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -564,8 +574,8 @@ namespace GfxRenderEngine void VK_Renderer::BeginShadowRenderPass1(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -647,8 +657,8 @@ namespace GfxRenderEngine void VK_Renderer::Begin3DRenderPass(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -685,8 +695,8 @@ namespace GfxRenderEngine void VK_Renderer::BeginPostProcessingRenderPass(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -718,8 +728,8 @@ namespace GfxRenderEngine void VK_Renderer::BeginGUIRenderPass(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -747,8 +757,8 @@ namespace GfxRenderEngine void VK_Renderer::EndRenderPass(VkCommandBuffer commandBuffer) { - ASSERT(m_FrameInProgress); - ASSERT(commandBuffer == GetCurrentCommandBuffer()); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); + CORE_ASSERT(commandBuffer == GetCurrentCommandBuffer(), "command buffer must be current command buffer"); vkCmdEndRenderPass(commandBuffer); } @@ -786,8 +796,9 @@ namespace GfxRenderEngine void VK_Renderer::UpdateTransformCache(Scene& scene, uint const nodeIndex, glm::mat4 const& parentMat4, bool parentDirtyFlag) { - TreeNode& node = scene.GetTreeNode(nodeIndex); + auto& node = scene.GetTreeNode(nodeIndex); entt::entity gameObject = node.GetGameObject(); + auto& transform = scene.GetRegistry().get(gameObject); bool dirtyFlag = transform.GetDirtyFlag() || parentDirtyFlag; @@ -895,7 +906,7 @@ namespace GfxRenderEngine int VK_Renderer::GetFrameIndex() const { - ASSERT(m_FrameInProgress); + CORE_ASSERT(m_FrameInProgress, "frame must be in progress"); return m_CurrentFrameIndex; } diff --git a/engine/platform/Vulkan/VKshadowMap.cpp b/engine/platform/Vulkan/VKshadowMap.cpp index b713cccc..8051eb11 100644 --- a/engine/platform/Vulkan/VKshadowMap.cpp +++ b/engine/platform/Vulkan/VKshadowMap.cpp @@ -117,8 +117,10 @@ namespace GfxRenderEngine renderPassInfo.dependencyCount = NUMBER_OF_DEPENDENCIES; renderPassInfo.pDependencies = dependencies.data(); - if (vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_ShadowRenderPass) != VK_SUCCESS) + auto result = vkCreateRenderPass(m_Device->Device(), &renderPassInfo, nullptr, &m_ShadowRenderPass); + if (result != VK_SUCCESS) { + m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create render pass!"); } } @@ -157,9 +159,13 @@ namespace GfxRenderEngine viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_ShadowDepthImageView) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create texture image view! (CreateShadowDepthResources)"); + auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_ShadowDepthImageView); + if (result != VK_SUCCESS) + { + m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create texture image view! (CreateShadowDepthResources)"); + } } // sampler @@ -183,6 +189,7 @@ namespace GfxRenderEngine auto result = vkCreateSampler(m_Device->Device(), &samplerCreateInfo, nullptr, &m_ShadowDepthSampler); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create sampler!"); } } diff --git a/engine/platform/Vulkan/VKswapChain.cpp b/engine/platform/Vulkan/VKswapChain.cpp index e171d781..6e2d65f9 100644 --- a/engine/platform/Vulkan/VKswapChain.cpp +++ b/engine/platform/Vulkan/VKswapChain.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -77,10 +77,9 @@ namespace GfxRenderEngine vkWaitForFences(m_Device->Device(), 1, &m_InFlightFences[m_CurrentFrame], VK_TRUE, std::numeric_limits::max()); - VkResult result = - vkAcquireNextImageKHR(m_Device->Device(), m_SwapChain, std::numeric_limits::max(), - m_ImageAvailableSemaphores[m_CurrentFrame], // must be a not signaled semaphore - VK_NULL_HANDLE, imageIndex); + auto result = vkAcquireNextImageKHR(m_Device->Device(), m_SwapChain, std::numeric_limits::max(), + m_ImageAvailableSemaphores[m_CurrentFrame], // must be a not signaled semaphore + VK_NULL_HANDLE, imageIndex); return result; } @@ -89,7 +88,6 @@ namespace GfxRenderEngine { if (m_ImagesInFlight[*imageIndex] != VK_NULL_HANDLE) { - std::lock_guard guard(VK_Core::m_Device->m_QueueAccessMutex); ZoneScopedN("SCB waitFence"); // SCB: submit command buffers PROFILE_SCOPE("waitFor ImagesInFlight"); vkWaitForFences(m_Device->Device(), 1, &m_ImagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); @@ -113,12 +111,14 @@ namespace GfxRenderEngine submitInfo.pSignalSemaphores = signalSemaphores; { - std::lock_guard guard(VK_Core::m_Device->m_QueueAccessMutex); vkResetFences(m_Device->Device(), 1, &m_InFlightFences[m_CurrentFrame]); { ZoneScopedN("SCB queueSubmit"); - if (vkQueueSubmit(m_Device->GraphicsQueue(), 1, &submitInfo, m_InFlightFences[m_CurrentFrame]) != VK_SUCCESS) + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + auto result = vkQueueSubmit(m_Device->GraphicsQueue(), 1, &submitInfo, m_InFlightFences[m_CurrentFrame]); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to submit draw command buffer!"); } } @@ -139,7 +139,7 @@ namespace GfxRenderEngine VkResult result{}; { ZoneScopedN("vkQueuePresentKHR"); - std::lock_guard guard(VK_Core::m_Device->m_QueueAccessMutex); + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); result = vkQueuePresentKHR(m_Device->PresentQueue(), &presentInfo); } @@ -201,6 +201,7 @@ namespace GfxRenderEngine auto result = vkCreateSwapchainKHR(m_Device->Device(), &createInfo, nullptr, &m_SwapChain); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create swap chain!"); } @@ -235,6 +236,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(m_Device->Device(), &viewInfo, nullptr, &m_SwapChainImageViews[i]); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } diff --git a/engine/platform/Vulkan/VKswapChain.h b/engine/platform/Vulkan/VKswapChain.h index 3aa5ec06..cffbbe75 100644 --- a/engine/platform/Vulkan/VKswapChain.h +++ b/engine/platform/Vulkan/VKswapChain.h @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person diff --git a/engine/platform/Vulkan/VKtexture.cpp b/engine/platform/Vulkan/VKtexture.cpp index 19f21b24..0f2ed6bd 100644 --- a/engine/platform/Vulkan/VKtexture.cpp +++ b/engine/platform/Vulkan/VKtexture.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -43,6 +43,7 @@ namespace GfxRenderEngine { auto device = VK_Core::m_Device->Device(); + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); vkDestroyImage(device, m_TextureImage, nullptr); vkDestroyImageView(device, m_ImageView, nullptr); vkDestroySampler(device, m_Sampler, nullptr); @@ -155,7 +156,10 @@ namespace GfxRenderEngine return; } - vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + } VK_Core::m_Device->EndSingleTimeCommands(commandBuffer); } @@ -186,6 +190,7 @@ namespace GfxRenderEngine auto result = vkCreateImage(device, &imageInfo, nullptr, &m_TextureImage); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create image!"); } } @@ -202,12 +207,15 @@ namespace GfxRenderEngine auto result = vkAllocateMemory(device, &allocInfo, nullptr, &m_TextureImageMemory); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate image memory in 'void " "VK_Texture::CreateImage'"); } } - - vkBindImageMemory(device, m_TextureImage, m_TextureImageMemory, 0); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkBindImageMemory(device, m_TextureImage, m_TextureImageMemory, 0); + } } void VK_Texture::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, @@ -221,9 +229,13 @@ namespace GfxRenderEngine bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create buffer!"); + auto result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer); + if (result != VK_SUCCESS) + { + VK_Core::m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create buffer!"); + } } VkMemoryRequirements memRequirements; @@ -238,11 +250,14 @@ namespace GfxRenderEngine auto result = vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to allocate buffer memory!"); } } - - vkBindBufferMemory(device, buffer, bufferMemory, 0); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkBindBufferMemory(device, buffer, bufferMemory, 0); + } } bool VK_Texture::Create() @@ -264,9 +279,15 @@ namespace GfxRenderEngine stagingBufferMemory); void* data; - vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data); + } memcpy(data, m_LocalBuffer, static_cast(imageSize)); - vkUnmapMemory(device, stagingBufferMemory); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkUnmapMemory(device, stagingBufferMemory); + } VkFormat format = m_sRGB ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; CreateImage(format, VK_IMAGE_TILING_OPTIMAL, @@ -283,8 +304,11 @@ namespace GfxRenderEngine m_ImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkDestroyBuffer(device, stagingBuffer, nullptr); - vkFreeMemory(device, stagingBufferMemory, nullptr); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkDestroyBuffer(device, stagingBuffer, nullptr); + vkFreeMemory(device, stagingBufferMemory, nullptr); + } // Create a texture sampler // In Vulkan, textures are accessed by samplers @@ -312,6 +336,7 @@ namespace GfxRenderEngine auto result = vkCreateSampler(device, &samplerCreateInfo, nullptr, &m_Sampler); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create sampler!"); } } @@ -343,6 +368,7 @@ namespace GfxRenderEngine auto result = vkCreateImageView(device, &view, nullptr, &m_ImageView); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create image view!"); } } @@ -405,8 +431,11 @@ namespace GfxRenderEngine barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, + nullptr, 0, nullptr, 1, &barrier); + } VkImageBlit blit{}; blit.srcOffsets[0] = {0, 0, 0}; @@ -421,22 +450,30 @@ namespace GfxRenderEngine blit.dstSubresource.mipLevel = i; blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.layerCount = 1; - - vkCmdBlitImage(commandBuffer, m_TextureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_TextureImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, m_MinFilterMip); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkCmdBlitImage(commandBuffer, m_TextureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_TextureImage, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, m_MinFilterMip); + } barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + 0, nullptr, 0, nullptr, 1, &barrier); + } if (mipWidth > 1) + { mipWidth /= 2; + } if (mipHeight > 1) + { mipHeight /= 2; + } } barrier.subresourceRange.baseMipLevel = m_MipLevels - 1; @@ -445,8 +482,11 @@ namespace GfxRenderEngine barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); + { + std::lock_guard guard(VK_Core::m_Device->m_DeviceAccessMutex); + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, + nullptr, 0, nullptr, 1, &barrier); + } VK_Core::m_Device->EndSingleTimeCommands(commandBuffer); } diff --git a/engine/platform/Vulkan/VKwindow.cpp b/engine/platform/Vulkan/VKwindow.cpp index b56b0335..f14cdf18 100644 --- a/engine/platform/Vulkan/VKwindow.cpp +++ b/engine/platform/Vulkan/VKwindow.cpp @@ -309,8 +309,10 @@ namespace GfxRenderEngine void VK_Window::CreateWindowSurface(VkInstance instance, VkSurfaceKHR* surface) { - if (glfwCreateWindowSurface(instance, m_Window, nullptr, surface) != VK_SUCCESS) + auto result = glfwCreateWindowSurface(instance, m_Window, nullptr, surface); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("Could not create window surface"); } } diff --git a/engine/platform/Vulkan/imguiEngine/VKimgui.cpp b/engine/platform/Vulkan/imguiEngine/VKimgui.cpp index 5452338c..6f5563d1 100644 --- a/engine/platform/Vulkan/imguiEngine/VKimgui.cpp +++ b/engine/platform/Vulkan/imguiEngine/VKimgui.cpp @@ -64,6 +64,7 @@ namespace GfxRenderEngine auto result = vkCreateDescriptorPool(VK_Core::m_Device->Device(), &pool_info, nullptr, &m_DescriptorPool); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); throw std::runtime_error("failed to set up descriptor pool for imgui"); } diff --git a/engine/platform/Vulkan/systems/VKcubemapRenderSys.cpp b/engine/platform/Vulkan/systems/VKcubemapRenderSys.cpp index cfe45923..6298476c 100644 --- a/engine/platform/Vulkan/systems/VKcubemapRenderSys.cpp +++ b/engine/platform/Vulkan/systems/VKcubemapRenderSys.cpp @@ -55,16 +55,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemCubemap::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKdebugRenderSys.cpp b/engine/platform/Vulkan/systems/VKdebugRenderSys.cpp index 82379beb..720dbd74 100644 --- a/engine/platform/Vulkan/systems/VKdebugRenderSys.cpp +++ b/engine/platform/Vulkan/systems/VKdebugRenderSys.cpp @@ -50,16 +50,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemDebug::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKdeferredShading.cpp b/engine/platform/Vulkan/systems/VKdeferredShading.cpp index 1f7664b0..73bf72fa 100644 --- a/engine/platform/Vulkan/systems/VKdeferredShading.cpp +++ b/engine/platform/Vulkan/systems/VKdeferredShading.cpp @@ -61,16 +61,18 @@ namespace GfxRenderEngine lightingPipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); lightingPipelineLayoutInfo.pushConstantRangeCount = 1; lightingPipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &lightingPipelineLayoutInfo, nullptr, - &m_LightingPipelineLayout) != VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &lightingPipelineLayoutInfo, nullptr, + &m_LightingPipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemDeferredShading::CreateLightingPipeline(VkRenderPass renderPass) { - ASSERT(m_LightingPipelineLayout != nullptr); + CORE_ASSERT(m_LightingPipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKgrassSys.cpp b/engine/platform/Vulkan/systems/VKgrassSys.cpp index a4d67b32..68d24bf0 100644 --- a/engine/platform/Vulkan/systems/VKgrassSys.cpp +++ b/engine/platform/Vulkan/systems/VKgrassSys.cpp @@ -58,9 +58,10 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } diff --git a/engine/platform/Vulkan/systems/VKguiRenderSys.cpp b/engine/platform/Vulkan/systems/VKguiRenderSys.cpp index 486e949d..d4df5f4c 100644 --- a/engine/platform/Vulkan/systems/VKguiRenderSys.cpp +++ b/engine/platform/Vulkan/systems/VKguiRenderSys.cpp @@ -59,16 +59,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemGUIRenderer::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKlightSys.cpp b/engine/platform/Vulkan/systems/VKlightSys.cpp index 59071798..da667543 100644 --- a/engine/platform/Vulkan/systems/VKlightSys.cpp +++ b/engine/platform/Vulkan/systems/VKlightSys.cpp @@ -64,15 +64,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != VK_SUCCESS) + auto result = vkCreatePipelineLayout(m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_LightSystem::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; @@ -129,7 +131,7 @@ namespace GfxRenderEngine { auto& transform = view.get(entity); - ASSERT(lightIndex < MAX_LIGHTS); + CORE_ASSERT(lightIndex < MAX_LIGHTS, "light index must be less than MAX_LIGHTS"); auto& mat4Global = transform.GetMat4Global(); constexpr int column = 3; @@ -169,7 +171,7 @@ namespace GfxRenderEngine { auto& directionalLight = view.get(entity); - ASSERT(lightIndex < MAX_LIGHTS); + CORE_ASSERT(lightIndex < MAX_LIGHTS, "light index must be less than MAX_LIGHTS"); // copy light to ubo ubo.m_DirectionalLight.m_Direction = glm::vec4(directionalLight.m_Direction, 0.0f); diff --git a/engine/platform/Vulkan/systems/VKpbrSASys.cpp b/engine/platform/Vulkan/systems/VKpbrSASys.cpp index 27def66b..f6db6948 100644 --- a/engine/platform/Vulkan/systems/VKpbrSASys.cpp +++ b/engine/platform/Vulkan/systems/VKpbrSASys.cpp @@ -57,9 +57,10 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } diff --git a/engine/platform/Vulkan/systems/VKpbrSys.cpp b/engine/platform/Vulkan/systems/VKpbrSys.cpp index 06d08ae2..ce2382a5 100644 --- a/engine/platform/Vulkan/systems/VKpbrSys.cpp +++ b/engine/platform/Vulkan/systems/VKpbrSys.cpp @@ -54,9 +54,10 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } diff --git a/engine/platform/Vulkan/systems/VKpostprocessingSys.cpp b/engine/platform/Vulkan/systems/VKpostprocessingSys.cpp index cdbfff31..e69cee6f 100644 --- a/engine/platform/Vulkan/systems/VKpostprocessingSys.cpp +++ b/engine/platform/Vulkan/systems/VKpostprocessingSys.cpp @@ -59,16 +59,18 @@ namespace GfxRenderEngine postProcessingPipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); postProcessingPipelineLayoutInfo.pushConstantRangeCount = 1; postProcessingPipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &postProcessingPipelineLayoutInfo, nullptr, - &m_PostProcessingPipelineLayout) != VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &postProcessingPipelineLayoutInfo, nullptr, + &m_PostProcessingPipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemPostProcessing::CreatePostProcessingPipeline(VkRenderPass renderPass) { - ASSERT(m_PostProcessingPipelineLayout != nullptr); + CORE_ASSERT(m_PostProcessingPipelineLayout != nullptr, "m_PostProcessingPipelineLayout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKshadowAnimatedRenderSysInstanced.cpp b/engine/platform/Vulkan/systems/VKshadowAnimatedRenderSysInstanced.cpp index dfda5a9c..7e73b3b2 100644 --- a/engine/platform/Vulkan/systems/VKshadowAnimatedRenderSysInstanced.cpp +++ b/engine/platform/Vulkan/systems/VKshadowAnimatedRenderSysInstanced.cpp @@ -52,9 +52,10 @@ namespace GfxRenderEngine pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } @@ -62,7 +63,7 @@ namespace GfxRenderEngine void VK_RenderSystemShadowAnimatedInstanced::CreatePipeline(std::unique_ptr& pipeline, VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKshadowRenderSysInstanced.cpp b/engine/platform/Vulkan/systems/VKshadowRenderSysInstanced.cpp index cbbc2888..252135e2 100644 --- a/engine/platform/Vulkan/systems/VKshadowRenderSysInstanced.cpp +++ b/engine/platform/Vulkan/systems/VKshadowRenderSysInstanced.cpp @@ -49,16 +49,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemShadowInstanced::CreatePipeline(std::unique_ptr& pipeline, VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKspriteRenderSys.cpp b/engine/platform/Vulkan/systems/VKspriteRenderSys.cpp index f53b12af..0ab851af 100644 --- a/engine/platform/Vulkan/systems/VKspriteRenderSys.cpp +++ b/engine/platform/Vulkan/systems/VKspriteRenderSys.cpp @@ -55,16 +55,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemSpriteRenderer::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/platform/Vulkan/systems/VKspriteRenderSys2D.cpp b/engine/platform/Vulkan/systems/VKspriteRenderSys2D.cpp index 7bc141b5..2eee310c 100644 --- a/engine/platform/Vulkan/systems/VKspriteRenderSys2D.cpp +++ b/engine/platform/Vulkan/systems/VKspriteRenderSys2D.cpp @@ -56,16 +56,17 @@ namespace GfxRenderEngine pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout) != - VK_SUCCESS) + auto result = vkCreatePipelineLayout(VK_Core::m_Device->Device(), &pipelineLayoutInfo, nullptr, &m_PipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemSpriteRenderer2D::CreatePipeline(VkRenderPass renderPass) { - ASSERT(m_PipelineLayout != nullptr); + CORE_ASSERT(m_PipelineLayout != nullptr, "pipeline layout is null"); PipelineConfigInfo pipelineConfig{}; @@ -79,8 +80,7 @@ namespace GfxRenderEngine "bin-int/spriteRenderer2D.frag.spv", pipelineConfig); } - void VK_RenderSystemSpriteRenderer2D::RenderEntities(const VK_FrameInfo& frameInfo, Registry& registry, - Camera* camera) + void VK_RenderSystemSpriteRenderer2D::RenderEntities(const VK_FrameInfo& frameInfo, Registry& registry, Camera* camera) { vkCmdBindDescriptorSets(frameInfo.m_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_PipelineLayout, 0, 1, &frameInfo.m_GlobalDescriptorSet, 0, nullptr); diff --git a/engine/platform/Vulkan/systems/bloom/VKbloomFrameBuffer.cpp b/engine/platform/Vulkan/systems/bloom/VKbloomFrameBuffer.cpp index a17d0b3c..0f68f4bd 100644 --- a/engine/platform/Vulkan/systems/bloom/VKbloomFrameBuffer.cpp +++ b/engine/platform/Vulkan/systems/bloom/VKbloomFrameBuffer.cpp @@ -39,8 +39,10 @@ namespace GfxRenderEngine framebufferInfo.height = m_Attachment.m_Extent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(VK_Core::m_Device->Device(), &framebufferInfo, nullptr, &m_Framebuffer) != VK_SUCCESS) + auto result = vkCreateFramebuffer(VK_Core::m_Device->Device(), &framebufferInfo, nullptr, &m_Framebuffer); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create framebuffer!"); } } diff --git a/engine/platform/Vulkan/systems/bloom/VKbloomRenderPass.cpp b/engine/platform/Vulkan/systems/bloom/VKbloomRenderPass.cpp index a6c4af7c..f9c60706 100644 --- a/engine/platform/Vulkan/systems/bloom/VKbloomRenderPass.cpp +++ b/engine/platform/Vulkan/systems/bloom/VKbloomRenderPass.cpp @@ -87,9 +87,11 @@ namespace GfxRenderEngine renderPassInfo.dependencyCount = 2; renderPassInfo.pDependencies = subpassDependencies.data(); - if (vkCreateRenderPass(VK_Core::m_Device->Device(), &renderPassInfo, nullptr, &m_RenderPass) != VK_SUCCESS) + auto result = vkCreateRenderPass(VK_Core::m_Device->Device(), &renderPassInfo, nullptr, &m_RenderPass); + if (result != VK_SUCCESS) { - LOG_CORE_CRITICAL("failed to create render pass!"); + VK_Core::m_Device->PrintError(result); + LOG_CORE_CRITICAL("failed to create renderpass!"); } } diff --git a/engine/platform/Vulkan/systems/bloom/VKbloomRenderSystem.cpp b/engine/platform/Vulkan/systems/bloom/VKbloomRenderSystem.cpp index 132d411b..b758c125 100644 --- a/engine/platform/Vulkan/systems/bloom/VKbloomRenderSystem.cpp +++ b/engine/platform/Vulkan/systems/bloom/VKbloomRenderSystem.cpp @@ -81,6 +81,7 @@ namespace GfxRenderEngine vkCreateImageView(VK_Core::m_Device->Device(), &viewInfo, nullptr, &m_EmissionMipmapViews[mipLevel]); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create texture image view!"); } } @@ -232,6 +233,7 @@ namespace GfxRenderEngine auto result = vkCreateSampler(VK_Core::m_Device->Device(), &samplerCreateInfo, nullptr, &m_Sampler); if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create sampler!"); } } @@ -265,16 +267,18 @@ namespace GfxRenderEngine bloomPipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; bloomPipelineLayoutInfo.pushConstantRangeCount = 1; bloomPipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - if (vkCreatePipelineLayout(VK_Core::m_Device->Device(), &bloomPipelineLayoutInfo, nullptr, &m_BloomPipelineLayout) != - VK_SUCCESS) + auto result = + vkCreatePipelineLayout(VK_Core::m_Device->Device(), &bloomPipelineLayoutInfo, nullptr, &m_BloomPipelineLayout); + if (result != VK_SUCCESS) { + VK_Core::m_Device->PrintError(result); LOG_CORE_CRITICAL("failed to create pipeline layout!"); } } void VK_RenderSystemBloom::CreateBloomPipelines() { - ASSERT(m_BloomPipelineLayout != nullptr); + CORE_ASSERT(m_BloomPipelineLayout != nullptr, "m_BloomPipelineLayout is null"); PipelineConfigInfo pipelineConfig{}; diff --git a/engine/renderer/builder/builder.cpp b/engine/renderer/builder/builder.cpp index 790b08bb..8b188fae 100644 --- a/engine/renderer/builder/builder.cpp +++ b/engine/renderer/builder/builder.cpp @@ -29,7 +29,6 @@ #include "renderer/builder/builder.h" #include "renderer/model.h" - #include "VKmodel.h" namespace std @@ -52,58 +51,39 @@ namespace GfxRenderEngine { m_Vertices.clear(); m_Indices.clear(); - + m_Vertices.reserve(4); + m_Indices.reserve(6); // 0 - 1 // | / | // 3 - 2 - Vertex vertex[4]; - // index 0, 0.0f, 1.0f - vertex[0] = {/*pos*/ {-1.0f, 1.0f, 0.0f}, - /*col*/ {0.0f, 0.1f, 0.9f, 1.0f}, - /*norm*/ {0.0f, 0.0f, 1.0f}, - /*uv*/ {sprite.m_Pos1X, sprite.m_Pos1Y}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}; - + m_Vertices.emplace_back(/*pos*/ glm::vec3{-1.0f, 1.0f, 0.0f}, + /*col*/ glm::vec4{0.0f, 0.1f, 0.9f, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, 1.0f}, + /*uv*/ glm::vec2{sprite.m_Pos1X, sprite.m_Pos1Y}); // index 1, 1.0f, 1.0f - vertex[1] = {/*pos*/ {1.0f, 1.0f, 0.0f}, - /*col*/ {0.0f, 0.1f, 0.9f, 1.0f}, - /*norm*/ {0.0f, 0.0f, 1.0f}, - /*uv*/ {sprite.m_Pos2X, sprite.m_Pos1Y}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}; - + m_Vertices.emplace_back(/*pos*/ glm::vec3{1.0f, 1.0f, 0.0f}, + /*col*/ glm::vec4{0.0f, 0.1f, 0.9f, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, 1.0f}, + /*uv*/ glm::vec2{sprite.m_Pos2X, sprite.m_Pos1Y}); // index 2, 1.0f, 0.0f - vertex[2] = {/*pos*/ {1.0f, -1.0f, 0.0f}, - /*col*/ {0.0f, 0.9f, 0.1f, 1.0f}, - /*norm*/ {0.0f, 0.0f, 1.0f}, - /*uv*/ {sprite.m_Pos2X, sprite.m_Pos2Y}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}; - + m_Vertices.emplace_back(/*pos*/ glm::vec3{1.0f, -1.0f, 0.0f}, + /*col*/ glm::vec4{0.0f, 0.9f, 0.1f, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, 1.0f}, + /*uv*/ glm::vec2{sprite.m_Pos2X, sprite.m_Pos2Y}); // index 3, 0.0f, 0.0f - vertex[3] = {/*pos*/ {-1.0f, -1.0f, 0.0f}, - /*col*/ {0.0f, 0.9f, 0.1f, 1.0f}, - /*norm*/ {0.0f, 0.0f, 1.0f}, - /*uv*/ {sprite.m_Pos1X, sprite.m_Pos2Y}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}; - - for (int i = 0; i < 4; i++) - m_Vertices.push_back(vertex[i]); - - m_Indices.push_back(0); - m_Indices.push_back(1); - m_Indices.push_back(3); - m_Indices.push_back(1); - m_Indices.push_back(2); - m_Indices.push_back(3); + m_Vertices.emplace_back(/*pos*/ glm::vec3{-1.0f, -1.0f, 0.0f}, + /*col*/ glm::vec4{0.0f, 0.9f, 0.1f, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, 1.0f}, + /*uv*/ glm::vec2{sprite.m_Pos1X, sprite.m_Pos2Y}); + + m_Indices.emplace_back(0); + m_Indices.emplace_back(1); + m_Indices.emplace_back(3); + m_Indices.emplace_back(1); + m_Indices.emplace_back(2); + m_Indices.emplace_back(3); } void Builder::LoadParticle(glm::vec4 const& color) @@ -111,58 +91,48 @@ namespace GfxRenderEngine m_Vertices.clear(); m_Indices.clear(); + m_Vertices.reserve(4); + m_Indices.reserve(6); + // 0 - 1 // | / | // 3 - 2 - Vertex vertex[4]{// index 0, 0.0f, 1.0f - {/*pos*/ {-1.0f, 1.0f, 0.0f}, - {color.x, color.y, color.z, 1.0f}, - /*norm*/ {0.0f, 0.0f, -1.0f}, - /*uv*/ {0.0f, 1.0f}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}, - - // index 1, 1.0f, 1.0f - {/*pos*/ {1.0f, 1.0f, 0.0f}, - {color.x, color.y, color.z, 1.0f}, - /*norm*/ {0.0f, 0.0f, -1.0f}, - /*uv*/ {1.0f, 1.0f}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}, - - // index 2, 1.0f, 0.0f - {/*pos*/ {1.0f, -1.0f, 0.0f}, - {color.x, color.y, color.z, 1.0f}, - /*norm*/ {0.0f, 0.0f, -1.0f}, - /*uv*/ {1.0f, 0.0f}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}, - - // index 3, 0.0f, 0.0f - {/*pos*/ {-1.0f, -1.0f, 0.0f}, - {color.x, color.y, color.z, 1.0f}, - /*norm*/ {0.0f, 0.0f, -1.0f}, - /*uv*/ {0.0f, 0.0f}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}}; - for (int i = 0; i < 4; i++) - m_Vertices.push_back(vertex[i]); - - m_Indices.push_back(0); - m_Indices.push_back(1); - m_Indices.push_back(3); - m_Indices.push_back(1); - m_Indices.push_back(2); - m_Indices.push_back(3); + // index 0, 0.0f, 1.0f + m_Vertices.emplace_back(/*pos*/ glm::vec3{-1.0f, 1.0f, 0.0f}, + /*col*/ glm::vec4{color.x, color.y, color.z, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, -1.0f}, + /*uv*/ glm::vec2{0.0f, 1.0f}); + + // index 1, 1.0f, 1.0f + m_Vertices.emplace_back(/*pos*/ glm::vec3{1.0f, 1.0f, 0.0f}, + /*col*/ glm::vec4{color.x, color.y, color.z, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, -1.0f}, + /*uv*/ glm::vec2{1.0f, 1.0f}); + + // index 2, 1.0f, 0.0f + m_Vertices.emplace_back(/*pos*/ glm::vec3{1.0f, -1.0f, 0.0f}, + /*col*/ glm::vec4{color.x, color.y, color.z, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, -1.0f}, + /*uv*/ glm::vec2{1.0f, 0.0f}); + + // index 3, 0.0f, 0.0f + m_Vertices.emplace_back(/*pos*/ glm::vec3{-1.0f, -1.0f, 0.0f}, + /*col*/ glm::vec4{color.x, color.y, color.z, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, -1.0f}, + /*uv*/ glm::vec2{0.0f, 0.0f}); + + m_Indices.emplace_back(0); + m_Indices.emplace_back(1); + m_Indices.emplace_back(3); + m_Indices.emplace_back(1); + m_Indices.emplace_back(2); + m_Indices.emplace_back(3); } entt::entity Builder::LoadCubemap(std::vector const& faces, Registry& registry) { + ZoneScopedN("Builder::LoadCubemap()"); entt::entity entity; static constexpr uint VERTEX_COUNT = 36; @@ -191,16 +161,13 @@ namespace GfxRenderEngine // create vertices { + m_Vertices.reserve(VERTEX_COUNT); for (uint i = 0; i < VERTEX_COUNT; i++) { - Vertex vertex = {/*pos*/ cubemapVertices[i], - /*col*/ {0.0f, 0.0f, 0.0f, 1.0f}, - /*norm*/ {0.0f, 0.0f, 0.0f}, - /*uv*/ {0.0f, 0.0f}, - /*tangent*/ glm::vec3(0.0), - glm::ivec4(0.0), - glm::vec4(0.0f)}; - m_Vertices.push_back(vertex); + m_Vertices.emplace_back(/*pos*/ std::move(cubemapVertices[i]), + /*col*/ glm::vec4{0.0f, 0.0f, 0.0f, 1.0f}, + /*norm*/ glm::vec3{0.0f, 0.0f, 0.0f}, + /*uv*/ glm::vec2{0.0f, 0.0f}); } } diff --git a/engine/renderer/builder/builder.h b/engine/renderer/builder/builder.h index 51dd28a7..7662767a 100644 --- a/engine/renderer/builder/builder.h +++ b/engine/renderer/builder/builder.h @@ -49,8 +49,8 @@ namespace GfxRenderEngine void CalculateTangentsFromIndexBuffer(std::vector const& indices); public: - std::vector m_Indices{}; std::vector m_Vertices{}; + std::vector m_Indices{}; std::vector m_Submeshes{}; // cubemap diff --git a/engine/renderer/builder/fastgltfBuilder.cpp b/engine/renderer/builder/fastgltfBuilder.cpp index e8976bfe..80513a01 100644 --- a/engine/renderer/builder/fastgltfBuilder.cpp +++ b/engine/renderer/builder/fastgltfBuilder.cpp @@ -25,7 +25,6 @@ #include "core.h" #include "scene/scene.h" -#include "renderer/model.h" #include "renderer/instanceBuffer.h" #include "renderer/builder/fastgltfBuilder.h" #include "renderer/materialDescriptor.h" @@ -36,7 +35,7 @@ namespace GfxRenderEngine { FastgltfBuilder::FastgltfBuilder(const std::string& filepath, Scene& scene, Resources::ResourceBuffers* resourceBuffers) : m_Filepath{filepath}, m_SkeletalAnimation{false}, m_Registry{scene.GetRegistry()}, - m_SceneGraph{scene.GetSceneGraph()}, m_Dictionary{scene.GetDictionary()}, m_InstanceCount{0}, m_InstanceIndex{0} + m_SceneGraph{scene.GetSceneGraph()}, m_Dictionary{scene.GetDictionary()} { m_Basepath = EngineCore::GetPathWithoutFilename(filepath); if (resourceBuffers) @@ -83,10 +82,11 @@ namespace GfxRenderEngine PrintAssetError(assetErrorCode); return Gltf::GLTF_LOAD_FAILURE; } - m_GltfModel = std::move(asset.get()); + m_GltfAsset = std::move(asset.get()); + m_Models.resize(m_GltfAsset.nodes.size()); } - if (!m_GltfModel.meshes.size() && !m_GltfModel.lights.size() && !m_GltfModel.cameras.size()) + if (!m_GltfAsset.meshes.size() && !m_GltfAsset.lights.size() && !m_GltfAsset.cameras.size()) { LOG_CORE_CRITICAL("Load: no meshes found in {0}", m_Filepath); return Gltf::GLTF_LOAD_FAILURE; @@ -95,7 +95,7 @@ namespace GfxRenderEngine if (sceneID > Gltf::GLTF_NOT_USED) // a scene ID was provided { // check if valid - if ((m_GltfModel.scenes.size() - 1) < static_cast(sceneID)) + if ((m_GltfAsset.scenes.size() - 1) < static_cast(sceneID)) { LOG_CORE_CRITICAL("Load: scene not found in {0}", m_Filepath); return Gltf::GLTF_LOAD_FAILURE; @@ -109,31 +109,27 @@ namespace GfxRenderEngine // PASS 1 // mark gltf nodes to receive a game object ID if they have a mesh or any child has // --> create array of flags for all nodes of the gltf file - m_HasMesh.resize(m_GltfModel.nodes.size(), false); + m_HasMesh.resize(m_GltfAsset.nodes.size(), false); { // if a scene ID was provided, use it, otherwise use scene 0 int sceneIDLocal = (sceneID > Gltf::GLTF_NOT_USED) ? sceneID : 0; - fastgltf::Scene& scene = m_GltfModel.scenes[sceneIDLocal]; + fastgltf::Scene const& scene = m_GltfAsset.scenes[sceneIDLocal]; size_t nodeCount = scene.nodeIndices.size(); for (size_t nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) { - MarkNode(scene, scene.nodeIndices[nodeIndex]); + MarkNode(scene.nodeIndices[nodeIndex]); } } // PASS 2 (for all instances) m_InstanceCount = instanceCount; - for (m_InstanceIndex = 0; m_InstanceIndex < m_InstanceCount; ++m_InstanceIndex) + for (uint instanceIndex = 0; instanceIndex < m_InstanceCount; ++instanceIndex) { // create group game object(s) for all instances to apply transform from JSON file to auto entity = m_Registry.Create(); - - std::string name = EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath); - auto shortName = m_DictionaryPrefix + "::" + name + "::" + std::to_string(m_InstanceIndex) + "::root"; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; - uint groupNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetRoot().AddChild(groupNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(instanceIndex) + "::root"; + uint groupNode = m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, entity, name, m_Dictionary); { TransformComponent transform{}; @@ -143,23 +139,23 @@ namespace GfxRenderEngine // a scene ID was provided if (sceneID > Gltf::GLTF_NOT_USED) { - ProcessScene(m_GltfModel.scenes[sceneID], groupNode); + ProcessScene(m_GltfAsset.scenes[sceneID], groupNode, instanceIndex); } else // no scene ID was provided --> use all scenes { - for (auto& scene : m_GltfModel.scenes) + for (auto& scene : m_GltfAsset.scenes) { - ProcessScene(scene, groupNode); + ProcessScene(scene, groupNode, instanceIndex); } } } return Gltf::GLTF_LOAD_SUCCESS; } - bool FastgltfBuilder::MarkNode(fastgltf::Scene& scene, int const gltfNodeIndex) + bool FastgltfBuilder::MarkNode(int const gltfNodeIndex) { // each recursive call of this function marks a node in "m_HasMesh" if itself or a child has a mesh - auto& node = m_GltfModel.nodes[gltfNodeIndex]; + auto& node = m_GltfAsset.nodes[gltfNodeIndex]; // does this gltf node have a mesh? bool localHasMesh = (node.meshIndex.has_value() || node.cameraIndex.has_value() || node.lightIndex.has_value()); @@ -169,14 +165,14 @@ namespace GfxRenderEngine for (size_t childNodeIndex = 0; childNodeIndex < childNodeCount; ++childNodeIndex) { int gltfChildNodeIndex = node.children[childNodeIndex]; - bool childHasMesh = MarkNode(scene, gltfChildNodeIndex); + bool childHasMesh = MarkNode(gltfChildNodeIndex); localHasMesh = localHasMesh || childHasMesh; } m_HasMesh[gltfNodeIndex] = localHasMesh; return localHasMesh; } - void FastgltfBuilder::ProcessScene(fastgltf::Scene& scene, uint const parentNode) + void FastgltfBuilder::ProcessScene(fastgltf::Scene& scene, uint const parentNode, uint instanceIndex) { size_t nodeCount = scene.nodeIndices.size(); if (!nodeCount) @@ -185,74 +181,80 @@ namespace GfxRenderEngine return; } - m_RenderObject = 0; for (uint nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) { - ProcessNode(scene, scene.nodeIndices[nodeIndex], parentNode); + ProcessNode(&scene, scene.nodeIndices[nodeIndex], parentNode, instanceIndex); } + + auto wait = [](std::future&& future) { future.get(); }; + m_NodeFuturesQueue.DoAll(wait); } - void FastgltfBuilder::ProcessNode(fastgltf::Scene& scene, int const gltfNodeIndex, uint const parentNode) + void FastgltfBuilder::ProcessNode(fastgltf::Scene* scene, int const gltfNodeIndex, uint const parentNode, + uint instanceIndex) { - auto& node = m_GltfModel.nodes[gltfNodeIndex]; - std::string nodeName(node.name); + auto loadNode = [this, scene, gltfNodeIndex, parentNode, instanceIndex]() + { + ZoneScopedN("FastgltfBuilder::ProcessNode"); + auto& node = m_GltfAsset.nodes[gltfNodeIndex]; + std::string nodeName(node.name); - uint currentNode = parentNode; + uint currentNode = parentNode; - if (m_HasMesh[gltfNodeIndex]) - { - int meshIndex = node.meshIndex.has_value() ? node.meshIndex.value() : Gltf::GLTF_NOT_USED; - int lightIndex = node.lightIndex.has_value() ? node.lightIndex.value() : Gltf::GLTF_NOT_USED; - int cameraIndex = node.cameraIndex.has_value() ? node.cameraIndex.value() : Gltf::GLTF_NOT_USED; - if ((meshIndex != Gltf::GLTF_NOT_USED) || (lightIndex != Gltf::GLTF_NOT_USED) || - (cameraIndex != Gltf::GLTF_NOT_USED)) - { - currentNode = CreateGameObject(scene, gltfNodeIndex, parentNode); - } - else // one or more children have a mesh, but not this one --> create group node + if (m_HasMesh[gltfNodeIndex]) { - // create game object and transform component - auto entity = m_Registry.Create(); + int meshIndex = node.meshIndex.has_value() ? node.meshIndex.value() : Gltf::GLTF_NOT_USED; + int lightIndex = node.lightIndex.has_value() ? node.lightIndex.value() : Gltf::GLTF_NOT_USED; + int cameraIndex = node.cameraIndex.has_value() ? node.cameraIndex.value() : Gltf::GLTF_NOT_USED; + if ((meshIndex != Gltf::GLTF_NOT_USED) || (lightIndex != Gltf::GLTF_NOT_USED) || + (cameraIndex != Gltf::GLTF_NOT_USED)) + { + currentNode = CreateGameObject(scene, gltfNodeIndex, parentNode, instanceIndex); + } + else // one or more children have a mesh, but not this one --> create group node + { + std::lock_guard guard(m_Mutex); + // create game object and transform component + auto entity = m_Registry.Create(); - // create scene graph node and add to parent - auto shortName = m_DictionaryPrefix + "::" + std::to_string(m_InstanceIndex) + - "::" + std::string(scene.name) + "::" + nodeName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + - "::" + std::string(scene.name) + "::" + nodeName; - currentNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(currentNode); + // create scene graph node and add to parent + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(instanceIndex) + + "::" + std::string(scene->name) + "::" + nodeName; + currentNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); - { - TransformComponent transform{}; - LoadTransformationMatrix(transform, gltfNodeIndex); - m_Registry.emplace(entity, transform); + { + TransformComponent transform{}; + LoadTransformationMatrix(transform, gltfNodeIndex); + m_Registry.emplace(entity, transform); + } } } - } - size_t childNodeCount = node.children.size(); - for (size_t childNodeIndex = 0; childNodeIndex < childNodeCount; ++childNodeIndex) - { - int gltfChildNodeIndex = node.children[childNodeIndex]; - ProcessNode(scene, gltfChildNodeIndex, currentNode); - } + size_t childNodeCount = node.children.size(); + for (size_t childNodeIndex = 0; childNodeIndex < childNodeCount; ++childNodeIndex) + { + int gltfChildNodeIndex = node.children[childNodeIndex]; + ProcessNode(scene, gltfChildNodeIndex, currentNode, instanceIndex); + } + return true; + }; + m_NodeFuturesQueue.EmplaceBack(Engine::m_Engine->m_PoolSecondary.SubmitTask(loadNode)); } - uint FastgltfBuilder::CreateGameObject(fastgltf::Scene& scene, int const gltfNodeIndex, uint const parentNode) + uint FastgltfBuilder::CreateGameObject(fastgltf::Scene* scene, int const gltfNodeIndex, uint const parentNode, + uint instanceIndex) { - auto& node = m_GltfModel.nodes[gltfNodeIndex]; + auto& node = m_GltfAsset.nodes[gltfNodeIndex]; std::string nodeName(node.name); + int meshIndex = node.meshIndex.has_value() ? node.meshIndex.value() : Gltf::GLTF_NOT_USED; int lightIndex = node.lightIndex.has_value() ? node.lightIndex.value() : Gltf::GLTF_NOT_USED; int cameraIndex = node.cameraIndex.has_value() ? node.cameraIndex.value() : Gltf::GLTF_NOT_USED; auto entity = m_Registry.Create(); - auto baseName = "::" + std::to_string(m_InstanceIndex) + "::" + std::string(scene.name) + "::" + nodeName; - auto shortName = m_DictionaryPrefix + "::" + EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath) + baseName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + baseName; - - uint newNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(newNode); + auto baseName = "::" + std::to_string(instanceIndex) + "::" + std::string(scene->name) + "::" + nodeName; + auto name = m_DictionaryPrefix + "::" + m_Filepath + baseName; + uint newNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); TransformComponent transform{}; LoadTransformationMatrix(transform, gltfNodeIndex); @@ -260,6 +262,8 @@ namespace GfxRenderEngine if (meshIndex != Gltf::GLTF_NOT_USED) { // create a model + Model::ModelData modelData = { + .m_Skeleton = m_Skeleton, .m_ShaderData = m_ShaderData, .m_Animations = m_Animations}; // *** Instancing *** // create instance tag for first game object; @@ -267,38 +271,44 @@ namespace GfxRenderEngine // The renderer can loop over all instance tags // to retrieve the corresponding game objects. - if (!m_InstanceIndex) + if (!instanceIndex) { InstanceTag instanceTag; - instanceTag.m_Instances.push_back(entity); - m_InstanceBuffer = InstanceBuffer::Create(m_InstanceCount); - instanceTag.m_InstanceBuffer = m_InstanceBuffer; - instanceTag.m_InstanceBuffer->SetInstanceData(m_InstanceIndex, transform.GetMat4Global(), - transform.GetNormalMatrix()); + instanceTag.m_Instances.resize(m_InstanceCount); + instanceTag.m_Instances[instanceIndex] = entity; + + auto& instanceBuffer = instanceTag.m_InstanceBuffer; + instanceBuffer = InstanceBuffer::Create(m_InstanceCount); + instanceBuffer->SetInstanceData(instanceIndex, transform.GetMat4Global(), transform.GetNormalMatrix()); + m_Registry.emplace(entity, instanceTag); - transform.SetInstance(m_InstanceBuffer, m_InstanceIndex); - m_InstancedObjects.push_back(entity); + transform.SetInstance(instanceBuffer, instanceIndex); + + { + std::lock_guard guard(m_Mutex); + m_InstancedObjects[gltfNodeIndex] = entity; + } // create model for 1st instance - LoadVertexData(meshIndex); - LOG_CORE_INFO("Vertex count: {0}, Index count: {1} (file: {2}, node: {3})", m_Vertices.size(), - m_Indices.size(), m_Filepath, nodeName); + LoadVertexData(meshIndex, modelData); + LOG_CORE_INFO("Vertex count: {0}, Index count: {1} (file: {2}, node: {3})", modelData.m_Vertices.size(), + modelData.m_Indices.size(), m_Filepath, nodeName); { // assign material uint primitiveIndex = 0; - for (const auto& glTFPrimitive : m_GltfModel.meshes[meshIndex].primitives) + for (const auto& glTFPrimitive : m_GltfAsset.meshes[meshIndex].primitives) { - Submesh& submesh = m_Submeshes[primitiveIndex]; + Submesh& submesh = modelData.m_Submeshes[primitiveIndex]; ++primitiveIndex; if (glTFPrimitive.materialIndex.has_value()) { - AssignMaterial(submesh, glTFPrimitive.materialIndex.value()); + AssignMaterial(submesh, glTFPrimitive.materialIndex.value(), instanceBuffer.get()); } else { LOG_CORE_ERROR("submesh has no material, check your 3D model"); - AssignMaterial(submesh, Gltf::GLTF_NOT_USED); + AssignMaterial(submesh, Gltf::GLTF_NOT_USED, instanceBuffer.get()); } } } @@ -316,27 +326,30 @@ namespace GfxRenderEngine } // submit to engine - m_Model = Engine::m_Engine->LoadModel(*this); + m_Models[gltfNodeIndex] = Engine::m_Engine->LoadModel(modelData); } else { - entt::entity instance = m_InstancedObjects[m_RenderObject++]; + std::lock_guard lock(m_Mutex); + CORE_ASSERT(m_InstancedObjects.find(gltfNodeIndex) != m_InstancedObjects.end(), + "instanced object not found"); + entt::entity instance = m_InstancedObjects[gltfNodeIndex]; InstanceTag& instanceTag = m_Registry.get(instance); - instanceTag.m_Instances.push_back(entity); - instanceTag.m_InstanceBuffer->SetInstanceData(m_InstanceIndex, transform.GetMat4Global(), + instanceTag.m_Instances[instanceIndex] = entity; + instanceTag.m_InstanceBuffer->SetInstanceData(instanceIndex, transform.GetMat4Global(), transform.GetNormalMatrix()); - transform.SetInstance(instanceTag.m_InstanceBuffer, m_InstanceIndex); + transform.SetInstance(instanceTag.m_InstanceBuffer, instanceIndex); } { // add mesh component to all instances - MeshComponent mesh{nodeName, m_Model}; + MeshComponent mesh{nodeName, m_Models[gltfNodeIndex]}; m_Registry.emplace(entity, mesh); } } else if (lightIndex != Gltf::GLTF_NOT_USED) { // create a light - fastgltf::Light& glTFLight = m_GltfModel.lights[lightIndex]; + fastgltf::Light& glTFLight = m_GltfAsset.lights[lightIndex]; switch (glTFLight.type) { case fastgltf::LightType::Directional: @@ -366,7 +379,7 @@ namespace GfxRenderEngine else if (cameraIndex != Gltf::GLTF_NOT_USED) { // create a camera - fastgltf::Camera& glTFCamera = m_GltfModel.cameras[cameraIndex]; + fastgltf::Camera& glTFCamera = m_GltfAsset.cameras[cameraIndex]; if (const auto* pOrthographic = std::get_if(&glTFCamera.camera)) { float xmag = pOrthographic->xmag; @@ -391,16 +404,16 @@ namespace GfxRenderEngine m_Registry.emplace(entity, transform); return newNode; - } + } // namespace GfxRenderEngine bool FastgltfBuilder::GetImageFormat(uint const imageIndex) { - for (fastgltf::Material& material : m_GltfModel.materials) + for (fastgltf::Material& material : m_GltfAsset.materials) { if (material.pbrData.baseColorTexture.has_value()) // albedo aka diffuse map aka bas color -> sRGB { uint diffuseTextureIndex = material.pbrData.baseColorTexture.value().textureIndex; - auto& diffuseTexture = m_GltfModel.textures[diffuseTextureIndex]; + auto& diffuseTexture = m_GltfAsset.textures[diffuseTextureIndex]; if (imageIndex == diffuseTexture.imageIndex.value()) { return Texture::USE_SRGB; @@ -409,7 +422,7 @@ namespace GfxRenderEngine if (material.emissiveTexture.has_value()) { uint emissiveTextureIndex = material.emissiveTexture.value().textureIndex; - auto& emissiveTexture = m_GltfModel.textures[emissiveTextureIndex]; + auto& emissiveTexture = m_GltfAsset.textures[emissiveTextureIndex]; if (imageIndex == emissiveTexture.imageIndex.value()) { return Texture::USE_SRGB; @@ -423,12 +436,12 @@ namespace GfxRenderEngine int FastgltfBuilder::GetMinFilter(uint index) { fastgltf::Filter filter = fastgltf::Filter::Linear; - if (m_GltfModel.textures[index].samplerIndex.has_value()) + if (m_GltfAsset.textures[index].samplerIndex.has_value()) { - size_t sampler = m_GltfModel.textures[index].samplerIndex.value(); - if (m_GltfModel.samplers[sampler].minFilter.has_value()) + size_t sampler = m_GltfAsset.textures[index].samplerIndex.value(); + if (m_GltfAsset.samplers[sampler].minFilter.has_value()) { - filter = m_GltfModel.samplers[sampler].minFilter.value(); + filter = m_GltfAsset.samplers[sampler].minFilter.value(); } } return static_cast(filter); @@ -437,12 +450,12 @@ namespace GfxRenderEngine int FastgltfBuilder::GetMagFilter(uint index) { fastgltf::Filter filter = fastgltf::Filter::Linear; - if (m_GltfModel.textures[index].samplerIndex.has_value()) + if (m_GltfAsset.textures[index].samplerIndex.has_value()) { - size_t sampler = m_GltfModel.textures[index].samplerIndex.value(); - if (m_GltfModel.samplers[sampler].magFilter.has_value()) + size_t sampler = m_GltfAsset.textures[index].samplerIndex.value(); + if (m_GltfAsset.samplers[sampler].magFilter.has_value()) { - filter = m_GltfModel.samplers[sampler].magFilter.value(); + filter = m_GltfAsset.samplers[sampler].magFilter.value(); } } return static_cast(filter); @@ -450,7 +463,7 @@ namespace GfxRenderEngine void FastgltfBuilder::LoadTextures() { - size_t numTextures = m_GltfModel.images.size(); + size_t numTextures = m_GltfAsset.images.size(); m_Textures.resize(numTextures); std::vector>> futures; futures.resize(numTextures); @@ -462,7 +475,7 @@ namespace GfxRenderEngine { ZoneScopedNC("FastgltfBuilder::LoadTextures", 0x0000ff); - fastgltf::Image& glTFImage = m_GltfModel.images[imageIndex]; + fastgltf::Image& glTFImage = m_GltfAsset.images[imageIndex]; auto texture = Texture::Create(); // image data is of type std::variant: the data type can be a URI/filepath, an Array, or a BufferView @@ -507,8 +520,8 @@ namespace GfxRenderEngine }, [&](fastgltf::sources::BufferView& view) // load from buffer view { - auto& bufferView = m_GltfModel.bufferViews[view.bufferViewIndex]; - auto& bufferFromBufferView = m_GltfModel.buffers[bufferView.bufferIndex]; + auto& bufferView = m_GltfAsset.bufferViews[view.bufferViewIndex]; + auto& bufferFromBufferView = m_GltfAsset.buffers[bufferView.bufferIndex]; std::visit( fastgltf::visitor{ @@ -551,14 +564,14 @@ namespace GfxRenderEngine void FastgltfBuilder::LoadMaterials() { - size_t numMaterials = m_GltfModel.materials.size(); + size_t numMaterials = m_GltfAsset.materials.size(); m_Materials.resize(numMaterials); m_MaterialTextures.resize(numMaterials); uint materialIndex = 0; for (Material& material : m_Materials) { - fastgltf::Material& glTFMaterial = m_GltfModel.materials[materialIndex]; + fastgltf::Material& glTFMaterial = m_GltfAsset.materials[materialIndex]; Material::PbrMaterial& pbrMaterial = material.m_PbrMaterial; Material::MaterialTextures& materialTextures = m_MaterialTextures[materialIndex]; @@ -573,7 +586,7 @@ namespace GfxRenderEngine if (glTFMaterial.pbrData.baseColorTexture.has_value()) { uint diffuseMapIndex = glTFMaterial.pbrData.baseColorTexture.value().textureIndex; - uint imageIndex = m_GltfModel.textures[diffuseMapIndex].imageIndex.value(); + uint imageIndex = m_GltfAsset.textures[diffuseMapIndex].imageIndex.value(); materialTextures[Material::DIFFUSE_MAP_INDEX] = m_Textures[imageIndex]; pbrMaterial.m_Features |= Material::HAS_DIFFUSE_MAP; } @@ -582,7 +595,7 @@ namespace GfxRenderEngine if (glTFMaterial.normalTexture.has_value()) { uint normalMapIndex = glTFMaterial.normalTexture.value().textureIndex; - uint imageIndex = m_GltfModel.textures[normalMapIndex].imageIndex.value(); + uint imageIndex = m_GltfAsset.textures[normalMapIndex].imageIndex.value(); materialTextures[Material::NORMAL_MAP_INDEX] = m_Textures[imageIndex]; pbrMaterial.m_NormalMapIntensity = glTFMaterial.normalTexture.value().scale; pbrMaterial.m_Features |= Material::HAS_NORMAL_MAP; @@ -598,7 +611,7 @@ namespace GfxRenderEngine if (glTFMaterial.pbrData.metallicRoughnessTexture.has_value()) { int metallicRoughnessMapIndex = glTFMaterial.pbrData.metallicRoughnessTexture.value().textureIndex; - uint imageIndex = m_GltfModel.textures[metallicRoughnessMapIndex].imageIndex.value(); + uint imageIndex = m_GltfAsset.textures[metallicRoughnessMapIndex].imageIndex.value(); materialTextures[Material::ROUGHNESS_METALLIC_MAP_INDEX] = m_Textures[imageIndex]; pbrMaterial.m_Features |= Material::HAS_ROUGHNESS_METALLIC_MAP; } @@ -613,7 +626,7 @@ namespace GfxRenderEngine if (glTFMaterial.emissiveTexture.has_value()) { uint emissiveTextureIndex = glTFMaterial.emissiveTexture.value().textureIndex; - uint imageIndex = m_GltfModel.textures[emissiveTextureIndex].imageIndex.value(); + uint imageIndex = m_GltfAsset.textures[emissiveTextureIndex].imageIndex.value(); materialTextures[Material::EMISSIVE_MAP_INDEX] = m_Textures[imageIndex]; pbrMaterial.m_Features |= Material::HAS_EMISSIVE_MAP; } @@ -622,25 +635,25 @@ namespace GfxRenderEngine } } - // handle vertex data - void FastgltfBuilder::LoadVertexData(uint const meshIndex) + // load vertex data + void FastgltfBuilder::LoadVertexData(uint const meshIndex, Model::ModelData& modelData) { ZoneScopedN("FastgltfBuilder::LoadVertexData"); - m_Vertices.clear(); - m_Indices.clear(); - m_Submeshes.clear(); + auto& vertices = modelData.m_Vertices; + auto& indices = modelData.m_Indices; + auto& submeshes = modelData.m_Submeshes; - uint numPrimitives = m_GltfModel.meshes[meshIndex].primitives.size(); - m_Submeshes.resize(numPrimitives); + uint numPrimitives = m_GltfAsset.meshes[meshIndex].primitives.size(); + submeshes.resize(numPrimitives); uint primitiveIndex = 0; - for (const auto& glTFPrimitive : m_GltfModel.meshes[meshIndex].primitives) + for (const auto& glTFPrimitive : m_GltfAsset.meshes[meshIndex].primitives) { - Submesh& submesh = m_Submeshes[primitiveIndex]; + Submesh& submesh = submeshes[primitiveIndex]; ++primitiveIndex; - submesh.m_FirstVertex = static_cast(m_Vertices.size()); - submesh.m_FirstIndex = static_cast(m_Indices.size()); + submesh.m_FirstVertex = static_cast(vertices.size()); + submesh.m_FirstIndex = static_cast(indices.size()); submesh.m_InstanceCount = m_InstanceCount; size_t vertexCount = 0; @@ -672,21 +685,21 @@ namespace GfxRenderEngine if (glTFPrimitive.findAttribute("POSITION") != glTFPrimitive.attributes.end()) { auto componentType = - LoadAccessor(m_GltfModel.accessors[glTFPrimitive.findAttribute("POSITION")->second], + LoadAccessor(m_GltfAsset.accessors[glTFPrimitive.findAttribute("POSITION")->second], positionBuffer, &vertexCount); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); } // Get buffer data for vertex color if (glTFPrimitive.findAttribute("COLOR_0") != glTFPrimitive.attributes.end()) { - fastgltf::Accessor& accessor = m_GltfModel.accessors[glTFPrimitive.findAttribute("COLOR_0")->second]; + fastgltf::Accessor& accessor = m_GltfAsset.accessors[glTFPrimitive.findAttribute("COLOR_0")->second]; colorBufferComponentType = accessor.componentType; switch (colorBufferComponentType) { case fastgltf::ComponentType::Float: { const float* buffer; - LoadAccessor(m_GltfModel.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], + LoadAccessor(m_GltfAsset.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], buffer); colorBuffer = buffer; break; @@ -694,7 +707,7 @@ namespace GfxRenderEngine case fastgltf::ComponentType::UnsignedShort: { const uint16_t* buffer; - LoadAccessor(m_GltfModel.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], + LoadAccessor(m_GltfAsset.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], buffer); colorBuffer = buffer; break; @@ -702,7 +715,7 @@ namespace GfxRenderEngine case fastgltf::ComponentType::UnsignedByte: { const uint8_t* buffer; - LoadAccessor(m_GltfModel.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], + LoadAccessor(m_GltfAsset.accessors[glTFPrimitive.findAttribute("COLOR_0")->second], buffer); colorBuffer = buffer; break; @@ -720,14 +733,14 @@ namespace GfxRenderEngine if (glTFPrimitive.findAttribute("NORMAL") != glTFPrimitive.attributes.end()) { auto componentType = LoadAccessor( - m_GltfModel.accessors[glTFPrimitive.findAttribute("NORMAL")->second], normalsBuffer); + m_GltfAsset.accessors[glTFPrimitive.findAttribute("NORMAL")->second], normalsBuffer); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); } // Get buffer data for vertex tangents if (glTFPrimitive.findAttribute("TANGENT") != glTFPrimitive.attributes.end()) { auto componentType = LoadAccessor( - m_GltfModel.accessors[glTFPrimitive.findAttribute("TANGENT")->second], tangentsBuffer); + m_GltfAsset.accessors[glTFPrimitive.findAttribute("TANGENT")->second], tangentsBuffer); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); } // Get buffer data for vertex texture coordinates @@ -735,7 +748,7 @@ namespace GfxRenderEngine if (glTFPrimitive.findAttribute("TEXCOORD_0") != glTFPrimitive.attributes.end()) { auto componentType = LoadAccessor( - m_GltfModel.accessors[glTFPrimitive.findAttribute("TEXCOORD_0")->second], texCoordsBuffer); + m_GltfAsset.accessors[glTFPrimitive.findAttribute("TEXCOORD_0")->second], texCoordsBuffer); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); } @@ -743,7 +756,7 @@ namespace GfxRenderEngine if (glTFPrimitive.findAttribute("JOINTS_0") != glTFPrimitive.attributes.end()) { jointsBufferComponentType = LoadAccessor( - m_GltfModel.accessors[glTFPrimitive.findAttribute("JOINTS_0")->second], jointsBuffer); + m_GltfAsset.accessors[glTFPrimitive.findAttribute("JOINTS_0")->second], jointsBuffer); auto glComponentType = fastgltf::getGLComponentType(jointsBufferComponentType); CORE_ASSERT((glComponentType == GL_BYTE) || (glComponentType == GL_UNSIGNED_BYTE), "unexpected component type " + std::to_string(glComponentType)); @@ -752,13 +765,13 @@ namespace GfxRenderEngine if (glTFPrimitive.findAttribute("WEIGHTS_0") != glTFPrimitive.attributes.end()) { auto componentType = LoadAccessor( - m_GltfModel.accessors[glTFPrimitive.findAttribute("WEIGHTS_0")->second], weightsBuffer); + m_GltfAsset.accessors[glTFPrimitive.findAttribute("WEIGHTS_0")->second], weightsBuffer); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); } // Append data to model's vertex buffer - uint numVerticesBefore = m_Vertices.size(); - m_Vertices.resize(numVerticesBefore + vertexCount); + uint numVerticesBefore = vertices.size(); + vertices.resize(numVerticesBefore + vertexCount); uint vertexIndex = numVerticesBefore; for (size_t vertexIterator = 0; vertexIterator < vertexCount; ++vertexIterator) { @@ -839,28 +852,28 @@ namespace GfxRenderEngine } vertex.m_Weights = glm::make_vec4(&weightsBuffer[vertexIterator * 4]); } - m_Vertices[vertexIndex] = vertex; + vertices[vertexIndex] = vertex; ++vertexIndex; } // calculate tangents if (!tangentsBuffer) { - CalculateTangents(); + CalculateTangents(modelData); } } // Indices if (glTFPrimitive.indicesAccessor.has_value()) { - auto& accessor = m_GltfModel.accessors[glTFPrimitive.indicesAccessor.value()]; + auto& accessor = m_GltfAsset.accessors[glTFPrimitive.indicesAccessor.value()]; indexCount = accessor.count; // append indices for submesh to global index array - size_t globalIndicesOffset = m_Indices.size(); - m_Indices.resize(m_Indices.size() + indexCount); - uint* destination = m_Indices.data() + globalIndicesOffset; - fastgltf::iterateAccessorWithIndex(m_GltfModel, accessor, [&](uint submeshIndex, size_t iterator) + size_t globalIndicesOffset = indices.size(); + indices.resize(indices.size() + indexCount); + uint* destination = indices.data() + globalIndicesOffset; + fastgltf::iterateAccessorWithIndex(m_GltfAsset, accessor, [&](uint submeshIndex, size_t iterator) { destination[iterator] = submeshIndex; }); } @@ -871,7 +884,7 @@ namespace GfxRenderEngine void FastgltfBuilder::LoadTransformationMatrix(TransformComponent& transform, int const gltfNodeIndex) { - auto& node = m_GltfModel.nodes[gltfNodeIndex]; + auto& node = m_GltfAsset.nodes[gltfNodeIndex]; std::visit( fastgltf::visitor{ @@ -888,7 +901,7 @@ namespace GfxRenderEngine node.transform); } - void FastgltfBuilder::AssignMaterial(Submesh& submesh, int const materialIndex) + void FastgltfBuilder::AssignMaterial(Submesh& submesh, int const materialIndex, InstanceBuffer* instanceBuffer) { ZoneScopedN("AssignMaterial"); { // material @@ -914,7 +927,7 @@ namespace GfxRenderEngine { // resources Resources::ResourceBuffers& resourceBuffers = submesh.m_Resources.m_ResourceBuffers; resourceBuffers = m_ResourceBuffersPre; - std::shared_ptr instanceUbo{m_InstanceBuffer->GetBuffer()}; + std::shared_ptr instanceUbo{instanceBuffer->GetBuffer()}; resourceBuffers[Resources::INSTANCE_BUFFER_INDEX] = instanceUbo; if (m_SkeletalAnimation) { @@ -926,15 +939,15 @@ namespace GfxRenderEngine LOG_CORE_INFO("material assigned (fastgltf): material index {0}", materialIndex); } - void FastgltfBuilder::CalculateTangents() + void FastgltfBuilder::CalculateTangents(Model::ModelData& modelData) { - if (m_Indices.size()) + if (modelData.m_Indices.size()) { - CalculateTangentsFromIndexBuffer(m_Indices); + CalculateTangentsFromIndexBuffer(modelData, modelData.m_Indices); } else { - uint vertexCount = m_Vertices.size(); + uint vertexCount = modelData.m_Vertices.size(); if (vertexCount) { std::vector indices; @@ -943,12 +956,12 @@ namespace GfxRenderEngine { indices[i] = i; } - CalculateTangentsFromIndexBuffer(indices); + CalculateTangentsFromIndexBuffer(modelData, indices); } } } - void FastgltfBuilder::CalculateTangentsFromIndexBuffer(const std::vector& indices) + void FastgltfBuilder::CalculateTangentsFromIndexBuffer(Model::ModelData& modelData, const std::vector& indices) { uint cnt = 0; uint vertexIndex1 = 0; @@ -963,7 +976,7 @@ namespace GfxRenderEngine for (uint index : indices) { - auto& vertex = m_Vertices[index]; + auto& vertex = modelData.m_Vertices[index]; switch (cnt) { @@ -1016,9 +1029,9 @@ namespace GfxRenderEngine if (tangent.x == 0.0f && tangent.y == 0.0f && tangent.z == 0.0f) tangent = glm::vec3(1.0f, 0.0f, 0.0f); - m_Vertices[vertexIndex1].m_Tangent = tangent; - m_Vertices[vertexIndex2].m_Tangent = tangent; - m_Vertices[vertexIndex3].m_Tangent = tangent; + modelData.m_Vertices[vertexIndex1].m_Tangent = tangent; + modelData.m_Vertices[vertexIndex2].m_Tangent = tangent; + modelData.m_Vertices[vertexIndex3].m_Tangent = tangent; break; } diff --git a/engine/renderer/builder/fastgltfBuilder.h b/engine/renderer/builder/fastgltfBuilder.h index e3f6c11d..fbcb45f6 100644 --- a/engine/renderer/builder/fastgltfBuilder.h +++ b/engine/renderer/builder/fastgltfBuilder.h @@ -22,6 +22,8 @@ #pragma once +#include + #include #include #include @@ -31,7 +33,9 @@ #include "scene/gltf.h" #include "scene/material.h" #include "scene/registry.h" +#include "renderer/model.h" #include "renderer/resourceDescriptor.h" +#include "auxiliary/queue.h" namespace GfxRenderEngine { @@ -43,7 +47,6 @@ namespace GfxRenderEngine class Dictionary; class InstanceBuffer; class Material; - class Model; class Scene; class SceneGraph; class SkeletalAnimations; @@ -62,25 +65,20 @@ namespace GfxRenderEngine bool Load(uint const instanceCount = 1, int const sceneID = Gltf::GLTF_NOT_USED); void SetDictionaryPrefix(std::string const&); - public: - std::vector m_Indices{}; - std::vector m_Vertices{}; - std::vector m_Submeshes{}; - private: void LoadTextures(); void LoadMaterials(); - void LoadVertexData(uint const meshIndex); + void LoadVertexData(uint const, Model::ModelData&); bool GetImageFormat(uint const imageIndex); - void AssignMaterial(Submesh& submesh, int const materialIndex); + void AssignMaterial(Submesh& submesh, int const materialIndex, InstanceBuffer* instanceBuffer); void LoadTransformationMatrix(TransformComponent& transform, int const gltfNodeIndex); - void CalculateTangents(); - void CalculateTangentsFromIndexBuffer(const std::vector& indices); + void CalculateTangents(Model::ModelData&); + void CalculateTangentsFromIndexBuffer(Model::ModelData&, const std::vector& indices); - bool MarkNode(fastgltf::Scene& scene, int const gltfNodeIndex); - void ProcessScene(fastgltf::Scene& scene, uint const parentNode); - void ProcessNode(fastgltf::Scene& scene, int const gltfNodeIndex, uint const parentNode); - uint CreateGameObject(fastgltf::Scene& scene, int const gltfNodeIndex, uint const parentNode); + bool MarkNode(int const gltfNodeIndex); + void ProcessScene(fastgltf::Scene& scene, uint const parentNode, uint instanceIndex); + void ProcessNode(fastgltf::Scene* scene, int const gltfNodeIndex, uint const parentNode, uint instanceIndex); + uint CreateGameObject(fastgltf::Scene* scene, int const gltfNodeIndex, uint const parentNode, uint instanceIndex); int GetMinFilter(uint index); int GetMagFilter(uint index); @@ -93,8 +91,8 @@ namespace GfxRenderEngine { CORE_ASSERT(accessor.bufferViewIndex.has_value(), "Loadaccessor: no buffer view index provided"); - const fastgltf::BufferView& bufferView = m_GltfModel.bufferViews[accessor.bufferViewIndex.value()]; - auto& buffer = m_GltfModel.buffers[bufferView.bufferIndex]; + const fastgltf::BufferView& bufferView = m_GltfAsset.bufferViews[accessor.bufferViewIndex.value()]; + auto& buffer = m_GltfAsset.buffers[bufferView.bufferIndex]; const fastgltf::sources::Array* vector = std::get_if(&buffer.data); CORE_ASSERT(vector, "FastgltfBuilder::LoadAccessor: unsupported data type"); @@ -117,27 +115,25 @@ namespace GfxRenderEngine std::string m_Filepath; std::string m_Basepath; std::string m_DictionaryPrefix; - fastgltf::Asset m_GltfModel; - std::shared_ptr m_Model; + fastgltf::Asset m_GltfAsset; + std::vector> m_Models; std::vector m_Materials; std::vector m_MaterialTextures{}; std::vector> m_Textures{}; // scene graph - uint m_InstanceCount; - uint m_InstanceIndex; + uint m_InstanceCount{0}; std::vector m_HasMesh; - entt::entity m_GameObject; - - std::vector m_InstancedObjects; - std::shared_ptr m_InstanceBuffer; + Atomic::Queue> m_NodeFuturesQueue; + std::unordered_map m_InstancedObjects; Resources::ResourceBuffers m_ResourceBuffersPre; - uint m_RenderObject; Registry& m_Registry; SceneGraph& m_SceneGraph; Dictionary& m_Dictionary; + std::mutex m_Mutex; + // skeletal animation private: void LoadSkeletonsGltf(); diff --git a/engine/renderer/builder/fbxBuilder.cpp b/engine/renderer/builder/fbxBuilder.cpp index acd2598a..aa753b56 100644 --- a/engine/renderer/builder/fbxBuilder.cpp +++ b/engine/renderer/builder/fbxBuilder.cpp @@ -84,12 +84,8 @@ namespace GfxRenderEngine { // create group game object(s) for all instances to apply transform from JSON file to auto entity = m_Registry.Create(); - - std::string name = EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath); - auto shortName = m_DictionaryPrefix + "::" + name + "::" + std::to_string(m_InstanceIndex) + "::root"; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; - uint groupNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetRoot().AddChild(groupNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; + uint groupNode = m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, entity, name, m_Dictionary); { TransformComponent transform{}; @@ -167,11 +163,9 @@ namespace GfxRenderEngine } // create scene graph node and add to parent - auto shortName = m_DictionaryPrefix + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - auto longName = + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - currentNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(currentNode); + currentNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); } } ++hasMeshIndex; @@ -188,12 +182,8 @@ namespace GfxRenderEngine std::string nodeName = std::string(fbxNodePtr->mName.C_Str()); auto entity = m_Registry.Create(); - auto shortName = m_DictionaryPrefix + "::" + EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath) + - "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - - uint newNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(newNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; + uint newNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); TransformComponent transform(LoadTransformationMatrix(fbxNodePtr)); if (fbxNodePtr->mParent == m_FbxScene->mRootNode) @@ -454,7 +444,7 @@ namespace GfxRenderEngine } } - // handle vertex data + // load vertex data void FbxBuilder::LoadVertexData(const aiNode* fbxNodePtr, int vertexColorSet, uint uvSet) { m_Vertices.clear(); diff --git a/engine/renderer/builder/gltfBuilder.cpp b/engine/renderer/builder/gltfBuilder.cpp index a405d214..e9dcf770 100644 --- a/engine/renderer/builder/gltfBuilder.cpp +++ b/engine/renderer/builder/gltfBuilder.cpp @@ -124,11 +124,8 @@ namespace GfxRenderEngine // create group game object(s) for all instances to apply transform from JSON file to auto entity = m_Registry.Create(); - std::string name = EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath); - auto shortName = m_DictionaryPrefix + "::" + name + "::" + std::to_string(m_InstanceIndex) + "::root"; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; - uint groupNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetRoot().AddChild(groupNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; + uint groupNode = m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, entity, name, m_Dictionary); { TransformComponent transform{}; @@ -208,12 +205,9 @@ namespace GfxRenderEngine auto entity = m_Registry.Create(); // create scene graph node and add to parent - auto shortName = - m_DictionaryPrefix + "::" + std::to_string(m_InstanceIndex) + "::" + scene.name + "::" + nodeName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + - "::" + scene.name + "::" + nodeName; - currentNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(currentNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + + "::" + scene.name + "::" + nodeName; + currentNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); { TransformComponent transform{}; @@ -238,13 +232,9 @@ namespace GfxRenderEngine uint meshIndex = node.mesh; auto entity = m_Registry.Create(); - auto shortName = m_DictionaryPrefix + "::" + EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath) + - "::" + std::to_string(m_InstanceIndex) + "::" + scene.name + "::" + nodeName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + scene.name + - "::" + nodeName; - - uint newNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(newNode); + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + scene.name + + "::" + nodeName; + uint newNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); TransformComponent transform{}; LoadTransformationMatrix(transform, gltfNodeIndex); @@ -583,7 +573,7 @@ namespace GfxRenderEngine } } - // handle vertex data + // load vertex data void GltfBuilder::LoadVertexData(uint const meshIndex) { m_Vertices.clear(); diff --git a/engine/renderer/builder/terrainBuilder.cpp b/engine/renderer/builder/terrainBuilder.cpp index c394fc16..5eab2d6a 100644 --- a/engine/renderer/builder/terrainBuilder.cpp +++ b/engine/renderer/builder/terrainBuilder.cpp @@ -220,8 +220,6 @@ namespace GfxRenderEngine { // create game objects for all instances - auto name = EngineCore::GetFilenameWithoutPath(terrainSpec.m_FilepathTerrainDescription); - name = EngineCore::GetFilenameWithoutExtension(name); InstanceTag instanceTag; for (int instanceIndex = 0; instanceIndex < instanceCount; ++instanceIndex) @@ -233,11 +231,8 @@ namespace GfxRenderEngine instanceTag.m_Instances.push_back(entity); // add to scene graph - auto instanceStr = std::to_string(instanceIndex); - auto shortName = name + "::" + instanceStr; - auto longName = terrainSpec.m_FilepathTerrainDescription + "::" + instanceStr; - uint newNode = sceneGraph.CreateNode(entity, shortName, longName, dictionary); - sceneGraph.GetRoot().AddChild(newNode); + auto name = terrainSpec.m_FilepathTerrainDescription + "::" + std::to_string(instanceIndex); + sceneGraph.CreateNode(SceneGraph::ROOT_NODE, entity, name, dictionary); // only for the 1st instance if (!instanceIndex) @@ -280,6 +275,8 @@ namespace GfxRenderEngine transform.SetInstance(instanceTag.m_InstanceBuffer, instanceIndex); registry.emplace(entity, transform); + auto shortName = EngineCore::GetFilenameWithoutPathAndExtension(terrainSpec.m_FilepathTerrainDescription) + + std::string("::") + std::to_string(instanceIndex); MeshComponent mesh{shortName, model}; registry.emplace(entity, mesh); registry.emplace(entity, terrainComponent); @@ -350,9 +347,8 @@ namespace GfxRenderEngine dictionary.Retrieve(std::string("terrain::") + grassSpec.m_FilepathGrassModel + "::0::root"); if (grassEntityRoot != entt::null) { - TreeNode rootNode = sceneGraph.GetNodeByGameObject(grassEntityRoot); - TreeNode grassNode = - sceneGraph.GetNode(rootNode.GetChild(0)); // grass model must be single game object + auto rootNode = sceneGraph.GetNodeByGameObject(grassEntityRoot); + auto& grassNode = sceneGraph.GetNode(rootNode.GetChild(0)); // grass model must be single game object GrassTag grassTag{grassInstances}; registry.emplace(grassNode.GetGameObject(), grassTag); diff --git a/engine/renderer/builder/ufbxBuilder.cpp b/engine/renderer/builder/ufbxBuilder.cpp index e8cdddcf..5676e3ed 100644 --- a/engine/renderer/builder/ufbxBuilder.cpp +++ b/engine/renderer/builder/ufbxBuilder.cpp @@ -168,22 +168,16 @@ namespace GfxRenderEngine } // create scene graph node and add to parent - std::string shortName; - std::string longName; + std::string name; if (fbxNodePtr == m_FbxScene->root_node) { // special name in scene graph for root node - std::string name = EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath); - shortName = m_DictionaryPrefix + "::" + name + "::" + std::to_string(m_InstanceIndex) + "::root"; - longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; + name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::root"; } else { - shortName = m_DictionaryPrefix + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - longName = - m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; + name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; } - currentNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(currentNode); + currentNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); } } ++hasMeshIndex; @@ -200,12 +194,9 @@ namespace GfxRenderEngine std::string nodeName(fbxNodePtr->name.data); auto entity = m_Registry.Create(); - auto shortName = m_DictionaryPrefix + "::" + EngineCore::GetFilenameWithoutPathAndExtension(m_Filepath) + - "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - auto longName = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; + auto name = m_DictionaryPrefix + "::" + m_Filepath + "::" + std::to_string(m_InstanceIndex) + "::" + nodeName; - uint newNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(parentNode).AddChild(newNode); + uint newNode = m_SceneGraph.CreateNode(parentNode, entity, name, m_Dictionary); glm::vec3 scale; glm::quat rotation; @@ -464,7 +455,7 @@ namespace GfxRenderEngine } } - // handle vertex data + // load vertex data void UFbxBuilder::LoadVertexData(const ufbx_node* fbxNodePtr) { m_Vertices.clear(); diff --git a/engine/renderer/camera.cpp b/engine/renderer/camera.cpp index 5c759bfc..7d127461 100644 --- a/engine/renderer/camera.cpp +++ b/engine/renderer/camera.cpp @@ -53,7 +53,7 @@ namespace GfxRenderEngine void Camera::SetPerspectiveProjection(float fovy, float aspect, float near, float far) { - ASSERT(glm::abs(aspect - std::numeric_limits::epsilon()) > 0.0f); + CORE_ASSERT(glm::abs(aspect - std::numeric_limits::epsilon()) > 0.0f, "aspect too small"); m_ProjectionType = PERSPECTIVE_PROJECTION; const float tanHalfFovy = tan(fovy / 2.f); m_ProjectionMatrix = glm::mat4{0.0f}; diff --git a/engine/renderer/graphicsContext.h b/engine/renderer/graphicsContext.h index 8296f1ad..17bbd6c9 100644 --- a/engine/renderer/graphicsContext.h +++ b/engine/renderer/graphicsContext.h @@ -60,7 +60,7 @@ namespace GfxRenderEngine virtual std::shared_ptr LoadModel(const Builder& builder) = 0; virtual std::shared_ptr LoadModel(const TerrainBuilder& builder) = 0; virtual std::shared_ptr LoadModel(const GltfBuilder& builder) = 0; - virtual std::shared_ptr LoadModel(const FastgltfBuilder& builder) = 0; + virtual std::shared_ptr LoadModel(const Model::ModelData& modelData) = 0; virtual std::shared_ptr LoadModel(const FbxBuilder& builder) = 0; virtual std::shared_ptr LoadModel(const UFbxBuilder& builder) = 0; virtual void ToggleDebugWindow(const GenericCallback& callback = nullptr) = 0; @@ -68,6 +68,8 @@ namespace GfxRenderEngine virtual uint GetContextWidth() const = 0; virtual uint GetContextHeight() const = 0; virtual bool MultiThreadingSupport() const = 0; + virtual void WaitIdle() const = 0; + virtual void ResetDescriptorPool(ThreadPool& threadPool) = 0; static std::shared_ptr Create(void* window, ThreadPool& threadPoolPrimary, ThreadPool& threadPoolSecondary); diff --git a/engine/renderer/model.h b/engine/renderer/model.h index 111f3e77..364ecf4c 100644 --- a/engine/renderer/model.h +++ b/engine/renderer/model.h @@ -56,6 +56,36 @@ namespace GfxRenderEngine { struct Vertex // 3D, with animation { + + // default + Vertex() + : m_Position{0.0f}, m_Color{0.0f}, m_Normal{0.0f}, m_UV{0.0f}, m_Tangent{0.0f}, m_JointIds{0}, m_Weights{0.0f} + { + } + + // copy + Vertex(glm::vec3& position, glm::vec4& color, glm::vec3& normal, glm::vec2& uv, glm::vec3& tangent, + glm::ivec4& jointIds, glm::vec4& weights) + : m_Position{position}, m_Color{color}, m_Normal{normal}, m_UV{uv}, m_Tangent{tangent}, m_JointIds{jointIds}, + m_Weights{weights} + { + } + + // move + Vertex(glm::vec3&& position, glm::vec4&& color, glm::vec3&& normal, glm::vec2&& uv, glm::vec3&& tangent, + glm::ivec4&& jointIds, glm::vec4&& weights) + : m_Position{std::move(position)}, m_Color{std::move(color)}, m_Normal{std::move(normal)}, m_UV{std::move(uv)}, + m_Tangent{std::move(tangent)}, m_JointIds{std::move(jointIds)}, m_Weights{std::move(weights)} + { + } + + // move with some default args + Vertex(glm::vec3&& position, glm::vec4&& color, glm::vec3&& normal, glm::vec2&& uv) + : m_Position{std::move(position)}, m_Color{std::move(color)}, m_Normal{std::move(normal)}, m_UV{std::move(uv)}, + m_Tangent{0.0f}, m_JointIds{0}, m_Weights{0.0f} + { + } + glm::vec3 m_Position; // layout(location = 0) glm::vec4 m_Color; // layout(location = 1) glm::vec3 m_Normal; // layout(location = 2) @@ -79,6 +109,17 @@ namespace GfxRenderEngine class Model { + public: + struct ModelData + { + std::vector m_Indices{}; + std::vector m_Vertices{}; + std::vector m_Submeshes{}; + std::shared_ptr m_Skeleton; + std::shared_ptr m_ShaderData; + std::shared_ptr m_Animations; + }; + public: Model() {} virtual ~Model() = default; diff --git a/engine/renderer/skeletalAnimation/fastgltfModelSA.cpp b/engine/renderer/skeletalAnimation/fastgltfModelSA.cpp index f2d49da4..f3f93cfd 100644 --- a/engine/renderer/skeletalAnimation/fastgltfModelSA.cpp +++ b/engine/renderer/skeletalAnimation/fastgltfModelSA.cpp @@ -35,7 +35,7 @@ namespace GfxRenderEngine void FastgltfBuilder::LoadSkeletonsGltf() { - size_t numberOfSkeletons = m_GltfModel.skins.size(); + size_t numberOfSkeletons = m_GltfAsset.skins.size(); if (!numberOfSkeletons) { return; @@ -51,7 +51,7 @@ namespace GfxRenderEngine // use skeleton 0 from the glTF model to fill the skeleton { - const fastgltf::Skin& glTFSkin = m_GltfModel.skins[0]; + const fastgltf::Skin& glTFSkin = m_GltfAsset.skins[0]; // does it have information about joints? if (glTFSkin.inverseBindMatrices.has_value()) // glTFSkin.inverseBindMatrices refers to an gltf accessor @@ -77,7 +77,7 @@ namespace GfxRenderEngine size_t count = 0; fastgltf::AccessorType type; fastgltf::ComponentType componentType = LoadAccessor( - m_GltfModel.accessors[glTFSkin.inverseBindMatrices.value()], inverseBindMatrices, &count, &type); + m_GltfAsset.accessors[glTFSkin.inverseBindMatrices.value()], inverseBindMatrices, &count, &type); CORE_ASSERT(type == fastgltf::AccessorType::Mat4, "unexpected type"); CORE_ASSERT(fastgltf::getGLComponentType(componentType) == GL_FLOAT, "unexpected component type"); // assert # of matrices matches # of joints @@ -90,7 +90,7 @@ namespace GfxRenderEngine int globalGltfNodeIndex = glTFSkin.joints[jointIndex]; auto& joint = joints[jointIndex]; // just a reference for easier code joint.m_InverseBindMatrix = inverseBindMatrices[jointIndex]; - joint.m_Name = m_GltfModel.nodes[globalGltfNodeIndex].name; + joint.m_Name = m_GltfAsset.nodes[globalGltfNodeIndex].name; // set up map "global node" to "joint index" m_Skeleton->m_GlobalNodeToJointIndex[globalGltfNodeIndex] = jointIndex; @@ -111,10 +111,10 @@ namespace GfxRenderEngine m_ShaderData->MapBuffer(); } - size_t numberOfAnimations = m_GltfModel.animations.size(); + size_t numberOfAnimations = m_GltfAsset.animations.size(); for (size_t animationIndex = 0; animationIndex < numberOfAnimations; ++animationIndex) { - auto& gltfAnimation = m_GltfModel.animations[animationIndex]; + auto& gltfAnimation = m_GltfAsset.animations[animationIndex]; std::string name(gltfAnimation.name); LOG_CORE_INFO("name of animation: {0}", name); std::shared_ptr animation = std::make_shared(name); @@ -134,7 +134,7 @@ namespace GfxRenderEngine size_t count = 0; const float* timestampBuffer; fastgltf::ComponentType componentType = - LoadAccessor(m_GltfModel.accessors[glTFSampler.inputAccessor], timestampBuffer, &count); + LoadAccessor(m_GltfAsset.accessors[glTFSampler.inputAccessor], timestampBuffer, &count); if (fastgltf::getGLComponentType(componentType) == GL_FLOAT) { @@ -155,7 +155,7 @@ namespace GfxRenderEngine size_t count = 0; fastgltf::AccessorType type; const uint* buffer; - LoadAccessor(m_GltfModel.accessors[glTFSampler.outputAccessor], buffer, &count, &type); + LoadAccessor(m_GltfAsset.accessors[glTFSampler.outputAccessor], buffer, &count, &type); switch (type) { @@ -246,13 +246,13 @@ namespace GfxRenderEngine joint.m_ParentJoint = parentJoint; // process children (if any) - size_t numberOfChildren = m_GltfModel.nodes[globalGltfNodeIndex].children.size(); + size_t numberOfChildren = m_GltfAsset.nodes[globalGltfNodeIndex].children.size(); if (numberOfChildren > 0) { joint.m_Children.resize(numberOfChildren); for (size_t childIndex = 0; childIndex < numberOfChildren; ++childIndex) { - uint globalGltfNodeIndexForChild = m_GltfModel.nodes[globalGltfNodeIndex].children[childIndex]; + uint globalGltfNodeIndexForChild = m_GltfAsset.nodes[globalGltfNodeIndex].children[childIndex]; joint.m_Children[childIndex] = m_Skeleton->m_GlobalNodeToJointIndex[globalGltfNodeIndexForChild]; LoadJoint(globalGltfNodeIndexForChild, currentJoint); } diff --git a/engine/scene/dictionary.cpp b/engine/scene/dictionary.cpp index ce8619db..030ef686 100644 --- a/engine/scene/dictionary.cpp +++ b/engine/scene/dictionary.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -12,37 +12,28 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "scene/dictionary.h" namespace GfxRenderEngine { - void Dictionary::Insert(const std::string& key, entt::entity value) + void Dictionary::Insert(std::string const& key, entt::entity value) { + std::lock_guard guard(m_Mutex); m_DictStr2GameObject[key] = value; - } - - void Dictionary::InsertLong(const std::string& key, entt::entity value) - { - m_GameObject2LongStr[value] = key; - Insert(key, value); - } - - void Dictionary::InsertShort(const std::string& key, entt::entity value) - { - m_GameObject2ShortStr[value] = key; - Insert(key, value); + m_GameObject2Str[value] = key; } entt::entity Dictionary::Retrieve(const std::string& key) { + std::lock_guard guard(m_Mutex); if (m_DictStr2GameObject.find(key) != m_DictStr2GameObject.end()) { return m_DictStr2GameObject[key]; @@ -54,24 +45,26 @@ namespace GfxRenderEngine } } - void Dictionary::List() const + void Dictionary::List() { + std::lock_guard guard(m_Mutex); LOG_CORE_INFO("listing dictionary:"); - for (auto& it: m_DictStr2GameObject) + for (auto& it : m_DictStr2GameObject) { LOG_CORE_INFO("key: `{0}`, value: `{1}`", it.first, it.second); } } - const std::string& Dictionary::GetShortName(entt::entity gameObject) + const std::string& Dictionary::GetName(entt::entity gameObject) { - ASSERT(m_GameObject2ShortStr.find(gameObject) != m_GameObject2ShortStr.end()); - return m_GameObject2ShortStr[gameObject]; + std::lock_guard guard(m_Mutex); + CORE_ASSERT((m_GameObject2Str.find(gameObject) != m_GameObject2Str.end()), "Dictionary::GetName no entry found"); + return m_GameObject2Str[gameObject]; } - const std::string& Dictionary::GetLongName(entt::entity gameObject) + size_t Dictionary::Size() { - ASSERT(m_GameObject2LongStr.find(gameObject) != m_GameObject2LongStr.end()); - return m_GameObject2LongStr[gameObject]; + std::lock_guard guard(m_Mutex); + return m_DictStr2GameObject.size(); } -} +} // namespace GfxRenderEngine diff --git a/engine/scene/dictionary.h b/engine/scene/dictionary.h index 7a5b418a..f2d2d362 100644 --- a/engine/scene/dictionary.h +++ b/engine/scene/dictionary.h @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2024 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -12,12 +12,12 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once @@ -35,26 +35,18 @@ namespace GfxRenderEngine { public: + void Insert(std::string const& key, entt::entity value); + entt::entity Retrieve(std::string const& key); + size_t Size(); + void List(); - void InsertShort(const std::string& key, entt::entity value); - void InsertLong(const std::string& key, entt::entity value); - entt::entity Retrieve(const std::string& key); - size_t Size() const { return m_DictStr2GameObject.size(); } - void List() const; - - const std::string& GetShortName(entt::entity gameObject); - const std::string& GetLongName(entt::entity gameObject); - - private: - - void Insert(const std::string& key, entt::entity value); + const std::string& GetName(entt::entity gameObject); private: + std::mutex m_Mutex; std::unordered_map m_DictStr2GameObject; - std::unordered_map m_GameObject2ShortStr; - std::unordered_map m_GameObject2LongStr; - + std::unordered_map m_GameObject2Str; }; -} +} // namespace GfxRenderEngine diff --git a/engine/scene/particleSystem.cpp b/engine/scene/particleSystem.cpp index 25afcf3d..a3e392b5 100644 --- a/engine/scene/particleSystem.cpp +++ b/engine/scene/particleSystem.cpp @@ -1,4 +1,4 @@ -/* Engine Copyright (c) 2022 Engine Development Team +/* Engine Copyright (c) 2022 Engine Development Team https://github.com/beaumanvienna/vulkan Permission is hereby granted, free of charge, to any person @@ -12,12 +12,12 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "core.h" @@ -30,7 +30,7 @@ namespace GfxRenderEngine ParticleSystem::ParticleSystem(uint poolSize, SpriteSheet* spritesheet, float amplification) : m_ParticlePool{poolSize}, m_PoolIndex{0}, m_Spritesheet{spritesheet} { - ASSERT(poolSize); + CORE_ASSERT(poolSize, "pool size is zero"); auto numberOfSprites = m_Spritesheet->GetNumberOfSprites(); m_AnimationSprites.resize(numberOfSprites); for (uint i = 0; i < numberOfSprites; i++) @@ -52,24 +52,23 @@ namespace GfxRenderEngine { Particle& particle = m_ParticlePool[m_PoolIndex]; - glm::vec3 variationVelocity = glm::vec3 - { + glm::vec3 variationVelocity = glm::vec3{ variation.m_Velocity.x * EngineCore::RandomPlusMinusOne(), variation.m_Velocity.y * EngineCore::RandomPlusMinusOne(), variation.m_Velocity.z * EngineCore::RandomPlusMinusOne(), }; - particle.m_Velocity = spec.m_Velocity + variationVelocity; - particle.m_Acceleration = spec.m_Acceleration; + particle.m_Velocity = spec.m_Velocity + variationVelocity; + particle.m_Acceleration = spec.m_Acceleration; - particle.m_RotationSpeed = spec.m_RotationSpeed; + particle.m_RotationSpeed = spec.m_RotationSpeed; - particle.m_StartColor = spec.m_StartColor; - particle.m_EndColor = spec.m_EndColor; + particle.m_StartColor = spec.m_StartColor; + particle.m_EndColor = spec.m_EndColor; - particle.m_StartSize = spec.m_StartSize; - particle.m_FinalSize = spec.m_FinalSize; + particle.m_StartSize = spec.m_StartSize; + particle.m_FinalSize = spec.m_FinalSize; - particle.m_LifeTime = spec.m_LifeTime; + particle.m_LifeTime = spec.m_LifeTime; particle.m_RemainingLifeTime = particle.m_LifeTime; particle.m_Enabled = true; @@ -85,14 +84,14 @@ namespace GfxRenderEngine m_Registry.emplace(particle.m_Entity, mesh); TransformComponent transform{}; - transform.SetTranslation(glm::vec3 - { + transform.SetTranslation(glm::vec3{ spec.m_Position.x + variation.m_Position.x * EngineCore::RandomPlusMinusOne(), spec.m_Position.y + variation.m_Position.y * EngineCore::RandomPlusMinusOne(), spec.m_Position.z + variation.m_Position.z * EngineCore::RandomPlusMinusOne(), }); transform.SetScale(glm::vec3{1.0f} * particle.m_StartSize); - transform.SetRotation(glm::vec3{spec.m_Rotation.x, spec.m_Rotation.y, spec.m_Rotation.z + variation.m_Rotation.z * EngineCore::RandomPlusMinusOne()}); + transform.SetRotation(glm::vec3{spec.m_Rotation.x, spec.m_Rotation.y, + spec.m_Rotation.z + variation.m_Rotation.z * EngineCore::RandomPlusMinusOne()}); m_Registry.emplace(particle.m_Entity, transform); particle.m_SmokeAnimation.Create(100ms /* per frame */, m_Spritesheet); @@ -148,4 +147,4 @@ namespace GfxRenderEngine } } } -} +} // namespace GfxRenderEngine diff --git a/engine/scene/scene.cpp b/engine/scene/scene.cpp index d3d8fe2d..1e57d3ae 100644 --- a/engine/scene/scene.cpp +++ b/engine/scene/scene.cpp @@ -46,19 +46,17 @@ namespace GfxRenderEngine TransformComponent transform{}; m_Registry.emplace(entity, transform); - m_SceneGraph.CreateNode(entity, "root", m_Name + "::sceneRoot", m_Dictionary); + m_SceneGraph.CreateRootNode(entity, m_Name + "::sceneRoot", m_Dictionary); } { // create lights group + auto name = "SceneLights"; auto entity = m_Registry.Create(); - TransformComponent lightGroupTransform{}; - m_Registry.emplace(entity, lightGroupTransform); + TransformComponent transform{}; + m_Registry.emplace(entity, transform); - auto shortName = "SceneLights"; - auto longName = "SceneLights"; - m_SceneLightsGroupNode = m_SceneGraph.CreateNode(entity, shortName, longName, m_Dictionary); - m_SceneGraph.GetRoot().AddChild(m_SceneLightsGroupNode); + m_SceneLightsGroupNode = m_SceneGraph.CreateNode(SceneGraph::ROOT_NODE, entity, name, m_Dictionary); } } @@ -77,10 +75,8 @@ namespace GfxRenderEngine m_Registry.emplace(pointLight, pointLightComponent); // add to scene graph - std::string shortName = "light" + std::to_string(m_LightCounter); - std::string longName = "light" + std::to_string(m_LightCounter); - uint currentNode = m_SceneGraph.CreateNode(pointLight, shortName, longName, m_Dictionary); - m_SceneGraph.GetNode(m_SceneLightsGroupNode).AddChild(currentNode); + std::string name = "light" + std::to_string(m_LightCounter); + m_SceneGraph.CreateNode(m_SceneLightsGroupNode, pointLight, name, m_Dictionary); ++m_LightCounter; return pointLight; diff --git a/engine/scene/scene.h b/engine/scene/scene.h index 36713ece..89670f39 100644 --- a/engine/scene/scene.h +++ b/engine/scene/scene.h @@ -57,8 +57,6 @@ namespace GfxRenderEngine virtual void StartScripts() = 0; virtual void ResetTimer() {} - void DestroyEntity(entt::entity entity); - entt::entity CreatePointLight(const float intensity = 1.0f, const float radius = 0.1f, const glm::vec3& color = glm::vec3{1.0f, 1.0f, 1.0f}); entt::entity CreateDirectionalLight(const float intensity = 1.0f, @@ -69,8 +67,8 @@ namespace GfxRenderEngine Registry& GetRegistry() { return m_Registry; }; Dictionary& GetDictionary() { return m_Dictionary; }; SceneGraph& GetSceneGraph() { return m_SceneGraph; } - TreeNode* GetTreeNode(entt::entity entity) { return &m_SceneGraph.GetNodeByGameObject(entity); } - TreeNode& GetTreeNode(uint nodeIndex) { return m_SceneGraph.GetNode(nodeIndex); } + SceneGraph::TreeNode* GetTreeNode(entt::entity entity) { return &m_SceneGraph.GetNodeByGameObject(entity); } + SceneGraph::TreeNode& GetTreeNode(uint nodeIndex) { return m_SceneGraph.GetNode(nodeIndex); } uint GetTreeNodeIndex(entt::entity entity) { return m_SceneGraph.GetTreeNodeIndex(entity); } protected: diff --git a/engine/scene/sceneGraph.cpp b/engine/scene/sceneGraph.cpp index d5968b46..e193827c 100644 --- a/engine/scene/sceneGraph.cpp +++ b/engine/scene/sceneGraph.cpp @@ -24,46 +24,50 @@ namespace GfxRenderEngine { - TreeNode::TreeNode(entt::entity gameObject, const std::string& name, const std::string& longName) - : m_GameObject(gameObject), m_LongName(longName), m_Name(name) + SceneGraph::TreeNode::TreeNode(entt::entity gameObject, const std::string& name) : m_GameObject(gameObject), m_Name(name) { } - TreeNode::TreeNode(GfxRenderEngine::TreeNode const& other) - : m_GameObject(other.m_GameObject), m_LongName(other.m_LongName), m_Name(other.m_Name), m_Children(other.m_Children) + SceneGraph::TreeNode::TreeNode(TreeNode const& other) + : m_GameObject(other.m_GameObject), m_Name(other.m_Name), m_Children(other.m_Children) { } - TreeNode::~TreeNode() {} + SceneGraph::TreeNode::~TreeNode() {} - entt::entity TreeNode::GetGameObject() const { return m_GameObject; } + entt::entity SceneGraph::TreeNode::GetGameObject() const { return m_GameObject; } - const std::string& TreeNode::GetName() const { return m_Name; } + const std::string& SceneGraph::TreeNode::GetName() const { return m_Name; } - const std::string& TreeNode::GetLongName() const { return m_LongName; } + uint SceneGraph::TreeNode::Children() { return m_Children.size(); } - uint TreeNode::Children() const { return m_Children.size(); } + uint SceneGraph::TreeNode::GetChild(uint const childIndex) { return m_Children[childIndex]; } - uint TreeNode::GetChild(uint const childIndex) { return m_Children[childIndex]; } - - uint TreeNode::AddChild(uint const nodeIndex) + uint SceneGraph::TreeNode::AddChild(uint const nodeIndex) { - std::lock_guard guard(m_Mutex); uint childIndex = m_Children.size(); m_Children.push_back(nodeIndex); return childIndex; } - void TreeNode::SetGameObject(entt::entity gameObject) { m_GameObject = gameObject; } - - uint SceneGraph::CreateNode(entt::entity const gameObject, std::string const& name, std::string const& longName, + uint SceneGraph::CreateNode(uint parentNode, entt::entity const gameObject, std::string const& name, Dictionary& dictionary) { - std::lock_guard guard(m_Mutex); + std::lock_guard guard(m_MutexSceneGraph); uint nodeIndex = m_Nodes.size(); - m_Nodes.push_back({gameObject, name, longName}); - dictionary.InsertShort(name, gameObject); - dictionary.InsertLong(longName, gameObject); + m_Nodes.push_back({gameObject, name}); + dictionary.Insert(name, gameObject); + m_MapFromGameObjectToNode[gameObject] = nodeIndex; + m_Nodes[parentNode].AddChild(nodeIndex); + return nodeIndex; + } + + uint SceneGraph::CreateRootNode(entt::entity const gameObject, std::string const& name, Dictionary& dictionary) + { + std::lock_guard guard(m_MutexSceneGraph); + uint nodeIndex = m_Nodes.size(); + m_Nodes.push_back({gameObject, name}); + dictionary.Insert(name, gameObject); m_MapFromGameObjectToNode[gameObject] = nodeIndex; return nodeIndex; } @@ -80,23 +84,29 @@ namespace GfxRenderEngine } } - TreeNode& SceneGraph::GetNode(uint const nodeIndex) { return m_Nodes[nodeIndex]; } + SceneGraph::TreeNode& SceneGraph::GetNode(uint const nodeIndex) + { + std::lock_guard guard(m_MutexSceneGraph); + return m_Nodes[nodeIndex]; + } - TreeNode& SceneGraph::GetNodeByGameObject(entt::entity const gameObject) + SceneGraph::TreeNode& SceneGraph::GetNodeByGameObject(entt::entity const gameObject) { + std::lock_guard guard(m_MutexSceneGraph); uint nodeIndex = m_MapFromGameObjectToNode[gameObject]; return m_Nodes[nodeIndex]; } - TreeNode& SceneGraph::GetRoot() + SceneGraph::TreeNode& SceneGraph::GetRoot() { - std::lock_guard guard(m_Mutex); + std::lock_guard guard(m_MutexSceneGraph); CORE_ASSERT(m_Nodes.size(), "SceneGraph::GetRoot(): scene graph is empty"); return m_Nodes[SceneGraph::ROOT_NODE]; } uint SceneGraph::GetTreeNodeIndex(entt::entity const gameObject) { + std::lock_guard guard(m_MutexSceneGraph); uint returnValue = NODE_INVALID; if (m_MapFromGameObjectToNode.find(gameObject) != m_MapFromGameObjectToNode.end()) diff --git a/engine/scene/sceneGraph.h b/engine/scene/sceneGraph.h index 5acf6a02..3de6e6f7 100644 --- a/engine/scene/sceneGraph.h +++ b/engine/scene/sceneGraph.h @@ -30,42 +30,42 @@ namespace GfxRenderEngine { - - class TreeNode + class SceneGraph { - public: - TreeNode(entt::entity gameObject, const std::string& name, const std::string& longName); - TreeNode(GfxRenderEngine::TreeNode const& other); - ~TreeNode(); - - entt::entity GetGameObject() const; - const std::string& GetName() const; - const std::string& GetLongName() const; - uint Children() const; - uint GetChild(uint const childIndex); - uint AddChild(uint const nodeIndex); - void SetGameObject(entt::entity gameObject); - std::vector& GetChildren() { return m_Children; } + class TreeNode + { - private: - entt::entity m_GameObject; - std::string m_Name; - std::string m_LongName; - std::mutex m_Mutex; - std::vector m_Children; - }; + public: + TreeNode(entt::entity gameObject, const std::string& name); + TreeNode(TreeNode const& other); + ~TreeNode(); - class SceneGraph - { + const std::string& GetName() const; + uint GetChild(uint const childIndex); + std::vector& GetChildren() { return m_Children; } + + uint Children(); + entt::entity GetGameObject() const; + + private: + uint AddChild(uint const nodeIndex); + + private: + entt::entity m_GameObject; + std::string m_Name; + std::vector m_Children; + + friend SceneGraph; + }; public: static constexpr uint ROOT_NODE = 0; static constexpr uint NODE_INVALID = -1; public: - uint CreateNode(entt::entity const gameObject, std::string const& name, std::string const& longName, - Dictionary& dictionary); + uint CreateNode(uint parentNode, entt::entity const gameObject, std::string const& name, Dictionary& dictionary); + uint CreateRootNode(entt::entity const gameObject, std::string const& name, Dictionary& dictionary); TreeNode& GetNode(uint const nodeIndex); TreeNode& GetNodeByGameObject(entt::entity const gameObject); TreeNode& GetRoot(); @@ -74,7 +74,7 @@ namespace GfxRenderEngine void TraverseLog(uint nodeIndex, uint indent = 0); private: - std::mutex m_Mutex; + std::mutex m_MutexSceneGraph; std::vector m_Nodes; std::map m_MapFromGameObjectToNode; }; diff --git a/engine/scene/sceneLoaderDeserializeJSON.cpp b/engine/scene/sceneLoaderDeserializeJSON.cpp index 2879254c..a2a8d301 100644 --- a/engine/scene/sceneLoaderDeserializeJSON.cpp +++ b/engine/scene/sceneLoaderDeserializeJSON.cpp @@ -167,7 +167,7 @@ namespace GfxRenderEngine std::string fullEntityName = std::string("SL::") + gltfInfo.m_GltfFile.m_Filename + std::string("::" + std::to_string(instanceIndex) + "::root"); entt::entity entity = m_Scene.m_Dictionary.Retrieve(fullEntityName); - + CORE_ASSERT(entity != entt::null, "couldn't find entity"); gltfFileInstance.m_Entity = entity; TransformComponent& transform = m_Scene.m_Registry.get(entity); transform.SetScale(gltfInfo.m_InstanceTransforms[instanceIndex].GetScale()); @@ -184,6 +184,7 @@ namespace GfxRenderEngine "::" + std::to_string(instanceIndex) + "::" + gltfNode.m_Name; entt::entity gameObject = m_Scene.m_Dictionary.Retrieve(fullEntityName); + if (gameObject != entt::null) { LOG_CORE_INFO("found script '{0}' for entity '{1}' in scene description", @@ -779,13 +780,11 @@ namespace GfxRenderEngine terrainInstances.resize(terrainInfo.m_InstanceCount); { - auto name = EngineCore::GetFilenameWithoutPath(terrainInfo.m_Filename); - name = EngineCore::GetFilenameWithoutExtension(name); uint instanceIndex = 0; for (auto& terrainInstance : terrainInstances) { - std::string entityName = name + std::string("::" + std::to_string(instanceIndex)); - entt::entity entity = m_Scene.m_Dictionary.Retrieve(entityName); + std::string name = terrainInfo.m_Filename + std::string("::") + std::to_string(instanceIndex); + entt::entity entity = m_Scene.m_Dictionary.Retrieve(name); CORE_ASSERT(entity != entt::null, "couldn't find entity"); terrainInstance.m_Entity = entity; TransformComponent& transform = m_Scene.m_Registry.get(entity);