update vulkan api
This commit is contained in:
parent
722396f613
commit
6f423500b6
20
engine/modules/engine/render/include/render/asset/material.h
Normal file
20
engine/modules/engine/render/include/render/asset/material.h
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
33
engine/modules/engine/render/include/render/asset/mesh.h
Normal file
33
engine/modules/engine/render/include/render/asset/mesh.h
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
25
engine/modules/engine/render/include/render/asset/shader.h
Normal file
25
engine/modules/engine/render/include/render/asset/shader.h
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
46
engine/modules/engine/render/include/render/asset/vertex.h
Normal file
46
engine/modules/engine/render/include/render/asset/vertex.h
Normal 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] = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -12,6 +12,11 @@ namespace api {
|
|||||||
public:
|
public:
|
||||||
RenderAPI() {};
|
RenderAPI() {};
|
||||||
virtual ~RenderAPI() {};
|
virtual ~RenderAPI() {};
|
||||||
|
public:
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
return ::operator new(size, GlobalPool());
|
||||||
|
}
|
||||||
|
void operator delete(void* p) {}
|
||||||
public:
|
public:
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include "singleton.h"
|
#include "singleton.h"
|
||||||
|
#include "pmr/frame_allocator.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
class RENDER_API Window : public Singleton<Window> {
|
class RENDER_API Window : public Singleton<Window> {
|
||||||
protected:
|
protected:
|
||||||
@ -13,6 +14,11 @@ namespace api {
|
|||||||
bool resizeable = true;
|
bool resizeable = true;
|
||||||
bool headless = false;
|
bool headless = false;
|
||||||
};
|
};
|
||||||
|
public:
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
return ::operator new(size, GlobalPool());
|
||||||
|
}
|
||||||
|
void operator delete(void* p) {}
|
||||||
public:
|
public:
|
||||||
Window(CreatePFN func, const Args& args, int width, int height) noexcept;
|
Window(CreatePFN func, const Args& args, int width, int height) noexcept;
|
||||||
SDL_Window* GetPtr() { return mPtr; }
|
SDL_Window* GetPtr() { return mPtr; }
|
||||||
|
|||||||
7
engine/modules/engine/render/src/asset/mesh.cpp
Normal file
7
engine/modules/engine/render/src/asset/mesh.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "render/asset/mesh.h"
|
||||||
|
namespace api {
|
||||||
|
Mesh::Mesh() : Asset(type_info<Mesh>())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
0
engine/modules/engine/render/src/asset/shader.cpp
Normal file
0
engine/modules/engine/render/src/asset/shader.cpp
Normal file
@ -6,6 +6,10 @@
|
|||||||
#define UPROPERTY(...) __Meta(__VA_ARGS__)
|
#define UPROPERTY(...) __Meta(__VA_ARGS__)
|
||||||
#define UFUNCTION(...) __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 __vkMeta(...) __cppast(vkMeta=__VA_ARGS__)
|
||||||
#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
|
#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
|
||||||
#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__)
|
#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__)
|
||||||
|
|||||||
73
engine/modules/engine/zlib/include/refl/std/parray.h
Normal file
73
engine/modules/engine/zlib/include/refl/std/parray.h
Normal 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};
|
||||||
|
}
|
||||||
|
}
|
||||||
58
engine/modules/engine/zlib/include/std/channel.h
Normal file
58
engine/modules/engine/zlib/include/std/channel.h
Normal 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));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,6 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "thread/worker.h"
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
|
class Device;
|
||||||
|
class Instance;
|
||||||
class Backend {
|
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;
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,10 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "std/channel.h"
|
||||||
|
#include "pmr/frame_allocator.h"
|
||||||
|
#include "pmr/name.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#define VK_NO_PROTOTYPES
|
#define VK_NO_PROTOTYPES
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
#include <string>
|
#define Z_RENDER_DEBUG 1
|
||||||
#include <vector>
|
|
||||||
namespace vkn {
|
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)>;
|
||||||
}
|
}
|
||||||
@ -1,11 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "render/renderapi.h"
|
#include "render/renderapi.h"
|
||||||
|
#include "backend.h"
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
|
class Backend;
|
||||||
class VulkanWindow;
|
class VulkanWindow;
|
||||||
class VulkanAPI : public api::RenderAPI {
|
class VULKAN_API VulkanAPI : public api::RenderAPI {
|
||||||
private:
|
private:
|
||||||
VulkanWindow* window;
|
VulkanWindow& window;
|
||||||
|
Backend backend;
|
||||||
public:
|
public:
|
||||||
VulkanAPI();
|
VulkanAPI();
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,17 @@ namespace vkn {
|
|||||||
class VulkanWindow : public api::Window {
|
class VulkanWindow : public api::Window {
|
||||||
private:
|
private:
|
||||||
VkSurfaceKHR mSurfaceKHR;
|
VkSurfaceKHR mSurfaceKHR;
|
||||||
|
public:
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
return ::operator new(size, GlobalPool());
|
||||||
|
}
|
||||||
|
void operator delete(void* p) {}
|
||||||
public:
|
public:
|
||||||
using api::Window::Window;
|
using api::Window::Window;
|
||||||
void CreateRender();
|
void CreateRender();
|
||||||
|
static VulkanWindow* Ptr() {
|
||||||
|
//return dynamic_cast<VulkanWindow*>(api::Window::Ptr());
|
||||||
|
return (VulkanWindow*)api::Window::Ptr();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -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*);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -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);
|
||||||
|
};
|
||||||
|
};
|
||||||
26
engine/modules/render/vulkan/include/vkn/wrapper/queue.h
Normal file
26
engine/modules/render/vulkan/include/vkn/wrapper/queue.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
engine/modules/render/vulkan/src/thread/thread_worker.cpp
Normal file
36
engine/modules/render/vulkan/src/thread/thread_worker.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
47
engine/modules/render/vulkan/src/thread/worker.cpp
Normal file
47
engine/modules/render/vulkan/src/thread/worker.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,9 @@
|
|||||||
#include "vkn/vulkan_api.h"
|
#include "vkn/vulkan_api.h"
|
||||||
#include "vkn/vulkan_window.h"
|
#include "vkn/vulkan_window.h"
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
VulkanAPI::VulkanAPI()
|
VulkanAPI::VulkanAPI() : window(*VulkanWindow::Ptr()), backend(VulkanEngineName)
|
||||||
{
|
{
|
||||||
window = (VulkanWindow*) api::Window::Ptr();
|
|
||||||
window->CreateRender();
|
|
||||||
}
|
}
|
||||||
void VulkanAPI::Init()
|
void VulkanAPI::Init()
|
||||||
{
|
{
|
||||||
|
|||||||
46
engine/modules/render/vulkan/src/wrapper/commandbuffer.cpp
Normal file
46
engine/modules/render/vulkan/src/wrapper/commandbuffer.cpp
Normal 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, ©);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
58
engine/modules/render/vulkan/src/wrapper/commandpool.cpp
Normal file
58
engine/modules/render/vulkan/src/wrapper/commandpool.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
211
engine/modules/render/vulkan/src/wrapper/device_create.cpp
Normal file
211
engine/modules/render/vulkan/src/wrapper/device_create.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
165
engine/modules/render/vulkan/src/wrapper/instance_create.cpp
Normal file
165
engine/modules/render/vulkan/src/wrapper/instance_create.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
engine/modules/render/vulkan/src/wrapper/queue.cpp
Normal file
12
engine/modules/render/vulkan/src/wrapper/queue.cpp
Normal 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,4 +2,13 @@ shared_module("vulkan","engine")
|
|||||||
add_headerfiles("include/**.h")
|
add_headerfiles("include/**.h")
|
||||||
add_files("src/**.cpp", "include/volk/volk.c")
|
add_files("src/**.cpp", "include/volk/volk.c")
|
||||||
add_packages("vulkansdk", {public = true})
|
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)
|
||||||
@ -6,8 +6,8 @@ using namespace api;
|
|||||||
void ZWorldModule::OnLoad(int argc, char** argv)
|
void ZWorldModule::OnLoad(int argc, char** argv)
|
||||||
{
|
{
|
||||||
// 创建窗口
|
// 创建窗口
|
||||||
new (GlobalPool()) vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" }, 1080, 720);
|
new vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" }, 1080, 720);
|
||||||
new (GlobalPool()) vkn::VulkanAPI();
|
new vkn::VulkanAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZWorldModule::OnUnload()
|
void ZWorldModule::OnUnload()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user