update zlib.zstd.pool

This commit is contained in:
ouczbs 2024-03-13 22:29:47 +08:00
parent e7c702113f
commit 5e9b0bb305
48 changed files with 343 additions and 120 deletions

View File

@ -0,0 +1,51 @@
#include <concepts>
namespace zstd {
template<std::move_constructible T>
class pool {
using NewFn = std::function<T()>;
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<typename... Args>
void release(Args... args) {
if (m_head >= m_tail + m_size) {
return;
}
std::construct_at(m_buf + m_head % m_size, std::forward<Args>(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));
};
};
}

View File

@ -0,0 +1,58 @@
#include <concepts>
namespace zstd {
template<size_t T>
struct static_buffer {
char data[T];
};
template<std::move_constructible T, size_t T_capacity = 1>
class channel_static {
static_assert(T_capacity != 0);
protected:
int m_tail;
int m_head;
static_buffer<sizeof(T)> 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<typename... Args>
void release(Args... args) {
std::unique_lock<std::mutex> 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>(args)...);
if (m_head++ == m_tail)
m_cv.notify_one();
};
T acquire() {
std::unique_lock<std::mutex> 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));
};
};
}

View File

@ -1,6 +1,6 @@
#include <condition_variable> #include <condition_variable>
#include <semaphore> #include <semaphore>
#include <iostream> #include <concepts>
namespace zstd { namespace zstd {
template<std::move_constructible T> template<std::move_constructible T>
class channel { class channel {

View File

@ -1,6 +1,6 @@
#include <condition_variable> #include <condition_variable>
#include <semaphore> #include <semaphore>
#include <iostream> #include <concepts>
namespace zstd { namespace zstd {
template<size_t T> template<size_t T>
struct static_buffer { struct static_buffer {

View File

@ -1,29 +1,29 @@
set_languages("cxx20") set_languages("cxx20")
target("zcoro") target("zlib")
set_kind("static") set_kind("static")
add_includedirs("include", {public = true}) add_includedirs("include", {public = true})
add_files("src/**/*.cpp") add_files("src/**/*.cpp")
add_headerfiles("include/**/*.h") add_headerfiles("include/**/*.h")
target("zcoro_test") target("zlib_test")
set_kind("binary") set_kind("binary")
add_deps("zcoro") add_deps("zlib")
add_files("main.cpp") add_files("main.cpp")
-- target("zcoro_test01_mutex") -- target("zlib_test01_mutex")
-- set_kind("binary") -- set_kind("binary")
-- add_deps("zcoro") -- add_deps("zlib")
-- add_files("test/01mutex.cpp") -- add_files("test/01mutex.cpp")
-- target("zcoro_test02_condition") -- target("zlib_test02_condition")
-- set_kind("binary") -- set_kind("binary")
-- add_deps("zcoro") -- add_deps("zlib")
-- add_files("test/02condition.cpp") -- add_files("test/02condition.cpp")
target("zcoro_test03_semaphore") target("zlib_test03_semaphore")
set_kind("binary") set_kind("binary")
add_deps("zcoro") add_deps("zlib")
add_files("test/03semaphore.cpp") add_files("test/03semaphore.cpp")
-- target("zcoro_test04_promise") -- target("zlib_test04_promise")
-- set_kind("binary") -- set_kind("binary")
-- add_deps("zcoro") -- add_deps("zlib")
-- add_files("test/04promise.cpp") -- add_files("test/04promise.cpp")

View File

@ -24,16 +24,8 @@ namespace engineapi
string mName; string mName;
public: public:
Asset(string name, uint32_t flags):mName(name),mFlags(flags) {}; Asset(string name, uint32_t flags):mName(name),mFlags(flags) {};
virtual void SyncLoad() {};
virtual void AsyncLoad() {};
virtual void BeginLoad() { virtual void BeginLoad() {
mFlags |= ASSET_LOADING_FLAG; mFlags |= ASSET_LOADING_FLAG;
if (IsAsync()) {
AsyncLoad();
}
else {
SyncLoad();
}
}; };
virtual void EndLoad() { virtual void EndLoad() {
mFlags &= ~ASSET_LOADING_FLAG; mFlags &= ~ASSET_LOADING_FLAG;

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "asset.h" #include "../asset.h"
#include "math/math.h" #include "math/math.h"
#include "asset_enum.h" #include "asset_enum.h"
// 顶点最多关联4个骨骼 // 顶点最多关联4个骨骼

View File

@ -1,2 +0,0 @@
#pragma once
#include "asset/asset_struct.h"

View File

@ -0,0 +1,2 @@
#pragma once
#include "asset/render/asset_struct.h"

View File

@ -1,4 +1,4 @@
#include "asset.h" #include "asset_render.h"
namespace engineapi { namespace engineapi {
class Material : public Asset { class Material : public Asset {

View File

@ -8,8 +8,9 @@ namespace engineapi {
{ {
BeginLoad(); BeginLoad();
} }
void Mesh::SyncLoad() void Mesh::BeginLoad()
{ {
RenderAPI::GetInstance()->SetStaticMesh(VAO, mVertices, mIndices, IsAsync()); Asset::BeginLoad();
RenderAPI::GetInstance()->SetStaticMesh(this);
} }
} }

View File

@ -1,9 +1,10 @@
#pragma once #pragma once
#include "asset.h" #include "asset_render.h"
namespace engineapi { namespace engineapi {
class Texture; class Texture;
class Material; class Material;
class Mesh : public Asset { class Mesh : public Asset {
friend class RenderVulkanAPI;
protected: protected:
uint32_t VAO = 0; uint32_t VAO = 0;
vector<Vertex> mVertices; vector<Vertex> mVertices;
@ -11,6 +12,6 @@ namespace engineapi {
public: public:
Mesh(string name, uint32_t flags, vector<Vertex>& vertices, vector<uint32_t>& indices); Mesh(string name, uint32_t flags, vector<Vertex>& vertices, vector<uint32_t>& indices);
void SyncLoad()override; void BeginLoad()override;
}; };
}; };

View File

@ -1,12 +1,14 @@
#include "model.h" #include "model.h"
#include "zlog.h" #include "zlog.h"
#include "mesh.h"
#include "assimp/Importer.hpp" #include "assimp/Importer.hpp"
#include "assimp/scene.h" #include "assimp/scene.h"
#include "assimp/postprocess.h" #include "assimp/postprocess.h"
#include "asset/asset_manager.h" #include "asset/asset_manager.h"
namespace engineapi { namespace engineapi {
void Model::SyncLoad() void Model::BeginLoad()
{ {
Asset::BeginLoad();
// 用ASSIMP加载模型文件 // 用ASSIMP加载模型文件
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "mesh.h" #include "asset_render.h"
class aiNode; class aiNode;
class aiMesh; class aiMesh;
class aiScene; class aiScene;
@ -10,7 +10,7 @@ namespace engineapi {
public: public:
using Asset::Asset; using Asset::Asset;
void SyncLoad()override; void BeginLoad()override;
void ProcessNode(const aiNode* pNode, const aiScene* pScene); void ProcessNode(const aiNode* pNode, const aiScene* pScene);
Mesh* ProcessMesh(const aiMesh* mesh); Mesh* ProcessMesh(const aiMesh* mesh);
}; };

View File

@ -1,4 +1,4 @@
#include "asset.h" #include "asset_render.h"
namespace engineapi { namespace engineapi {
class Texture : public Asset { class Texture : public Asset {

View File

@ -10,7 +10,7 @@ namespace engineapi {
void RenderAPI::MakeInstance() void RenderAPI::MakeInstance()
{ {
#ifdef VULKAN_API #ifdef VULKAN_API
Instance = new vulkanapi::RenderVulkanAPI(); Instance = new RenderVulkanAPI();
#endif #endif
} }
} }

View File

@ -1,13 +1,14 @@
#pragma once #pragma once
#include "asset/asset_struct.h" #include "asset/asset_render.h"
namespace engineapi namespace engineapi
{ {
class Mesh;
class RenderAPI class RenderAPI
{ {
public: public:
virtual void BeginFrame() = 0; virtual void BeginFrame() = 0;
virtual void EndFrame() = 0; virtual void EndFrame() = 0;
virtual void SetStaticMesh(uint32_t& VAO, vector<Vertex>& vertices, vector<uint32_t>& indices, bool Async) = 0; virtual void SetStaticMesh(Mesh* mesh) = 0;
public: public:
static RenderAPI* Instance; static RenderAPI* Instance;
static void MakeInstance(); static void MakeInstance();

View File

@ -12,9 +12,6 @@ namespace vulkanapi {
auto deviceCreator = DeviceCreator(*mInstance); auto deviceCreator = DeviceCreator(*mInstance);
deviceCreator.AddWindowExtension(); 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::TransferQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
deviceCreator.AddQueue(Queue::RenderQueue, 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); deviceCreator.AddQueue(Queue::ComputeQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);

View File

@ -1,52 +1,43 @@
#include "worker.h" #include "worker.h"
#include "thread_worker.h"
#include "../wrapper/queue.h" #include "../wrapper/queue.h"
#include "../wrapper/device.h" #include "../wrapper/device.h"
#include "../wrapper/commandpool.h"
#include "../wrapper/commandbuffer.h"
namespace vulkanapi { namespace vulkanapi {
CommandWorker::CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags) CommandWorker::CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
:mName(name) :mName(name)
,mDevice(device)
,mQueue(queue) ,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) 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([=]() { mWork.Invoke([=]() {
Buffer(fn); 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); fn(cmd);
cmd->EndRecord(); cmd.EndRecord();
} cmd.Submit(mQueue.Ptr());
cmd.WaitFofFence(mDevice.Ptr());
void CommandWorker::InvokeSubmit() mCommandPool.Push(cmd);
{ callback();
mWork->Invoke([=]() {
Submit();
});
}
void CommandWorker::Submit()
{
} }
void CommandWorker::Flush() void CommandWorker::Flush()
{ {
mWork->SyncInvoke([]() {}); mWork.SyncInvoke([]() {});
} }
} }

View File

@ -1,24 +1,28 @@
#pragma once #pragma once
#include "../vulkan.h" #include "../vulkan.h"
#include "thread_worker.h"
#include "../wrapper/commandpool.h"
#include "../wrapper/commandbuffer.h"
namespace vulkanapi { namespace vulkanapi {
class Device; class Device;
class CommandThreadWorker;
class CommandPool;
class Queue; class Queue;
class CommandWorker { class CommandWorker {
protected: protected:
Device& mDevice;
Queue& mQueue; Queue& mQueue;
const string& mName; const string& mName;
CommandThreadWorker* mWork; CommandThreadWorker mWork;
CommandPool* mCommandPool; CommandPool mCommandPool;
CommandBuffer mImmediateExeCmd;
public: public:
CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags); CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags);
void Invoke(voidFn fn); void Invoke(voidFn fn);
void InvokeBuffer(commandFn fn); void InvokeBuffer(commandFn fn, voidFn callback);
void Buffer(commandFn fn); void Buffer(CommandBuffer& cmd,commandFn fn, voidFn callback);
void InvokeSubmit();
void Submit();
void Flush(); void Flush();
void ImmediatelyExecute(commandFn fn, voidFn callback) {
Buffer(mImmediateExeCmd, fn , callback);
}
}; };
}; };

View File

@ -13,5 +13,5 @@ using std::string;
using std::vector; using std::vector;
using std::map; using std::map;
using voidFn = std::function<void()>; using voidFn = std::function<void()>;
using commandFn = std::function<void(CommandBuffer* cmd)>; using commandFn = std::function<void(CommandBuffer& cmd)>;
} }

View File

@ -3,7 +3,7 @@
// AMD写的Vulkan内存分配器 // AMD写的Vulkan内存分配器
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include "math/matrix4.h" #include "math/matrix4.h"
#include "asset/asset_struct.h" #include "render/asset/asset_render.h"
using engineapi::Matrix4; using engineapi::Matrix4;
using engineapi::FrameBufferType; using engineapi::FrameBufferType;
using engineapi::ClearInfo; using engineapi::ClearInfo;

View File

@ -3,7 +3,8 @@
#include "wrapper/buffer.h" #include "wrapper/buffer.h"
#include "wrapper/commandbuffer.h" #include "wrapper/commandbuffer.h"
#include "thread/worker.h" #include "thread/worker.h"
namespace vulkanapi { #include "render/asset/mesh.h"
namespace engineapi {
RenderVulkanAPI::RenderVulkanAPI() RenderVulkanAPI::RenderVulkanAPI()
:backend("vulkan") :backend("vulkan")
{ {
@ -17,14 +18,14 @@ namespace vulkanapi {
{ {
} }
void RenderVulkanAPI::SetStaticMesh(uint32_t& VAO, vector<Vertex>& vertices, vector<uint32_t>& indices, bool Async) void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
{ {
auto meshBuffer = GetNextVAO(VAO); auto meshBuffer = GetNextVAO(mesh->VAO);
meshBuffer->indexCount = indices.size(); meshBuffer->indexCount = mesh->mIndices.size();
meshBuffer->vertexCount = vertices.size(); meshBuffer->vertexCount = mesh->mVertices.size();
// ----------------------------------------------- Vertex Buffer ----------------------------------------------- // ----------------------------------------------- Vertex Buffer -----------------------------------------------
VkDeviceSize vertexBufferSize = sizeof(Vertex) * vertices.size(); VkDeviceSize vertexBufferSize = sizeof(Vertex) * mesh->mVertices.size();
VmaAllocationCreateInfo vertexStagingAllocInfo = {}; VmaAllocationCreateInfo vertexStagingAllocInfo = {};
VkBufferCreateInfo vertexStagingBufferInfo = Buffer::MakeStageInfo(vertexStagingAllocInfo, vertexBufferSize); VkBufferCreateInfo vertexStagingBufferInfo = Buffer::MakeStageInfo(vertexStagingAllocInfo, vertexBufferSize);
@ -32,20 +33,25 @@ namespace vulkanapi {
VkBuffer vertexStagingBuffer = Buffer::CreateBuffer(vertexStagingBufferInfo, vertexStagingAllocInfo, vertexStagingBufferAlloc); VkBuffer vertexStagingBuffer = Buffer::CreateBuffer(vertexStagingBufferInfo, vertexStagingAllocInfo, vertexStagingBufferAlloc);
// 拷贝数据到StagingBuffer // 拷贝数据到StagingBuffer
Buffer::CopyData(vertexStagingBufferAlloc, vertices.data(), vertexBufferSize); Buffer::CopyData(vertexStagingBufferAlloc, mesh->mVertices.data(), vertexBufferSize);
VkBufferUsageFlags flags = 0;//加入光线追踪 VkBufferUsageFlags flags = 0;//加入光线追踪
VmaAllocationCreateInfo vertexBufferAllocInfo = {}; VmaAllocationCreateInfo vertexBufferAllocInfo = {};
VkBufferCreateInfo vertexBufferInfo = Buffer::MakeDeviceInfo(vertexBufferAllocInfo, vertexBufferSize, flags); VkBufferCreateInfo vertexBufferInfo = Buffer::MakeDeviceInfo(vertexBufferAllocInfo, vertexBufferSize, flags);
meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexBufferInfo, vertexBufferAllocInfo, meshBuffer->vertexBufferAlloc); meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexBufferInfo, vertexBufferAllocInfo, meshBuffer->vertexBufferAlloc);
auto fn = [=](CommandBuffer* cmd) { auto fn = [=](CommandBuffer& cmd) {
cmd->CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize); cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize);
}; };
if (Async) { auto callback = [=]() {
Backend::TransferWorker->InvokeBuffer(fn); // 销毁StagingBuffer
Buffer::DestroyBuffer(vertexStagingBuffer, vertexStagingBufferAlloc);
mesh->EndLoad();
};
if (mesh->IsAsync()) {
Backend::TransferWorker->InvokeBuffer(fn, callback);
} }
else { else {
Backend::TransferWorker->InvokeBuffer(fn); Backend::TransferWorker->ImmediatelyExecute(fn, callback);
} }
} }
VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& VAO_index) VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& VAO_index)

View File

@ -2,10 +2,10 @@
#include "backend.h" #include "backend.h"
#include "render/renderapi.h" #include "render/renderapi.h"
#include "vulkan_struct.h" #include "vulkan_struct.h"
using engineapi::Vertex; using namespace vulkanapi;
namespace vulkanapi namespace engineapi
{ {
class RenderVulkanAPI : public engineapi::RenderAPI class RenderVulkanAPI : public RenderAPI
{ {
public: public:
Backend backend; Backend backend;
@ -15,13 +15,12 @@ namespace vulkanapi
virtual void BeginFrame()override; virtual void BeginFrame()override;
virtual void EndFrame()override; virtual void EndFrame()override;
virtual void SetStaticMesh(Mesh* mesh)override;
virtual void SetStaticMesh(uint32_t& VAO, vector<Vertex>& vertices, vector<uint32_t>& indices, bool Async)override;
public: public:
VulkanVAO* GetNextVAO(uint32_t& VAO_index); VulkanVAO* GetNextVAO(uint32_t& VAO_index);
public: public:
static RenderVulkanAPI* GetInstance() { static RenderVulkanAPI* GetInstance() {
return (RenderVulkanAPI*)engineapi::RenderAPI::GetInstance(); return (RenderVulkanAPI*)RenderAPI::GetInstance();
} }
}; };
} }

View File

@ -6,6 +6,7 @@
#include "wrapper/swapchain_creator.h" #include "wrapper/swapchain_creator.h"
#include "vulkanapi.h" #include "vulkanapi.h"
#include "zlog.h" #include "zlog.h"
using engineapi::RenderVulkanAPI;
namespace vulkanapi { namespace vulkanapi {
Window::Window(int frames, uint32_t width, uint32_t height, const char* title) Window::Window(int frames, uint32_t width, uint32_t height, const char* title)
:engineapi::Window(width, height , title) :engineapi::Window(width, height , title)

View File

@ -5,7 +5,7 @@ namespace vulkanapi {
class Swapchain; class Swapchain;
class Window : public engineapi::Window { class Window : public engineapi::Window {
protected: protected:
VkSurfaceKHR mSurfaceKHR{NULL}; VkSurfaceKHR mSurfaceKHR;
Swapchain* mSwapchain; Swapchain* mSwapchain;
public: public:
Window(int frames, uint32_t width, uint32_t height, const char* title); Window(int frames, uint32_t width, uint32_t height, const char* title);

View File

@ -59,4 +59,9 @@ namespace vulkanapi {
memcpy(vertexData, data, size); memcpy(vertexData, data, size);
vmaUnmapMemory(vmaAllocator, allocation); vmaUnmapMemory(vmaAllocator, allocation);
} }
void Buffer::DestroyBuffer(VkBuffer buffer, VmaAllocation bufferAlloc)
{
// 销毁StagingBuffer
vmaDestroyBuffer(vmaAllocator, buffer, bufferAlloc);
}
} }

View File

@ -14,5 +14,6 @@ namespace vulkanapi {
VmaAllocationCreateInfo& allocationCreateInfo, VmaAllocationCreateInfo& allocationCreateInfo,
VmaAllocation& allocation); VmaAllocation& allocation);
static void CopyData(VmaAllocation& allocation,void* data, VkDeviceSize size); static void CopyData(VmaAllocation& allocation,void* data, VkDeviceSize size);
static void DestroyBuffer(VkBuffer buffer, VmaAllocation bufferAlloc);
}; };
} }

View File

@ -3,9 +3,30 @@
#include "device.h" #include "device.h"
namespace vulkanapi { namespace vulkanapi {
CommandBuffer::CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level) 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() void CommandBuffer::Reset()
{ {
@ -32,5 +53,17 @@ namespace vulkanapi {
copy.size = size; copy.size = size;
vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, &copy); vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, &copy);
} }
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);
}
} }

View File

@ -5,13 +5,24 @@ namespace vulkanapi {
class CommandPool; class CommandPool;
class CommandBuffer { class CommandBuffer {
protected: protected:
CommandPool& mPool;
VkCommandBuffer mPtr; VkCommandBuffer mPtr;
VkFence mFence;
public: public:
CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level); CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level);
~CommandBuffer();
CommandBuffer(CommandBuffer&& other)noexcept;
VkCommandBuffer& Ptr() {
return mPtr;
};
VkFence& Fence() {
return mFence;
};
void Reset(); void Reset();
void BeginRecord(VkCommandBufferUsageFlags flag); void BeginRecord(VkCommandBufferUsageFlags flag);
void EndRecord(); void EndRecord();
void CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); void CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
void Submit(VkQueue& queue);
void WaitFofFence(VkDevice& device);
}; };
} }

View File

@ -1,5 +1,5 @@
#include "commandpool.h" #include "commandpool.h"
#include "commandbuffer.h"
#include "device.h" #include "device.h"
#include "queue.h" #include "queue.h"
#include "zlog.h" #include "zlog.h"
@ -7,6 +7,9 @@ namespace vulkanapi {
CommandPool::CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex) CommandPool::CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex)
:mPtr(nullptr) :mPtr(nullptr)
,mDevice(device) ,mDevice(device)
,mPool([=]()->CommandBuffer {
return std::move(CommandBuffer(*this, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
}, 256)
{ {
VkCommandPoolCreateInfo pCreateInfo{ VkCommandPoolCreateInfo pCreateInfo{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
@ -16,7 +19,7 @@ namespace vulkanapi {
}; };
vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr); vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr);
} }
VkCommandBuffer CommandPool::Allocate(VkCommandBufferLevel level) VkCommandBuffer CommandPool::AllocateBuffer(VkCommandBufferLevel level)
{ {
VkCommandBufferAllocateInfo allocInfo{ VkCommandBufferAllocateInfo allocInfo{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, //sType VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, //sType
@ -29,18 +32,21 @@ namespace vulkanapi {
vkAllocateCommandBuffers(mDevice.Ptr(), &allocInfo, &cmd); vkAllocateCommandBuffers(mDevice.Ptr(), &allocInfo, &cmd);
return cmd; return cmd;
} }
CommandBuffer* CommandPool::Pop() void CommandPool::FreeBuffer(VkCommandBuffer& buf)
{ {
if (top < mBufferList.size()) { vkFreeCommandBuffers(mDevice.Ptr(), mPtr, 1, &buf);
auto cmd = mBufferList[top]; buf = nullptr;
cmd->Reset();
top++;
return cmd;
} }
CommandBuffer* cmd = new CommandBuffer(*this, VK_COMMAND_BUFFER_LEVEL_PRIMARY); void CommandPool::FreeFence(VkFence& fence)
mBufferList.push_back(cmd); {
top++; vkDestroyFence(mDevice.Ptr(), fence, NULL);
return cmd; fence = nullptr;
}
VkFence CommandPool::AllocateFence()
{
VkFence fence;
mDevice.CreateFence(fence);
return fence;
} }
} }

View File

@ -1,22 +1,33 @@
#pragma once #pragma once
#include "../vulkan.h" #include "../vulkan.h"
#include "zstd/pool.h"
#include "zlog.h"
#include "commandbuffer.h"
namespace vulkanapi { namespace vulkanapi {
class Device; class Device;
class Queue; class Queue;
class CommandBuffer;
class CommandPool { class CommandPool {
protected: protected:
VkCommandPool mPtr; VkCommandPool mPtr;
Device& mDevice; Device& mDevice;
vector<CommandBuffer*> mBufferList; zstd::pool<CommandBuffer> mPool;
int top = 0;
public: public:
CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex); CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex);
VkCommandBuffer Allocate(VkCommandBufferLevel level); VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level);
CommandBuffer* Pop(); void FreeBuffer(VkCommandBuffer& buf);
void FreeFence(VkFence& fence);
VkFence AllocateFence();
VkCommandPool& Ptr() { VkCommandPool& Ptr() {
return mPtr; return mPtr;
}; };
CommandBuffer Pop()
{
return std::move(mPool.acquire());
}
void Push(CommandBuffer& cmd)
{
mPool.release(std::forward<CommandBuffer>(cmd));
}
}; };
} }

View File

@ -5,16 +5,23 @@
namespace vulkanapi { namespace vulkanapi {
Device::Device(DeviceCreator& Creator) Device::Device(DeviceCreator& Creator)
{ {
//物理设备
Creator.FindDevice(mPhysical); Creator.FindDevice(mPhysical);
//队列信息
vector<VkQueueFamilyProperties> queue_families; vector<VkQueueFamilyProperties> queue_families;
Creator.CheckAvailableQueueFamilies(mPhysical, queue_families); Creator.CheckAvailableQueueFamilies(mPhysical, queue_families);
vector<VkDeviceQueueCreateInfo> queue_create_infos; vector<VkDeviceQueueCreateInfo> queue_create_infos;
vector<vector<float>> queue_prioritie; vector<vector<float>> queue_prioritie;
Creator.QueueCreateInfos(queue_create_infos, queue_prioritie, queue_families); Creator.QueueCreateInfos(queue_create_infos, queue_prioritie, queue_families);
//扩展
auto extensions = Creator.EnabledExtensionNames(); auto extensions = Creator.EnabledExtensionNames();
//特性
VkPhysicalDeviceFeatures2 deviceFeatures = Creator.GetDeviceFeature2();
VkPhysicalDeviceVulkan12Features deviceVulkan12Features = Creator.GetVulkan12Features();
deviceFeatures.pNext = &deviceVulkan12Features;
VkDeviceCreateInfo device_create_info = { VkDeviceCreateInfo device_create_info = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType
nullptr, // const void * pNext &deviceFeatures, // const void * pNext
0, // VkDeviceCreateFlags flags 0, // VkDeviceCreateFlags flags
static_cast<uint32_t>(queue_create_infos.size()), // uint32_t queueCreateInfoCount static_cast<uint32_t>(queue_create_infos.size()), // uint32_t queueCreateInfoCount
queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos
@ -22,7 +29,7 @@ namespace vulkanapi {
nullptr, // const char * const * ppEnabledLayerNames nullptr, // const char * const * ppEnabledLayerNames
static_cast<uint32_t>(extensions.size()), // uint32_t enabledExtensionCount static_cast<uint32_t>(extensions.size()), // uint32_t enabledExtensionCount
extensions.data(), // const char * const * ppEnabledExtensionNames extensions.data(), // const char * const * ppEnabledExtensionNames
&Creator.desiredPhysicalDeviceFeatures // const VkPhysicalDeviceFeatures * pEnabledFeatures nullptr // const VkPhysicalDeviceFeatures * pEnabledFeatures
}; };
#ifdef Z_USE_GRAPHIC_DEBUG #ifdef Z_USE_GRAPHIC_DEBUG
auto layers = Creator.EnabledLayerNames(); auto layers = Creator.EnabledLayerNames();
@ -54,5 +61,14 @@ namespace vulkanapi {
} }
return nullptr; 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;
}
} }

View File

@ -22,5 +22,6 @@ namespace vulkanapi {
~Device(); ~Device();
Queue* GetQueue(const string& name); Queue* GetQueue(const string& name);
bool CreateFence(VkFence& fence);
}; };
}; };

View File

@ -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) void DeviceCreator::AddExtension(string extensionName)
{ {
desiredExtensions.push_back(extensionName); desiredExtensions.push_back(extensionName);

View File

@ -37,6 +37,9 @@ namespace vulkanapi {
void QueueCreateInfos(vector<VkDeviceQueueCreateInfo>& queue_create_infos, void QueueCreateInfos(vector<VkDeviceQueueCreateInfo>& queue_create_infos,
vector<vector<float>>& queue_prioritie, vector<vector<float>>& queue_prioritie,
vector<VkQueueFamilyProperties>& queue_families); vector<VkQueueFamilyProperties>& queue_families);
void EnableDeviceFeatures();
VkPhysicalDeviceFeatures2 GetDeviceFeature2();
VkPhysicalDeviceVulkan12Features GetVulkan12Features();
#ifdef Z_USE_GRAPHIC_DEBUG #ifdef Z_USE_GRAPHIC_DEBUG
public: public:
vector<string> desiredLayers; vector<string> desiredLayers;

View File

@ -15,7 +15,7 @@ int main(int argc, char** argv)
auto wnd = vulkanapi::Window(3, 640, 720, name); auto wnd = vulkanapi::Window(3, 640, 720, name);
ActorProperty property; ActorProperty property;
property.id = 1; 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"; property.path = "assets/models/cube.obj";
AssetManager instance; AssetManager instance;
AssetManager::Instance = &instance; AssetManager::Instance = &instance;

View File

@ -6,7 +6,7 @@ target("zengine")
set_kind("binary") set_kind("binary")
set_rundir(".") set_rundir(".")
add_rules("volk.env") add_rules("volk.env")
add_deps("zcoro","zlog") add_deps("zlib","zlog")
add_packages("vulkansdk","tinyobjloader","assimp") add_packages("vulkansdk","tinyobjloader","assimp")
add_includedirs("src/engine") add_includedirs("src/engine")
add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator") add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator")