From 70f66ab7b998ab843c4a2b490268fdb893db7f53 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Fri, 12 Jul 2024 22:09:03 +0800 Subject: [PATCH] vulkan bugfix --- engine/src/engine/asset/res/resource_handle.h | 3 + engine/src/engine/object/scene/scene.cpp | 4 +- engine/src/engine/openglapi/openglapi.cpp | 24 +++--- engine/src/engine/openglapi/openglapi.h | 6 +- engine/src/engine/render/asset/mesh.cpp | 2 +- engine/src/engine/render/asset/shader.cpp | 2 +- engine/src/engine/render/node/rendernode.h | 2 +- .../engine/render/node/rendernode_forward.cpp | 8 +- .../engine/render/node/rendernode_forward.h | 4 +- engine/src/engine/render/renderapi.cpp | 2 +- engine/src/engine/render/renderapi.h | 8 +- engine/src/engine/vulkanapi/backend.cpp | 2 +- .../engine/vulkanapi/thread/thread_worker.cpp | 6 +- .../engine/vulkanapi/thread/thread_worker.h | 4 +- engine/src/engine/vulkanapi/thread/worker.cpp | 31 ++----- engine/src/engine/vulkanapi/thread/worker.h | 16 ++-- engine/src/engine/vulkanapi/vulkan_context.h | 1 + engine/src/engine/vulkanapi/vulkanapi.cpp | 86 ++++++++++--------- engine/src/engine/vulkanapi/vulkanapi.h | 6 +- .../vulkanapi/wrapper/commandbuffer.cpp | 37 +------- .../engine/vulkanapi/wrapper/commandbuffer.h | 15 +--- .../engine/vulkanapi/wrapper/commandpool.cpp | 29 ++++--- .../engine/vulkanapi/wrapper/commandpool.h | 17 +--- .../src/engine/vulkanapi/wrapper/device.cpp | 35 ++++++-- engine/src/engine/vulkanapi/wrapper/device.h | 10 ++- .../engine/vulkanapi/wrapper/device_creator.h | 1 + .../engine/vulkanapi/wrapper/swapchain.cpp | 13 ++- .../src/engine/vulkanapi/wrapper/swapchain.h | 1 + 28 files changed, 179 insertions(+), 196 deletions(-) diff --git a/engine/src/engine/asset/res/resource_handle.h b/engine/src/engine/asset/res/resource_handle.h index d4dbd4e..2781f55 100644 --- a/engine/src/engine/asset/res/resource_handle.h +++ b/engine/src/engine/asset/res/resource_handle.h @@ -20,6 +20,9 @@ namespace engineapi constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) {} void Init(); void Clear() { res = nullptr; }; + Res* Ptr() { + return (Res*)res; + } Res* operator->() { if (!res && guid) Init(); return (Res*)res; } Res& operator*() { if (!res && guid) Init(); return *(Res*)res; } operator bool() { if (!res && guid) Init(); return res; } diff --git a/engine/src/engine/object/scene/scene.cpp b/engine/src/engine/object/scene/scene.cpp index afba74d..7f1d813 100644 --- a/engine/src/engine/object/scene/scene.cpp +++ b/engine/src/engine/object/scene/scene.cpp @@ -31,10 +31,10 @@ namespace engineapi { } void Scene::Render() { - RenderAPI::GetSingletonPtr()->Render(*mCamera); + RenderAPI::GetSingletonPtr()->Render(mCamera); auto& meshs = actor1->Ptr().GetMeshs(); for (auto it : meshs) { - RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it); + RenderAPI::GetSingletonPtr()->DrawStaticMesh(it.Ptr()); } } void Scene::AddGameObject(GameObject* gameObject) diff --git a/engine/src/engine/openglapi/openglapi.cpp b/engine/src/engine/openglapi/openglapi.cpp index b91e041..a41eb65 100644 --- a/engine/src/engine/openglapi/openglapi.cpp +++ b/engine/src/engine/openglapi/openglapi.cpp @@ -54,10 +54,10 @@ namespace openglapi { window->Present(); GL_CHECK(); } - void RenderOpenGLApi::SetStaticMesh(Mesh& mesh) + void RenderOpenGLApi::SetStaticMesh(Mesh* mesh) { - auto Indices = mesh.GetIndices(); - auto Vertices = mesh.GetVertices(); + auto Indices = mesh->GetIndices(); + auto Vertices = mesh->GetVertices(); unsigned int VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); @@ -90,28 +90,28 @@ namespace openglapi { glBindBuffer(GL_ARRAY_BUFFER, 0); // 解绑VAO glBindVertexArray(0); - VAOTable[mesh.GetGuid()] = OpenGLPtr{ VAO }; + VAOTable[mesh->GetGuid()] = OpenGLPtr{ VAO }; } - void RenderOpenGLApi::DrawStaticMesh(Mesh& mesh) + void RenderOpenGLApi::DrawStaticMesh(Mesh* mesh) { - OpenGLPtr& shaderPtr = ShaderTable[mesh.GetShaderGuid()]; + OpenGLPtr& shaderPtr = ShaderTable[mesh->GetShaderGuid()]; glUseProgram(shaderPtr); - OpenGLPtr& meshPtr = VAOTable[mesh.GetGuid()]; + OpenGLPtr& meshPtr = VAOTable[mesh->GetGuid()]; glBindVertexArray(meshPtr); - glDrawElements(GL_TRIANGLES, mesh.GetIndices().size(), GL_UNSIGNED_INT, 0); + glDrawElements(GL_TRIANGLES, mesh->GetIndices().size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); } - void RenderOpenGLApi::LoadShader(Shader& shader) + void RenderOpenGLApi::LoadShader(Shader* shader) { - auto vertModule = shader.GetVertHandle()->Ptr(); - auto fragModule = shader.GetFragHandle()->Ptr(); + auto vertModule = shader->GetVertHandle()->Ptr(); + auto fragModule = shader->GetFragHandle()->Ptr(); GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertModule); glAttachShader(shaderProgram, fragModule); glLinkProgram(shaderProgram); glDeleteShader(vertModule); glDeleteShader(fragModule); - ShaderTable[shader.GetGuid()] = OpenGLPtr{shaderProgram}; + ShaderTable[shader->GetGuid()] = OpenGLPtr{shaderProgram}; Backend::CheckShaderProgram(shaderProgram); } } \ No newline at end of file diff --git a/engine/src/engine/openglapi/openglapi.h b/engine/src/engine/openglapi/openglapi.h index f773a7f..25bdbb3 100644 --- a/engine/src/engine/openglapi/openglapi.h +++ b/engine/src/engine/openglapi/openglapi.h @@ -31,9 +31,9 @@ namespace openglapi { void BeginFrame()override; void EndFrame()override; - void SetStaticMesh(Mesh& mesh)override; - void DrawStaticMesh(Mesh& mesh)override; + void SetStaticMesh(Mesh* mesh)override; + void DrawStaticMesh(Mesh* mesh)override; - void LoadShader(Shader& shader)override; + void LoadShader(Shader* shader)override; }; } \ No newline at end of file diff --git a/engine/src/engine/render/asset/mesh.cpp b/engine/src/engine/render/asset/mesh.cpp index f768676..b37038e 100644 --- a/engine/src/engine/render/asset/mesh.cpp +++ b/engine/src/engine/render/asset/mesh.cpp @@ -7,6 +7,6 @@ namespace engineapi { void Mesh::BeginLoad() { mMaterial->BeginLoad(); - RenderAPI::GetSingletonPtr()->SetStaticMesh(*this); + RenderAPI::GetSingletonPtr()->SetStaticMesh(this); } } diff --git a/engine/src/engine/render/asset/shader.cpp b/engine/src/engine/render/asset/shader.cpp index 86bb24c..6b759ea 100644 --- a/engine/src/engine/render/asset/shader.cpp +++ b/engine/src/engine/render/asset/shader.cpp @@ -10,6 +10,6 @@ namespace engineapi { } void Shader::BeginLoad() { - RenderAPI::GetSingletonPtr()->LoadShader(*this); + RenderAPI::GetSingletonPtr()->LoadShader(this); } } diff --git a/engine/src/engine/render/node/rendernode.h b/engine/src/engine/render/node/rendernode.h index 4809d44..ba81e51 100644 --- a/engine/src/engine/render/node/rendernode.h +++ b/engine/src/engine/render/node/rendernode.h @@ -22,7 +22,7 @@ namespace engineapi { RenderNode(RenderType type); ~RenderNode() {}; - virtual void Render(Camera& camera) = 0; + virtual void Render(Camera* camera) = 0; public: RenderType GetType() { return mType; diff --git a/engine/src/engine/render/node/rendernode_forward.cpp b/engine/src/engine/render/node/rendernode_forward.cpp index af2c5fa..7268e8b 100644 --- a/engine/src/engine/render/node/rendernode_forward.cpp +++ b/engine/src/engine/render/node/rendernode_forward.cpp @@ -16,7 +16,7 @@ namespace engineapi { RenderNodeForwardRendering::~RenderNodeForwardRendering() { } - void RenderNodeForwardRendering::Render(Camera& camera) + void RenderNodeForwardRendering::Render(Camera* camera) { auto renderAPI = RenderAPI::GetSingletonPtr(); auto window = Window::GetSingletonPtr(); @@ -29,11 +29,11 @@ namespace engineapi { mContext->UsePass(mType); mContext->UseContext(); } - void RenderNodeForwardRendering::RenderSkyBox(Camera& camera) + void RenderNodeForwardRendering::RenderSkyBox(Camera* camera) { // 先转3x3再回4x4,把相机位移信息去除 - Matrix4 mat_V = Matrix4(Matrix3(camera.GetViewMatrix())); - Matrix4 mat_P = camera.GetProjectionMatrix(); + Matrix4 mat_V = Matrix4(Matrix3(camera->GetViewMatrix())); + Matrix4 mat_P = camera->GetProjectionMatrix(); mSky->Use(); //skyBoxMaterial->Use(); diff --git a/engine/src/engine/render/node/rendernode_forward.h b/engine/src/engine/render/node/rendernode_forward.h index 0b3f5e3..7567f00 100644 --- a/engine/src/engine/render/node/rendernode_forward.h +++ b/engine/src/engine/render/node/rendernode_forward.h @@ -10,12 +10,12 @@ namespace engineapi { RenderNodeForwardRendering(); ~RenderNodeForwardRendering(); - virtual void Render(Camera& camera); + virtual void Render(Camera* camera); private: Model* mSky; - void RenderSkyBox(Camera& camera); + void RenderSkyBox(Camera* camera); void RenderBatches(const table>& batchs); }; } \ No newline at end of file diff --git a/engine/src/engine/render/renderapi.cpp b/engine/src/engine/render/renderapi.cpp index 3ffcebb..1d16822 100644 --- a/engine/src/engine/render/renderapi.cpp +++ b/engine/src/engine/render/renderapi.cpp @@ -29,7 +29,7 @@ namespace engineapi { //mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_AFTER_EFFECT_RENDERING]); //mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_UI_RENDERING]); } - void RenderAPI::Render(Camera& camera) + void RenderAPI::Render(Camera* camera) { for (auto node : mCurNodes) { node->Render(camera); diff --git a/engine/src/engine/render/renderapi.h b/engine/src/engine/render/renderapi.h index bebe3b0..e158455 100644 --- a/engine/src/engine/render/renderapi.h +++ b/engine/src/engine/render/renderapi.h @@ -30,12 +30,12 @@ namespace engineapi virtual void OnWindowSizeChange(uint32_t width, uint32_t height) = 0; virtual void SetViewPort(uint32_t width, uint32_t height, uint32_t xOffset = 0, uint32_t yOffset = 0) = 0; virtual void BeginFrame() = 0; - virtual void Render(Camera& camera); + virtual void Render(Camera* camera); virtual void EndFrame() = 0; - virtual void SetStaticMesh(Mesh& mesh) = 0; - virtual void DrawStaticMesh(Mesh& mesh) = 0; + virtual void SetStaticMesh(Mesh* mesh) = 0; + virtual void DrawStaticMesh(Mesh* mesh) = 0; - virtual void LoadShader(Shader& shader) = 0; + virtual void LoadShader(Shader* shader) = 0; virtual void SwitchContext() = 0; diff --git a/engine/src/engine/vulkanapi/backend.cpp b/engine/src/engine/vulkanapi/backend.cpp index 6f5ba16..e63beff 100644 --- a/engine/src/engine/vulkanapi/backend.cpp +++ b/engine/src/engine/vulkanapi/backend.cpp @@ -29,7 +29,7 @@ namespace vulkanapi { Backend::TransferWorker = GetWorker(Queue::TransferQueue); Backend::RenderWorker = GetWorker(Queue::RenderQueue); - Backend::PresentWorker = GetWorker(Queue::PresentQueue); + //Backend::PresentWorker = GetWorker(Queue::PresentQueue); auto poolSizes = DescriptorPool::DefaultDescriptorPoolSize(); mPool = new DescriptorPool(*mDevice, poolSizes, 1000); diff --git a/engine/src/engine/vulkanapi/thread/thread_worker.cpp b/engine/src/engine/vulkanapi/thread/thread_worker.cpp index 91b54e8..e57b3c4 100644 --- a/engine/src/engine/vulkanapi/thread/thread_worker.cpp +++ b/engine/src/engine/vulkanapi/thread/thread_worker.cpp @@ -20,14 +20,14 @@ namespace vulkanapi { fn(); } } - void CommandThreadWorker::Invoke(voidFn fn) + void CommandThreadWorker::Invoke(const voidFn& fn) { mChannel.release(fn); } - void CommandThreadWorker::SyncInvoke(voidFn fn) + void CommandThreadWorker::SyncInvoke(const voidFn& fn) { - Invoke([=]() { + Invoke([=,this]() { fn(); mSemaphore.release(); }); diff --git a/engine/src/engine/vulkanapi/thread/thread_worker.h b/engine/src/engine/vulkanapi/thread/thread_worker.h index 5a4abdc..6a85a32 100644 --- a/engine/src/engine/vulkanapi/thread/thread_worker.h +++ b/engine/src/engine/vulkanapi/thread/thread_worker.h @@ -15,7 +15,7 @@ namespace vulkanapi { CommandThreadWorker(const string name, int buffer); ~CommandThreadWorker(); - void Invoke(voidFn fn); - void SyncInvoke(voidFn fn); + void Invoke(const voidFn& fn); + void SyncInvoke(const voidFn& fn); }; }; diff --git a/engine/src/engine/vulkanapi/thread/worker.cpp b/engine/src/engine/vulkanapi/thread/worker.cpp index 70d7cd1..f220206 100644 --- a/engine/src/engine/vulkanapi/thread/worker.cpp +++ b/engine/src/engine/vulkanapi/thread/worker.cpp @@ -8,49 +8,36 @@ namespace vulkanapi { ,mQueue(queue) ,mCommandPool(device, queueFlags, queue.QueueFamilyIndex()) ,mWork(name, 64) - ,mImmediateExeCmd(mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY) + ,mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY)) { - mImmediateExeCmd.Fence() = mCommandPool.AllocateFence(); } - void CommandWorker::Invoke(voidFn fn) + void CommandWorker::Invoke(const voidFn& fn) { mWork.Invoke(fn); } - void CommandWorker::InvokeBuffer(commandFn fn, voidFn callback) + void CommandWorker::InvokeBuffer(const commandFn& fn, const voidFn& callback) { - mWork.Invoke([=]() { + mWork.Invoke([=, this]() { CommandBuffer cmd = mCommandPool.Pop(); Buffer(cmd, fn, callback); mCommandPool.Push(cmd); }); } - - void CommandWorker::Buffer(CommandBuffer& cmd, commandFn fn, voidFn callback) + void CommandWorker::Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback) { - cmd.Reset(); cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); fn(cmd); cmd.EndRecord(); - cmd.Submit(mQueue.Ptr()); - cmd.WaitFofFence(mDevice.Ptr()); + VkFence fence = mDevice.PopFence(); + cmd.Submit(mQueue.Ptr(), fence); + mDevice.PushWaitFence(fence); callback(); } void CommandWorker::Flush() { - mWork.SyncInvoke([]() {}); - } - void CommandWorker::Draw(commandFn fn) - { - CommandBuffer cmd = mCommandPool.Pop(); - cmd.Reset(); - cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - fn(cmd); - cmd.EndRecord(); - cmd.Submit(mQueue.Ptr()); - cmd.WaitFofFence(mDevice.Ptr()); - mCommandPool.Push(cmd); + mWork.SyncInvoke([]{}); } bool CommandWorker::Present(VkPresentInfoKHR& presentInfo) { diff --git a/engine/src/engine/vulkanapi/thread/worker.h b/engine/src/engine/vulkanapi/thread/worker.h index e285c93..0f613d1 100644 --- a/engine/src/engine/vulkanapi/thread/worker.h +++ b/engine/src/engine/vulkanapi/thread/worker.h @@ -16,15 +16,19 @@ namespace vulkanapi { CommandBuffer mImmediateExeCmd; public: CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags); - - void Invoke(voidFn fn); - void InvokeBuffer(commandFn fn, voidFn callback); - void Buffer(CommandBuffer& cmd,commandFn fn, voidFn callback); + CommandPool& GetCommandPool() { + return mCommandPool; + } + Queue& GetQueue() { + return mQueue; + } + void Invoke(const voidFn& fn); + void InvokeBuffer(const commandFn& fn, const voidFn& callback); + void Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback); void Flush(); - void ImmediatelyExecute(commandFn fn, voidFn callback) { + void ImmediatelyExecute(const commandFn& fn, const voidFn callback) { Buffer(mImmediateExeCmd, fn , callback); } - void Draw(commandFn fn); bool Present(VkPresentInfoKHR& presentInfo); }; }; \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan_context.h b/engine/src/engine/vulkanapi/vulkan_context.h index 8209efe..c4ed77d 100644 --- a/engine/src/engine/vulkanapi/vulkan_context.h +++ b/engine/src/engine/vulkanapi/vulkan_context.h @@ -13,6 +13,7 @@ namespace vulkanapi { uint32_t presentFrame{0}; VkFence surfaceFence; VkSemaphore surfaceSemaphore; + VkCommandBuffer drawCommand; public: VulkanContext(RenderVulkanAPI* _API){ API = _API; diff --git a/engine/src/engine/vulkanapi/vulkanapi.cpp b/engine/src/engine/vulkanapi/vulkanapi.cpp index 18429c4..1062a6b 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.cpp +++ b/engine/src/engine/vulkanapi/vulkanapi.cpp @@ -68,11 +68,11 @@ namespace vulkanapi { { swapchain->Present(context); } - void RenderVulkanAPI::SetStaticMesh(Mesh& mesh) + void RenderVulkanAPI::SetStaticMesh(Mesh* mesh) { - auto Indices = mesh.GetIndices(); - auto Vertices = mesh.GetVertices(); - VulkanVAO& meshBuffer = VAOTable[mesh.GetGuid()]; + auto Indices = mesh->GetIndices(); + auto Vertices = mesh->GetVertices(); + VulkanVAO& meshBuffer = VAOTable[mesh->GetGuid()]; meshBuffer.indexCount = Indices.size(); meshBuffer.vertexCount = Vertices.size(); @@ -102,7 +102,7 @@ namespace vulkanapi { VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); meshBuffer.indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer.vertexBufferAlloc); - auto fn = [=](CommandBuffer& cmd) { + auto fn = [=, &meshBuffer](CommandBuffer& cmd) { cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer.vertexBuffer, vertexBufferSize); cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer.indexBuffer, indexBufferSize); }; @@ -119,48 +119,52 @@ namespace vulkanapi { Backend::TransferWorker->ImmediatelyExecute(fn, callback); } } - void RenderVulkanAPI::DrawStaticMesh(Mesh& mesh) + void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh) { - VulkanVAO& vulkanVAO = VAOTable[mesh.GetGuid()]; - VulkanPipeline& pipeline = PipelineTable[mesh.GetShaderGuid()]; uint32_t frame = context.frame; context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset); - Backend::RenderWorker->Draw([=](CommandBuffer& cmd) { - VkCommandBuffer ptr = cmd.Ptr(); - context.Pass->BeginPass(cmd, frame); - VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer }; - VkDeviceSize offsets[] = { 0 }; - VkViewport viewport = {}; - viewport.x = static_cast(mViewPortInfo.xOffset); - viewport.y = static_cast(mViewPortInfo.yOffset); - viewport.width = static_cast(mViewPortInfo.width); - viewport.height = static_cast(mViewPortInfo.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(ptr, 0, 1, &viewport); + VkFence fence{ context.surfaceFence}; + CommandBuffer cmd(context.drawCommand); + VkCommandBuffer ptr = cmd.Ptr(); + cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - VkRect2D scissor = {}; - scissor.offset = { mViewPortInfo.xOffset, mViewPortInfo.yOffset }; - scissor.extent = { mViewPortInfo.width, mViewPortInfo.height }; - vkCmdSetScissor(ptr, 0, 1, &scissor); + context.Pass->BeginPass(cmd, frame); + VulkanVAO& vulkanVAO = VAOTable[mesh->GetGuid()]; + VulkanPipeline& pipeline = PipelineTable[mesh->GetShaderGuid()]; + VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer }; + VkDeviceSize offsets[] = { 0 }; + VkViewport viewport = {}; + viewport.x = static_cast(mViewPortInfo.xOffset); + viewport.y = static_cast(mViewPortInfo.yOffset); + viewport.width = static_cast(mViewPortInfo.width); + viewport.height = static_cast(mViewPortInfo.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(ptr, 0, 1, &viewport); - vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); - vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, 1, &pipeline.descriptorSet, 0, VK_NULL_HANDLE); - vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0); - context.Pass->EndPass(cmd); - }); - Backend::RenderWorker->Flush(); + VkRect2D scissor = {}; + scissor.offset = { mViewPortInfo.xOffset, mViewPortInfo.yOffset }; + scissor.extent = { mViewPortInfo.width, mViewPortInfo.height }; + vkCmdSetScissor(ptr, 0, 1, &scissor); + + vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets); + vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); + vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, 1, &pipeline.descriptorSet, 0, VK_NULL_HANDLE); + vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0); + + context.Pass->EndPass(cmd); + cmd.EndRecord(); + cmd.Submit(Backend::RenderWorker->GetQueue().Ptr(), fence); } - void RenderVulkanAPI::LoadShader(Shader& shader) + void RenderVulkanAPI::LoadShader(Shader* shader) { vector shaderStages; std::map shaderModules; - auto device = backend.GetDevice(); - auto vertModule = shader.GetVertHandle()->Ptr(); + auto& device = backend.GetDevice(); + auto vertModule = shader->GetVertHandle()->Ptr(); shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule)); - auto fragModule = shader.GetFragHandle()->Ptr(); + auto fragModule = shader->GetFragHandle()->Ptr(); shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule)); for (auto& shaderModule : shaderModules) { @@ -171,7 +175,7 @@ namespace vulkanapi { shaderStageInfo.pName = "main"; shaderStages.push_back(shaderStageInfo); } - auto it = refl::UClass::MetaTable.find(shader.Name()); + auto it = refl::UClass::MetaTable.find(shader->Name()); auto meta = it->second->vtable.GetMeta("vkMeta"); // 设置顶点输入格式 VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; @@ -281,7 +285,7 @@ namespace vulkanapi { depthStencilInfo.front = {}; depthStencilInfo.back = {}; - auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader.GetInfo()); + auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo()); auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {}); VkGraphicsPipelineCreateInfo pipelineInfo{}; @@ -309,8 +313,8 @@ namespace vulkanapi { for (auto& shaderModule : shaderModules) vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr); - VulkanPipeline& vulkan_pipeline = PipelineTable[shader.GetGuid()]; - vulkan_pipeline.name = shader.Name(); + VulkanPipeline& vulkan_pipeline = PipelineTable[shader->GetGuid()]; + vulkan_pipeline.name = shader->Name(); vulkan_pipeline.pipeline = pipeLine; vulkan_pipeline.inUse = true; vulkan_pipeline.pipelineLayout = pipelineLayout; diff --git a/engine/src/engine/vulkanapi/vulkanapi.h b/engine/src/engine/vulkanapi/vulkanapi.h index feae040..53a1c66 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.h +++ b/engine/src/engine/vulkanapi/vulkanapi.h @@ -38,10 +38,10 @@ namespace vulkanapi void BeginFrame()override; void EndFrame()override; - void SetStaticMesh(Mesh& mesh)override; - void DrawStaticMesh(Mesh& mesh)override; + void SetStaticMesh(Mesh* mesh)override; + void DrawStaticMesh(Mesh* mesh)override; - void LoadShader(Shader& shader)override; + void LoadShader(Shader* shader)override; public: static RenderVulkanAPI* GetSingletonPtr() { return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr(); diff --git a/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp b/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp index 7eb6d2b..5e5fc78 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp +++ b/engine/src/engine/vulkanapi/wrapper/commandbuffer.cpp @@ -1,37 +1,8 @@ #include "commandbuffer.h" -#include "commandpool.h" -#include "device.h" namespace vulkanapi { - CommandBuffer::CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel 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() { vkResetCommandBuffer(mPtr, VkCommandBufferResetFlagBits::VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); - mPool.ResetFence(mFence); } void CommandBuffer::BeginRecord(VkCommandBufferUsageFlags flag) { @@ -54,17 +25,13 @@ namespace vulkanapi { copy.size = size; vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, ©); } - void CommandBuffer::Submit(VkQueue& queue) + void CommandBuffer::Submit(VkQueue& queue, VkFence fence) { 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); + vkQueueSubmit(queue, 1, &submitInfo, fence); } void CommandBuffer::BindVertexBuffer(VkBuffer buffer, uint32_t offset) { diff --git a/engine/src/engine/vulkanapi/wrapper/commandbuffer.h b/engine/src/engine/vulkanapi/wrapper/commandbuffer.h index a11ff2e..9629b83 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandbuffer.h +++ b/engine/src/engine/vulkanapi/wrapper/commandbuffer.h @@ -1,30 +1,19 @@ #pragma once #include "../vulkan.h" namespace vulkanapi { - class Device; - class CommandPool; class CommandBuffer { protected: - CommandPool& mPool; VkCommandBuffer mPtr; - VkFence mFence; public: - CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level); - ~CommandBuffer(); - CommandBuffer(CommandBuffer* other)noexcept:CommandBuffer(std::forward(*other)) {}; - CommandBuffer(CommandBuffer&& other)noexcept; + CommandBuffer(VkCommandBuffer ptr) : mPtr(ptr) {}; 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); + void Submit(VkQueue& queue,VkFence fence); void BindVertexBuffer(VkBuffer buffer, uint32_t offset); void BindIndexBuffers(VkBuffer buffer, uint32_t offset, VkIndexType type); diff --git a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp index df0cefd..6cbd4d5 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp +++ b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp @@ -7,9 +7,6 @@ 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, @@ -19,6 +16,13 @@ namespace vulkanapi { }; vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr); } + CommandPool::~CommandPool() + { + for (auto cb : mPool) { + FreeBuffer(cb.Ptr()); + } + mPool.clear(); + } VkCommandBuffer CommandPool::AllocateBuffer(VkCommandBufferLevel level) { VkCommandBufferAllocateInfo allocInfo{ @@ -37,18 +41,19 @@ namespace vulkanapi { vkFreeCommandBuffers(mDevice.Ptr(), mPtr, 1, &buf); buf = nullptr; } - void CommandPool::FreeFence(VkFence& fence) + CommandBuffer CommandPool::Pop() { - vkDestroyFence(mDevice.Ptr(), fence, NULL); - fence = nullptr; + if (mPool.empty()) { + return AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + } + CommandBuffer buffer = mPool.back(); + mPool.pop_back(); + return buffer; } - void CommandPool::ResetFence(VkFence& fence) + void CommandPool::Push(CommandBuffer& cmd) { - vkResetFences(mDevice.Ptr(), 1, &fence); - } - VkFence CommandPool::AllocateFence() - { - return mDevice.CreateFence(); + cmd.Reset(); + mPool.push_back(cmd); } } diff --git a/engine/src/engine/vulkanapi/wrapper/commandpool.h b/engine/src/engine/vulkanapi/wrapper/commandpool.h index e4f52df..f4be8bc 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandpool.h +++ b/engine/src/engine/vulkanapi/wrapper/commandpool.h @@ -9,25 +9,16 @@ namespace vulkanapi { protected: VkCommandPool mPtr; Device& mDevice; - zstd::pool mPool; + std::vector mPool; public: CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex); - + ~CommandPool(); VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level); void FreeBuffer(VkCommandBuffer& buf); - void FreeFence(VkFence& fence); - void ResetFence(VkFence& fence); - VkFence AllocateFence(); VkCommandPool& Ptr() { return mPtr; }; - CommandBuffer Pop() - { - return mPool.acquire(); - } - void Push(CommandBuffer& cmd) - { - mPool.release(&cmd); - } + CommandBuffer Pop(); + void Push(CommandBuffer& 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 de13c10..e40d975 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.cpp +++ b/engine/src/engine/vulkanapi/wrapper/device.cpp @@ -52,6 +52,20 @@ namespace vulkanapi { delete queue.second; } mQueueMap.clear(); + for (auto& fence : mFencePool) { + vkDestroyFence(mPtr, fence, nullptr); + } + mFencePool.clear(); + } + VkFence Device::CreateFence(VkFenceCreateFlags flags) + { + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + // 创建时立刻设置为signaled状态(否则第一次永远等不到) + fenceInfo.flags = flags; + VkFence fence; + VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence); + return fence; } Queue* Device::GetQueue(const string& name) { @@ -61,16 +75,23 @@ namespace vulkanapi { } return nullptr; } - VkFence Device::CreateFence() + VkFence Device::PopFence() { - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - // 创建时立刻设置为signaled状态(否则第一次永远等不到) - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - VkFence fence; - VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence); + if (mFencePool.empty()) { + return CreateFence(0); + } + std::lock_guard lock(mFenceMutex); + VkFence fence = mFencePool.back(); + mFencePool.pop_back(); return fence; } + void Device::PushWaitFence(VkFence fence) + { + vkWaitForFences(mPtr, 1, &fence, VK_TRUE, UINT64_MAX); + vkResetFences(mPtr, 1, &fence); + std::lock_guard lock(mFenceMutex); + mFencePool.push_back(fence); + } VkSemaphore Device::CreateSemaphore() { VkSemaphoreCreateInfo semaphoreInfo = {}; diff --git a/engine/src/engine/vulkanapi/wrapper/device.h b/engine/src/engine/vulkanapi/wrapper/device.h index 1342c3f..af4ba5e 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.h +++ b/engine/src/engine/vulkanapi/wrapper/device.h @@ -1,6 +1,7 @@ #pragma once #include "../vulkan.h" - +#include "zstd/pool.h" +#include namespace vulkanapi { class DeviceCreator; class Queue; @@ -10,6 +11,8 @@ namespace vulkanapi { VkDevice mPtr{ NULL }; VkPhysicalDevice mPhysical{NULL}; table mQueueMap; + vector mFencePool; + std::mutex mFenceMutex; public: VkDevice& Ptr() { return mPtr; @@ -20,9 +23,10 @@ namespace vulkanapi { public: Device(DeviceCreator& Creator); ~Device(); - + VkFence CreateFence(VkFenceCreateFlags flags); Queue* GetQueue(const string& name); - VkFence CreateFence(); + VkFence PopFence(); + void PushWaitFence(VkFence fence); VkSemaphore CreateSemaphore(); VkShaderModule CreateShaderModule(vector code); VkShaderModule CreateShaderModule(vector code); diff --git a/engine/src/engine/vulkanapi/wrapper/device_creator.h b/engine/src/engine/vulkanapi/wrapper/device_creator.h index 8a538f2..8dce958 100644 --- a/engine/src/engine/vulkanapi/wrapper/device_creator.h +++ b/engine/src/engine/vulkanapi/wrapper/device_creator.h @@ -22,6 +22,7 @@ namespace vulkanapi { VkPhysicalDeviceType desiredPhysicalDeviceType; vector desiredExtensions; vector desiredQueues; + int fencePoolCount = 256; public: Instance& instance; diff --git a/engine/src/engine/vulkanapi/wrapper/swapchain.cpp b/engine/src/engine/vulkanapi/wrapper/swapchain.cpp index 8423f44..d42f421 100644 --- a/engine/src/engine/vulkanapi/wrapper/swapchain.cpp +++ b/engine/src/engine/vulkanapi/wrapper/swapchain.cpp @@ -42,26 +42,31 @@ namespace vulkanapi { Creator.CreateSwapchainImages(mPtr, swapchain_images); auto args = Image::Make2DArgs(Creator.width, Creator.height, Creator.imageFormat, VK_SAMPLE_COUNT_8_BIT, Creator.imageUsage, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE); args.Sharing = VK_SHARING_MODE_EXCLUSIVE; + auto& pool = Backend::RenderWorker->GetCommandPool(); for (int i = 0; i < Creator.frames;i++) { mSurfaces.push_back(new Image(Creator.device,"swapchain" + to_string(i), swapchain_images[i], args)); mSemaphores.push_back(Creator.device.CreateSemaphore()); - mFences.push_back(Creator.device.CreateFence()); + mFences.push_back(Creator.device.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT)); + mCommands.push_back(pool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY)); } mFrames = Creator.frames; } void Swapchain::Aquire(VulkanContext& ctx) { + ctx.drawCommand = mCommands[ctx.frame]; ctx.surfaceFence = mFences[ctx.frame]; ctx.surfaceSemaphore = mSemaphores[ctx.frame]; - //if (vkWaitForFences(mDevice.Ptr(), 1, &ctx.surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) - //throw std::runtime_error("Failed to wait for fence!"); + if (vkWaitForFences(mDevice.Ptr(), 1, &ctx.surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) + throw std::runtime_error("Failed to wait for fence!"); + CommandBuffer cmd(ctx.drawCommand); + cmd.Reset();//surfaceSemaphore unsignaled state = > signaled state vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, ctx.surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame); vkResetFences(mDevice.Ptr(), 1, &ctx.surfaceFence); } void Swapchain::Present(VulkanContext& ctx) { VkSwapchainKHR swapChains[] = { mPtr }; - VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore }; + VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore };//wait signaled state VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.pWaitSemaphores = waitSemaphores; diff --git a/engine/src/engine/vulkanapi/wrapper/swapchain.h b/engine/src/engine/vulkanapi/wrapper/swapchain.h index de4c63c..c91d9c8 100644 --- a/engine/src/engine/vulkanapi/wrapper/swapchain.h +++ b/engine/src/engine/vulkanapi/wrapper/swapchain.h @@ -13,6 +13,7 @@ namespace vulkanapi { Device& mDevice; int mFrames; vector mSurfaces; + vector mCommands; vector mFences; vector mSemaphores; public: