diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b1d21d..b0afd13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,11 +31,11 @@ project(LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description") add_library(luavox_common INTERFACE) target_compile_features(luavox_common INTERFACE cxx_std_23) -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - target_compile_options(luavox_common INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all) - target_link_options(luavox_common INTERFACE -fsanitize=address,undefined) - set(ENV{ASAN_OPTIONS} detect_leaks=0) -endif() +# if(CMAKE_BUILD_TYPE STREQUAL "Debug") +# target_compile_options(luavox_common INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all) +# target_link_options(luavox_common INTERFACE -fsanitize=address,undefined) +# set(ENV{ASAN_OPTIONS} detect_leaks=0) +# endif() if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") target_compile_options(luavox_common INTERFACE -fcoroutines) diff --git a/Src/Client/Vulkan/Vulkan.cpp b/Src/Client/Vulkan/Vulkan.cpp index a491183..85aaa85 100644 --- a/Src/Client/Vulkan/Vulkan.cpp +++ b/Src/Client/Vulkan/Vulkan.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -158,17 +159,35 @@ void Vulkan::run() NeedShutdown = false; Graphics.ThisThread = std::this_thread::get_id(); - VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0 }; - VkSemaphore SemaphoreImageAcquired, SemaphoreDrawComplete; + VkSemaphoreCreateInfo semaphoreCreateInfo = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + nullptr, + 0 + }; - vkAssert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, NULL, &SemaphoreImageAcquired)); - vkAssert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, NULL, &SemaphoreDrawComplete)); + VkSemaphore SemaphoreImageAcquired[4], SemaphoreDrawComplete[4]; + int semNext = 0; + for(int iter = 0; iter < 4; iter++) { + vkAssert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, nullptr, &SemaphoreImageAcquired[iter])); + vkAssert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, nullptr, &SemaphoreDrawComplete[iter])); + } + + VkFence drawEndFence = VK_NULL_HANDLE; + + { + VkFenceCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .pNext = nullptr, + .flags = 0 + }; + + vkCreateFence(Graphics.Device, &info, nullptr, &drawEndFence); + } double prevTime = glfwGetTime(); while(!NeedShutdown) { - float dTime = glfwGetTime()-prevTime; prevTime += dTime; @@ -230,7 +249,8 @@ void Vulkan::run() glfwPollEvents(); VkResult err; - err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, 1000000000ULL/20, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent); + semNext = ++semNext % 4; + err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, 1000000000ULL/20, SemaphoreImageAcquired[semNext], (VkFence) 0, &Graphics.DrawBufferCurrent); GlobalTime gTime = glfwGetTime(); if (err == VK_ERROR_OUT_OF_DATE_KHR) @@ -529,19 +549,25 @@ void Vulkan::run() .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 1, - .pWaitSemaphores = &SemaphoreImageAcquired, + .pWaitSemaphores = &SemaphoreImageAcquired[semNext], .pWaitDstStageMask = &pipe_stage_flags, .commandBufferCount = 1, .pCommandBuffers = &Graphics.CommandBufferRender, .signalSemaphoreCount = 1, - .pSignalSemaphores = &SemaphoreDrawComplete + .pSignalSemaphores = &SemaphoreDrawComplete[semNext] }; - //Рисуем, когда получим картинку + // Отправляем команды рендера в очередь { auto lockQueue = Graphics.DeviceQueueGraphic.lock(); - vkAssert(!vkQueueSubmit(*lockQueue, 1, &submit_info, nullFence)); + vkAssert(!vkQueueSubmit(*lockQueue, 1, &submit_info, drawEndFence)); } + + // auto now = std::chrono::high_resolution_clock::now(); + // Насильно ожидаем завершения рендера кадра + vkWaitForFences(Graphics.Device, 1, &drawEndFence, true, -1); + vkResetFences(Graphics.Device, 1, &drawEndFence); + // LOG.debug() << (std::chrono::high_resolution_clock::now()-now).count(); } { @@ -550,13 +576,13 @@ void Vulkan::run() .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = NULL, .waitSemaphoreCount = 1, - .pWaitSemaphores = &SemaphoreDrawComplete, + .pWaitSemaphores = &SemaphoreDrawComplete[semNext], .swapchainCount = 1, .pSwapchains = &Graphics.Swapchain, .pImageIndices = &Graphics.DrawBufferCurrent }; - // Завершаем картинку + // Передадим фрейм, когда рендер будет завершён { auto lockQueue = Graphics.DeviceQueueGraphic.lock(); err = vkQueuePresentKHR(*lockQueue, &present); @@ -580,20 +606,21 @@ void Vulkan::run() Game.Session->atFreeDrawTime(gTime, dTime); } - - // vkAssert(!vkQueueWaitIdle(Graphics.DeviceQueueGraphic)); - - { - // Эту хрень надо убрать - auto lockQueue = Graphics.DeviceQueueGraphic.lock(); - vkDeviceWaitIdle(Graphics.Device); - lockQueue.unlock(); - } Screen.State = DrawState::End; } - vkDestroySemaphore(Graphics.Device, SemaphoreImageAcquired, nullptr); - vkDestroySemaphore(Graphics.Device, SemaphoreDrawComplete, nullptr); + { + auto lockQueue = Graphics.DeviceQueueGraphic.lock(); + vkDeviceWaitIdle(Graphics.Device); + lockQueue.unlock(); + } + + for(int iter = 0; iter < 4; iter++) { + vkDestroySemaphore(Graphics.Device, SemaphoreImageAcquired[iter], nullptr); + vkDestroySemaphore(Graphics.Device, SemaphoreDrawComplete[iter], nullptr); + } + + vkDestroyFence(Graphics.Device, drawEndFence, nullptr); } void Vulkan::glfwCallbackError(int error, const char *description) @@ -777,8 +804,8 @@ void Vulkan::buildSwapchains() .imageColorSpace = Graphics.SurfaceColorSpace, .imageExtent = swapchainExtent, .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + // | VK_IMAGE_USAGE_TRANSFER_DST_BIT, .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index 1419b9f..f253dfc 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -816,7 +816,7 @@ void VulkanRenderSession::init(Vulkan *instance) { .flags = 0, .depthTestEnable = true, .depthWriteEnable = true, - .depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL, + .depthCompareOp = VK_COMPARE_OP_LESS, .depthBoundsTestEnable = false, .stencilTestEnable = false, .front = VkStencilOpState @@ -1209,7 +1209,7 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff Pos::GlobalChunk x64offset = X64Offset >> Pos::Object_t::BS_Bit >> 4; Pos::GlobalRegion x64offset_region = x64offset >> 2; - auto [voxelVertexs, nodeVertexs] = VKCTX->ThreadVertexObj.getChunksForRender(WorldId, Pos, 1, PCO.ProjView, x64offset_region); + auto [voxelVertexs, nodeVertexs] = VKCTX->ThreadVertexObj.getChunksForRender(WorldId, Pos, 2, PCO.ProjView, x64offset_region); size_t count = 0; @@ -1233,8 +1233,8 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff vkCmdDraw(drawCmd, vertexCount, 1, offset, 0); } - TOS::Logger LOG = "VRS"; - LOG.debug() << "Node: drawCals: " << nodeVertexs.size() << " vertexs: " << count; + // TOS::Logger LOG = "VRS"; + // LOG.debug() << "Node: drawCals: " << nodeVertexs.size() << " vertexs: " << count; PCO.Model = orig; diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index da2dfa5..e4e083b 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -3,6 +3,7 @@ #include "Client/Abstract.hpp" #include "Common/Abstract.hpp" #include +#include #include #include #include @@ -15,6 +16,7 @@ #include "VertexPool.hpp" #include "glm/fwd.hpp" #include "../FrustumCull.h" +#include "glm/geometric.hpp" /* У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур @@ -184,10 +186,11 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { std::vector, uint32_t>>, std::vector, uint32_t>> > getChunksForRender(WorldId_t worldId, Pos::Object pos, uint8_t distance, glm::mat4 projView, Pos::GlobalRegion x64offset) { - Pos::GlobalRegion center = pos >> Pos::Object_t::BS_Bit >> 4 >> 2; + Pos::GlobalChunk playerChunk = pos >> Pos::Object_t::BS_Bit >> 4; + Pos::GlobalRegion center = playerChunk >> 2; - std::vector, uint32_t>> vertexVoxels; - std::vector, uint32_t>> vertexNodes; + std::vector, uint32_t>> vertexVoxels; + std::vector, uint32_t>> vertexNodes; auto iterWorld = ChunkMesh.find(worldId); if(iterWorld == ChunkMesh.end()) @@ -220,17 +223,50 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { continue; auto &chunk = iterRegion->second[index]; + + float distance; - if(chunk.VoxelPointer) - vertexVoxels.emplace_back(local+Pos::GlobalChunk(localPos), VertexPool_Voxels.map(chunk.VoxelPointer), chunk.VoxelPointer.VertexCount); - if(chunk.NodePointer) - vertexNodes.emplace_back(local+Pos::GlobalChunk(localPos), VertexPool_Nodes.map(chunk.NodePointer), chunk.NodePointer.VertexCount); + if(chunk.VoxelPointer || chunk.NodePointer) { + Pos::GlobalChunk cp = local+Pos::GlobalChunk(localPos)-playerChunk; + distance = cp.x*cp.x+cp.y*cp.y+cp.z*cp.z; + } + + if(chunk.VoxelPointer) { + vertexVoxels.emplace_back(distance, local+Pos::GlobalChunk(localPos), VertexPool_Voxels.map(chunk.VoxelPointer), chunk.VoxelPointer.VertexCount); + } + + if(chunk.NodePointer) { + vertexNodes.emplace_back(distance, local+Pos::GlobalChunk(localPos), VertexPool_Nodes.map(chunk.NodePointer), chunk.NodePointer.VertexCount); + } } } } } - return std::pair{vertexVoxels, vertexNodes}; + auto sortByDistance = [] + ( + const std::tuple, uint32_t>& a, + const std::tuple, uint32_t>& b + ) { + return std::get<0>(a) < std::get<0>(b); + }; + + std::sort(vertexVoxels.begin(), vertexVoxels.end(), sortByDistance); + std::sort(vertexNodes.begin(), vertexNodes.end(), sortByDistance); + + std::vector, uint32_t>> resVertexVoxels; + std::vector, uint32_t>> resVertexNodes; + + resVertexVoxels.reserve(vertexVoxels.size()); + resVertexNodes.reserve(vertexNodes.size()); + + for(const auto& [d, pos, ptr, count] : vertexVoxels) + resVertexVoxels.emplace_back(pos, ptr, count); + + for(const auto& [d, pos, ptr, count] : vertexNodes) + resVertexNodes.emplace_back(pos, ptr, count); + + return std::pair{resVertexVoxels, resVertexNodes}; } void join() { diff --git a/assets/shaders/chunk/node.geom b/assets/shaders/chunk/node.geom index fa2cb47..f9a3fff 100644 --- a/assets/shaders/chunk/node.geom +++ b/assets/shaders/chunk/node.geom @@ -1,4 +1,4 @@ -#version 450 +#version 460 layout (triangles) in; layout (triangle_strip, max_vertices = 3) out; diff --git a/assets/shaders/chunk/node.geom.bin b/assets/shaders/chunk/node.geom.bin index cc30b5c..5839b65 100644 Binary files a/assets/shaders/chunk/node.geom.bin and b/assets/shaders/chunk/node.geom.bin differ diff --git a/assets/shaders/chunk/node.vert b/assets/shaders/chunk/node.vert index 75383b8..d75b827 100644 --- a/assets/shaders/chunk/node.vert +++ b/assets/shaders/chunk/node.vert @@ -1,4 +1,4 @@ -#version 450 +#version 460 layout(location = 0) in uvec3 Vertex; diff --git a/assets/shaders/chunk/node.vert.bin b/assets/shaders/chunk/node.vert.bin index e89b91f..c255cd6 100644 Binary files a/assets/shaders/chunk/node.vert.bin and b/assets/shaders/chunk/node.vert.bin differ diff --git a/assets/shaders/chunk/node_opaque.frag b/assets/shaders/chunk/node_opaque.frag index 4465ed4..3300e4f 100644 --- a/assets/shaders/chunk/node_opaque.frag +++ b/assets/shaders/chunk/node_opaque.frag @@ -1,4 +1,6 @@ -#version 450 +#version 460 + +// layout(early_fragment_tests) in; layout(location = 0) in FragmentObj { vec3 GeoPos; // Реальная позиция в мире diff --git a/assets/shaders/chunk/node_opaque.frag.bin b/assets/shaders/chunk/node_opaque.frag.bin index bb2c2f5..780834d 100644 Binary files a/assets/shaders/chunk/node_opaque.frag.bin and b/assets/shaders/chunk/node_opaque.frag.bin differ diff --git a/assets/shaders/chunk/node_transparent.frag b/assets/shaders/chunk/node_transparent.frag index 5d241a3..81b14c2 100644 --- a/assets/shaders/chunk/node_transparent.frag +++ b/assets/shaders/chunk/node_transparent.frag @@ -1,4 +1,4 @@ -#version 450 +#version 460 layout(location = 0) in FragmentObj { vec3 GeoPos; // Реальная позиция в мире @@ -20,5 +20,5 @@ layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj { } LightMapLayout; void main() { - Frame = vec4(1); -} \ No newline at end of file + Frame = vec4(Fragment.GeoPos, 1); +} diff --git a/assets/shaders/chunk/node_transparent.frag.bin b/assets/shaders/chunk/node_transparent.frag.bin index 8a5b3c5..6c6c733 100644 Binary files a/assets/shaders/chunk/node_transparent.frag.bin and b/assets/shaders/chunk/node_transparent.frag.bin differ