From 133782b18541216d7adaa03758b8c55290155148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9?= Date: Sun, 16 Feb 2025 21:36:05 +0600 Subject: [PATCH] - --- .gitignore | 1 + CMakeLists.txt | 66 ++- Src/Client/Abstract.hpp | 13 +- Src/Client/ServerSession.cpp | 81 ++- Src/Client/ServerSession.hpp | 16 +- Src/Client/Vulkan/Vulkan.cpp | 665 +++++++++++----------- Src/Client/Vulkan/Vulkan.hpp | 8 +- Src/Client/Vulkan/VulkanRenderSession.cpp | 83 ++- Src/Client/Vulkan/VulkanRenderSession.hpp | 11 +- Src/Server/GameServer.cpp | 64 ++- Src/Server/GameServer.hpp | 3 + Src/Server/SaveBackend.hpp | 1 + Src/Server/World.cpp | 13 - Src/Server/World.hpp | 15 +- assets/grass.png | Bin 0 -> 10253 bytes assets/shaders/chunk/node_opaque.frag | 59 +- assets/shaders/chunk/node_opaque.frag.bin | Bin 1264 -> 6224 bytes imgui.ini | 8 - 18 files changed, 698 insertions(+), 409 deletions(-) create mode 100644 assets/grass.png delete mode 100644 imgui.ini diff --git a/.gitignore b/.gitignore index ab446f9..c3fc602 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ /cmake_install.cmake /libassets.a /resources.cpp +/imgui.ini diff --git a/CMakeLists.txt b/CMakeLists.txt index 966b1de..a49703e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,18 @@ cmake_minimum_required(VERSION 3.13) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -DGLM_FORCE_DEPTH_ZERO_TO_ONE") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdynamic +# gprof +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") +# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") + +# sanitizer +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") + +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment") + project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description") add_executable(${PROJECT_NAME}) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20) @@ -11,20 +21,41 @@ file(GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "Src/*.cpp") target_sources(${PROJECT_NAME} PRIVATE ${SOURCES}) target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Src") +include(FetchContent) + # Boost if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) endif() set(Boost_USE_STATIC_LIBS ON) -find_package(Boost REQUIRED COMPONENTS thread json) -target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR}) -target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json) +# find_package(Boost REQUIRED COMPONENTS thread json) +# target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR}) +# target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json) + +set(BOOST_INCLUDE_LIBRARIES asio thread json) +set(BOOST_ENABLE_CMAKE ON) +FetchContent_Declare( + Boost + URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.7z + USES_TERMINAL_DOWNLOAD TRUE + DOWNLOAD_NO_EXTRACT FALSE +) +FetchContent_MakeAvailable(Boost) +target_link_libraries(${PROJECT_NAME} PUBLIC Boost::asio Boost::thread Boost::json) # glm -find_package(glm REQUIRED) -target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR}) -target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY}) +# find_package(glm REQUIRED) +# target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR}) +# target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY}) + +FetchContent_Declare( + glm + GIT_REPOSITORY https://github.com/g-truc/glm.git + GIT_TAG 1.0.1 +) +FetchContent_MakeAvailable(glm) +target_link_libraries(${PROJECT_NAME} PUBLIC glm) # JPEG find_package(JPEG REQUIRED) @@ -40,13 +71,26 @@ target_link_libraries(${PROJECT_NAME} PUBLIC PNG::PNG) target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/png++") # GLFW3 -find_package(glfw3 REQUIRED) -target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS}) +# find_package(glfw3 REQUIRED) +# target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS}) + +FetchContent_Declare( + glfw + GIT_REPOSITORY https://github.com/glfw/glfw.git + GIT_TAG 3.4 +) +FetchContent_MakeAvailable(glfw) target_link_libraries(${PROJECT_NAME} PUBLIC glfw) # FreeType find_package(Freetype REQUIRED) -target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) +# FetchContent_Declare( +# freetype +# GIT_REPOSITORY https://github.com/freetype/freetype.git +# GIT_TAG freetype +# ) +# FetchContent_MakeAvailable(freetype) +target_include_directories(${PROJECT_NAME} PUBLIC ${freetype_INCLUDE_DIRS}) target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype) # ImGui @@ -70,5 +114,3 @@ SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED t add_library(assets STATIC resources.cpp assets.o) SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C) target_link_libraries(${PROJECT_NAME} PUBLIC assets uring) - -#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment") \ No newline at end of file diff --git a/Src/Client/Abstract.hpp b/Src/Client/Abstract.hpp index dc96080..7d34ed7 100644 --- a/Src/Client/Abstract.hpp +++ b/Src/Client/Abstract.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -81,7 +82,7 @@ public: virtual void onDefEntityUpdates(const std::vector &updates) = 0; // Сообщаем об изменившихся чанках - virtual void onChunksChange(WorldId_c worldId, const std::vector &changeOrAddList, const std::vector &remove) = 0; + virtual void onChunksChange(WorldId_c worldId, const std::unordered_set &changeOrAddList, const std::unordered_set &remove) = 0; // Установить позицию для камеры virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0; @@ -90,7 +91,7 @@ public: struct Region { - std::unordered_map Subs; + std::unordered_map Chunks; }; @@ -137,8 +138,8 @@ class IServerSession { public: struct { std::unordered_map DefWorlds; - std::unordered_map DefVoxels; - std::unordered_map DefNodes; + std::unordered_map DefVoxels; + std::unordered_map DefNodes; std::unordered_map DefPortals; std::unordered_map DefEntityes; @@ -147,6 +148,10 @@ public: std::unordered_map Entityes; } Registry; + struct { + std::unordered_map Worlds; + } External; + virtual ~IServerSession(); virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0; diff --git a/Src/Client/ServerSession.cpp b/Src/Client/ServerSession.cpp index 0581352..e415b5d 100644 --- a/Src/Client/ServerSession.cpp +++ b/Src/Client/ServerSession.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace LV::Client { @@ -163,6 +165,9 @@ void ServerSession::onCursorPosChange(int32_t width, int32_t height) { } void ServerSession::onCursorMove(float xMove, float yMove) { + xMove /= 10.f; + yMove /= 10.f; + glm::vec3 deltaPYR; static constexpr float PI = glm::pi(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180; @@ -186,6 +191,26 @@ void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool s void ServerSession::onKeyboardBtn(int btn, int state) { if(btn == GLFW_KEY_TAB && !state) { CursorMode = CursorMode == EnumCursorMoveMode::Default ? EnumCursorMoveMode::MoveAndHidden : EnumCursorMoveMode::Default; + Keys.clear(); + } + + + if(CursorMode == EnumCursorMoveMode::MoveAndHidden) + { + if(btn == GLFW_KEY_W) + Keys.W = state; + else if(btn == GLFW_KEY_A) + Keys.A = state; + else if(btn == GLFW_KEY_S) + Keys.S = state; + else if(btn == GLFW_KEY_D) + Keys.D = state; + else if(btn == GLFW_KEY_LEFT_SHIFT) + Keys.SHIFT = state; + else if(btn == GLFW_KEY_SPACE) + Keys.SPACE = state; + else if(btn == GLFW_KEY_LEFT_CONTROL) + Keys.CTRL = state; } } @@ -196,17 +221,62 @@ void ServerSession::onJoystick() { void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) { GTime = gTime; + Pos += glm::vec3(Speed) * dTime; + Speed -= glm::dvec3(Speed) * double(dTime); + + glm::mat4 rot(1); + float deltaTime = 1-std::min(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA; + rot = glm::rotate(rot, PYR.y-deltaTime*PYR_Offset.y, {0, 1, 0}); + + float mltpl = 16*dTime*Pos::Object_t::BS; + if(Keys.CTRL) + mltpl *= 16; + + Speed += glm::vec3(rot*glm::vec4(0, 0, 1, 1)*float(Keys.W))*mltpl; + Speed += glm::vec3(rot*glm::vec4(-1, 0, 0, 1)*float(Keys.A))*mltpl; + Speed += glm::vec3(rot*glm::vec4(0, 0, -1, 1)*float(Keys.S))*mltpl; + Speed += glm::vec3(rot*glm::vec4(1, 0, 0, 1)*float(Keys.D))*mltpl; + Speed += glm::vec3(0, -1, 0)*float(Keys.SHIFT)*mltpl; + Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl; + + { + std::unordered_map, std::unordered_set>> changeOrAddList_removeList; + + // Пакеты + ParsedPacket *pack; + while(NetInputPackets.pop(pack)) { + if(pack->Level1 == ToClient::L1::Content && ToClient::L2Content(pack->Level2) == ToClient::L2Content::ChunkVoxels) { + PP_Content_ChunkVoxels &p = *dynamic_cast(pack); + Pos::GlobalRegion rPos(p.Pos.X >> 4, p.Pos.Y >> 4, p.Pos.Z >> 4); + Pos::Local16_u cPos(p.Pos.X & 0xf, p.Pos.Y & 0xf, p.Pos.Z & 0xf); + External.Worlds[p.Id].Regions[rPos].Chunks[cPos].Voxels = std::move(p.Cubes); + + auto &pair = changeOrAddList_removeList[p.Id]; + std::get<0>(pair).insert(p.Pos); + } + + delete pack; + } + + if(RS && !changeOrAddList_removeList.empty()) { + for(auto &pair : changeOrAddList_removeList) { + RS->onChunksChange(pair.first, std::get<0>(pair.second), std::get<1>(pair.second)); + } + } + } + if(!RS) return; // Расчёт камеры { float deltaTime = 1-std::min(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA; - glm::quat quat = - glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(1.f, 0.f, 0.f)) - * glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, 1.f, 0.f)); - RS->setCameraPos(0, {0, 0, 0}, quat); + glm::quat quat = + glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(-1.f, 0.f, 0.f)) + * glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, -1.f, 0.f)); + + RS->setCameraPos(0, Pos, quat); } } @@ -387,6 +457,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey; std::vector cubes(co_await sock.read()); + uint16_t debugCubesCount = cubes.size(); for(size_t iter = 0; iter < cubes.size(); iter++) { VoxelCube &cube = cubes[iter]; @@ -409,7 +480,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { while(!NetInputPackets.push(packet)); - LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << cubes.size(); + LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << debugCubesCount; co_return; } diff --git a/Src/Client/ServerSession.hpp b/Src/Client/ServerSession.hpp index 2dcd856..1f797a8 100644 --- a/Src/Client/ServerSession.hpp +++ b/Src/Client/ServerSession.hpp @@ -1,6 +1,7 @@ #pragma once #include "Abstract.hpp" +#include "Common/Abstract.hpp" #include "Common/Async.hpp" #include "Common/Lockable.hpp" #include "Common/Net.hpp" @@ -31,10 +32,6 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface TOS::Logger LOG = "ServerSession"; - struct { - glm::quat Quat; - } Camera; - boost::lockfree::spsc_queue NetInputPackets; // PYR - поворот камеры по осям xyz в радианах, PYR_Offset для сглаживание поворота @@ -43,6 +40,17 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface static constexpr float PYR_TIME_DELTA = 30; GlobalTime GTime; + struct { + bool W = false, A = false, S = false, D = false, SHIFT = false, SPACE = false; + bool CTRL = false; + + void clear() + { + std::memset(this, 0, sizeof(*this)); + } + } Keys; + Pos::Object Pos = Pos::Object(0), Speed = Pos::Object(0); + public: // Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol) ServerSession(asio::io_context &ioc, std::unique_ptr &&socket, IRenderSession *rs = nullptr) diff --git a/Src/Client/Vulkan/Vulkan.cpp b/Src/Client/Vulkan/Vulkan.cpp index 735c2ba..061dc9c 100644 --- a/Src/Client/Vulkan/Vulkan.cpp +++ b/Src/Client/Vulkan/Vulkan.cpp @@ -140,7 +140,7 @@ void Vulkan::run() while(!NeedShutdown) { float dTime = glfwGetTime()-prevTime; - prevTime = glfwGetTime(); + prevTime += dTime; Screen.State = DrawState::Begin; { @@ -176,15 +176,15 @@ void Vulkan::run() // Спрятать или показать курсор { int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR); - if(mode == GLFW_CURSOR_HIDDEN && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden) + if(mode == GLFW_CURSOR_DISABLED && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden) glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); else if(mode == GLFW_CURSOR_NORMAL && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::Default) { - glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetCursorPos(Graphics.Window, Screen.Width/2., Screen.Height/2.); + Game.MLastPosX = Screen.Width/2.; + Game.MLastPosY = Screen.Height/2.; + glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } } - - } // if(CallBeforeDraw) @@ -197,7 +197,8 @@ void Vulkan::run() glfwPollEvents(); VkResult err; - err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, UINT64_MAX, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent); + err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, 1000000000ULL/20, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent); + GlobalTime gTime = glfwGetTime(); if (err == VK_ERROR_OUT_OF_DATE_KHR) { @@ -207,327 +208,325 @@ void Vulkan::run() } else if (err == VK_SUBOPTIMAL_KHR) { LOGGER.debug() << "VK_SUBOPTIMAL_KHR Pre"; + } else if(err == VK_SUCCESS) { + + Screen.State = DrawState::Drawing; + //Готовим инструкции рисовки + { + const VkCommandBufferBeginInfo cmd_buf_info = + { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .pNext = nullptr, + .flags = 0, + .pInheritanceInfo = nullptr + }; + + assert(!vkBeginCommandBuffer(Graphics.CommandBufferRender, &cmd_buf_info)); + } + + { + VkImageMemoryBarrier image_memory_barrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, // Graphics.InlineTexture.Image, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + + vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + } + + { + const VkClearValue clear_values[2] = + { + [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.f }}}, + [1] = { .depthStencil = { 1, 0 } }, + }; + + const VkRenderPassBeginInfo rp_begin = + { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .pNext = nullptr, + .renderPass = Graphics.RenderPass, + .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, //Graphics.InlineTexture.Frame, + .renderArea = VkRect2D { + .offset = {0, 0}, + .extent = Screen.FrameExtent + }, + .clearValueCount = 2, + .pClearValues = clear_values + }; + + vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); + } + + + { + VkViewport viewport = { 0.f, 0.f, float(Screen.Width), float(Screen.Height), 0.f, 1.f }; + vkCmdSetViewport(Graphics.CommandBufferRender, 0, 1, &viewport); + + VkRect2D scissor = { { int32_t(0), int32_t(0) }, { Screen.Width, Screen.Height } }; + vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor); + } + + if(Game.RSession) { + auto &robj = *Game.RSession; + // Рендер мира + + robj.drawWorld(gTime, dTime, Graphics.CommandBufferRender); + + uint16_t minSize = std::min(Screen.Width, Screen.Height); + glm::ivec2 interfaceSize = {int(Screen.Width*720/minSize), int(Screen.Height*720/minSize)}; + } + + // vkCmdEndRenderPass(Graphics.CommandBufferRender); + + // { + // VkImageMemoryBarrier src_barrier = + // { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .pNext = nullptr, + // .srcAccessMask = 0, + // .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .image = Graphics.InlineTexture.Image, + // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + // }; + + // VkImageMemoryBarrier dst_barrier = + // { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .pNext = nullptr, + // .srcAccessMask = 0, + // .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + // .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, + // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + // }; + + // vkCmdPipelineBarrier( + // Graphics.CommandBufferRender, + // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + // VK_PIPELINE_STAGE_TRANSFER_BIT, + // 0, + // 0, nullptr, + // 0, nullptr, + // 1, &src_barrier + // ); + + // vkCmdPipelineBarrier( + // Graphics.CommandBufferRender, + // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + // VK_PIPELINE_STAGE_TRANSFER_BIT, + // 0, + // 0, nullptr, + // 0, nullptr, + // 1, &dst_barrier + // ); + + // VkImageCopy copy_region = + // { + // .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + // .srcOffset = {0, 0, 0}, + // .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + // .dstOffset = {0, 0, 0}, + // .extent = {Screen.FrameExtent.width, Screen.FrameExtent.height, 1} + // }; + + // vkCmdCopyImage( + // Graphics.CommandBufferRender, + // Graphics.InlineTexture.Image, + // VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + // Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, + // VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + // 1, ©_region + // ); + + // VkImageMemoryBarrier post_copy_barrier = + // { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .pNext = nullptr, + // .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + // .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + // .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, + // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + // }; + + // vkCmdPipelineBarrier( + // Graphics.CommandBufferRender, + // VK_PIPELINE_STAGE_TRANSFER_BIT, + // VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // 0, + // 0, nullptr, + // 0, nullptr, + // 1, &post_copy_barrier + // ); + // } + + // { + // VkImageMemoryBarrier prePresentBarrier = + // { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .pNext = nullptr, + // .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .image = Graphics.InlineTexture.Image, + // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + // }; + + // vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + // 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier); + // } + + // { + // VkImageMemoryBarrier image_memory_barrier = + // { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .pNext = nullptr, + // .srcAccessMask = 0, + // .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + // .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, + // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + // }; + + // vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + // } + + // { + // const VkClearValue clear_values[2] = + // { + // [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.0f }}}, + // [1] = { .depthStencil = { 1, 0 } }, + // }; + + // const VkRenderPassBeginInfo rp_begin = + // { + // .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + // .pNext = nullptr, + // .renderPass = Graphics.RenderPass, + // .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, + // .renderArea = VkRect2D { + // .offset = {0, 0}, + // .extent = Screen.FrameExtent + // }, + // .clearValueCount = 2, + // .pClearValues = clear_values + // }; + + // vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); + // } + + + + #ifdef HAS_IMGUI + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + ImGui::SetNextWindowPos({0, 0}); + ImGui::SetNextWindowSize({(float) Screen.Width, (float) Screen.Height}); + + assert(Game.ImGuiInterfaces.size()); + (this->*Game.ImGuiInterfaces.back())(); + + ImGui::Render(); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender); + #endif + + vkCmdEndRenderPass(Graphics.CommandBufferRender); + + { + VkImageMemoryBarrier prePresentBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + + vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier); + } + + assert(!vkEndCommandBuffer(Graphics.CommandBufferRender)); + + { + VkFence nullFence = VK_NULL_HANDLE; + VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + VkSubmitInfo submit_info = + { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &SemaphoreImageAcquired, + .pWaitDstStageMask = &pipe_stage_flags, + .commandBufferCount = 1, + .pCommandBuffers = &Graphics.CommandBufferRender, + .signalSemaphoreCount = 1, + .pSignalSemaphores = &SemaphoreDrawComplete + }; + + //Рисуем, когда получим картинку + assert(!vkQueueSubmit(Graphics.DeviceQueueGraphic, 1, &submit_info, nullFence)); + } + + { + VkPresentInfoKHR present = + { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = NULL, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &SemaphoreDrawComplete, + .swapchainCount = 1, + .pSwapchains = &Graphics.Swapchain, + .pImageIndices = &Graphics.DrawBufferCurrent + }; + + // Завершаем картинку + err = vkQueuePresentKHR(Graphics.DeviceQueueGraphic, &present); + if (err == VK_ERROR_OUT_OF_DATE_KHR) + { + freeSwapchains(); + buildSwapchains(); + } else if (err == VK_SUBOPTIMAL_KHR) + LOGGER.debug() << "VK_SUBOPTIMAL_KHR Post"; + else + assert(!err); + } } else - assert(!err); - - - Screen.State = DrawState::Drawing; - //Готовим инструкции рисовки - { - const VkCommandBufferBeginInfo cmd_buf_info = - { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .pNext = nullptr, - .flags = 0, - .pInheritanceInfo = nullptr - }; - - assert(!vkBeginCommandBuffer(Graphics.CommandBufferRender, &cmd_buf_info)); - } - - { - VkImageMemoryBarrier image_memory_barrier = - { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, // Graphics.InlineTexture.Image, - .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }; - - vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); - } - - { - const VkClearValue clear_values[2] = - { - [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.f }}}, - [1] = { .depthStencil = { 1, 0 } }, - }; - - const VkRenderPassBeginInfo rp_begin = - { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = Graphics.RenderPass, - .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, //Graphics.InlineTexture.Frame, - .renderArea = VkRect2D { - .offset = {0, 0}, - .extent = Screen.FrameExtent - }, - .clearValueCount = 2, - .pClearValues = clear_values - }; - - vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); - } - - - { - VkViewport viewport = { 0.f, 0.f, float(Screen.Width), float(Screen.Height), 0.f, 1.f }; - vkCmdSetViewport(Graphics.CommandBufferRender, 0, 1, &viewport); - - VkRect2D scissor = { { int32_t(0), int32_t(0) }, { Screen.Width, Screen.Height } }; - vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor); - } - - GlobalTime gTime = glfwGetTime(); - - if(Game.RSession) { - auto &robj = *Game.RSession; - // Рендер мира - - robj.drawWorld(gTime, dTime, Graphics.CommandBufferRender); - - uint16_t minSize = std::min(Screen.Width, Screen.Height); - glm::ivec2 interfaceSize = {int(Screen.Width*720/minSize), int(Screen.Height*720/minSize)}; - } - - // vkCmdEndRenderPass(Graphics.CommandBufferRender); - - // { - // VkImageMemoryBarrier src_barrier = - // { - // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - // .pNext = nullptr, - // .srcAccessMask = 0, - // .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, - // .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - // .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .image = Graphics.InlineTexture.Image, - // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - // }; - - // VkImageMemoryBarrier dst_barrier = - // { - // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - // .pNext = nullptr, - // .srcAccessMask = 0, - // .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - // .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - // .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, - // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - // }; - - // vkCmdPipelineBarrier( - // Graphics.CommandBufferRender, - // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, - // VK_PIPELINE_STAGE_TRANSFER_BIT, - // 0, - // 0, nullptr, - // 0, nullptr, - // 1, &src_barrier - // ); - - // vkCmdPipelineBarrier( - // Graphics.CommandBufferRender, - // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, - // VK_PIPELINE_STAGE_TRANSFER_BIT, - // 0, - // 0, nullptr, - // 0, nullptr, - // 1, &dst_barrier - // ); - - // VkImageCopy copy_region = - // { - // .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - // .srcOffset = {0, 0, 0}, - // .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - // .dstOffset = {0, 0, 0}, - // .extent = {Screen.FrameExtent.width, Screen.FrameExtent.height, 1} - // }; - - // vkCmdCopyImage( - // Graphics.CommandBufferRender, - // Graphics.InlineTexture.Image, - // VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - // Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, - // VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - // 1, ©_region - // ); - - // VkImageMemoryBarrier post_copy_barrier = - // { - // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - // .pNext = nullptr, - // .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - // .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - // .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, - // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - // }; - - // vkCmdPipelineBarrier( - // Graphics.CommandBufferRender, - // VK_PIPELINE_STAGE_TRANSFER_BIT, - // VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // 0, - // 0, nullptr, - // 0, nullptr, - // 1, &post_copy_barrier - // ); - // } - - // { - // VkImageMemoryBarrier prePresentBarrier = - // { - // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - // .pNext = nullptr, - // .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - // .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - // .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .image = Graphics.InlineTexture.Image, - // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - // }; - - // vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - // 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier); - // } - - // { - // VkImageMemoryBarrier image_memory_barrier = - // { - // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - // .pNext = nullptr, - // .srcAccessMask = 0, - // .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - // .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - // .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - // .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, - // .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - // }; - - // vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); - // } - - // { - // const VkClearValue clear_values[2] = - // { - // [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.0f }}}, - // [1] = { .depthStencil = { 1, 0 } }, - // }; - - // const VkRenderPassBeginInfo rp_begin = - // { - // .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - // .pNext = nullptr, - // .renderPass = Graphics.RenderPass, - // .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, - // .renderArea = VkRect2D { - // .offset = {0, 0}, - // .extent = Screen.FrameExtent - // }, - // .clearValueCount = 2, - // .pClearValues = clear_values - // }; - - // vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); - // } - - - - #ifdef HAS_IMGUI - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - ImGui::SetNextWindowPos({0, 0}); - ImGui::SetNextWindowSize({(float) Screen.Width, (float) Screen.Height}); - - assert(Game.ImGuiInterfaces.size()); - (this->*Game.ImGuiInterfaces.back())(); - - ImGui::Render(); - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender); - #endif - - vkCmdEndRenderPass(Graphics.CommandBufferRender); - - { - VkImageMemoryBarrier prePresentBarrier = - { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, - .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }; - - vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier); - } - - assert(!vkEndCommandBuffer(Graphics.CommandBufferRender)); - - { - VkFence nullFence = VK_NULL_HANDLE; - VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - VkSubmitInfo submit_info = - { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = nullptr, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &SemaphoreImageAcquired, - .pWaitDstStageMask = &pipe_stage_flags, - .commandBufferCount = 1, - .pCommandBuffers = &Graphics.CommandBufferRender, - .signalSemaphoreCount = 1, - .pSignalSemaphores = &SemaphoreDrawComplete - }; - - //Рисуем, когда получим картинку - assert(!vkQueueSubmit(Graphics.DeviceQueueGraphic, 1, &submit_info, nullFence)); - } - - { - VkPresentInfoKHR present = - { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .pNext = NULL, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &SemaphoreDrawComplete, - .swapchainCount = 1, - .pSwapchains = &Graphics.Swapchain, - .pImageIndices = &Graphics.DrawBufferCurrent - }; - - // Завершаем картинку - err = vkQueuePresentKHR(Graphics.DeviceQueueGraphic, &present); - if (err == VK_ERROR_OUT_OF_DATE_KHR) - { - freeSwapchains(); - buildSwapchains(); - } else if (err == VK_SUBOPTIMAL_KHR) - LOGGER.debug() << "VK_SUBOPTIMAL_KHR Post"; - else - assert(!err); - } + assert(err == VK_TIMEOUT); if(Game.Session) { Game.Session->atFreeDrawTime(gTime, dTime); @@ -996,8 +995,15 @@ void Vulkan::glfwCallbackOnResize(GLFWwindow *window, int width, int height) handler->freeSwapchains(); handler->buildSwapchains(); - if(handler->Game.Session) + if(handler->Game.Session) { handler->Game.Session->onResize(width, height); + + if(handler->Game.Session->CursorMode == ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden) { + glfwSetCursorPos(window, width/2., height/2.); + handler->Game.MLastPosX = width/2.; + handler->Game.MLastPosY = height/2.; + } + } } } @@ -1018,8 +1024,9 @@ void Vulkan::glfwCallbackOnCursorPos(GLFWwindow* window, double xpos, double ypo if(sobj.CursorMode == ISurfaceEventListener::EnumCursorMoveMode::Default) { sobj.onCursorPosChange((int32_t) xpos, (int32_t) ypos); } else { - glfwSetCursorPos(handler->Graphics.Window, handler->Screen.Width/2., handler->Screen.Height/2.); - sobj.onCursorMove(xpos-handler->Screen.Width/2., handler->Screen.Height/2.-ypos); + sobj.onCursorMove(xpos-handler->Game.MLastPosX, handler->Game.MLastPosY-ypos); + handler->Game.MLastPosX = xpos; + handler->Game.MLastPosY = ypos; } } } diff --git a/Src/Client/Vulkan/Vulkan.hpp b/Src/Client/Vulkan/Vulkan.hpp index 2a1314d..2981249 100644 --- a/Src/Client/Vulkan/Vulkan.hpp +++ b/Src/Client/Vulkan/Vulkan.hpp @@ -16,9 +16,7 @@ #define HAS_IMGUI -#define GLM_FORCE_DEPTH_ZERO_TO_ONE - -#include +#include "freetype/freetype.h" #include #include @@ -28,6 +26,8 @@ #define GLFW_INCLUDE_NONE #include +static_assert(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO); + #define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE namespace LV::Client::VK { @@ -245,6 +245,8 @@ public: std::list ImGuiInterfaces; std::unique_ptr Server; + + double MLastPosX, MLastPosY; } Game; private: diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index b17baef..64e4d44 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -1,8 +1,10 @@ #include "VulkanRenderSession.hpp" #include "Client/Vulkan/Vulkan.hpp" +#include "Common/Abstract.hpp" #include "assets.hpp" -#include +#include #include +#include namespace LV::Client::VK { @@ -92,7 +94,7 @@ void VulkanRenderSession::init(Vulkan *instance) { .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, .pImmutableSamplers = nullptr } }; @@ -136,7 +138,7 @@ void VulkanRenderSession::init(Vulkan *instance) { .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, .pImmutableSamplers = nullptr } }; @@ -188,13 +190,28 @@ void VulkanRenderSession::init(Vulkan *instance) { return true; }); + int width, height; + bool hasAlpha; + ByteBuffer image = VK::loadPNG(std::ifstream("/home/mr_s/Workspace/Alpha/LuaVox/assets/grass.png"), width, height, hasAlpha); + uint16_t texId = VKCTX->MainTest.atlasAddTexture(width, height); + VKCTX->MainTest.atlasChangeTextureData(texId, (const uint32_t*) image.data()); + + /* + x left -1 ~ right 1 + y up -1 ~ down 1 + z far 1 ~ near 0 + + glm + + */ + NodeVertexStatic *array = (NodeVertexStatic*) VKCTX->TestQuad.mapMemory(); - array[0] = {112, 114, 113, 0, 0, 0, 0, 0, 0}; - array[1] = {114, 114, 113, 0, 0, 0, 0, 65535, 0}; - array[2] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535}; - array[3] = {112, 114, 113, 0, 0, 0, 0, 0, 0}; - array[4] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535}; - array[5] = {112, 112, 113, 0, 0, 0, 0, 0, 65535}; + array[0] = {112, 114, 50, 0, 0, 0, 0, 0, 0}; + array[1] = {114, 114, 50, 0, 0, 0, 0, 65535, 0}; + array[2] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535}; + array[3] = {112, 114, 50, 0, 0, 0, 0, 0, 0}; + array[4] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535}; + array[5] = {112, 112, 50, 0, 0, 0, 0, 0, 65535}; VKCTX->TestQuad.unMapMemory(); } @@ -576,8 +593,32 @@ void VulkanRenderSession::onDefEntityUpdates(const std::vector &u } -void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::vector &changeOrAddList, const std::vector &remove) { +void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::unordered_set &changeOrAddList, const std::unordered_set &remove) { + for(Pos::GlobalChunk pos : changeOrAddList) { + Pos::GlobalRegion rPos(pos.X >> 4, pos.Y >> 4, pos.Z >> 4); + Pos::Local16_u cPos(pos.X & 0xf, pos.Y & 0xf, pos.Z & 0xf); + const auto &voxels = ServerSession->External.Worlds[worldId].Regions[rPos].Chunks[cPos].Voxels; + auto &table = External.ChunkVoxelMesh[worldId]; + + if(voxels.empty()) { + auto iter = table.find(pos); + if(iter != table.end()) + table.erase(iter); + + if(table.empty()) + External.ChunkVoxelMesh.erase(External.ChunkVoxelMesh.find(worldId)); + } else { + auto &buffer = table[pos] = std::make_unique(VkInst, voxels.size()*6*6*sizeof(NodeVertexStatic)); + NodeVertexStatic *vertex = (NodeVertexStatic*) buffer->mapMemory(); + + for(const VoxelCube &cube : voxels) { + + } + + buffer->unMapMemory(); + } + } } void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) { @@ -587,14 +628,19 @@ void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm:: } void VulkanRenderSession::beforeDraw() { - + if(VKCTX) { + VKCTX->MainTest.atlasUpdateDynamicData(); + VKCTX->LightDummy.atlasUpdateDynamicData(); + } } void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) { glm::mat4 proj = glm::perspective(75, float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17)); - PCO.ProjView = glm::mat4(Quat); - //PCO.ProjView *= proj; - PCO.Model = glm::mat4(1); //= glm::rotate(glm::mat4(1), float(gTime/10), glm::vec3(0, 1, 0)); + // Сместить в координаты игрока, повернуть относительно взгляда, ещё поворот на 180 и проецировать на экран + PCO.ProjView = glm::mat4(1); + PCO.ProjView = glm::translate(PCO.ProjView, -glm::vec3(Pos)/float(Pos::Object_t::BS)); + PCO.ProjView = proj*glm::mat4(Quat)*glm::rotate(glm::mat4(1), glm::pi(), glm::vec3(0, 1, 0))*PCO.ProjView; + PCO.Model = glm::mat4(1); vkCmdBindPipeline(drawCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, NodeStaticOpaquePipeline); vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout, @@ -606,7 +652,14 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff VkDeviceSize vkOffsets = 0; VkBuffer vkBuffer = VKCTX->TestQuad; vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets); - vkCmdDraw(drawCmd, 6, 1, 0, 0); + + for(int i = 0; i < 16; i++) { + PCO.Model = glm::rotate(PCO.Model, glm::half_pi()*i/4, glm::vec3(0, 1, 0)); + vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0, sizeof(WorldPCO), &PCO); + vkCmdDraw(drawCmd, 6, 1, 0, 0); + } + } void VulkanRenderSession::updateDescriptor_MainAtlas() { diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index c256fa6..ff379e0 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -1,10 +1,13 @@ #pragma once + #include "Client/Abstract.hpp" #include "Common/Abstract.hpp" #include -#include +#include +#include #include + /* У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур Это общий для всех VkDescriptorSetLayout и VkDescriptorSet @@ -127,6 +130,10 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { std::map ServerToAtlas; + struct { + std::unordered_map>> ChunkVoxelMesh; + } External; + virtual void free(Vulkan *instance) override; virtual void init(Vulkan *instance) override; @@ -153,7 +160,7 @@ public: virtual void onDefPortalUpdates(const std::vector &updates) override; virtual void onDefEntityUpdates(const std::vector &updates) override; - virtual void onChunksChange(WorldId_c worldId, const std::vector &changeOrAddList, const std::vector &remove) override; + virtual void onChunksChange(WorldId_c worldId, const std::unordered_set &changeOrAddList, const std::unordered_set &remove) override; virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override; glm::mat4 calcViewMatrix(glm::quat quat, glm::vec3 camOffset = glm::vec3(0)) { diff --git a/Src/Server/GameServer.cpp b/Src/Server/GameServer.cpp index 8d897f4..dd7c281 100644 --- a/Src/Server/GameServer.cpp +++ b/Src/Server/GameServer.cpp @@ -8,10 +8,12 @@ #include #include #include +#include #include #include #include #include "SaveBackends/Filesystem.hpp" +#include "Server/SaveBackend.hpp" namespace LV::Server { @@ -27,9 +29,10 @@ static thread_local std::vector TL_Circles; std::vector GameServer::WorldObj::calcCVCs(ContentViewCircle circle, int depth) { - TL_Circles.reserve(4096); + TL_Circles.clear(); + TL_Circles.reserve(256); TL_Circles.push_back(circle); - _calcContentViewCircles(TL_Circles.front(), depth); + _calcContentViewCircles(circle, depth); return TL_Circles; } @@ -215,6 +218,42 @@ coro<> GameServer::pushSocketGameProtocol(tcp::socket socket, const std::string } } +Region* GameServer::forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos) { + auto worldIter = Expanse.Worlds.find(worldId); + assert(worldIter != Expanse.Worlds.end()); + World &world = *worldIter->second; + + auto iterRegion = world.Regions.find(pos); + if(iterRegion == world.Regions.end() || !iterRegion->second->IsLoaded) { + std::unique_ptr ®ion = world.Regions[pos]; + + if(!region) + region = std::make_unique(); + + std::string worldName = "world_"+std::to_string(worldId); + if(SaveBackend.World->isExist(worldName, pos)) { + SB_Region data; + SaveBackend.World->load(worldName, pos, &data); + + region->IsLoaded = true; + region->load(&data); + } else { + region->IsLoaded = true; + if(pos.Y == 0) { + for(int z = 0; z < 16; z++) + for(int x = 0; x < 16; x++) { + region->Voxels[x][0][z].push_back({{0, 0, 0}, {255, 255, 255}, 0}); + } + } + } + + std::fill(region->IsChunkChanged_Voxels, region->IsChunkChanged_Voxels+64, ~0); + return region.get(); + } else { + return iterRegion->second.get(); + } +} + void GameServer::init(fs::path worldPath) { Expanse.Worlds[0] = std::make_unique(0); @@ -302,16 +341,16 @@ void GameServer::run() { // Сон или подгонка длительности такта при высоких нагрузках std::chrono::steady_clock::time_point atTickEnd = std::chrono::steady_clock::now(); float currentWastedTime = double((atTickEnd-atTickStart).count() * std::chrono::steady_clock::duration::period::num) / std::chrono::steady_clock::duration::period::den; - float freeTime = CurrentTickDuration-currentWastedTime-GlobalTickLagTime; + GlobalTickLagTime += CurrentTickDuration-currentWastedTime; - if(freeTime > 0) { + if(GlobalTickLagTime > 0) { CurrentTickDuration -= PerTickAdjustment; if(CurrentTickDuration < PerTickDuration) CurrentTickDuration = PerTickDuration; - std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*freeTime))); + std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*GlobalTickLagTime))); + GlobalTickLagTime = 0; } else { - GlobalTickLagTime = freeTime; CurrentTickDuration += PerTickAdjustment; } } @@ -558,7 +597,7 @@ void GameServer::stepWorlds() { if(rPos != pRegion.first || pWorld.first != entity.WorldId) { - Region *toRegion = Expanse.Worlds[entity.WorldId]->forceLoadOrGetRegion(rPos); + Region *toRegion = forceGetRegion(entity.WorldId, rPos); LocalEntityId_t newId = toRegion->pushEntity(entity); // toRegion->Entityes[newId].WorldId = Если мир изменился @@ -808,6 +847,11 @@ void GameServer::stepWorlds() { if(needToUnload) { regionsToRemove.push_back(pRegion.first); } + + // Сброс информации об изменившихся данных + + std::fill(region.IsChunkChanged_Voxels, region.IsChunkChanged_Voxels+64, 0); + std::fill(region.IsChunkChanged_Nodes, region.IsChunkChanged_Nodes+64, 0); } for(Pos::GlobalRegion regionPos : regionsToRemove) { @@ -962,7 +1006,13 @@ void GameServer::stepSendPlayersPackets() { } void GameServer::stepLoadRegions() { + for(auto &iterWorld : Expanse.Worlds) { + for(Pos::GlobalRegion pos : iterWorld.second->NeedToLoad) { + forceGetRegion(iterWorld.first, pos); + } + iterWorld.second->NeedToLoad.clear(); + } } void GameServer::stepGlobal() { diff --git a/Src/Server/GameServer.hpp b/Src/Server/GameServer.hpp index 35f012c..f26ffa7 100644 --- a/Src/Server/GameServer.hpp +++ b/Src/Server/GameServer.hpp @@ -134,6 +134,9 @@ public: // Инициализация игрового протокола для сокета (onSocketAuthorized() может передать сокет в onSocketGame()) coro<> pushSocketGameProtocol(tcp::socket socket, const std::string username); + /* Загрузит, сгенерирует или просто выдаст регион из мира, который должен существовать */ + Region* forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos); + private: void init(fs::path worldPath); void prerun(); diff --git a/Src/Server/SaveBackend.hpp b/Src/Server/SaveBackend.hpp index cbe4e96..b110d6d 100644 --- a/Src/Server/SaveBackend.hpp +++ b/Src/Server/SaveBackend.hpp @@ -16,6 +16,7 @@ struct SB_Region { std::unordered_map Nodes; std::unordered_map NodeMap; std::vector Entityes; + std::unordered_map EntityMap; }; class IWorldSaveBackend { diff --git a/Src/Server/World.cpp b/Src/Server/World.cpp index 7775415..a0c965a 100644 --- a/Src/Server/World.cpp +++ b/Src/Server/World.cpp @@ -46,17 +46,4 @@ void World::onCEC_RegionsLost(ContentEventController *cec, const std::vector ®ion = Regions[pos]; - if(!region) - region = std::make_unique(); - - if(!region->IsLoaded) { - region->IsLoaded = true; - } - - return region.get(); -} - - } \ No newline at end of file diff --git a/Src/Server/World.hpp b/Src/Server/World.hpp index 2043021..979fe90 100644 --- a/Src/Server/World.hpp +++ b/Src/Server/World.hpp @@ -3,8 +3,10 @@ #include "Common/Abstract.hpp" #include "Server/Abstract.hpp" #include "Server/ContentEventController.hpp" +#include "Server/SaveBackend.hpp" #include #include +#include namespace LV::Server { @@ -15,7 +17,7 @@ class Region { public: uint64_t IsChunkChanged_Voxels[64] = {0}; uint64_t IsChunkChanged_Nodes[64] = {0}; - bool IsChanged = false; + bool IsChanged = false; // Изменён ли был регион, относительно последнего сохранения // cx cy cz std::vector Voxels[16][16][16]; // x y cx cy cz @@ -132,6 +134,15 @@ public: return LocalEntityId_t(-1); } + + void load(SB_Region *data) { + convertRegionVoxelsToChunks(data->Voxels, (std::vector*) Voxels); + } + + void save(SB_Region *data) { + data->Voxels.clear(); + convertChunkVoxelsToRegion((const std::vector*) Voxels, data->Voxels); + } }; class World { @@ -154,8 +165,6 @@ public: void onCEC_RegionsEnter(ContentEventController *cec, const std::vector &enter); void onCEC_RegionsLost(ContentEventController *cec, const std::vector &lost); - Region* forceLoadOrGetRegion(Pos::GlobalRegion pos); - DefWorldId_t getDefId() const { return DefId; } }; diff --git a/assets/grass.png b/assets/grass.png new file mode 100644 index 0000000000000000000000000000000000000000..3ec069ce303798e6c58657e59686b681b19d768c GIT binary patch literal 10253 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 T2w=;e00000NkvXXu0mjfFoh(3 literal 0 HcmV?d00001 diff --git a/assets/shaders/chunk/node_opaque.frag b/assets/shaders/chunk/node_opaque.frag index 174bcc7..fe26e51 100644 --- a/assets/shaders/chunk/node_opaque.frag +++ b/assets/shaders/chunk/node_opaque.frag @@ -8,16 +8,67 @@ layout(location = 0) in FragmentObj { layout(location = 0) out vec4 Frame; -uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas; +struct InfoSubTexture { + uint Flags; // 1 isExist + uint PosXY, WidthHeight; + + uint AnimationFrames_AnimationTimePerFrame; +}; + +uniform layout(set = 0, binding = 0) sampler2D MainAtlas; layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj { - vec3 Color; + uint SubsCount; + uint Counter; + uint WidthHeight; + + InfoSubTexture SubTextures[]; } MainAtlasLayout; -uniform layout(set = 1, binding = 0) sampler2DArray LightMap; +uniform layout(set = 1, binding = 0) sampler2D LightMap; layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj { vec3 Color; } LightMapLayout; +vec4 atlasColor(uint texId, vec2 uv) +{ + uint flags = (texId & 0xffff0000) >> 16; + texId &= 0xffff; + vec4 color = vec4(uv, 0, 1); + + if((flags & (2 | 4)) > 0) + { + if((flags & 2) > 0) + color = vec4(1, 1, 1, 1); + else if((flags & 4) > 0) + { + color = vec4(1); + } + + } + else if(texId >= uint(MainAtlasLayout.SubsCount)) + return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(0, 1, 1), 1); + else { + InfoSubTexture texInfo = MainAtlasLayout.SubTextures[texId]; + if(texInfo.Flags == 0) + return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(1, 0, 1), 1); + + uint posX = texInfo.PosXY & 0xffff; + uint posY = (texInfo.PosXY >> 16) & 0xffff; + uint width = texInfo.WidthHeight & 0xffff; + uint height = (texInfo.WidthHeight >> 16) & 0xffff; + uint awidth = MainAtlasLayout.WidthHeight & 0xffff; + uint aheight = (MainAtlasLayout.WidthHeight >> 16) & 0xffff; + + if((flags & 1) > 0) + color = texture(MainAtlas, vec2((posX+0.5f+uv.x*(width-1))/awidth, (posY+0.5f+(1-uv.y)*(height-1))/aheight)); + else + color = texture(MainAtlas, vec2((posX+uv.x*width)/awidth, (posY+(1-uv.y)*height)/aheight)); + } + + + return color; +} + void main() { - Frame = vec4(1); + Frame = atlasColor(Fragment.Texture, Fragment.UV); } \ No newline at end of file diff --git a/assets/shaders/chunk/node_opaque.frag.bin b/assets/shaders/chunk/node_opaque.frag.bin index 6bc20349bf49ebb2bc6b51e63c68c58884199e8d..603f8c37568ada6867093e9ea5ff60f78884fd87 100644 GIT binary patch literal 6224 zcmb7{d6<=T702IML2*!05L0mwQ&S=_+#&@cnW2Ve3=nJ^FEf|n+RWT(<_>~wf=L!7 zR#dbvrsb0D`({+yzVCa_Q-Em`Mmc%@SAJ@^zxkNe9!ls-}#;2IluS4Lre35 zX<1uSHY4lE{+89BSy^+|1e}qz=enzBZO@{K+Tfxk=bdB3%&a93H0J2+sH_#OjFc*) zI+h{b$Sue(kpsw|kq3}tSZnMwq=kRY==~&W&5q2vdiuM1d%Jor?H?E$>z}A?A1?O~ zS4PYIgO%~}K&`U1Y~1uDt};3>JUN&Kv=Nck(#B3lvqz~mT$)%}9j=a_Ik|Z0*3IWG z%`#&<@YTxORu7`vsAnd6a%TCe0>BwUe9HmABO< z$EmNKEb>09inYPnufFQU#w*b6{4>t;Z>S8`wse;(LtARF9XW4@SBzFhO0`OLbk%ri zq&(4o$X-_&DfgAfbDB8Mcrkhn{a@iZdrI4@leOMWSJn5?=R=*eU~;quwkCON%DM7* zUX$E|YiiG9t?BStC&&30gqF&|WJ@2cC5E4O!}uXa|2y$8LeKDOMy7rRshm~WqU z5zt12@57;9fsOI~I6TL;?7q4^G*TYT2k4ySe7ee2T2Y^!oV|&Q*G?`ud$ay>bGPO1 zodYlzbiUvH=&=&_sjz=H#cs>r(;jc)n$j39)=bO(f(|aZTKOH)=aau$XzzsY`P6v7 z2Z!H_1uozT&U485-UjD6_%s~8ZX?t&s_X#_V z_YTd=z4}`Y-2-C}O!2km^G$R4T{c&}mX>_hp3nZoY~x&EI~O1Ka@KJ!vAOHHT616I zK9-wl-ubMtH{#js;ru!gpH6Il7Zmw9L^}UYIi&%FBGFM1#LDR5bK?Xp;Z z8kYNpeY$R*<2cC~=-?NEJ=;QdF#lr2T&YCt5_r!!kIep#m_L=1>7DO~K4W|zQolZX zcnR7*>0esd%L>lD?8kD%$M_X!FKu*Y(=n1*d;?f$fv|)IA8#$~a3ehB;!t z^;$w~ffN4V;>$&bn)Y`tA{tjucAj-OagIKFQznBG|yUW`D@wByz3Bi%kM6@%L{%zx?0q@0W5zbF&oiOMy^2Q zCDHlvgLA#{`eWwu_RwC&e69mKpPfj| z=lNjy_(on2mYa(>;~i+Z$ngSjV~!i(2bPN-y&gOZi8|f@mh+nyzXxvw%f~zS zX0VU%oW3_9_aNREvAJ(X--_H)*zM@IA>M~E{L|5IKg89)xwjYGZD`MZ2l`HACgR@a zb=^A<`8dN}U}w3LHSY6HM9wqBUhgXS>xnVPyAkuq?| ze?QoD^0DRv;9W?p`5;&>_W2N4E^k{a^G$GiAHIbx7xjM|+&KI1z{$t# zzYBKu@{#v@U}qm^`aW1L&h!JY>*V81KLoqKzR2?+;_G961T`ZxFHnXZkNOD~RX- literal 1264 zcmZ9LO>fgc5QaCg-IRuYQQA@pQA&@XiUS}dBoIR29$W>9kE>-8t2J`sC~*+I@!R-S zT#$I5bv9kG(PVaJ-g#$db{(`&J0@zGuGusXO|y1Q+qAUpnl-EA0lE`9gDeTbG%rc_SDU?G8{2X3i51=x`*NEa2imX6*OwgX?7VAi-e6z< z>(YEF_+Kq;-Xp%pvcYahjQREEiBRCW5`4bEeOo^89uA zju_|Jk#0$daUN{$7T=M+lsnRJV6*<$$Ev<3KREdA0@A_