vulkan bugfix

This commit is contained in:
ouczbs 2024-07-12 22:09:03 +08:00
parent 6975d71a19
commit 70f66ab7b9
28 changed files with 179 additions and 196 deletions

View File

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

View File

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

View File

@ -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<glShaderProgram>()->Ptr();
auto fragModule = shader.GetFragHandle<glShaderProgram>()->Ptr();
auto vertModule = shader->GetVertHandle<glShaderProgram>()->Ptr();
auto fragModule = shader->GetFragHandle<glShaderProgram>()->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);
}
}

View File

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

View File

@ -7,6 +7,6 @@ namespace engineapi {
void Mesh::BeginLoad()
{
mMaterial->BeginLoad();
RenderAPI::GetSingletonPtr()->SetStaticMesh(*this);
RenderAPI::GetSingletonPtr()->SetStaticMesh(this);
}
}

View File

@ -10,6 +10,6 @@ namespace engineapi {
}
void Shader::BeginLoad()
{
RenderAPI::GetSingletonPtr()->LoadShader(*this);
RenderAPI::GetSingletonPtr()->LoadShader(this);
}
}

View File

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

View File

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

View File

@ -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<uint32_t, vector<MeshRenderer*>>& batchs);
};
}

View File

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

View File

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

View File

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

View File

@ -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();
});

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@ namespace vulkanapi {
uint32_t presentFrame{0};
VkFence surfaceFence;
VkSemaphore surfaceSemaphore;
VkCommandBuffer drawCommand;
public:
VulkanContext(RenderVulkanAPI* _API){
API = _API;

View File

@ -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<float>(mViewPortInfo.xOffset);
viewport.y = static_cast<float>(mViewPortInfo.yOffset);
viewport.width = static_cast<float>(mViewPortInfo.width);
viewport.height = static_cast<float>(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<float>(mViewPortInfo.xOffset);
viewport.y = static_cast<float>(mViewPortInfo.yOffset);
viewport.width = static_cast<float>(mViewPortInfo.width);
viewport.height = static_cast<float>(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<VkPipelineShaderStageCreateInfo> shaderStages;
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
auto device = backend.GetDevice();
auto vertModule = shader.GetVertHandle<vkShaderProgram>()->Ptr();
auto& device = backend.GetDevice();
auto vertModule = shader->GetVertHandle<vkShaderProgram>()->Ptr();
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
auto fragModule = shader.GetFragHandle<vkShaderProgram>()->Ptr();
auto fragModule = shader->GetFragHandle<vkShaderProgram>()->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;

View File

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

View File

@ -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, &copy);
}
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)
{

View File

@ -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<CommandBuffer>(*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);

View File

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

View File

@ -9,25 +9,16 @@ namespace vulkanapi {
protected:
VkCommandPool mPtr;
Device& mDevice;
zstd::pool<CommandBuffer> mPool;
std::vector<CommandBuffer> 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);
};
}

View File

@ -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<std::mutex> 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<std::mutex> lock(mFenceMutex);
mFencePool.push_back(fence);
}
VkSemaphore Device::CreateSemaphore()
{
VkSemaphoreCreateInfo semaphoreInfo = {};

View File

@ -1,6 +1,7 @@
#pragma once
#include "../vulkan.h"
#include "zstd/pool.h"
#include <mutex>
namespace vulkanapi {
class DeviceCreator;
class Queue;
@ -10,6 +11,8 @@ namespace vulkanapi {
VkDevice mPtr{ NULL };
VkPhysicalDevice mPhysical{NULL};
table<const string*, Queue*> mQueueMap;
vector<VkFence> 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<char> code);
VkShaderModule CreateShaderModule(vector<uint32_t> code);

View File

@ -22,6 +22,7 @@ namespace vulkanapi {
VkPhysicalDeviceType desiredPhysicalDeviceType;
vector<string> desiredExtensions;
vector<DesiredQueue> desiredQueues;
int fencePoolCount = 256;
public:
Instance& instance;

View File

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

View File

@ -13,6 +13,7 @@ namespace vulkanapi {
Device& mDevice;
int mFrames;
vector<Image*> mSurfaces;
vector<VkCommandBuffer> mCommands;
vector<VkFence> mFences;
vector<VkSemaphore> mSemaphores;
public: