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 0000000..3ec069c Binary files /dev/null and b/assets/grass.png differ 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 6bc2034..603f8c3 100644 Binary files a/assets/shaders/chunk/node_opaque.frag.bin and b/assets/shaders/chunk/node_opaque.frag.bin differ diff --git a/imgui.ini b/imgui.ini deleted file mode 100644 index cb4f8f5..0000000 --- a/imgui.ini +++ /dev/null @@ -1,8 +0,0 @@ -[Window][Debug##Default] -Pos=0,0 -Size=400,400 - -[Window][MainMenu] -Pos=0,0 -Size=960,540 -