diff --git a/Src/Client/ServerSession.cpp b/Src/Client/ServerSession.cpp index d06d6ef..72f1c5b 100644 --- a/Src/Client/ServerSession.cpp +++ b/Src/Client/ServerSession.cpp @@ -26,6 +26,12 @@ ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptrsecond.Regions.find(rPos); + if(iterRegion != iterWorld->second.Regions.end()) + iterWorld->second.Regions.erase(iterRegion); + } + } + + for(auto& [wId, voxels] : chunks_AddOrChange_Voxel_Result) { + auto& regions = Content.Worlds[wId].Regions; + + for(auto& [pos, data] : voxels) { + regions[pos >> 2].Chunks[Pos::bvec4u(pos & 0x3).pack()].Voxels = std::move(data); + } + } + + for(auto& [wId, nodes] : chunks_AddOrChange_Node_Result) { + auto& regions = Content.Worlds[wId].Regions; + + for(auto& [pos, data] : nodes) { + regions[pos >> 2].Chunks[Pos::bvec4u(pos & 0x3).pack()].Nodes = std::move(data); + } + } + + } + if(RS) RS->tickSync(result); } diff --git a/Src/Client/Vulkan/Vulkan.cpp b/Src/Client/Vulkan/Vulkan.cpp index 425e6b0..fefc70f 100644 --- a/Src/Client/Vulkan/Vulkan.cpp +++ b/Src/Client/Vulkan/Vulkan.cpp @@ -192,9 +192,8 @@ void Vulkan::run() prevTime += dTime; Screen.State = DrawState::Begin; - if(Game.RSession) - Game.RSession->pushStage(EnumRenderStage::ComposingCommandBuffer); - + + /// TODO: Нужно синхронизировать с vkQueue { std::lock_guard lock(Screen.BeforeDrawMtx); while(!Screen.BeforeDraw.empty()) @@ -204,12 +203,44 @@ void Vulkan::run() } } + if(Game.Выйти) { + Game.Выйти = false; + + try { + if(Game.Session) + Game.Session->setRenderSession(nullptr); + + if(Game.RSession) + Game.RSession = nullptr; + } catch(const std::exception &exc) { + LOG.error() << "Game.RSession->shutdown: " << exc.what(); + } + + try { + if(Game.Session) + Game.Session->shutdown(EnumDisconnect::ByInterface); + } catch(const std::exception &exc) { + LOG.error() << "Game.Session->shutdown: " << exc.what(); + } + } + if(!NeedShutdown && glfwWindowShouldClose(Graphics.Window)) { NeedShutdown = true; + try { + if(Game.Session) + Game.Session->setRenderSession(nullptr); + + if(Game.RSession) + Game.RSession = nullptr; + } catch(const std::exception &exc) { + LOG.error() << "Game.RSession->shutdown: " << exc.what(); + } + try { if(Game.Session) Game.Session->shutdown(EnumDisconnect::ByInterface); + Game.Session = nullptr; } catch(const std::exception &exc) { LOG.error() << "Game.Session->shutdown: " << exc.what(); } @@ -220,6 +251,8 @@ void Vulkan::run() } catch(const std::exception &exc) { LOG.error() << "Game.Server->GS.shutdown: " << exc.what(); } + + continue; } if(Game.Session) { @@ -2258,7 +2291,7 @@ void Vulkan::gui_MainMenu() { } void Vulkan::gui_ConnectedToServer() { - if(Game.Session) { + if(Game.Session && Game.RSession) { if(ImGui::Begin("MainMenu", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) { ImGui::Text("fps: %2.2f World: %u Pos: %i %i %i Region: %i %i %i", @@ -2271,25 +2304,13 @@ void Vulkan::gui_ConnectedToServer() { LOG.debug(); if(ImGui::Button("Выйти")) { - try { - if(Game.Session) - Game.Session->shutdown(EnumDisconnect::ByInterface); - } catch(const std::exception &exc) { - LOG.error() << "Game.Session->shutdown: " << exc.what(); - } - - Game.RSession->pushStage(EnumRenderStage::Shutdown); - Game.RSession = nullptr; - Game.Session = nullptr; + Game.Выйти = true; Game.ImGuiInterfaces.pop_back(); - int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR); - if(mode != GLFW_CURSOR_NORMAL) - glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } ImGui::End(); - if(!Game.RSession) + if(Game.Выйти) return; } diff --git a/Src/Client/Vulkan/Vulkan.hpp b/Src/Client/Vulkan/Vulkan.hpp index 955322b..b86e95c 100644 --- a/Src/Client/Vulkan/Vulkan.hpp +++ b/Src/Client/Vulkan/Vulkan.hpp @@ -251,6 +251,7 @@ public: std::thread MainThread; std::shared_ptr RSession; ServerSession::Ptr Session; + bool Выйти = false; std::list ImGuiInterfaces; std::unique_ptr Server; diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index bcb3679..c028e2e 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -31,7 +31,7 @@ void ChunkMeshGenerator::run(uint8_t id) { Sync.CV_CountInRun.notify_all(); } - LOG.debug() << "Старт потока подготовки чанков к рендеру"; + LOG.debug() << "Старт потока верширования чанков"; int timeWait = 1; try { @@ -239,17 +239,8 @@ void ChunkMeshGenerator::run(uint8_t id) { for(int x = 0; x < 16; x++) fullNodes[x+0][y+1][0] = 1; } - } - - { - result.NodeDefines.reserve(16*16*16); - for(int iter = 0; iter < 16*16*16; iter++) - result.NodeDefines.push_back((*chunk)[iter].NodeId); - std::sort(result.NodeDefines.begin(), result.NodeDefines.end()); - auto eraseIter = std::unique(result.NodeDefines.begin(), result.NodeDefines.end()); - result.NodeDefines.erase(eraseIter, result.NodeDefines.end()); - result.NodeDefines.shrink_to_fit(); - } + } else + goto end; { result.VoxelDefines.reserve(voxels->size()); @@ -262,6 +253,16 @@ void ChunkMeshGenerator::run(uint8_t id) { result.VoxelDefines.shrink_to_fit(); } + { + result.NodeDefines.reserve(16*16*16); + for(int iter = 0; iter < 16*16*16; iter++) + result.NodeDefines.push_back((*chunk)[iter].NodeId); + std::sort(result.NodeDefines.begin(), result.NodeDefines.end()); + auto eraseIter = std::unique(result.NodeDefines.begin(), result.NodeDefines.end()); + result.NodeDefines.erase(eraseIter, result.NodeDefines.end()); + result.NodeDefines.shrink_to_fit(); + } + // Генерация вершин вокселей { @@ -277,12 +278,12 @@ void ChunkMeshGenerator::run(uint8_t id) { for(int x = 0; x < 16; x++) { int fullCovered = 0; - fullCovered |= fullNodes[x+1][y][z]; - fullCovered |= fullNodes[x-1][y][z] << 1; - fullCovered |= fullNodes[x][y+1][z] << 2; - fullCovered |= fullNodes[x][y-1][z] << 3; - fullCovered |= fullNodes[x][y][z+1] << 4; - fullCovered |= fullNodes[x][y][z-1] << 5; + fullCovered |= fullNodes[x+1+1][y+1][z+1]; + fullCovered |= fullNodes[x+1-1][y+1][z+1] << 1; + fullCovered |= fullNodes[x+1][y+1+1][z+1] << 2; + fullCovered |= fullNodes[x+1][y+1-1][z+1] << 3; + fullCovered |= fullNodes[x+1][y+1][z+1+1] << 4; + fullCovered |= fullNodes[x+1][y+1][z+1-1] << 5; if(fullCovered == 0b111111) continue; @@ -394,7 +395,7 @@ void ChunkMeshGenerator::run(uint8_t id) { result.NodeVertexs.push_back(v); } - if(!(fullCovered & 0b000001)) { + if(!(fullCovered & 0b000010)) { v.FX = 135+x*16; v.FY = 135+y*16; v.FZ = 135+z*16+16; @@ -515,13 +516,13 @@ void ChunkMeshGenerator::run(uint8_t id) { Sync.CV_CountInRun.notify_all(); } - LOG.debug() << "Завершение потока подготовки чанков к рендеру"; + LOG.debug() << "Завершение потока верширования чанков"; } std::pair< std::vector, uint32_t>>, std::vector, uint32_t>> -> ModuleChunkPreparator::getChunksForRender( +> ChunkPreparator::getChunksForRender( WorldId_t worldId, Pos::Object pos, uint8_t distance, glm::mat4 projView, Pos::GlobalRegion x64offset ) { Pos::GlobalChunk playerChunk = pos >> Pos::Object_t::BS_Bit >> 4; @@ -610,7 +611,7 @@ std::pair< VulkanRenderSession::VulkanRenderSession(Vulkan *vkInst, IServerSession *serverSession) : VkInst(vkInst), ServerSession(serverSession), - MCP(vkInst, serverSession), + CP(vkInst, serverSession), MainTest(vkInst), LightDummy(vkInst), TestQuad(vkInst, sizeof(NodeVertexStatic)*6*3*2) { @@ -1231,11 +1232,11 @@ VulkanRenderSession::~VulkanRenderSession() { } void VulkanRenderSession::prepareTickSync() { - MCP.prepareTickSync(); + CP.prepareTickSync(); } void VulkanRenderSession::pushStageTickSync() { - MCP.pushStageTickSync(); + CP.pushStageTickSync(); } void VulkanRenderSession::tickSync(const TickSyncData& data) { @@ -1243,8 +1244,10 @@ void VulkanRenderSession::tickSync(const TickSyncData& data) { // Профили // Чанки - ModuleChunkPreparator::TickSyncData mcpData; - MCP.tickSync(mcpData); + ChunkPreparator::TickSyncData mcpData; + mcpData.ChangedChunks = data.Chunks_ChangeOrAdd; + mcpData.LostRegions = data.Chunks_Lost; + CP.tickSync(mcpData); } void VulkanRenderSession::setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) { @@ -1416,7 +1419,7 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff Pos::GlobalChunk x64offset = X64Offset >> Pos::Object_t::BS_Bit >> 4; Pos::GlobalRegion x64offset_region = x64offset >> 2; - auto [voxelVertexs, nodeVertexs] = MCP.getChunksForRender(WorldId, Pos, 1, PCO.ProjView, x64offset_region); + auto [voxelVertexs, nodeVertexs] = CP.getChunksForRender(WorldId, Pos, 1, PCO.ProjView, x64offset_region); { static uint32_t l = TOS::Time::getSeconds(); diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index e39fe00..2d3fa25 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -148,7 +148,7 @@ private: /* Модуль обрабатывает рендер чанков */ -class ModuleChunkPreparator { +class ChunkPreparator { public: struct TickSyncData { // Профили на которые повлияли изменения, по ним нужно пересчитать чанки @@ -160,7 +160,7 @@ public: }; public: - ModuleChunkPreparator(Vulkan* vkInst, IServerSession* serverSession) + ChunkPreparator(Vulkan* vkInst, IServerSession* serverSession) : VkInst(vkInst), CMG(serverSession), VertexPool_Voxels(vkInst), @@ -182,7 +182,7 @@ public: vkAssert(!vkCreateCommandPool(VkInst->Graphics.Device, &infoCmdPool, nullptr, &CMDPool)); } - ~ModuleChunkPreparator() { + ~ChunkPreparator() { CMG.changeThreadsCount(0); if(CMDPool) @@ -203,6 +203,95 @@ public: // Пересчёт соседних чанков // Проверить необходимость пересчёта чанков при изменении профилей + // Добавляем к изменёным чанкам пересчёт соседей + { + std::vector> toBuild; + for(auto& [wId, chunks] : data.ChangedChunks) { + std::vector list; + for(const Pos::GlobalChunk& pos : chunks) { + list.push_back(pos); + list.push_back(pos+Pos::GlobalChunk(1, 0, 0)); + list.push_back(pos+Pos::GlobalChunk(-1, 0, 0)); + list.push_back(pos+Pos::GlobalChunk(0, 1, 0)); + list.push_back(pos+Pos::GlobalChunk(0, -1, 0)); + list.push_back(pos+Pos::GlobalChunk(0, 0, 1)); + list.push_back(pos+Pos::GlobalChunk(0, 0, -1)); + } + + std::sort(list.begin(), list.end()); + auto eraseIter = std::unique(list.begin(), list.end()); + list.erase(eraseIter, list.end()); + + + for(Pos::GlobalChunk& pos : list) { + Pos::GlobalRegion rPos = pos >> 2; + auto iterRegion = Requests[wId].find(rPos); + if(iterRegion != Requests[wId].end()) + toBuild.emplace_back(wId, pos, iterRegion->second); + else + toBuild.emplace_back(wId, pos, Requests[wId][rPos] = NextRequest++); + } + } + + CMG.Input.lock()->push_range(toBuild); + } + + // Чистим запросы и чанки + { + uint8_t frameRetirement = (FrameRoulette+FRAME_COUNT_RESOURCE_LATENCY) % FRAME_COUNT_RESOURCE_LATENCY; + for(auto& [wId, regions] : data.LostRegions) { + if(auto iterWorld = Requests.find(wId); iterWorld != Requests.end()) { + for(const Pos::GlobalRegion& rPos : regions) + if(auto iterRegion = iterWorld->second.find(rPos); iterRegion != iterWorld->second.end()) + iterWorld->second.erase(iterRegion); + } + + if(auto iterWorld = ChunksMesh.find(wId); iterWorld != ChunksMesh.end()) { + for(const Pos::GlobalRegion& rPos : regions) + if(auto iterRegion = iterWorld->second.find(rPos); iterRegion != iterWorld->second.end()) { + for(int iter = 0; iter < 4*4*4; iter++) { + auto& chunk = iterRegion->second[iter]; + if(chunk.VoxelPointer) + VPV_ToFree[frameRetirement].emplace_back(std::move(chunk.VoxelPointer)); + if(chunk.NodePointer) + VPN_ToFree[frameRetirement].emplace_back(std::move(chunk.NodePointer)); + } + + iterWorld->second.erase(iterRegion); + } + } + } + } + + // Получаем готовые чанки + { + std::vector chunks = std::move(*CMG.Output.lock()); + for(auto& chunk : chunks) { + auto iterWorld = Requests.find(chunk.WId); + if(iterWorld == Requests.end()) + continue; + + auto iterRegion = iterWorld->second.find(chunk.Pos >> 2); + if(iterRegion == iterWorld->second.end()) + continue; + + if(iterRegion->second != chunk.RequestId) + continue; + + // Чанк ожидаем + auto& rChunk = ChunksMesh[chunk.WId][chunk.Pos >> 2][Pos::bvec4u(chunk.Pos & 0x3).pack()]; + rChunk.Voxels = std::move(chunk.VoxelDefines); + if(!chunk.VoxelVertexs.empty()) + rChunk.VoxelPointer = VertexPool_Voxels.pushVertexs(std::move(chunk.VoxelVertexs)); + rChunk.Nodes = std::move(chunk.NodeDefines); + if(!chunk.NodeVertexs.empty()) + rChunk.NodePointer = VertexPool_Nodes.pushVertexs(std::move(chunk.NodeVertexs)); + } + } + + VertexPool_Voxels.update(CMDPool); + VertexPool_Nodes.update(CMDPool); + CMG.endTickSync(); } @@ -280,7 +369,7 @@ class VulkanRenderSession : public IRenderSession { glm::vec3 X64Offset_f, X64Delta; // Смещение мира относительно игрока в матрице вида (0 -> 64) glm::quat Quat; - ModuleChunkPreparator MCP; + ChunkPreparator CP; AtlasImage MainTest, LightDummy; Buffer TestQuad;