update vulkan api

This commit is contained in:
ouczbs 2024-08-23 22:13:05 +08:00
parent 722396f613
commit 6f423500b6
38 changed files with 1426 additions and 12 deletions

View File

@ -0,0 +1,20 @@
#pragma once
#include "asset/asset.h"
#include "shader.h"
namespace api {
class Material : public Asset {
protected:
RscHandle<Shader> mShader;
friend class Scene;
public:
Material();
~Material();
void BeginLoad() {
mShader->BeginLoad();
}
RscHandle<Shader> GetShader() {
return mShader;
}
};
};

View File

@ -0,0 +1,33 @@
#pragma once
#include "material.h"
#include "vertex.h"
#include "refl/std/parray.h"
namespace api {
using refl::parray;
class Mesh : public Asset {
protected:
RscHandle<Material> mMaterial;
parray<Vertex> mVertices;
vector<uint32_t> mIndices;
public:
Mesh();
void BeginLoad();
public:
Guid GetShaderGuid() {
return mMaterial->GetShader().guid;
}
void SetMaterial(RscHandle<Material> material) {
mMaterial = material;
}
RscHandle<Material> GetMaterial() {
return mMaterial;
}
parray<Vertex>& GetVertices() {
return mVertices;
}
vector<uint32_t>& GetIndices() {
return mIndices;
}
};
};

View File

@ -0,0 +1,25 @@
#pragma once
#include "asset/res/resource_handle.h"
namespace api {
class ShaderProgram : public Resource<ShaderProgram> {};
class Shader : public Asset {
private:
UPROPERTY()
RscHandle<ShaderProgram> mVert;
UPROPERTY()
RscHandle<ShaderProgram> mFrag;
friend class Scene;
public:
Shader();
~Shader();
void BeginLoad();
template<typename T = ShaderProgram>
RscHandle<T> GetVertHandle() {
return mVert;
}
template<typename T = ShaderProgram>
RscHandle<T> GetFragHandle() {
return mFrag;
}
};
};

View File

@ -0,0 +1,46 @@
#pragma once
#include "math/vector3.h"
#include "math/vector2.h"
#include "refl/pch.h"
// 顶点最多关联4个骨骼
#define MAX_NUM_BONES_PER_VERTEX 4
namespace api {
using refl::type_info;
struct Vertex {};
struct PosVertex : public Vertex {
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk({}, uint32_t{ VK_FORMAT_R32G32B32_SFLOAT })
Vector3 Position = {};
};
struct TexVertex : public Vertex {
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk({}, uint32_t{ VK_FORMAT_R32G32B32_SFLOAT })
Vector3 Position = {};
UPROPERTY_gl({}, glVertexMeta{ 2, GL_FLOAT, GL_FALSE })
UPROPERTY_vk()
Vector2 TexCoords = {};
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk()
Vector3 Normal = {};
};
struct BoneVertex : public Vertex
{
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk({}, uint32_t{ VK_FORMAT_R32G32B32_SFLOAT })
Vector3 Position = {};
UPROPERTY_gl({}, glVertexMeta{ 2, GL_FLOAT, GL_FALSE })
UPROPERTY_vk()
Vector2 TexCoords = {};
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk()
Vector3 Normal = {};
UPROPERTY_gl({}, glVertexMeta{ 3, GL_FLOAT, GL_FALSE })
UPROPERTY_vk()
Vector3 Tangent = {};
// 骨骼蒙皮数据
UPROPERTY_vk()
float Weights[MAX_NUM_BONES_PER_VERTEX] = {};
UPROPERTY_vk()
uint32_t BoneIDs[MAX_NUM_BONES_PER_VERTEX] = {};
};
};

View File

@ -12,6 +12,11 @@ namespace api {
public:
RenderAPI() {};
virtual ~RenderAPI() {};
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());
}
void operator delete(void* p) {}
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;

View File

@ -1,6 +1,7 @@
#pragma once
#include <SDL.h>
#include "singleton.h"
#include "pmr/frame_allocator.h"
namespace api {
class RENDER_API Window : public Singleton<Window> {
protected:
@ -13,6 +14,11 @@ namespace api {
bool resizeable = true;
bool headless = false;
};
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());
}
void operator delete(void* p) {}
public:
Window(CreatePFN func, const Args& args, int width, int height) noexcept;
SDL_Window* GetPtr() { return mPtr; }

View File

@ -0,0 +1,7 @@
#include "render/asset/mesh.h"
namespace api {
Mesh::Mesh() : Asset(type_info<Mesh>())
{
}
}

View File

@ -6,6 +6,10 @@
#define UPROPERTY(...) __Meta(__VA_ARGS__)
#define UFUNCTION(...) __Meta(__VA_ARGS__)
#define __glMeta(...) __cppast(glMeta=__VA_ARGS__)
#define UPROPERTY_gl(...) __glMeta(__VA_ARGS__)
#define UFUNCTION_gl(...) __glMeta(__VA_ARGS__)
#define __vkMeta(...) __cppast(vkMeta=__VA_ARGS__)
#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__)

View File

@ -0,0 +1,73 @@
#include "refl/refl.h"
namespace refl {
template<typename T>
class parray {
protected:
const UClass* m_cls;
T* m_ptr;
int m_count;
public:
parray(): m_cls(nullptr), m_ptr(nullptr),m_count(0) {}
template<typename C>
requires std::is_base_of_v<T, C>
parray(std::vector<C>& vec) : m_cls(&TypeInfo<C>::StaticClass), m_ptr(nullptr){
m_count = vec.size();
if (m_count > 0) {
C* ptr = new C[m_count];
m_ptr = ptr;
if constexpr (std::is_trivially_copyable_v<C>) {
memcpy(m_ptr, vec.data(), m_count * sizeof(C));
}
else {
for (int i = 0; i < m_count; i++) {
new(ptr + i) Vertex(vec[i]);
}
}
}
}
parray(parray<T>& parr) : m_cls(parr.m_cls)
, m_ptr(parr.data()), m_count(parr.size()) {
parr.reset();
}
~parray() {
if (!m_count || !m_cls)
return;
auto dest = m_cls->vtable.Destruct;
if (dest) {
for (int i = 0; i < m_count; i++) {
dest((char*)m_ptr + (i * m_cls->size));
}
}
m_count = 0;
m_ptr = nullptr;
}
T* at(int i)noexcept {
if(i < m_count)
return (T*)((char*)m_ptr + (i * m_cls->size));
return nullptr;
}
T* data() noexcept{
return m_ptr;
}
void reset() noexcept {
m_ptr = nullptr;
m_count = 0;
}
int size() const noexcept {
return m_count;
}
int data_size()const noexcept {
return m_count * m_cls->size;
}
int capicty() const noexcept {
return m_count * m_cls->size;
}
const UClass* uclass()const noexcept {
return m_cls;
}
};
template<typename T, typename C>
parray<T> ToParray(std::vector<C>& vec){
return parray<T>{vec};
}
}

View File

@ -0,0 +1,58 @@
#pragma once
#include <condition_variable>
#include <semaphore>
#include <concepts>
namespace zstd {
template<std::move_constructible T>
class channel {
protected:
int m_tail;
int m_head;
int m_size;
T* m_buf;
std::mutex m_mtx;
std::condition_variable m_cv;
public:
~channel() {
reset();
free(m_buf);
}
channel(int size = 1) : 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) {
std::unique_lock<std::mutex> lck(m_mtx);
while (m_head >= m_tail + m_size) {
m_cv.wait(lck);
}
std::construct_at(m_buf + m_head % m_size, 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 % m_size;
if(m_tail++ == m_head - m_size)
m_cv.notify_one();
return std::move(*(m_buf + tail));
};
};
}

View File

@ -1,6 +1,22 @@
#pragma once
#include "thread/worker.h"
namespace vkn {
class Device;
class Instance;
class Backend {
protected:
Instance* mInstance;
Device* mDevice;
table<Name, CommandWorker*> mWorkerMap;
public:
Backend(string_view appName);
~Backend();
void InitWorker(Name name, VkCommandPoolCreateFlags flag);
CommandWorker* GetWorker(Name name);
public:
static CommandWorker* TransferWorker;
static CommandWorker* RenderWorker;
static CommandWorker* PresentWorker;
};
}
};

View File

@ -0,0 +1,21 @@
#pragma once
#include <thread>
#include "vkn/type.h"
#include <semaphore>
namespace vkn {
class CommandThreadWorker {
protected:
std::thread mThread;
Name mName;
channel<voidFn> mChannel;
std::binary_semaphore mSemaphore;
protected:
void workloop();
public:
CommandThreadWorker(Name name, int buffer);
~CommandThreadWorker();
void Invoke(const voidFn& fn);
void SyncInvoke(const voidFn& fn);
};
};

View File

@ -0,0 +1,32 @@
#pragma once
#include "vkn/wrapper/commandpool.h"
#include "thread_worker.h"
namespace vkn {
class Device;
class Queue;
class CommandWorker {
protected:
Device& mDevice;
Queue& mQueue;
Name mName;
CommandThreadWorker mWork;
CommandPool mCommandPool;
CommandBuffer mImmediateExeCmd;
public:
CommandWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags);
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(const commandFn& fn, const voidFn callback) {
Buffer(mImmediateExeCmd, fn , callback);
}
bool Present(VkPresentInfoKHR& presentInfo);
};
};

View File

@ -1,10 +1,19 @@
#pragma once
#include "std/channel.h"
#include "pmr/frame_allocator.h"
#include "pmr/name.h"
#include <Windows.h>
#include <functional>
#define VK_NO_PROTOTYPES
#include "volk/volk.h"
#include <string>
#include <vector>
#define Z_RENDER_DEBUG 1
namespace vkn {
using pmr::Name;
using pmr::table;
using std::string_view;
using zstd::channel;
inline constexpr string_view VulkanEngineName = "vulkan";
class CommandBuffer;
using voidFn = std::function<void()>;
using commandFn = std::function<void(CommandBuffer& cmd)>;
}

View File

@ -1,11 +1,14 @@
#pragma once
#include "type.h"
#include "render/renderapi.h"
#include "backend.h"
namespace vkn {
class Backend;
class VulkanWindow;
class VulkanAPI : public api::RenderAPI {
class VULKAN_API VulkanAPI : public api::RenderAPI {
private:
VulkanWindow* window;
VulkanWindow& window;
Backend backend;
public:
VulkanAPI();

View File

@ -5,8 +5,17 @@ namespace vkn {
class VulkanWindow : public api::Window {
private:
VkSurfaceKHR mSurfaceKHR;
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());
}
void operator delete(void* p) {}
public:
using api::Window::Window;
void CreateRender();
static VulkanWindow* Ptr() {
//return dynamic_cast<VulkanWindow*>(api::Window::Ptr());
return (VulkanWindow*)api::Window::Ptr();
}
};
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class CommandBuffer {
protected:
VkCommandBuffer mPtr;
public:
CommandBuffer(VkCommandBuffer ptr) : mPtr(ptr) {};
VkCommandBuffer& Ptr() {
return mPtr;
};
void Reset();
void BeginRecord(VkCommandBufferUsageFlags flag);
void EndRecord();
void CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
void Submit(VkQueue& queue,VkFence fence);
void BindVertexBuffer(VkBuffer buffer, uint32_t offset);
void BindIndexBuffers(VkBuffer buffer, uint32_t offset, VkIndexType type);
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "commandbuffer.h"
namespace vkn {
class Device;
class Queue;
class CommandPool {
protected:
VkCommandPool mPtr;
Device& mDevice;
pmr::vector<CommandBuffer> mPool;
public:
CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex);
~CommandPool();
VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level);
void FreeBuffer(VkCommandBuffer& buf);
VkCommandPool& Ptr() {
return mPtr;
};
CommandBuffer Pop();
void Push(CommandBuffer& cmd);
};
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class DeviceCreator;
class Queue;
class Device {
friend class DeviceCreator;
protected:
VkDevice mPtr{ NULL };
VkPhysicalDevice mPhysical{ NULL };
table<Name, Queue*> mQueueMap;
pmr::vector<VkFence> mFencePool;
std::mutex mFenceMutex;
public:
VkDevice& Ptr() {
return mPtr;
}
VkPhysicalDevice GetPhysical() {
return mPhysical;
}
public:
Device(DeviceCreator& Creator);
~Device();
VkFence CreateFence(VkFenceCreateFlags flags);
Queue* GetQueue(Name name);
VkFence PopFence();
void PushWaitFence(VkFence fence);
VkSemaphore CreateSemaphore();
VkShaderModule CreateShaderModule(pmr::vector<char> code);
VkShaderModule CreateShaderModule(pmr::vector<uint32_t> code);
};
};

View File

@ -0,0 +1,50 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class Instance;
class DeviceCreator {
private:
class DesiredQueue final
{
public:
Name name;
VkQueueFlags flag;
float prioritie;
int queueFamilyIndex;
DesiredQueue(Name name, VkQueueFlags flag, float prioritie)
: name(name), flag(flag), prioritie(prioritie), queueFamilyIndex(0) {}
};
public:
VkPhysicalDeviceFeatures desiredPhysicalDeviceFeatures;
VkPhysicalDeviceType desiredPhysicalDeviceType;
pmr::vector<pmr::string> desiredExtensions;
pmr::vector<DesiredQueue> desiredQueues;
int fencePoolCount = 256;
Instance& instance;
public:
DeviceCreator(Instance& instance);
void AddQueue(Name name, VkQueueFlags flag, float prioritie);
void AddExtension(string_view extensionName);
void AddWindowExtension();
bool CheckProperty(const VkPhysicalDevice device);
bool CheckExtension(const VkPhysicalDevice device);
bool FindDevice(VkPhysicalDevice& device);
void QueueCreateInfos(pmr::vector<VkDeviceQueueCreateInfo>& queue_create_infos,
pmr::vector<pmr::vector<float>>& queue_prioritie,
pmr::vector<VkQueueFamilyProperties>& queue_families);
pmr::vector<char const*> EnabledExtensionNames();
void EnableDeviceFeatures();
VkPhysicalDeviceFeatures2 GetDeviceFeature2();
VkPhysicalDeviceVulkan12Features GetVulkan12Features();
#ifdef Z_RENDER_DEBUG
public:
pmr::vector<pmr::string> desiredLayers;
void AddLayer(string_view layerName);
bool CheckLayer(const VkPhysicalDevice device);
pmr::vector<char const*> EnabledLayerNames();
#endif
public:
static bool CheckAvailableQueueFamilies(VkPhysicalDevice physical_device, pmr::vector<VkQueueFamilyProperties>& queue_families);
};
};

View File

@ -0,0 +1,23 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class InstanceCreator;
class Instance {
friend class InstanceCreator;
protected:
VkInstance mPtr;
public:
Instance(InstanceCreator& Creator);
VkInstance& Ptr() {
return mPtr;
}
bool EnumerateAvailablePhysicalDevices(pmr::vector<VkPhysicalDevice>& available_devices);
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT,
VkDebugUtilsMessageTypeFlagsEXT,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void*);
};
};

View File

@ -0,0 +1,42 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class InstanceCreator {
public:
pmr::string appName;
uint32_t appVersion;
pmr::string engineName;
uint32_t engineVersion;
uint32_t apiVersion;
pmr::vector<pmr::string> desiredExtensions;
pmr::vector<pmr::string> desiredLayers;
#ifdef Z_RENDER_DEBUG
VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
VkDebugUtilsMessageTypeFlagsEXT messageType;
PFN_vkDebugUtilsMessengerCallbackEXT debugCallback;
VkDebugUtilsMessengerCreateInfoEXT DebugUtilsLayerNext();
#endif
public:
InstanceCreator();
void AddExtension(string_view extensionName);
void AddLayer(string_view layerName);
void AddWindowExtension();
void AddInstanceExtension();
void AddDebugExtension();
pmr::vector<char const*> EnabledExtensionNames();
pmr::vector<char const*> EnabledLayerNames();
private:
static bool CheckAvailableInstanceExtensions(pmr::vector<VkExtensionProperties>& available_extensions);
static bool CheckAvailableInstanceLayers(pmr::vector<VkLayerProperties>& available_layers);
static bool IsExtensionSupported(pmr::vector<VkExtensionProperties> const& available_extensions,
char const* const extension);
static bool IsLayerSupported(pmr::vector<VkLayerProperties> const& available_layers,
char const* const layer);
};
};

View File

@ -0,0 +1,26 @@
#pragma once
#include "vkn/type.h"
namespace vkn {
class Device;
class CommandBuffer;
class Queue {
protected:
VkQueue mPtr;
uint32_t mQueueFamilyIndex;
const Name mName;
public:
Queue(Name name, uint32_t queueFamilyIndex, VkQueue queue);
uint32_t QueueFamilyIndex()
{
return mQueueFamilyIndex;
}
VkQueue& Ptr() {
return mPtr;
}
public:
static const Name TransferQueue;
static const Name RenderQueue;
static const Name ComputeQueue;
static const Name PresentQueue;
};
}

View File

@ -0,0 +1,50 @@
#include "vkn/backend.h"
#include "vkn/wrapper/device.h"
#include "vkn/wrapper/device_create.h"
#include "vkn/wrapper/instance.h"
#include "vkn/wrapper/instance_create.h"
#include "vkn/wrapper/queue.h"
namespace vkn {
Backend::Backend(string_view appName) : mWorkerMap(GlobalPool())
{
InstanceCreator instanceCreator{};
mInstance = new (GlobalPool()) Instance(instanceCreator);
DeviceCreator deviceCreator = DeviceCreator{ *mInstance };
deviceCreator.AddWindowExtension();
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);
deviceCreator.AddQueue(Queue::PresentQueue, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
mDevice = new (GlobalPool()) Device(deviceCreator);
InitWorker(Queue::TransferQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
InitWorker(Queue::RenderQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
InitWorker(Queue::ComputeQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
InitWorker(Queue::PresentQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
Backend::TransferWorker = GetWorker(Queue::TransferQueue);
Backend::RenderWorker = GetWorker(Queue::RenderQueue);
}
Backend::~Backend()
{
mInstance->~Instance();
mDevice->~Device();
}
void Backend::InitWorker(Name name, VkCommandPoolCreateFlags flag)
{
auto queue = mDevice->GetQueue(name);
if (queue) {
auto worker = new CommandWorker(name, *mDevice, *queue, flag);
mWorkerMap.emplace(name, worker);
}
}
CommandWorker* Backend::GetWorker(Name name)
{
auto it = mWorkerMap.find(name);
if (it != mWorkerMap.end()) {
return it->second;
}
return nullptr;
}
}

View File

@ -0,0 +1,36 @@
#include "vkn/thread/thread_worker.h"
#include "zlog.h"
namespace vkn {
CommandThreadWorker::CommandThreadWorker(Name name, int buffer)
: mName(name)
, mChannel(buffer)
, mSemaphore(0)
{
mThread = std::thread(&CommandThreadWorker::workloop, this);
}
CommandThreadWorker::~CommandThreadWorker() {
zlog::info("~CommandThreadWorker");
zlog::flush();
}
void CommandThreadWorker::workloop()
{
mThread.detach();
while (true) {
voidFn fn = mChannel.acquire();
fn();
}
}
void CommandThreadWorker::Invoke(const voidFn& fn)
{
mChannel.release(fn);
}
void CommandThreadWorker::SyncInvoke(const voidFn& fn)
{
Invoke([=,this]() {
fn();
mSemaphore.release();
});
mSemaphore.acquire();
}
}

View File

@ -0,0 +1,47 @@
#include "vkn/thread/worker.h"
#include "vkn/wrapper/queue.h"
#include "vkn/wrapper/device.h"
namespace vkn {
CommandWorker::CommandWorker(Name name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
:mName(name)
,mDevice(device)
,mQueue(queue)
,mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
,mWork(name, 64)
,mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))
{
}
void CommandWorker::Invoke(const voidFn& fn)
{
mWork.Invoke(fn);
}
void CommandWorker::InvokeBuffer(const commandFn& fn, const voidFn& callback)
{
mWork.Invoke([=, this]() {
CommandBuffer cmd = mCommandPool.Pop();
Buffer(cmd, fn, callback);
mCommandPool.Push(cmd);
});
}
void CommandWorker::Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback)
{
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
fn(cmd);
cmd.EndRecord();
VkFence fence = mDevice.PopFence();
cmd.Submit(mQueue.Ptr(), fence);
mDevice.PushWaitFence(fence);
callback();
}
void CommandWorker::Flush()
{
mWork.SyncInvoke([]{});
}
bool CommandWorker::Present(VkPresentInfoKHR& presentInfo)
{
VkResult result = vkQueuePresentKHR(mQueue.Ptr(), &presentInfo);
return result == VK_SUCCESS;
}
}

View File

@ -1,10 +1,9 @@
#include "vkn/vulkan_api.h"
#include "vkn/vulkan_window.h"
namespace vkn {
VulkanAPI::VulkanAPI()
VulkanAPI::VulkanAPI() : window(*VulkanWindow::Ptr()), backend(VulkanEngineName)
{
window = (VulkanWindow*) api::Window::Ptr();
window->CreateRender();
}
void VulkanAPI::Init()
{

View File

@ -0,0 +1,46 @@
#include "vkn/wrapper/commandbuffer.h"
namespace vkn {
void CommandBuffer::Reset()
{
vkResetCommandBuffer(mPtr, VkCommandBufferResetFlagBits::VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
}
void CommandBuffer::BeginRecord(VkCommandBufferUsageFlags flag)
{
VkCommandBufferBeginInfo beginInfo{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,//sType
nullptr, //pNext
flag //flags
};
vkBeginCommandBuffer(mPtr, &beginInfo);
}
void CommandBuffer::EndRecord()
{
vkEndCommandBuffer(mPtr);
}
void CommandBuffer::CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
VkBufferCopy copy = {};
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = size;
vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, &copy);
}
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, fence);
}
void CommandBuffer::BindVertexBuffer(VkBuffer buffer, uint32_t offset)
{
VkDeviceSize offsets[] = { offset };
vkCmdBindVertexBuffers(mPtr, 0, 1, &buffer, offsets);
}
void CommandBuffer::BindIndexBuffers(VkBuffer buffer, uint32_t offset, VkIndexType type)
{
vkCmdBindIndexBuffer(mPtr, buffer, offset, type);
}
}

View File

@ -0,0 +1,58 @@
#include "vkn/wrapper/commandpool.h"
#include "vkn/wrapper/device.h"
#include "vkn/wrapper/queue.h"
#include "zlog.h"
namespace vkn {
CommandPool::CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex)
:mPtr(nullptr)
,mDevice(device)
{
VkCommandPoolCreateInfo pCreateInfo{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
nullptr,
queueFlags,
queueIndex
};
vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr);
}
CommandPool::~CommandPool()
{
for (auto cb : mPool) {
FreeBuffer(cb.Ptr());
}
mPool.clear();
}
VkCommandBuffer CommandPool::AllocateBuffer(VkCommandBufferLevel level)
{
VkCommandBufferAllocateInfo allocInfo{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, //sType
nullptr, //pNext
mPtr, //commandPool
level, //level
1, //commandBufferCount
};
VkCommandBuffer cmd;
vkAllocateCommandBuffers(mDevice.Ptr(), &allocInfo, &cmd);
return cmd;
}
void CommandPool::FreeBuffer(VkCommandBuffer& buf)
{
vkFreeCommandBuffers(mDevice.Ptr(), mPtr, 1, &buf);
buf = nullptr;
}
CommandBuffer CommandPool::Pop()
{
if (mPool.empty()) {
return AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}
CommandBuffer buffer = mPool.back();
mPool.pop_back();
return buffer;
}
void CommandPool::Push(CommandBuffer& cmd)
{
cmd.Reset();
mPool.push_back(cmd);
}
}

View File

@ -0,0 +1,124 @@
#include "vkn/wrapper/device.h"
#include "vkn/wrapper/device_create.h"
#include "vkn/wrapper/queue.h"
#include "zlog.h"
namespace vkn {
Device::Device(DeviceCreator& Creator) : mQueueMap(GlobalPool())
{
//物理设备
Creator.FindDevice(mPhysical);
//队列信息
pmr::vector<VkQueueFamilyProperties> queue_families{FramePool()};
Creator.CheckAvailableQueueFamilies(mPhysical, queue_families);
pmr::vector<VkDeviceQueueCreateInfo> queue_create_infos{ FramePool() };
pmr::vector<pmr::vector<float>> 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
&deviceFeatures, // const void * pNext
0, // VkDeviceCreateFlags flags
static_cast<uint32_t>(queue_create_infos.size()), // uint32_t queueCreateInfoCount
queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos
0, // uint32_t enabledLayerCount
nullptr, // const char * const * ppEnabledLayerNames
static_cast<uint32_t>(extensions.size()), // uint32_t enabledExtensionCount
extensions.data(), // const char * const * ppEnabledExtensionNames
nullptr // const VkPhysicalDeviceFeatures * pEnabledFeatures
};
#ifdef Z_USE_GRAPHIC_DEBUG
auto layers = Creator.EnabledLayerNames();
device_create_info.enabledLayerCount = layers.size();
device_create_info.ppEnabledLayerNames = layers.data();
#endif // Z_USE_GRAPHIC_DEBUG
VkResult result = vkCreateDevice(mPhysical, &device_create_info, nullptr, &mPtr);
if ((result != VK_SUCCESS) || (mPtr == VK_NULL_HANDLE)) {
zlog::error("Could not create logical device. VkResult {}", (int)result);
}
volkLoadDevice(mPtr);
for (auto& queue : Creator.desiredQueues) {
Queue* gq = new (GlobalPool()) Queue(queue.name, queue.queueFamilyIndex, VK_NULL_HANDLE);
vkGetDeviceQueue(mPtr, queue.queueFamilyIndex, 0, &(gq->Ptr()));
mQueueMap.emplace(queue.name, gq);
}
}
Device::~Device()
{
for (auto& queue : mQueueMap) {
queue.second->~Queue();
}
mQueueMap.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(Name name)
{
auto it = mQueueMap.find(name);
if (it != mQueueMap.end()) {
return it->second;
}
return nullptr;
}
VkFence Device::PopFence()
{
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 = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkSemaphore semaphore;
VkResult result = vkCreateSemaphore(mPtr, &semaphoreInfo, nullptr, &semaphore);
return semaphore;
}
VkShaderModule Device::CreateShaderModule(pmr::vector<char> code)
{
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
// 这里需要确保数据满足uint32_t的对齐要求,存储在vector中默认分配器已经确保数据满足最差情况下的对齐要求
createInfo.codeSize = code.size();
// 转换为Vulkan要求的uint32_t指针
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
VkShaderModule module;
VkResult result = vkCreateShaderModule(mPtr, &createInfo, nullptr, &module);
return module;
}
VkShaderModule Device::CreateShaderModule(pmr::vector<uint32_t> code)
{
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
//code size 是字节大小,需要 * sizeof
createInfo.codeSize = code.size() * sizeof(uint32_t);
// 转换为Vulkan要求的uint32_t指针
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
VkShaderModule module;
VkResult result = vkCreateShaderModule(mPtr, &createInfo, nullptr, &module);
return module;
}
}

View File

@ -0,0 +1,211 @@
#include "vkn/wrapper/device_create.h"
#include "vkn/wrapper/instance.h"
#include "zlog.h"
namespace vkn {
DeviceCreator::DeviceCreator(Instance& instance)
: instance(instance)
, desiredPhysicalDeviceType(VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
, desiredPhysicalDeviceFeatures()
, desiredExtensions{FramePool()}
, desiredQueues{ FramePool() }
#ifdef Z_RENDER_DEBUG
, desiredLayers{FramePool()}
#endif
{
}
void DeviceCreator::AddQueue(Name name, VkQueueFlags flag, float prioritie)
{
desiredQueues.emplace_back(name, flag, prioritie);
}
void DeviceCreator::AddExtension(string_view extensionName)
{
desiredExtensions.push_back(pmr::string{ extensionName , FramePool()});
}
void DeviceCreator::AddWindowExtension()
{
AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
#ifdef Z_RENDER_DEBUG
AddLayer("VK_LAYER_KHRONOS_validation");
AddLayer("VK_LAYER_RENDERDOC_Capture");
#endif
}
bool DeviceCreator::CheckProperty(const VkPhysicalDevice device)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
return (deviceProperties.deviceType & desiredPhysicalDeviceType) == desiredPhysicalDeviceType;
}
bool DeviceCreator::CheckExtension(const VkPhysicalDevice device)
{
uint32_t extensionCount = 0;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
pmr::vector<VkExtensionProperties> availableExtensions{FramePool()};
availableExtensions.resize(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
for (const auto& desiredExtension : desiredExtensions)
{
bool find = false;
for (const auto& availableExtension : availableExtensions)
{
if (strcmp(availableExtension.extensionName, desiredExtension.c_str()) == 0)
{
find = true;
break;
}
}
if (!find)return false;
}
return true;
}
bool DeviceCreator::FindDevice(VkPhysicalDevice& device)
{
pmr::vector<VkPhysicalDevice> available_devices{FramePool()};
instance.EnumerateAvailablePhysicalDevices(available_devices);
for (int i = 0, size = available_devices.size(); i < size; i++)
{
device = available_devices[i];
if (!CheckProperty(device))continue;
if (!CheckExtension(device))continue;
#ifdef Z_RENDER_DEBUG
if (!CheckLayer(device))continue;
#endif // Z_RENDER_DEBUG
return true;
}
return false;
}
void DeviceCreator::QueueCreateInfos(pmr::vector<VkDeviceQueueCreateInfo>& queue_create_infos, pmr::vector<pmr::vector<float>>& queue_prioritie, pmr::vector<VkQueueFamilyProperties>& queue_families)
{
uint32_t size = queue_families.size();
for (uint32_t i = 0; i < size; i++) {
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = i;
queueCreateInfo.queueCount = 0;
queue_create_infos.push_back(queueCreateInfo);
queue_prioritie.emplace_back(pmr::vector<float>{FramePool()});
}
uint32_t max_value = 1;
for (auto& queue : desiredQueues) {
uint32_t index = -1;
bool bFind = false;
for (uint32_t i = 0; i < size; i++) {
auto family = queue_families[i];
if ((family.queueFlags & queue.flag) == queue.flag) {
index = i;
if (queue_create_infos[i].queueCount < max_value * family.queueCount) {
bFind = true;
break;
}
}
}
if (index != -1 && queue_create_infos[index].queueCount < queue_families[index].queueCount) {
queue.queueFamilyIndex = index;
queue_create_infos[index].queueCount++;
queue_prioritie[index].push_back(queue.prioritie);
}
if (!bFind)
max_value++;
}
auto it = queue_create_infos.begin();
for (uint32_t i = 0; i < size; i++) {
if (it->queueCount == 0) {
it = queue_create_infos.erase(it);
}
else {
it->pQueuePriorities = queue_prioritie[i].data();
it++;
}
}
}
pmr::vector<char const*> DeviceCreator::EnabledExtensionNames()
{
pmr::vector<char const*> _extension;
for (int i = 0, l = desiredExtensions.size(); i < l; i++) {
_extension.push_back(desiredExtensions[i].c_str());
}
return _extension;
}
void DeviceCreator::EnableDeviceFeatures()
{
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;
}
#ifdef Z_RENDER_DEBUG
void DeviceCreator::AddLayer(string_view layerName)
{
desiredLayers.push_back(pmr::string{ layerName , FramePool()});
}
bool DeviceCreator::CheckLayer(const VkPhysicalDevice device)
{
uint32_t layerCount = 0;
vkEnumerateDeviceLayerProperties(device, &layerCount, nullptr);
pmr::vector<VkLayerProperties> availableLayers{FramePool()};
availableLayers.resize(layerCount);
vkEnumerateDeviceLayerProperties(device, &layerCount, availableLayers.data());
for (const auto& desiredLayer : desiredLayers)
{
bool find = false;
for (const auto& availableLayer : availableLayers)
{
if (strcmp(availableLayer.layerName, desiredLayer.c_str()) == 0)
{
find = true;
break;
}
}
if (!find)return false;
}
return true;
}
pmr::vector<char const*> DeviceCreator::EnabledLayerNames()
{
pmr::vector<char const*> _extension{FramePool()};
for (int i = 0, l = desiredLayers.size(); i < l; i++) {
_extension.push_back(desiredLayers[i].c_str());
}
return _extension;
}
#endif // Z_RENDER_DEBUG
bool DeviceCreator::CheckAvailableQueueFamilies(VkPhysicalDevice physical_device, pmr::vector<VkQueueFamilyProperties>& queue_families)
{
uint32_t queue_families_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr);
if (queue_families_count == 0) {
zlog::error("Could not get the number of queue families.");
return false;
}
queue_families.resize(queue_families_count);
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, queue_families.data());
if (queue_families_count == 0) {
zlog::error("Could not acquire properties of queue families.");
return false;
}
return true;
}
}

View File

@ -0,0 +1,73 @@
#include "vkn/wrapper/instance.h"
#include "vkn/wrapper/instance_create.h"
#include "zlog.h"
namespace vkn {
Instance::Instance(InstanceCreator& Creator)
{
VkResult res = volkInitialize();
if (res != VK_SUCCESS)
zlog::error("Could not initialize volk!");
VkApplicationInfo application_info = {
VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType
nullptr, // const void * pNext
Creator.appName.c_str(), // const char * pApplicationName
Creator.appVersion, // uint32_t applicationVersion
Creator.engineName.c_str(), // const char * pEngineName
Creator.engineVersion, // uint32_t engineVersion
Creator.apiVersion // uint32_t apiVersion
};
#ifdef Z_RENDER_DEBUG
Creator.AddDebugExtension();
#endif // Z_RENDER_DEBUG
Creator.AddWindowExtension();
Creator.AddInstanceExtension();
auto extensions = Creator.EnabledExtensionNames();
auto layers = Creator.EnabledLayerNames();;
VkInstanceCreateInfo instance_create_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType
nullptr, // const void * pNext
0, // VkInstanceCreateFlags flags
&application_info, // const VkApplicationInfo * pApplicationInfo
static_cast<uint32_t>(layers.size()), // uint32_t enabledLayerCount
layers.data(), // const char * const * ppEnabledLayerNames
static_cast<uint32_t>(extensions.size()), // uint32_t enabledExtensionCount
extensions.data() // const char * const * ppEnabledExtensionNames
};
#ifdef Z_RENDER_DEBUG
VkDebugUtilsMessengerCreateInfoEXT debugInfo = Creator.DebugUtilsLayerNext();
instance_create_info.pNext = &debugInfo;
#endif
VkResult result = vkCreateInstance(&instance_create_info, nullptr, &mPtr);
if (result != VK_SUCCESS) {
zlog::error("Failed to create instance.");
}
volkLoadInstanceOnly(mPtr);
}
bool Instance::EnumerateAvailablePhysicalDevices(pmr::vector<VkPhysicalDevice>& available_devices)
{
uint32_t devices_count = 0;
VkResult result = VK_SUCCESS;
result = vkEnumeratePhysicalDevices(mPtr, &devices_count, nullptr);
if ((result != VK_SUCCESS) ||
(devices_count == 0)) {
zlog::error("Could not get the number of available physical devices.");
return false;
}
available_devices.resize(devices_count);
result = vkEnumeratePhysicalDevices(mPtr, &devices_count, available_devices.data());
if ((result != VK_SUCCESS) ||
(devices_count == 0)) {
zlog::error("Could not enumerate physical devices.");
return false;
}
return true;
}
VKAPI_ATTR VkBool32 VKAPI_CALL Instance::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void*)
{
zlog::error("validation layer: {}", pCallbackData->pMessage);
return VK_FALSE;
}
}

View File

@ -0,0 +1,165 @@
#include "vkn/wrapper/instance_create.h"
#include "vkn/wrapper/instance.h"
#include "zlog.h"
namespace vkn {
VkDebugUtilsMessengerCreateInfoEXT InstanceCreator::DebugUtilsLayerNext()
{
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity =
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback;
return createInfo;
}
InstanceCreator::InstanceCreator()
: desiredExtensions(FramePool()), desiredLayers(FramePool())
, appName("Vulkan Application")
, appVersion(VK_API_VERSION_1_3)
, engineName("zengine")
, engineVersion(VK_API_VERSION_1_3)
, apiVersion(VK_API_VERSION_1_3)
#ifdef Z_RENDER_DEBUG
, messageSeverity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
, messageType(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
, debugCallback(Instance::DebugCallback)
#endif
{
}
void InstanceCreator::AddExtension(string_view extensionName)
{
desiredExtensions.push_back(pmr::string{ extensionName, FramePool() });
}
void InstanceCreator::AddLayer(string_view layerName)
{
desiredLayers.push_back(pmr::string{ layerName, FramePool() });
}
void InstanceCreator::AddWindowExtension()
{
#if defined(__ANDROID__)
AddExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
#elif defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
AddExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#elif defined(LINUX_OR_FREEBSD) && defined(FILAMENT_SUPPORTS_X11)
#if defined(FILAMENT_SUPPORTS_XCB)
AddExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#endif
#if defined(FILAMENT_SUPPORTS_XLIB)
AddExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
#endif
#elif defined(WIN32)
AddExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#endif
}
void InstanceCreator::AddInstanceExtension()
{
AddExtension(VK_KHR_SURFACE_EXTENSION_NAME);
AddExtension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
#ifdef Z_RENDER_DEBUG
void InstanceCreator::AddDebugExtension()
{
AddLayer("VK_LAYER_KHRONOS_validation");
AddExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
AddExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
}
#endif // Z_RENDER_DEBUG
pmr::vector<char const*> InstanceCreator::EnabledExtensionNames()
{
pmr::vector<VkExtensionProperties> available_extensions{ FramePool() };
pmr::vector<char const*> _extension{ FramePool() };
if (!CheckAvailableInstanceExtensions(available_extensions)) {
return _extension;
}
for (int i = 0, l = desiredExtensions.size(); i < l; i++) {
if (IsExtensionSupported(available_extensions, desiredExtensions[i].c_str())) {
_extension.push_back(desiredExtensions[i].c_str());
}
else {
zlog::error("cann't support extension: {}", desiredExtensions[i].c_str());
}
}
return _extension;
}
pmr::vector<char const*> InstanceCreator::EnabledLayerNames()
{
pmr::vector<VkLayerProperties> available_layers{ FramePool() };
pmr::vector<char const*> _layers{ FramePool() };
if (!CheckAvailableInstanceLayers(available_layers)) {
return _layers;
}
for (int i = 0, l = desiredLayers.size(); i < l; i++) {
if (IsLayerSupported(available_layers, desiredLayers[i].c_str())) {
_layers.push_back(desiredLayers[i].c_str());
}
else {
zlog::error("Could not load instance-level Vulkan function named: {}", desiredLayers[i].c_str());
}
}
return _layers;
}
bool InstanceCreator::CheckAvailableInstanceExtensions(pmr::vector<VkExtensionProperties>& available_extensions)
{
uint32_t extensions_count = 0;
VkResult result = VK_SUCCESS;
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, nullptr);
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not get the number of instance extensions.");
return false;
}
available_extensions.resize(extensions_count);
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensions_count, available_extensions.data());
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not enumerate instance extensions.");
return false;
}
return true;
}
bool InstanceCreator::CheckAvailableInstanceLayers(pmr::vector<VkLayerProperties>& available_layers)
{
uint32_t extensions_count = 0;
VkResult result = VK_SUCCESS;
result = vkEnumerateInstanceLayerProperties(&extensions_count, nullptr);
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not get the number of instance layers.");
return false;
}
available_layers.resize(extensions_count);
result = vkEnumerateInstanceLayerProperties(&extensions_count, available_layers.data());
if ((result != VK_SUCCESS) ||
(extensions_count == 0)) {
zlog::error("Could not enumerate instance layers.");
return false;
}
return true;
}
bool InstanceCreator::IsExtensionSupported(pmr::vector<VkExtensionProperties> const& available_extensions, char const* const extension)
{
for (auto& available_extension : available_extensions) {
if (strstr(available_extension.extensionName, extension)) {
return true;
}
}
return false;
}
bool InstanceCreator::IsLayerSupported(pmr::vector<VkLayerProperties> const& available_layers, char const* const layer)
{
for (auto& available_layer : available_layers) {
if (strstr(available_layer.layerName, layer)) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,12 @@
#include "vkn/wrapper/queue.h"
namespace vkn {
const Name Queue::TransferQueue = "transfer";
const Name Queue::RenderQueue = "render" ;
const Name Queue::ComputeQueue = "computer";
const Name Queue::PresentQueue = "present" ;
Queue::Queue(Name name, uint32_t queueFamilyIndex, VkQueue queue)
: mName(name)
{
}
}

View File

@ -2,4 +2,13 @@ shared_module("vulkan","engine")
add_headerfiles("include/**.h")
add_files("src/**.cpp", "include/volk/volk.c")
add_packages("vulkansdk", {public = true})
add_dependency("engine", {public = true})
add_dependency("engine", {public = true})
on_load(function (target)
if is_plat("windows") then
target:add("defines", "VK_USE_PLATFORM_WIN32_KHR=1")
elseif is_plat("linux") then
target:add("defines", "VK_USE_PLATFORM_XLIB_KHR=1")
elseif is_plat("macosx") then
target:add("defines", "VK_USE_PLATFORM_MACOS_MVK=1")
end
end)

View File

@ -6,8 +6,8 @@ using namespace api;
void ZWorldModule::OnLoad(int argc, char** argv)
{
// 创建窗口
new (GlobalPool()) vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" }, 1080, 720);
new (GlobalPool()) vkn::VulkanAPI();
new vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" }, 1080, 720);
new vkn::VulkanAPI();
}
void ZWorldModule::OnUnload()