Поправка порядка рендера чанков

This commit is contained in:
2025-08-27 22:54:47 +06:00
parent 388b59e9bf
commit bd1dec04f2
12 changed files with 113 additions and 48 deletions

View File

@@ -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)

View File

@@ -1,4 +1,5 @@
#include <boost/asio/io_context.hpp>
#include <chrono>
#include <filesystem>
#include <memory>
#include <mutex>
@@ -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,

View File

@@ -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;

View File

@@ -3,6 +3,7 @@
#include "Client/Abstract.hpp"
#include "Common/Abstract.hpp"
#include <Client/Vulkan/Vulkan.hpp>
#include <algorithm>
#include <memory>
#include <optional>
#include <queue>
@@ -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<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>>,
std::vector<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, 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<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>> vertexVoxels;
std::vector<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>> vertexNodes;
std::vector<std::tuple<float, Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>> vertexVoxels;
std::vector<std::tuple<float, Pos::GlobalChunk, std::pair<VkBuffer, int>, 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<float, Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>& a,
const std::tuple<float, Pos::GlobalChunk, std::pair<VkBuffer, int>, 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<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, uint32_t>> resVertexVoxels;
std::vector<std::tuple<Pos::GlobalChunk, std::pair<VkBuffer, int>, 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() {

View File

@@ -1,4 +1,4 @@
#version 450
#version 460
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

Binary file not shown.

View File

@@ -1,4 +1,4 @@
#version 450
#version 460
layout(location = 0) in uvec3 Vertex;

Binary file not shown.

View File

@@ -1,4 +1,6 @@
#version 450
#version 460
// layout(early_fragment_tests) in;
layout(location = 0) in FragmentObj {
vec3 GeoPos; // Реальная позиция в мире

View File

@@ -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);
}
Frame = vec4(Fragment.GeoPos, 1);
}