diff --git a/engine/3rdparty/zcoro/include/zcoro/co_context.h b/engine/3rdparty/zlib/include/zcoro/co_context.h similarity index 100% rename from engine/3rdparty/zcoro/include/zcoro/co_context.h rename to engine/3rdparty/zlib/include/zcoro/co_context.h diff --git a/engine/3rdparty/zcoro/include/zcoro/task.h b/engine/3rdparty/zlib/include/zcoro/task.h similarity index 100% rename from engine/3rdparty/zcoro/include/zcoro/task.h rename to engine/3rdparty/zlib/include/zcoro/task.h diff --git a/engine/3rdparty/zlib/include/zstd/pool.h b/engine/3rdparty/zlib/include/zstd/pool.h new file mode 100644 index 0000000..0ae8ba9 --- /dev/null +++ b/engine/3rdparty/zlib/include/zstd/pool.h @@ -0,0 +1,51 @@ +#include +namespace zstd { + template + class pool { + using NewFn = std::function; + protected: + int m_tail; + int m_head; + int m_size; + T* m_buf; + NewFn newT; + public: + ~pool() { + reset(); + free(m_buf); + } + pool(NewFn newT, int size = 1) : newT(newT), m_tail(0), m_head(0), m_buf((T*)malloc(sizeof(T)* size)), m_size(size) {} + int head() { + return m_head; + } + int tail() { + return m_tail; + } + int count() { + return m_head - m_tail; + } + void reset() { + for (int i = m_tail; i < m_head; i++) { + std::destroy_at(m_buf + (m_tail % m_size)); + } + m_tail = 0; + m_head = 0; + } + template + void release(Args... args) { + if (m_head >= m_tail + m_size) { + return; + } + std::construct_at(m_buf + m_head % m_size, std::forward(args)...); + m_head++; + }; + T acquire() { + if (m_tail == m_head) { + return std::move(newT()); + } + int tail = m_tail % m_size; + m_tail++; + return std::move(*(m_buf + tail)); + }; + }; +} \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/zstd/pool_static.h b/engine/3rdparty/zlib/include/zstd/pool_static.h new file mode 100644 index 0000000..6f77c86 --- /dev/null +++ b/engine/3rdparty/zlib/include/zstd/pool_static.h @@ -0,0 +1,58 @@ +#include +namespace zstd { + template + struct static_buffer { + char data[T]; + }; + template + class channel_static { + static_assert(T_capacity != 0); + protected: + int m_tail; + int m_head; + static_buffer m_buf[T_capacity]; + std::mutex m_mtx; + std::condition_variable m_cv; + public: + ~channel_static() { + reset(); + } + channel_static() : m_tail(0), m_head(0), m_buf() {} + int head() { + return m_head; + } + int tail() { + return m_tail; + } + int count() { + return m_head - m_tail; + } + void reset() { + for (int i = m_tail; i < m_head; i++) { + std::destroy_at((T*)(m_buf + m_tail % T_capacity)); + } + m_tail = 0; + m_head = 0; + } + template + void release(Args... args) { + std::unique_lock lck(m_mtx); + while (m_head >= m_tail + T_capacity) { + m_cv.wait(lck); + } + std::construct_at((T*)(m_buf + m_head % T_capacity), std::forward(args)...); + if (m_head++ == m_tail) + m_cv.notify_one(); + }; + T acquire() { + std::unique_lock lck(m_mtx); + while (m_tail >= m_head) { + m_cv.wait(lck); + } + int tail = m_tail % T_capacity; + if (m_tail++ == m_head - T_capacity) + m_cv.notify_one(); + return std::move(*(T*)(m_buf + tail)); + }; + }; +} \ No newline at end of file diff --git a/engine/3rdparty/zcoro/include/zthread/channel.h b/engine/3rdparty/zlib/include/zthread/channel.h similarity index 98% rename from engine/3rdparty/zcoro/include/zthread/channel.h rename to engine/3rdparty/zlib/include/zthread/channel.h index 17ccac6..5e681a6 100644 --- a/engine/3rdparty/zcoro/include/zthread/channel.h +++ b/engine/3rdparty/zlib/include/zthread/channel.h @@ -1,6 +1,6 @@ #include #include -#include +#include namespace zstd { template class channel { diff --git a/engine/3rdparty/zcoro/include/zthread/channel_static.h b/engine/3rdparty/zlib/include/zthread/channel_static.h similarity index 98% rename from engine/3rdparty/zcoro/include/zthread/channel_static.h rename to engine/3rdparty/zlib/include/zthread/channel_static.h index 3361991..4739ed1 100644 --- a/engine/3rdparty/zcoro/include/zthread/channel_static.h +++ b/engine/3rdparty/zlib/include/zthread/channel_static.h @@ -1,6 +1,6 @@ #include #include -#include +#include namespace zstd { template struct static_buffer { diff --git a/engine/3rdparty/zcoro/main.cpp b/engine/3rdparty/zlib/main.cpp similarity index 100% rename from engine/3rdparty/zcoro/main.cpp rename to engine/3rdparty/zlib/main.cpp diff --git a/engine/3rdparty/zcoro/src/zcoro/co_context.cpp b/engine/3rdparty/zlib/src/zcoro/co_context.cpp similarity index 100% rename from engine/3rdparty/zcoro/src/zcoro/co_context.cpp rename to engine/3rdparty/zlib/src/zcoro/co_context.cpp diff --git a/engine/3rdparty/zcoro/test/01mutex.cpp b/engine/3rdparty/zlib/test/01mutex.cpp similarity index 100% rename from engine/3rdparty/zcoro/test/01mutex.cpp rename to engine/3rdparty/zlib/test/01mutex.cpp diff --git a/engine/3rdparty/zcoro/test/02condition.cpp b/engine/3rdparty/zlib/test/02condition.cpp similarity index 100% rename from engine/3rdparty/zcoro/test/02condition.cpp rename to engine/3rdparty/zlib/test/02condition.cpp diff --git a/engine/3rdparty/zcoro/test/03semaphore.cpp b/engine/3rdparty/zlib/test/03semaphore.cpp similarity index 100% rename from engine/3rdparty/zcoro/test/03semaphore.cpp rename to engine/3rdparty/zlib/test/03semaphore.cpp diff --git a/engine/3rdparty/zcoro/test/04promise.cpp b/engine/3rdparty/zlib/test/04promise.cpp similarity index 100% rename from engine/3rdparty/zcoro/test/04promise.cpp rename to engine/3rdparty/zlib/test/04promise.cpp diff --git a/engine/3rdparty/zcoro/xmake.lua b/engine/3rdparty/zlib/xmake.lua similarity index 61% rename from engine/3rdparty/zcoro/xmake.lua rename to engine/3rdparty/zlib/xmake.lua index 368c033..88d0ace 100644 --- a/engine/3rdparty/zcoro/xmake.lua +++ b/engine/3rdparty/zlib/xmake.lua @@ -1,29 +1,29 @@ set_languages("cxx20") -target("zcoro") +target("zlib") set_kind("static") add_includedirs("include", {public = true}) add_files("src/**/*.cpp") add_headerfiles("include/**/*.h") -target("zcoro_test") +target("zlib_test") set_kind("binary") - add_deps("zcoro") + add_deps("zlib") add_files("main.cpp") --- target("zcoro_test01_mutex") +-- target("zlib_test01_mutex") -- set_kind("binary") --- add_deps("zcoro") +-- add_deps("zlib") -- add_files("test/01mutex.cpp") --- target("zcoro_test02_condition") +-- target("zlib_test02_condition") -- set_kind("binary") --- add_deps("zcoro") +-- add_deps("zlib") -- add_files("test/02condition.cpp") -target("zcoro_test03_semaphore") +target("zlib_test03_semaphore") set_kind("binary") - add_deps("zcoro") + add_deps("zlib") add_files("test/03semaphore.cpp") --- target("zcoro_test04_promise") +-- target("zlib_test04_promise") -- set_kind("binary") --- add_deps("zcoro") +-- add_deps("zlib") -- add_files("test/04promise.cpp") \ No newline at end of file diff --git a/engine/src/engine/asset/asset.h b/engine/src/engine/asset/asset.h index a58c3f2..f0b3381 100644 --- a/engine/src/engine/asset/asset.h +++ b/engine/src/engine/asset/asset.h @@ -24,16 +24,8 @@ namespace engineapi string mName; public: Asset(string name, uint32_t flags):mName(name),mFlags(flags) {}; - virtual void SyncLoad() {}; - virtual void AsyncLoad() {}; virtual void BeginLoad() { mFlags |= ASSET_LOADING_FLAG; - if (IsAsync()) { - AsyncLoad(); - } - else { - SyncLoad(); - } }; virtual void EndLoad() { mFlags &= ~ASSET_LOADING_FLAG; diff --git a/engine/src/engine/asset/asset_enum.h b/engine/src/engine/asset/render/asset_enum.h similarity index 100% rename from engine/src/engine/asset/asset_enum.h rename to engine/src/engine/asset/render/asset_enum.h diff --git a/engine/src/engine/asset/asset_struct.cpp b/engine/src/engine/asset/render/asset_struct.cpp similarity index 100% rename from engine/src/engine/asset/asset_struct.cpp rename to engine/src/engine/asset/render/asset_struct.cpp diff --git a/engine/src/engine/asset/asset_struct.h b/engine/src/engine/asset/render/asset_struct.h similarity index 99% rename from engine/src/engine/asset/asset_struct.h rename to engine/src/engine/asset/render/asset_struct.h index c2bd04c..95ecc1a 100644 --- a/engine/src/engine/asset/asset_struct.h +++ b/engine/src/engine/asset/render/asset_struct.h @@ -1,5 +1,5 @@ #pragma once -#include "asset.h" +#include "../asset.h" #include "math/math.h" #include "asset_enum.h" // 顶点最多关联4个骨骼 diff --git a/engine/src/engine/render/asset/asset.h b/engine/src/engine/render/asset/asset.h deleted file mode 100644 index c6622da..0000000 --- a/engine/src/engine/render/asset/asset.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include "asset/asset_struct.h" diff --git a/engine/src/engine/render/asset/asset_render.h b/engine/src/engine/render/asset/asset_render.h new file mode 100644 index 0000000..8b4d134 --- /dev/null +++ b/engine/src/engine/render/asset/asset_render.h @@ -0,0 +1,2 @@ +#pragma once +#include "asset/render/asset_struct.h" diff --git a/engine/src/engine/render/asset/material.h b/engine/src/engine/render/asset/material.h index 52ac28b..e84c9a4 100644 --- a/engine/src/engine/render/asset/material.h +++ b/engine/src/engine/render/asset/material.h @@ -1,4 +1,4 @@ -#include "asset.h" +#include "asset_render.h" namespace engineapi { class Material : public Asset { diff --git a/engine/src/engine/render/asset/mesh.cpp b/engine/src/engine/render/asset/mesh.cpp index fc94e48..2be7d0a 100644 --- a/engine/src/engine/render/asset/mesh.cpp +++ b/engine/src/engine/render/asset/mesh.cpp @@ -8,8 +8,9 @@ namespace engineapi { { BeginLoad(); } - void Mesh::SyncLoad() + void Mesh::BeginLoad() { - RenderAPI::GetInstance()->SetStaticMesh(VAO, mVertices, mIndices, IsAsync()); + Asset::BeginLoad(); + RenderAPI::GetInstance()->SetStaticMesh(this); } } diff --git a/engine/src/engine/render/asset/mesh.h b/engine/src/engine/render/asset/mesh.h index 5ddf9d1..293695f 100644 --- a/engine/src/engine/render/asset/mesh.h +++ b/engine/src/engine/render/asset/mesh.h @@ -1,9 +1,10 @@ #pragma once -#include "asset.h" +#include "asset_render.h" namespace engineapi { class Texture; class Material; class Mesh : public Asset { + friend class RenderVulkanAPI; protected: uint32_t VAO = 0; vector mVertices; @@ -11,6 +12,6 @@ namespace engineapi { public: Mesh(string name, uint32_t flags, vector& vertices, vector& indices); - void SyncLoad()override; + void BeginLoad()override; }; }; \ No newline at end of file diff --git a/engine/src/engine/render/asset/model.cpp b/engine/src/engine/render/asset/model.cpp index 008e067..cd75b0c 100644 --- a/engine/src/engine/render/asset/model.cpp +++ b/engine/src/engine/render/asset/model.cpp @@ -1,12 +1,14 @@ #include "model.h" #include "zlog.h" +#include "mesh.h" #include "assimp/Importer.hpp" #include "assimp/scene.h" #include "assimp/postprocess.h" #include "asset/asset_manager.h" namespace engineapi { - void Model::SyncLoad() + void Model::BeginLoad() { + Asset::BeginLoad(); // 用ASSIMP加载模型文件 Assimp::Importer importer; const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace diff --git a/engine/src/engine/render/asset/model.h b/engine/src/engine/render/asset/model.h index 392db3c..fc539eb 100644 --- a/engine/src/engine/render/asset/model.h +++ b/engine/src/engine/render/asset/model.h @@ -1,5 +1,5 @@ #pragma once -#include "mesh.h" +#include "asset_render.h" class aiNode; class aiMesh; class aiScene; @@ -10,7 +10,7 @@ namespace engineapi { public: using Asset::Asset; - void SyncLoad()override; + void BeginLoad()override; void ProcessNode(const aiNode* pNode, const aiScene* pScene); Mesh* ProcessMesh(const aiMesh* mesh); }; diff --git a/engine/src/engine/render/asset/texture.h b/engine/src/engine/render/asset/texture.h index 1b09df4..f8c7b39 100644 --- a/engine/src/engine/render/asset/texture.h +++ b/engine/src/engine/render/asset/texture.h @@ -1,4 +1,4 @@ -#include "asset.h" +#include "asset_render.h" namespace engineapi { class Texture : public Asset { diff --git a/engine/src/engine/render/renderapi.cpp b/engine/src/engine/render/renderapi.cpp index bcc4917..c209099 100644 --- a/engine/src/engine/render/renderapi.cpp +++ b/engine/src/engine/render/renderapi.cpp @@ -10,7 +10,7 @@ namespace engineapi { void RenderAPI::MakeInstance() { #ifdef VULKAN_API - Instance = new vulkanapi::RenderVulkanAPI(); + Instance = new RenderVulkanAPI(); #endif } } \ No newline at end of file diff --git a/engine/src/engine/render/renderapi.h b/engine/src/engine/render/renderapi.h index 94698bf..0bd4a22 100644 --- a/engine/src/engine/render/renderapi.h +++ b/engine/src/engine/render/renderapi.h @@ -1,13 +1,14 @@ #pragma once -#include "asset/asset_struct.h" +#include "asset/asset_render.h" namespace engineapi { + class Mesh; class RenderAPI { public: virtual void BeginFrame() = 0; virtual void EndFrame() = 0; - virtual void SetStaticMesh(uint32_t& VAO, vector& vertices, vector& indices, bool Async) = 0; + virtual void SetStaticMesh(Mesh* mesh) = 0; public: static RenderAPI* Instance; static void MakeInstance(); diff --git a/engine/src/engine/vulkanapi/backend.cpp b/engine/src/engine/vulkanapi/backend.cpp index 8a8a97c..ebf3bf1 100644 --- a/engine/src/engine/vulkanapi/backend.cpp +++ b/engine/src/engine/vulkanapi/backend.cpp @@ -12,9 +12,6 @@ namespace vulkanapi { auto deviceCreator = DeviceCreator(*mInstance); deviceCreator.AddWindowExtension(); - deviceCreator.desiredPhysicalDeviceFeatures.independentBlend = true; - deviceCreator.desiredPhysicalDeviceFeatures.depthClamp = true; - deviceCreator.desiredPhysicalDeviceFeatures.geometryShader = VK_TRUE; deviceCreator.AddQueue(Queue::TransferQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0); deviceCreator.AddQueue(Queue::RenderQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0); deviceCreator.AddQueue(Queue::ComputeQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0); diff --git a/engine/src/engine/vulkanapi/thread/worker.cpp b/engine/src/engine/vulkanapi/thread/worker.cpp index 17797fa..5f7a7f6 100644 --- a/engine/src/engine/vulkanapi/thread/worker.cpp +++ b/engine/src/engine/vulkanapi/thread/worker.cpp @@ -1,52 +1,43 @@ #include "worker.h" -#include "thread_worker.h" #include "../wrapper/queue.h" #include "../wrapper/device.h" -#include "../wrapper/commandpool.h" -#include "../wrapper/commandbuffer.h" namespace vulkanapi { CommandWorker::CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags) :mName(name) + ,mDevice(device) ,mQueue(queue) + ,mCommandPool(CommandPool(device, queueFlags, queue.QueueFamilyIndex())) + ,mWork(CommandThreadWorker(name, 64)) + ,mImmediateExeCmd(CommandBuffer(mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)) { - mCommandPool = new CommandPool(device, queueFlags, queue.QueueFamilyIndex()); - mWork = new CommandThreadWorker(name, 64); + } void CommandWorker::Invoke(voidFn fn) { - mWork->Invoke(fn); + mWork.Invoke(fn); } - void CommandWorker::InvokeBuffer(commandFn fn) + void CommandWorker::InvokeBuffer(commandFn fn, voidFn callback) { - mWork->Invoke([=]() { - Buffer(fn); + mWork.Invoke([=]() { + CommandBuffer cmd = mCommandPool.Pop(); + Buffer(cmd, fn, callback); }); } - void CommandWorker::Buffer(commandFn fn) + void CommandWorker::Buffer(CommandBuffer& cmd, commandFn fn, voidFn callback) { - CommandBuffer* cmd = mCommandPool->Pop(); - cmd->BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); fn(cmd); - cmd->EndRecord(); - } - - void CommandWorker::InvokeSubmit() - { - mWork->Invoke([=]() { - Submit(); - }); - } - - void CommandWorker::Submit() - { - + cmd.EndRecord(); + cmd.Submit(mQueue.Ptr()); + cmd.WaitFofFence(mDevice.Ptr()); + mCommandPool.Push(cmd); + callback(); } void CommandWorker::Flush() { - mWork->SyncInvoke([]() {}); + mWork.SyncInvoke([]() {}); } - } diff --git a/engine/src/engine/vulkanapi/thread/worker.h b/engine/src/engine/vulkanapi/thread/worker.h index 94391de..36a8546 100644 --- a/engine/src/engine/vulkanapi/thread/worker.h +++ b/engine/src/engine/vulkanapi/thread/worker.h @@ -1,24 +1,28 @@ #pragma once #include "../vulkan.h" +#include "thread_worker.h" +#include "../wrapper/commandpool.h" +#include "../wrapper/commandbuffer.h" namespace vulkanapi { class Device; - class CommandThreadWorker; - class CommandPool; class Queue; class CommandWorker { protected: + Device& mDevice; Queue& mQueue; const string& mName; - CommandThreadWorker* mWork; - CommandPool* mCommandPool; + CommandThreadWorker mWork; + CommandPool mCommandPool; + CommandBuffer mImmediateExeCmd; public: CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags); void Invoke(voidFn fn); - void InvokeBuffer(commandFn fn); - void Buffer(commandFn fn); - void InvokeSubmit(); - void Submit(); + void InvokeBuffer(commandFn fn, voidFn callback); + void Buffer(CommandBuffer& cmd,commandFn fn, voidFn callback); void Flush(); + void ImmediatelyExecute(commandFn fn, voidFn callback) { + Buffer(mImmediateExeCmd, fn , callback); + } }; }; \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan.h b/engine/src/engine/vulkanapi/vulkan.h index bb25c87..0aa444a 100644 --- a/engine/src/engine/vulkanapi/vulkan.h +++ b/engine/src/engine/vulkanapi/vulkan.h @@ -13,5 +13,5 @@ using std::string; using std::vector; using std::map; using voidFn = std::function; -using commandFn = std::function; +using commandFn = std::function; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan_struct.h b/engine/src/engine/vulkanapi/vulkan_struct.h index c2f769f..916dff6 100644 --- a/engine/src/engine/vulkanapi/vulkan_struct.h +++ b/engine/src/engine/vulkanapi/vulkan_struct.h @@ -3,7 +3,7 @@ // AMD写的Vulkan内存分配器 #include "vk_mem_alloc.h" #include "math/matrix4.h" -#include "asset/asset_struct.h" +#include "render/asset/asset_render.h" using engineapi::Matrix4; using engineapi::FrameBufferType; using engineapi::ClearInfo; diff --git a/engine/src/engine/vulkanapi/vulkanapi.cpp b/engine/src/engine/vulkanapi/vulkanapi.cpp index 9415e55..7a24464 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.cpp +++ b/engine/src/engine/vulkanapi/vulkanapi.cpp @@ -3,7 +3,8 @@ #include "wrapper/buffer.h" #include "wrapper/commandbuffer.h" #include "thread/worker.h" -namespace vulkanapi { +#include "render/asset/mesh.h" +namespace engineapi { RenderVulkanAPI::RenderVulkanAPI() :backend("vulkan") { @@ -17,35 +18,40 @@ namespace vulkanapi { { } - void RenderVulkanAPI::SetStaticMesh(uint32_t& VAO, vector& vertices, vector& indices, bool Async) + void RenderVulkanAPI::SetStaticMesh(Mesh* mesh) { - auto meshBuffer = GetNextVAO(VAO); - meshBuffer->indexCount = indices.size(); - meshBuffer->vertexCount = vertices.size(); + auto meshBuffer = GetNextVAO(mesh->VAO); + meshBuffer->indexCount = mesh->mIndices.size(); + meshBuffer->vertexCount = mesh->mVertices.size(); // ----------------------------------------------- Vertex Buffer ----------------------------------------------- - VkDeviceSize vertexBufferSize = sizeof(Vertex) * vertices.size(); + VkDeviceSize vertexBufferSize = sizeof(Vertex) * mesh->mVertices.size(); VmaAllocationCreateInfo vertexStagingAllocInfo = {}; VkBufferCreateInfo vertexStagingBufferInfo = Buffer::MakeStageInfo(vertexStagingAllocInfo, vertexBufferSize); VmaAllocation vertexStagingBufferAlloc; VkBuffer vertexStagingBuffer = Buffer::CreateBuffer(vertexStagingBufferInfo, vertexStagingAllocInfo, vertexStagingBufferAlloc); - + // 拷贝数据到StagingBuffer - Buffer::CopyData(vertexStagingBufferAlloc, vertices.data(), vertexBufferSize); + Buffer::CopyData(vertexStagingBufferAlloc, mesh->mVertices.data(), vertexBufferSize); VkBufferUsageFlags flags = 0;//加入光线追踪 VmaAllocationCreateInfo vertexBufferAllocInfo = {}; VkBufferCreateInfo vertexBufferInfo = Buffer::MakeDeviceInfo(vertexBufferAllocInfo, vertexBufferSize, flags); meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexBufferInfo, vertexBufferAllocInfo, meshBuffer->vertexBufferAlloc); - auto fn = [=](CommandBuffer* cmd) { - cmd->CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize); + auto fn = [=](CommandBuffer& cmd) { + cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize); }; - if (Async) { - Backend::TransferWorker->InvokeBuffer(fn); + auto callback = [=]() { + // 销毁StagingBuffer + Buffer::DestroyBuffer(vertexStagingBuffer, vertexStagingBufferAlloc); + mesh->EndLoad(); + }; + if (mesh->IsAsync()) { + Backend::TransferWorker->InvokeBuffer(fn, callback); } else { - Backend::TransferWorker->InvokeBuffer(fn); + Backend::TransferWorker->ImmediatelyExecute(fn, callback); } } VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& VAO_index) diff --git a/engine/src/engine/vulkanapi/vulkanapi.h b/engine/src/engine/vulkanapi/vulkanapi.h index 7b8730d..03d9cd9 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.h +++ b/engine/src/engine/vulkanapi/vulkanapi.h @@ -2,10 +2,10 @@ #include "backend.h" #include "render/renderapi.h" #include "vulkan_struct.h" -using engineapi::Vertex; -namespace vulkanapi +using namespace vulkanapi; +namespace engineapi { - class RenderVulkanAPI : public engineapi::RenderAPI + class RenderVulkanAPI : public RenderAPI { public: Backend backend; @@ -15,13 +15,12 @@ namespace vulkanapi virtual void BeginFrame()override; virtual void EndFrame()override; - - virtual void SetStaticMesh(uint32_t& VAO, vector& vertices, vector& indices, bool Async)override; + virtual void SetStaticMesh(Mesh* mesh)override; public: VulkanVAO* GetNextVAO(uint32_t& VAO_index); public: static RenderVulkanAPI* GetInstance() { - return (RenderVulkanAPI*)engineapi::RenderAPI::GetInstance(); + return (RenderVulkanAPI*)RenderAPI::GetInstance(); } }; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/window.cpp b/engine/src/engine/vulkanapi/window.cpp index 4db8757..2c8989d 100644 --- a/engine/src/engine/vulkanapi/window.cpp +++ b/engine/src/engine/vulkanapi/window.cpp @@ -6,6 +6,7 @@ #include "wrapper/swapchain_creator.h" #include "vulkanapi.h" #include "zlog.h" +using engineapi::RenderVulkanAPI; namespace vulkanapi { Window::Window(int frames, uint32_t width, uint32_t height, const char* title) :engineapi::Window(width, height , title) diff --git a/engine/src/engine/vulkanapi/window.h b/engine/src/engine/vulkanapi/window.h index 5412416..f2313da 100644 --- a/engine/src/engine/vulkanapi/window.h +++ b/engine/src/engine/vulkanapi/window.h @@ -5,7 +5,7 @@ namespace vulkanapi { class Swapchain; class Window : public engineapi::Window { protected: - VkSurfaceKHR mSurfaceKHR{NULL}; + VkSurfaceKHR mSurfaceKHR; Swapchain* mSwapchain; public: Window(int frames, uint32_t width, uint32_t height, const char* title); diff --git a/engine/src/engine/vulkanapi/wrapper/buffer.cpp b/engine/src/engine/vulkanapi/wrapper/buffer.cpp index 714fdff..c48a813 100644 --- a/engine/src/engine/vulkanapi/wrapper/buffer.cpp +++ b/engine/src/engine/vulkanapi/wrapper/buffer.cpp @@ -59,4 +59,9 @@ namespace vulkanapi { memcpy(vertexData, data, size); vmaUnmapMemory(vmaAllocator, allocation); } + void Buffer::DestroyBuffer(VkBuffer buffer, VmaAllocation bufferAlloc) + { + // 销毁StagingBuffer + vmaDestroyBuffer(vmaAllocator, buffer, bufferAlloc); + } } diff --git a/engine/src/engine/vulkanapi/wrapper/buffer.h b/engine/src/engine/vulkanapi/wrapper/buffer.h index 7afe468..787b25d 100644 --- a/engine/src/engine/vulkanapi/wrapper/buffer.h +++ b/engine/src/engine/vulkanapi/wrapper/buffer.h @@ -14,5 +14,6 @@ namespace vulkanapi { VmaAllocationCreateInfo& allocationCreateInfo, VmaAllocation& allocation); static void CopyData(VmaAllocation& allocation,void* data, VkDeviceSize size); + static void DestroyBuffer(VkBuffer buffer, VmaAllocation bufferAlloc); }; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp b/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp index 0e146e1..744ca3c 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp +++ b/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp @@ -3,9 +3,30 @@ #include "device.h" namespace vulkanapi { CommandBuffer::CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level) - : mPtr(commandPool.Allocate(level)) + :mPool(commandPool) + ,mPtr(commandPool.AllocateBuffer(level)) + ,mFence(commandPool.AllocateFence()) { + } + CommandBuffer::~CommandBuffer() + { + zlog::info("CommandBuffer Destruct {:#x} isNull = {}", (uint64_t)this, mPtr == nullptr || mFence == nullptr); + if (mPtr) { + mPool.FreeBuffer(mPtr); + } + if (mFence) { + mPool.FreeFence(mFence); + } + } + CommandBuffer::CommandBuffer(CommandBuffer&& other)noexcept + : mPtr(other.mPtr) + , mFence(other.mFence) + , mPool(other.mPool) + { + other.mPtr = nullptr; + other.mFence = nullptr; + zlog::info("CommandBuffer MoveConstruct {:#x} => {:#x}", (uint64_t)&other, (uint64_t)this); } void CommandBuffer::Reset() { @@ -32,5 +53,17 @@ namespace vulkanapi { copy.size = size; vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, ©); } + void CommandBuffer::Submit(VkQueue& queue) + { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &mPtr; + vkQueueSubmit(queue, 1, &submitInfo, mFence); + } + void CommandBuffer::WaitFofFence(VkDevice& device) + { + vkWaitForFences(device, 1, &mFence, VK_TRUE, UINT64_MAX); + } } diff --git a/engine/src/engine/vulkanapi/wrapper/commandbuffer.h b/engine/src/engine/vulkanapi/wrapper/commandbuffer.h index 621c800..912ce68 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandbuffer.h +++ b/engine/src/engine/vulkanapi/wrapper/commandbuffer.h @@ -5,13 +5,24 @@ namespace vulkanapi { class CommandPool; class CommandBuffer { protected: + CommandPool& mPool; VkCommandBuffer mPtr; + VkFence mFence; public: CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level); - + ~CommandBuffer(); + CommandBuffer(CommandBuffer&& other)noexcept; + VkCommandBuffer& Ptr() { + return mPtr; + }; + VkFence& Fence() { + return mFence; + }; void Reset(); void BeginRecord(VkCommandBufferUsageFlags flag); void EndRecord(); void CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); + void Submit(VkQueue& queue); + void WaitFofFence(VkDevice& device); }; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp index 01604cf..545d6ff 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp +++ b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp @@ -1,5 +1,5 @@ #include "commandpool.h" -#include "commandbuffer.h" + #include "device.h" #include "queue.h" #include "zlog.h" @@ -7,6 +7,9 @@ namespace vulkanapi { CommandPool::CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex) :mPtr(nullptr) ,mDevice(device) + ,mPool([=]()->CommandBuffer { + return std::move(CommandBuffer(*this, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); + }, 256) { VkCommandPoolCreateInfo pCreateInfo{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -16,7 +19,7 @@ namespace vulkanapi { }; vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr); } - VkCommandBuffer CommandPool::Allocate(VkCommandBufferLevel level) + VkCommandBuffer CommandPool::AllocateBuffer(VkCommandBufferLevel level) { VkCommandBufferAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, //sType @@ -29,18 +32,21 @@ namespace vulkanapi { vkAllocateCommandBuffers(mDevice.Ptr(), &allocInfo, &cmd); return cmd; } - CommandBuffer* CommandPool::Pop() + void CommandPool::FreeBuffer(VkCommandBuffer& buf) { - if (top < mBufferList.size()) { - auto cmd = mBufferList[top]; - cmd->Reset(); - top++; - return cmd; - } - CommandBuffer* cmd = new CommandBuffer(*this, VK_COMMAND_BUFFER_LEVEL_PRIMARY); - mBufferList.push_back(cmd); - top++; - return cmd; + vkFreeCommandBuffers(mDevice.Ptr(), mPtr, 1, &buf); + buf = nullptr; + } + void CommandPool::FreeFence(VkFence& fence) + { + vkDestroyFence(mDevice.Ptr(), fence, NULL); + fence = nullptr; + } + VkFence CommandPool::AllocateFence() + { + VkFence fence; + mDevice.CreateFence(fence); + return fence; } } diff --git a/engine/src/engine/vulkanapi/wrapper/commandpool.h b/engine/src/engine/vulkanapi/wrapper/commandpool.h index 466732a..85a1673 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandpool.h +++ b/engine/src/engine/vulkanapi/wrapper/commandpool.h @@ -1,22 +1,33 @@ #pragma once #include "../vulkan.h" +#include "zstd/pool.h" +#include "zlog.h" +#include "commandbuffer.h" namespace vulkanapi { class Device; class Queue; - class CommandBuffer; class CommandPool { protected: VkCommandPool mPtr; Device& mDevice; - vector mBufferList; - int top = 0; + zstd::pool mPool; public: CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex); - VkCommandBuffer Allocate(VkCommandBufferLevel level); - CommandBuffer* Pop(); + VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level); + void FreeBuffer(VkCommandBuffer& buf); + void FreeFence(VkFence& fence); + VkFence AllocateFence(); VkCommandPool& Ptr() { return mPtr; }; + CommandBuffer Pop() + { + return std::move(mPool.acquire()); + } + void Push(CommandBuffer& cmd) + { + mPool.release(std::forward(cmd)); + } }; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/device.cpp b/engine/src/engine/vulkanapi/wrapper/device.cpp index 7cb0d41..8560f4e 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.cpp +++ b/engine/src/engine/vulkanapi/wrapper/device.cpp @@ -5,16 +5,23 @@ namespace vulkanapi { Device::Device(DeviceCreator& Creator) { + //物理设备 Creator.FindDevice(mPhysical); + //队列信息 vector queue_families; Creator.CheckAvailableQueueFamilies(mPhysical, queue_families); vector queue_create_infos; vector> queue_prioritie; Creator.QueueCreateInfos(queue_create_infos, queue_prioritie, queue_families); + //扩展 auto extensions = Creator.EnabledExtensionNames(); + //特性 + VkPhysicalDeviceFeatures2 deviceFeatures = Creator.GetDeviceFeature2(); + VkPhysicalDeviceVulkan12Features deviceVulkan12Features = Creator.GetVulkan12Features(); + deviceFeatures.pNext = &deviceVulkan12Features; VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType - nullptr, // const void * pNext + &deviceFeatures, // const void * pNext 0, // VkDeviceCreateFlags flags static_cast(queue_create_infos.size()), // uint32_t queueCreateInfoCount queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos @@ -22,7 +29,7 @@ namespace vulkanapi { nullptr, // const char * const * ppEnabledLayerNames static_cast(extensions.size()), // uint32_t enabledExtensionCount extensions.data(), // const char * const * ppEnabledExtensionNames - &Creator.desiredPhysicalDeviceFeatures // const VkPhysicalDeviceFeatures * pEnabledFeatures + nullptr // const VkPhysicalDeviceFeatures * pEnabledFeatures }; #ifdef Z_USE_GRAPHIC_DEBUG auto layers = Creator.EnabledLayerNames(); @@ -54,5 +61,14 @@ namespace vulkanapi { } return nullptr; } + bool Device::CreateFence(VkFence& fence) + { + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + // 创建时立刻设置为signaled状态(否则第一次永远等不到) + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence); + return result == VK_SUCCESS; + } } diff --git a/engine/src/engine/vulkanapi/wrapper/device.h b/engine/src/engine/vulkanapi/wrapper/device.h index 029b450..f928765 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.h +++ b/engine/src/engine/vulkanapi/wrapper/device.h @@ -22,5 +22,6 @@ namespace vulkanapi { ~Device(); Queue* GetQueue(const string& name); + bool CreateFence(VkFence& fence); }; }; \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/device_creator.cpp b/engine/src/engine/vulkanapi/wrapper/device_creator.cpp index 6e254d3..978872a 100644 --- a/engine/src/engine/vulkanapi/wrapper/device_creator.cpp +++ b/engine/src/engine/vulkanapi/wrapper/device_creator.cpp @@ -119,6 +119,38 @@ namespace vulkanapi { } } } + void DeviceCreator::EnableDeviceFeatures() + { + //pEnabledFeatures 和 pNext是冲突的吗? pNext + desiredPhysicalDeviceFeatures.independentBlend = true; + desiredPhysicalDeviceFeatures.depthClamp = true; + desiredPhysicalDeviceFeatures.geometryShader = VK_TRUE; + } + VkPhysicalDeviceFeatures2 DeviceCreator::GetDeviceFeature2() + { + // 明确设备要使用的功能特性 + VkPhysicalDeviceFeatures2 deviceFeatures = {}; + deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + // 启用对各向异性采样的支持 + deviceFeatures.features.samplerAnisotropy = VK_TRUE; + deviceFeatures.features.geometryShader = VK_TRUE; + deviceFeatures.features.sampleRateShading = VK_TRUE; + deviceFeatures.features.shaderInt64 = VK_TRUE; + return deviceFeatures; + } + VkPhysicalDeviceVulkan12Features DeviceCreator::GetVulkan12Features() + { + // 添加Vulkan 1.2的特性 + VkPhysicalDeviceVulkan12Features deviceVulkan12Features = {}; + deviceVulkan12Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + // 启用对Device Address的支持 + deviceVulkan12Features.bufferDeviceAddress = VK_TRUE; + deviceVulkan12Features.runtimeDescriptorArray = VK_TRUE; + deviceVulkan12Features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE; + deviceVulkan12Features.hostQueryReset = VK_TRUE; + deviceVulkan12Features.pNext = nullptr; + return deviceVulkan12Features; + } void DeviceCreator::AddExtension(string extensionName) { desiredExtensions.push_back(extensionName); diff --git a/engine/src/engine/vulkanapi/wrapper/device_creator.h b/engine/src/engine/vulkanapi/wrapper/device_creator.h index b79de2e..8a538f2 100644 --- a/engine/src/engine/vulkanapi/wrapper/device_creator.h +++ b/engine/src/engine/vulkanapi/wrapper/device_creator.h @@ -37,6 +37,9 @@ namespace vulkanapi { void QueueCreateInfos(vector& queue_create_infos, vector>& queue_prioritie, vector& queue_families); + void EnableDeviceFeatures(); + VkPhysicalDeviceFeatures2 GetDeviceFeature2(); + VkPhysicalDeviceVulkan12Features GetVulkan12Features(); #ifdef Z_USE_GRAPHIC_DEBUG public: vector desiredLayers; diff --git a/engine/src/main.cpp b/engine/src/main.cpp index fca5950..719ee3d 100644 --- a/engine/src/main.cpp +++ b/engine/src/main.cpp @@ -15,7 +15,7 @@ int main(int argc, char** argv) auto wnd = vulkanapi::Window(3, 640, 720, name); ActorProperty property; property.id = 1; - property.flags = Asset::ASSET_SHARED_FLAG; + property.flags = Asset::ASSET_SHARED_FLAG | Asset::ASSET_ASYNC_FLAG; property.path = "assets/models/cube.obj"; AssetManager instance; AssetManager::Instance = &instance; diff --git a/engine/xmake.lua b/engine/xmake.lua index adb51de..c738598 100644 --- a/engine/xmake.lua +++ b/engine/xmake.lua @@ -6,7 +6,7 @@ target("zengine") set_kind("binary") set_rundir(".") add_rules("volk.env") - add_deps("zcoro","zlog") + add_deps("zlib","zlog") add_packages("vulkansdk","tinyobjloader","assimp") add_includedirs("src/engine") add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator")