support renderdoc
This commit is contained in:
parent
13aaa8cd63
commit
c39c997c8d
42
engine/3rdparty/json/xmake.lua
vendored
Normal file
42
engine/3rdparty/json/xmake.lua
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package("nlohmann_json")
|
||||||
|
|
||||||
|
set_homepage("https://nlohmann.github.io/json/")
|
||||||
|
set_description("JSON for Modern C++")
|
||||||
|
set_license("MIT")
|
||||||
|
|
||||||
|
add_urls("https://github.com/nlohmann/json/archive/$(version).tar.gz",
|
||||||
|
"https://github.com/nlohmann/json.git")
|
||||||
|
add_versions("v3.11.3", "0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406")
|
||||||
|
add_versions("v3.11.2", "d69f9deb6a75e2580465c6c4c5111b89c4dc2fa94e3a85fcd2ffcd9a143d9273")
|
||||||
|
add_versions("v3.10.5", "5daca6ca216495edf89d167f808d1d03c4a4d929cef7da5e10f135ae1540c7e4")
|
||||||
|
add_versions("v3.10.0", "eb8b07806efa5f95b349766ccc7a8ec2348f3b2ee9975ad879259a371aea8084")
|
||||||
|
add_versions("v3.9.1", "4cf0df69731494668bdd6460ed8cb269b68de9c19ad8c27abc24cd72605b2d5b")
|
||||||
|
|
||||||
|
add_configs("cmake", {description = "Use cmake buildsystem", default = false, type = "boolean"})
|
||||||
|
|
||||||
|
if is_plat("mingw") and is_subhost("msys") then
|
||||||
|
add_extsources("pacman::nlohmann-json")
|
||||||
|
elseif is_plat("linux") then
|
||||||
|
add_extsources("pacman::nlohmann-json", "apt::nlohmann-json3-dev")
|
||||||
|
elseif is_plat("macosx") then
|
||||||
|
add_extsources("brew::nlohmann-json")
|
||||||
|
end
|
||||||
|
|
||||||
|
on_load(function (package)
|
||||||
|
if package:config("cmake") then
|
||||||
|
package:add("deps", "cmake")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
on_install(function (package)
|
||||||
|
if package:config("cmake") then
|
||||||
|
local configs = {"-DJSON_BuildTests=OFF"}
|
||||||
|
import("package.tools.cmake").install(package, configs)
|
||||||
|
else
|
||||||
|
if os.isdir("include") then
|
||||||
|
os.cp("include", package:installdir())
|
||||||
|
else
|
||||||
|
os.cp("*", package:installdir("include"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
4
engine/3rdparty/xmake.lua
vendored
4
engine/3rdparty/xmake.lua
vendored
@ -2,4 +2,6 @@
|
|||||||
includes("**/xmake.lua")
|
includes("**/xmake.lua")
|
||||||
add_requires("spdlog")
|
add_requires("spdlog")
|
||||||
add_requires("tinyobjloader")
|
add_requires("tinyobjloader")
|
||||||
add_requires("vulkansdk")
|
add_requires("vulkansdk")
|
||||||
|
add_requires("assimp")
|
||||||
|
add_requires("nlohmann_json")
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
outColor = vec4(1.0, 1.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
BIN
engine/assets/shader/simple.frag.spv
Normal file
BIN
engine/assets/shader/simple.frag.spv
Normal file
Binary file not shown.
0
engine/assets/shader/simple.json
Normal file
0
engine/assets/shader/simple.json
Normal file
11
engine/assets/shader/simple.ps.glsl
Normal file
11
engine/assets/shader/simple.ps.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 inColor;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outFragColor = inColor;
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 inPosition;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(inPosition, 1.0);
|
|
||||||
}
|
|
||||||
BIN
engine/assets/shader/simple.vert.spv
Normal file
BIN
engine/assets/shader/simple.vert.spv
Normal file
Binary file not shown.
22
engine/assets/shader/simple.vs.glsl
Normal file
22
engine/assets/shader/simple.vs.glsl
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#version 450
|
||||||
|
#extension GL_GOOGLE_include_directive : enable
|
||||||
|
|
||||||
|
// 顶点位置输入变量
|
||||||
|
layout (location = 0) in vec3 position;
|
||||||
|
layout (location = 1) in vec2 texture;
|
||||||
|
layout (location = 2) in vec3 normal;
|
||||||
|
layout (location = 3) in vec3 tangent;
|
||||||
|
layout (location = 4) in vec4 weights;
|
||||||
|
layout (location = 5) in uvec4 bones;
|
||||||
|
|
||||||
|
// 在这里声明输出变量
|
||||||
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
|
// 顶点位置输出变量
|
||||||
|
//out vec4 outPosition;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(position, 1);
|
||||||
|
outColor = vec4(texture, 0, 1);
|
||||||
|
}
|
||||||
@ -33,7 +33,9 @@ namespace engineapi
|
|||||||
mFlags &= ~ASSET_LOADING_FLAG;
|
mFlags &= ~ASSET_LOADING_FLAG;
|
||||||
mFlags |= ASSET_LOADED_FLAG;
|
mFlags |= ASSET_LOADED_FLAG;
|
||||||
};
|
};
|
||||||
|
string& GetName() {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
inline bool IsShared() {
|
inline bool IsShared() {
|
||||||
return mFlags & ASSET_SHARED_FLAG;
|
return mFlags & ASSET_SHARED_FLAG;
|
||||||
|
|||||||
@ -41,8 +41,10 @@ namespace engineapi {
|
|||||||
{
|
{
|
||||||
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
||||||
ifstream file(path, std::ios::ate | std::ios::binary);
|
ifstream file(path, std::ios::ate | std::ios::binary);
|
||||||
if (!file.is_open())
|
if (!file.is_open()) {
|
||||||
zlog::info("Failed to load binary file: {}", path);
|
zlog::info("Failed to load binary file: {}", path);
|
||||||
|
return vector<char>();
|
||||||
|
}
|
||||||
|
|
||||||
// 使用读取位置来确定文件的大小并分配缓冲区
|
// 使用读取位置来确定文件的大小并分配缓冲区
|
||||||
size_t fileSize = (size_t)file.tellg();
|
size_t fileSize = (size_t)file.tellg();
|
||||||
@ -55,4 +57,25 @@ namespace engineapi {
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
json AssetManager::LoadJsonFile(const string& path)
|
||||||
|
{
|
||||||
|
std::ifstream f(path);
|
||||||
|
if (!f.is_open())
|
||||||
|
{
|
||||||
|
zlog::error("Load asset failed: {}", path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
json data;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = json::parse(f);
|
||||||
|
}
|
||||||
|
catch (json::exception& e)
|
||||||
|
{
|
||||||
|
zlog::error("Asset format error: {}", path);
|
||||||
|
string msg = e.what();
|
||||||
|
zlog::error("Error detail: {}", msg);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
#include "singleton.h"
|
#include "singleton.h"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
namespace engineapi
|
namespace engineapi
|
||||||
{
|
{
|
||||||
class AssetManager : public Singleton<AssetManager>
|
class AssetManager : public Singleton<AssetManager>
|
||||||
@ -50,6 +52,7 @@ namespace engineapi
|
|||||||
public:
|
public:
|
||||||
static string LoadTextFile(const string& path);
|
static string LoadTextFile(const string& path);
|
||||||
static vector<char> LoadBinaryFile(const string& path);
|
static vector<char> LoadBinaryFile(const string& path);
|
||||||
|
static json LoadJsonFile(const string& path);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
#include "shader.h"
|
||||||
#include "asset/asset_manager.h"
|
#include "asset/asset_manager.h"
|
||||||
#include "../renderapi.h"
|
#include "../renderapi.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
Material::Material(string name, uint32_t flags)
|
Material::Material(string name, uint32_t flags)
|
||||||
:Asset(name, flags)
|
:Asset(name, flags)
|
||||||
{
|
{
|
||||||
auto vertShader = AssetManager::LoadBinaryFile(name);
|
mShader = new Shader(name, flags);
|
||||||
}
|
}
|
||||||
Material::~Material()
|
Material::~Material()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,10 +2,11 @@
|
|||||||
#include "asset_render.h"
|
#include "asset_render.h"
|
||||||
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
|
class Shader;
|
||||||
class Material : public Asset {
|
class Material : public Asset {
|
||||||
protected:
|
protected:
|
||||||
uint32_t mId;
|
uint32_t mId{0};
|
||||||
|
Shader* mShader;
|
||||||
public:
|
public:
|
||||||
Material(string name, uint32_t flags);
|
Material(string name, uint32_t flags);
|
||||||
~Material();
|
~Material();
|
||||||
|
|||||||
@ -1,16 +1,28 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
#include "asset/asset_manager.h"
|
||||||
#include "../renderapi.h"
|
#include "../renderapi.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
Shader::Shader(string name, uint32_t flags)
|
Shader::Shader(string name, uint32_t flags)
|
||||||
:Asset(name, flags)
|
:Asset(name, flags)
|
||||||
{
|
{
|
||||||
|
BeginLoad();
|
||||||
}
|
}
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void Shader::BeginLoad()
|
void Shader::BeginLoad()
|
||||||
{
|
{
|
||||||
|
json data = AssetManager::LoadJsonFile(mName + ".json");
|
||||||
|
RenderAPI::GetSingletonPtr()->LoadShader(this);
|
||||||
|
//ShaderProperty
|
||||||
|
//mInfo.vertProperties.baseProperties.push_back
|
||||||
|
}
|
||||||
|
vector<char> Shader::GetVertData()
|
||||||
|
{
|
||||||
|
return AssetManager::LoadBinaryFile(mName + ".vert.spv");
|
||||||
|
}
|
||||||
|
vector<char> Shader::GetFragData()
|
||||||
|
{
|
||||||
|
return AssetManager::LoadBinaryFile(mName + ".frag.spv");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,19 @@ namespace engineapi {
|
|||||||
class Shader : public Asset {
|
class Shader : public Asset {
|
||||||
protected:
|
protected:
|
||||||
uint32_t mId;
|
uint32_t mId;
|
||||||
|
ShaderInfo mInfo;
|
||||||
public:
|
public:
|
||||||
Shader(string name, uint32_t flags);
|
Shader(string name, uint32_t flags);
|
||||||
~Shader();
|
~Shader();
|
||||||
void BeginLoad()override;
|
void BeginLoad()override;
|
||||||
|
|
||||||
|
uint32_t& GetID() {
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
ShaderInfo& GetInfo() {
|
||||||
|
return mInfo;
|
||||||
|
}
|
||||||
|
vector<char> GetVertData();
|
||||||
|
vector<char> GetFragData();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -4,6 +4,7 @@
|
|||||||
namespace engineapi
|
namespace engineapi
|
||||||
{
|
{
|
||||||
class Mesh;
|
class Mesh;
|
||||||
|
class Shader;
|
||||||
class Camera;
|
class Camera;
|
||||||
class RenderNode;
|
class RenderNode;
|
||||||
class RenderAPI : public Singleton<RenderAPI>
|
class RenderAPI : public Singleton<RenderAPI>
|
||||||
@ -31,7 +32,10 @@ namespace engineapi
|
|||||||
virtual void SetStaticMesh(Mesh* mesh) = 0;
|
virtual void SetStaticMesh(Mesh* mesh) = 0;
|
||||||
virtual void DrawStaticMesh(Mesh* mesh) = 0;
|
virtual void DrawStaticMesh(Mesh* mesh) = 0;
|
||||||
|
|
||||||
|
virtual void LoadShader(Shader* shader) = 0;
|
||||||
virtual void SwitchContext() = 0;
|
virtual void SwitchContext() = 0;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static RenderAPI* MakeInstance();
|
static RenderAPI* MakeInstance();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -31,10 +31,13 @@ namespace engineapi {
|
|||||||
:mWidth(width), mHeight(height)
|
:mWidth(width), mHeight(height)
|
||||||
{
|
{
|
||||||
RECT wr{};
|
RECT wr{};
|
||||||
wr.left = 100;
|
wr.left = 0;
|
||||||
wr.right = width + wr.left;
|
wr.right = width + wr.left;
|
||||||
wr.top = 100;
|
wr.top = 0;
|
||||||
wr.bottom = height + wr.top;
|
wr.bottom = height + wr.top;
|
||||||
|
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||||
|
DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||||
|
AdjustWindowRectEx(&wr, dwStyle, FALSE, dwExStyle);
|
||||||
mPtr = CreateWindow(
|
mPtr = CreateWindow(
|
||||||
WindowClass::GetName(), title,
|
WindowClass::GetName(), title,
|
||||||
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
|
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace vulkanapi {
|
|||||||
mTarget = target;
|
mTarget = target;
|
||||||
target->frames.reserve(target->size);
|
target->frames.reserve(target->size);
|
||||||
for (int i = 0; i < target->size; i++) {
|
for (int i = 0; i < target->size; i++) {
|
||||||
auto outputView = gBuffer.positions[i]->View(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_VIEW_TYPE_2D);
|
auto outputView = target->surfaces[i]->View(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_VIEW_TYPE_2D);
|
||||||
auto normalView = gBuffer.normals[i]->View(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_VIEW_TYPE_2D);
|
auto normalView = gBuffer.normals[i]->View(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_VIEW_TYPE_2D);
|
||||||
vector<VkImageView> surfaces = { outputView, normalView };
|
vector<VkImageView> surfaces = { outputView, normalView };
|
||||||
target->frames.emplace_back(device, target, this, surfaces);
|
target->frames.emplace_back(device, target, this, surfaces);
|
||||||
@ -28,13 +28,13 @@ namespace vulkanapi {
|
|||||||
{
|
{
|
||||||
VkAttachmentDescription positionAttachment{};
|
VkAttachmentDescription positionAttachment{};
|
||||||
positionAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
positionAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
positionAttachment.format = gBuffer.positions[0]->Format();
|
positionAttachment.format = target->surfaces[0]->Format();
|
||||||
positionAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
positionAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
positionAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
positionAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
positionAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
positionAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
positionAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
positionAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
positionAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
positionAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
positionAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
positionAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
VkAttachmentDescription normalAttachment{};
|
VkAttachmentDescription normalAttachment{};
|
||||||
normalAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
normalAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|||||||
33
engine/src/engine/vulkanapi/tool/spirv_compiler.cpp
Normal file
33
engine/src/engine/vulkanapi/tool/spirv_compiler.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "spirv_compiler.h"
|
||||||
|
|
||||||
|
namespace vulkanapi {
|
||||||
|
void SPIRVCompiler::CompileAllShader(string path)
|
||||||
|
{
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(path))
|
||||||
|
{
|
||||||
|
string extension = entry.path().filename().extension().string();
|
||||||
|
if (extension == ".vert")
|
||||||
|
GenerateSPIRVVertFile(entry.path().string());
|
||||||
|
else if (extension == ".frag")
|
||||||
|
GenerateSPIRVFragFile(entry.path());
|
||||||
|
else if (extension == "")
|
||||||
|
CompileAllShader(entry.path().string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SPIRVCompiler::GenerateSPIRVFragFile(const filesystem::path& path)
|
||||||
|
{
|
||||||
|
string filePath = path.string();
|
||||||
|
string outputFinalPath = path.parent_path().string() + "\\" + path.stem().string() + ".spv";
|
||||||
|
//glslc simple.vert -o simple.vert.spv
|
||||||
|
//glslc simple.frag -o simple.frag.spv
|
||||||
|
//glslc -fshader-stage=vertex simple.vs.glsl -o simple.vert.spv
|
||||||
|
//glslc -fshader-stage=fragment simple.ps.glsl -o simple.frag.spv
|
||||||
|
string command = "glslc ";
|
||||||
|
|
||||||
|
std::system(command.c_str());
|
||||||
|
}
|
||||||
|
void SPIRVCompiler::GenerateSPIRVVertFile(const filesystem::path& path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
16
engine/src/engine/vulkanapi/tool/spirv_compiler.h
Normal file
16
engine/src/engine/vulkanapi/tool/spirv_compiler.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../vulkan.h"
|
||||||
|
#include <filesystem>
|
||||||
|
namespace filesystem = std::filesystem;
|
||||||
|
namespace vulkanapi {
|
||||||
|
class Device;
|
||||||
|
class Queue;
|
||||||
|
class SPIRVCompiler {
|
||||||
|
public:
|
||||||
|
static void CompileAllShader(string path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void GenerateSPIRVFragFile(const filesystem::path& path);
|
||||||
|
static void GenerateSPIRVVertFile(const filesystem::path& path);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -9,10 +9,12 @@
|
|||||||
namespace vulkanapi {
|
namespace vulkanapi {
|
||||||
#define Z_USE_GRAPHIC_DEBUG
|
#define Z_USE_GRAPHIC_DEBUG
|
||||||
class CommandBuffer;
|
class CommandBuffer;
|
||||||
|
using std::array;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::to_string;
|
using std::to_string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
using std::make_pair;
|
||||||
using voidFn = std::function<void()>;
|
using voidFn = std::function<void()>;
|
||||||
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
||||||
}
|
}
|
||||||
@ -1,8 +1,104 @@
|
|||||||
#include "vulkan_context.h"
|
#include "vulkan_context.h"
|
||||||
#include "vulkanapi.h"
|
#include "vulkanapi.h"
|
||||||
|
#include "zlog.h"
|
||||||
namespace vulkanapi {
|
namespace vulkanapi {
|
||||||
|
RenderVulkanAPI* VulkanContext::API = nullptr;
|
||||||
void VulkanContext::UseContext()
|
void VulkanContext::UseContext()
|
||||||
{
|
{
|
||||||
Pass = API.PassList[PassId];
|
Pass = API->PassList[PassId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayout VulkanContext::CreateDescriptorSetLayout(const ShaderInfo& info)
|
||||||
|
{
|
||||||
|
vector<VkDescriptorSetLayoutBinding> bindings = {};
|
||||||
|
|
||||||
|
if (!info.vertProperties.baseProperties.empty())
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding uboBinding = {};
|
||||||
|
uboBinding.binding = info.vertProperties.baseProperties[0].binding;
|
||||||
|
uboBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
uboBinding.descriptorCount = 1;
|
||||||
|
uboBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
bindings.push_back(uboBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& texture : info.vertProperties.textureProperties)
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding samplerBinding = {};
|
||||||
|
samplerBinding.binding = texture.binding;
|
||||||
|
samplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
samplerBinding.descriptorCount = 1;
|
||||||
|
samplerBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
bindings.push_back(samplerBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.geomProperties.baseProperties.empty())
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding uboBinding = {};
|
||||||
|
uboBinding.binding = info.geomProperties.baseProperties[0].binding;
|
||||||
|
uboBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
uboBinding.descriptorCount = 1;
|
||||||
|
uboBinding.stageFlags = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
|
bindings.push_back(uboBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& texture : info.geomProperties.textureProperties)
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding samplerBinding = {};
|
||||||
|
samplerBinding.binding = texture.binding;
|
||||||
|
samplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
samplerBinding.descriptorCount = 1;
|
||||||
|
samplerBinding.stageFlags = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
|
bindings.push_back(samplerBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.fragProperties.baseProperties.empty())
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding uboBinding = {};
|
||||||
|
uboBinding.binding = info.fragProperties.baseProperties[0].binding;
|
||||||
|
uboBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
uboBinding.descriptorCount = 1;
|
||||||
|
uboBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
bindings.push_back(uboBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& texture : info.fragProperties.textureProperties)
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding samplerBinding = {};
|
||||||
|
samplerBinding.binding = texture.binding;
|
||||||
|
samplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
samplerBinding.descriptorCount = 1;
|
||||||
|
samplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
bindings.push_back(samplerBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateDescriptorSetLayout(bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayout VulkanContext::CreateDescriptorSetLayout(const vector<VkDescriptorSetLayoutBinding>& bindings)
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayout descriptorSetLayout = {};
|
||||||
|
VkDescriptorSetLayoutCreateInfo layoutInfo = {};
|
||||||
|
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
|
layoutInfo.pBindings = bindings.data();
|
||||||
|
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
|
||||||
|
if (vkCreateDescriptorSetLayout(API->backend.GetDevice().Ptr(), &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS)
|
||||||
|
zlog::error("failed to create descriptor set layout!");
|
||||||
|
|
||||||
|
return descriptorSetLayout;
|
||||||
|
}
|
||||||
|
VkPipelineLayout VulkanContext::CreatePipelineLayout(const vector<VkDescriptorSetLayout>& descriptorSetLayouts, const vector<VkPushConstantRange>& pushConstantRanges)
|
||||||
|
{
|
||||||
|
VkPipelineLayout pipelineLayout = {};
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||||
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data();
|
||||||
|
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(descriptorSetLayouts.size());
|
||||||
|
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
||||||
|
pipelineLayoutInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
|
||||||
|
if (vkCreatePipelineLayout(API->backend.GetDevice().Ptr(), &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
|
||||||
|
zlog::error("failed to create pipeline layout!");
|
||||||
|
|
||||||
|
return pipelineLayout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,15 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "render/render_context.h"
|
#include "render/render_context.h"
|
||||||
|
#include "render/asset/shader.h"
|
||||||
#include "wrapper/renderpass.h"
|
#include "wrapper/renderpass.h"
|
||||||
|
using namespace engineapi;
|
||||||
namespace vulkanapi {
|
namespace vulkanapi {
|
||||||
class RenderVulkanAPI;
|
class RenderVulkanAPI;
|
||||||
class VulkanContext : public engineapi::RenderContext {
|
class VulkanContext : public engineapi::RenderContext {
|
||||||
public:
|
public:
|
||||||
RenderVulkanAPI& API;
|
static RenderVulkanAPI* API;
|
||||||
RenderPass* Pass{ nullptr };
|
RenderPass* Pass{ nullptr };
|
||||||
|
uint32_t frame;
|
||||||
|
VkSemaphore surfaceSemaphore;
|
||||||
|
VkSemaphore renderSemaphore;
|
||||||
|
public:
|
||||||
|
VulkanContext(RenderVulkanAPI* _API){
|
||||||
|
API = _API;
|
||||||
|
};
|
||||||
|
virtual void UseContext()override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VulkanContext(RenderVulkanAPI& API):API(API){};
|
static VkDescriptorSetLayout CreateDescriptorSetLayout(const ShaderInfo& info);
|
||||||
virtual void UseContext()override;
|
static VkDescriptorSetLayout CreateDescriptorSetLayout(const vector<VkDescriptorSetLayoutBinding>& bindings);
|
||||||
|
|
||||||
|
static VkPipelineLayout CreatePipelineLayout(const vector<VkDescriptorSetLayout>& descriptorSetLayouts, const vector<VkPushConstantRange>& pushConstantRanges);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -3,17 +3,17 @@
|
|||||||
#include "wrapper/buffer.h"
|
#include "wrapper/buffer.h"
|
||||||
#include "wrapper/commandbuffer.h"
|
#include "wrapper/commandbuffer.h"
|
||||||
#include "thread/worker.h"
|
#include "thread/worker.h"
|
||||||
#include "render/asset/mesh.h"
|
|
||||||
#include "object/camera/camera.h"
|
#include "object/camera/camera.h"
|
||||||
#include "render/node/rendernode.h"
|
#include "render/node/rendernode.h"
|
||||||
#include "pass/forwardpass.h"
|
#include "pass/forwardpass.h"
|
||||||
#include "pass/target.h"
|
#include "pass/target.h"
|
||||||
#include "wrapper/swapchain.h"
|
#include "wrapper/swapchain.h"
|
||||||
|
#include "render/asset/mesh.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
namespace vulkanapi {
|
namespace vulkanapi {
|
||||||
RenderVulkanAPI::RenderVulkanAPI()
|
RenderVulkanAPI::RenderVulkanAPI()
|
||||||
:backend("vulkan")
|
:backend("vulkan")
|
||||||
,context(*this)
|
,context(this)
|
||||||
{
|
{
|
||||||
Buffer::MakeVmaAllocator(backend);
|
Buffer::MakeVmaAllocator(backend);
|
||||||
}
|
}
|
||||||
@ -50,11 +50,11 @@ namespace vulkanapi {
|
|||||||
}
|
}
|
||||||
void RenderVulkanAPI::BeginFrame()
|
void RenderVulkanAPI::BeginFrame()
|
||||||
{
|
{
|
||||||
mFrame = swapchain->Aquire();
|
swapchain->Aquire(context);
|
||||||
}
|
}
|
||||||
void RenderVulkanAPI::EndFrame()
|
void RenderVulkanAPI::EndFrame()
|
||||||
{
|
{
|
||||||
swapchain->Present(mFrame);
|
swapchain->Present(context);
|
||||||
}
|
}
|
||||||
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
|
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
|
||||||
{
|
{
|
||||||
@ -110,35 +110,244 @@ namespace vulkanapi {
|
|||||||
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
|
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
|
||||||
{
|
{
|
||||||
auto vulkanVAO = VAOList[mesh->GetVAO()];
|
auto vulkanVAO = VAOList[mesh->GetVAO()];
|
||||||
|
auto pipeline = PiPelineList[0];
|
||||||
|
uint32_t frame = context.frame;
|
||||||
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
|
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
|
||||||
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
|
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
|
||||||
VkCommandBuffer ptr = cmd.Ptr();
|
VkCommandBuffer ptr = cmd.Ptr();
|
||||||
context.Pass->BeginPass(cmd, mFrame);
|
context.Pass->BeginPass(cmd, frame);
|
||||||
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer };
|
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer };
|
||||||
VkDeviceSize offsets[] = { 0 };
|
VkDeviceSize offsets[] = { 0 };
|
||||||
|
VkViewport viewport = {};
|
||||||
|
viewport.x = static_cast<float>(mViewPortInfo.xOffset);
|
||||||
|
viewport.y = static_cast<float>(mViewPortInfo.yOffset);
|
||||||
|
viewport.width = static_cast<float>(mViewPortInfo.width);
|
||||||
|
viewport.height = static_cast<float>(mViewPortInfo.height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
vkCmdSetViewport(ptr, 0, 1, &viewport);
|
||||||
|
|
||||||
|
VkRect2D scissor = {};
|
||||||
|
scissor.offset = { mViewPortInfo.xOffset, mViewPortInfo.yOffset };
|
||||||
|
scissor.extent = { mViewPortInfo.width, mViewPortInfo.height };
|
||||||
|
vkCmdSetScissor(ptr, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
||||||
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
||||||
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipelineLayout, 0, 1, &materialData->descriptorSets[currentFrame], 0, VK_NULL_HANDLE);
|
//vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipelineLayout, 0, 1, &pipeline->descriptorSet, 0, VK_NULL_HANDLE);
|
||||||
vkCmdDrawIndexed(ptr, vulkanVAO->indexCount, 1, 0, 0, 0);
|
vkCmdDrawIndexed(ptr, vulkanVAO->indexCount, 1, 0, 0, 0);
|
||||||
context.Pass->EndPass(cmd);
|
context.Pass->EndPass(cmd);
|
||||||
});
|
});
|
||||||
|
Backend::RenderWorker->Flush();
|
||||||
}
|
}
|
||||||
VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& VAO_index)
|
void RenderVulkanAPI::LoadShader(Shader* shader)
|
||||||
|
{
|
||||||
|
vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||||
|
map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
|
||||||
|
auto device = backend.GetDevice();
|
||||||
|
auto vertData = shader->GetVertData();
|
||||||
|
auto vertModule = device.CreateShaderModule(vertData);
|
||||||
|
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
|
||||||
|
auto fragData = shader->GetFragData();
|
||||||
|
auto fragModule = device.CreateShaderModule(fragData);
|
||||||
|
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
|
||||||
|
for (auto& shaderModule : shaderModules)
|
||||||
|
{
|
||||||
|
VkPipelineShaderStageCreateInfo shaderStageInfo = {};
|
||||||
|
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
shaderStageInfo.stage = shaderModule.first;
|
||||||
|
shaderStageInfo.module = shaderModule.second;
|
||||||
|
shaderStageInfo.pName = "main";
|
||||||
|
shaderStages.push_back(shaderStageInfo);
|
||||||
|
}
|
||||||
|
// 设置顶点输入格式
|
||||||
|
VkVertexInputBindingDescription bindingDescription = {};
|
||||||
|
bindingDescription.binding = 0;
|
||||||
|
bindingDescription.stride = sizeof(Vertex);
|
||||||
|
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
array<VkVertexInputAttributeDescription, 6> attributeDescriptions = {};
|
||||||
|
attributeDescriptions[0].binding = 0;
|
||||||
|
attributeDescriptions[0].location = 0;
|
||||||
|
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
attributeDescriptions[0].offset = offsetof(Vertex, Position);
|
||||||
|
attributeDescriptions[1].binding = 0;
|
||||||
|
attributeDescriptions[1].location = 1;
|
||||||
|
attributeDescriptions[1].format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
attributeDescriptions[1].offset = offsetof(Vertex, TexCoords);
|
||||||
|
attributeDescriptions[2].binding = 0;
|
||||||
|
attributeDescriptions[2].location = 2;
|
||||||
|
attributeDescriptions[2].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
attributeDescriptions[2].offset = offsetof(Vertex, Normal);
|
||||||
|
attributeDescriptions[3].binding = 0;
|
||||||
|
attributeDescriptions[3].location = 3;
|
||||||
|
attributeDescriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
attributeDescriptions[3].offset = offsetof(Vertex, Tangent);
|
||||||
|
attributeDescriptions[4].binding = 0;
|
||||||
|
attributeDescriptions[4].location = 4;
|
||||||
|
attributeDescriptions[4].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
attributeDescriptions[4].offset = offsetof(Vertex, Weights);
|
||||||
|
attributeDescriptions[5].binding = 0;
|
||||||
|
attributeDescriptions[5].location = 5;
|
||||||
|
attributeDescriptions[5].format = VK_FORMAT_R32G32B32A32_UINT;
|
||||||
|
attributeDescriptions[5].offset = offsetof(Vertex, BoneIDs);
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||||
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||||
|
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||||
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||||
|
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
|
||||||
|
|
||||||
|
// 设置图元
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {};
|
||||||
|
inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
// ViewPort信息,这里不直接设置,下面弄成动态的
|
||||||
|
VkPipelineViewportStateCreateInfo viewportStateInfo = {};
|
||||||
|
viewportStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewportStateInfo.viewportCount = 1;
|
||||||
|
viewportStateInfo.scissorCount = 1;
|
||||||
|
|
||||||
|
// View Port和Scissor设置为动态,每帧绘制时决定
|
||||||
|
vector<VkDynamicState> dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicStateInfo = {};
|
||||||
|
dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
dynamicStateInfo.pDynamicStates = dynamicStates.data();
|
||||||
|
dynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
|
||||||
|
|
||||||
|
// 设置光栅化阶段
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizationInfo = {};
|
||||||
|
rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
// 如果depthClampEnable设置为VK_TRUE,超过远近裁剪面的片元会进行收敛,而不是丢弃它们
|
||||||
|
rasterizationInfo.depthClampEnable = VK_FALSE;
|
||||||
|
// 如果rasterizerDiscardEnable设置为VK_TRUE,那么几何图元永远不会传递到光栅化阶段
|
||||||
|
// 这是禁止任何数据输出到framebuffer的方法
|
||||||
|
rasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
|
||||||
|
// 设置片元如何从几何模型中产生,如果不是FILL,需要开启GPU feature
|
||||||
|
// VK_POLYGON_MODE_FILL: 多边形区域填充
|
||||||
|
// VK_POLYGON_MODE_LINE: 多边形边缘线框绘制
|
||||||
|
// VK_POLYGON_MODE_POINT : 多边形顶点作为描点绘制
|
||||||
|
rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
|
rasterizationInfo.lineWidth = 1.0f;
|
||||||
|
rasterizationInfo.cullMode = VK_CULL_MODE_FRONT_BIT;
|
||||||
|
rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||||
|
// 渲染阴影的偏移配置
|
||||||
|
rasterizationInfo.depthBiasEnable = VK_FALSE;
|
||||||
|
rasterizationInfo.depthBiasConstantFactor = 0.0f;
|
||||||
|
rasterizationInfo.depthBiasClamp = 0.0f;
|
||||||
|
rasterizationInfo.depthBiasSlopeFactor = 0.0f;
|
||||||
|
|
||||||
|
// 设置Shader采样纹理的MSAA(不是输出到屏幕上的MSAA),需要创建逻辑设备的时候开启VkPhysicalDeviceFeatures里的sampleRateShading才能生效,暂时关闭
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampleInfo = {};
|
||||||
|
multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
multisampleInfo.sampleShadingEnable = (VK_SAMPLE_COUNT_1_BIT & VK_SAMPLE_COUNT_1_BIT ? VK_FALSE : VK_TRUE);
|
||||||
|
multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
// 这个是调整sampleShading效果的,越接近1效果越平滑,越接近0性能越好
|
||||||
|
multisampleInfo.minSampleShading = 1.0f;
|
||||||
|
multisampleInfo.pSampleMask = VK_NULL_HANDLE;
|
||||||
|
multisampleInfo.alphaToCoverageEnable = VK_FALSE;
|
||||||
|
multisampleInfo.alphaToOneEnable = VK_FALSE;
|
||||||
|
|
||||||
|
// Color Blend
|
||||||
|
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
||||||
|
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
colorBlendAttachment.blendEnable = VK_TRUE;
|
||||||
|
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
|
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
|
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
|
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
||||||
|
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
|
colorBlending.logicOpEnable = VK_FALSE;
|
||||||
|
colorBlending.logicOp = VK_LOGIC_OP_COPY;
|
||||||
|
colorBlending.pAttachments = &colorBlendAttachment;
|
||||||
|
colorBlending.attachmentCount = 1;
|
||||||
|
|
||||||
|
// 深度和模板配置
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencilInfo = {};
|
||||||
|
depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
|
// Depth
|
||||||
|
depthStencilInfo.depthWriteEnable = VK_FALSE;
|
||||||
|
depthStencilInfo.depthTestEnable = VK_TRUE;
|
||||||
|
depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS;
|
||||||
|
depthStencilInfo.depthBoundsTestEnable = VK_FALSE;
|
||||||
|
depthStencilInfo.minDepthBounds = 0.0f;
|
||||||
|
depthStencilInfo.maxDepthBounds = 1.0f;
|
||||||
|
// Stencil
|
||||||
|
depthStencilInfo.stencilTestEnable = VK_FALSE;
|
||||||
|
depthStencilInfo.front = {};
|
||||||
|
depthStencilInfo.back = {};
|
||||||
|
|
||||||
|
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo());
|
||||||
|
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pipelineInfo.pStages = shaderStages.data();
|
||||||
|
pipelineInfo.stageCount = (uint32_t)shaderStages.size();
|
||||||
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||||
|
pipelineInfo.pInputAssemblyState = &inputAssemblyInfo;
|
||||||
|
pipelineInfo.pViewportState = &viewportStateInfo;
|
||||||
|
pipelineInfo.pDynamicState = &dynamicStateInfo;
|
||||||
|
pipelineInfo.pRasterizationState = &rasterizationInfo;
|
||||||
|
pipelineInfo.pMultisampleState = &multisampleInfo;
|
||||||
|
pipelineInfo.pColorBlendState = &colorBlending;
|
||||||
|
pipelineInfo.pDepthStencilState = &depthStencilInfo;
|
||||||
|
pipelineInfo.layout = pipelineLayout;
|
||||||
|
pipelineInfo.renderPass = PassList[RENDER_FORWARD_RENDERING]->Ptr();
|
||||||
|
pipelineInfo.subpass = 0;
|
||||||
|
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
pipelineInfo.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
VkPipeline pipeLine;
|
||||||
|
if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS)
|
||||||
|
throw std::runtime_error("failed to create graphics pipeline!");
|
||||||
|
|
||||||
|
for (auto& shaderModule : shaderModules)
|
||||||
|
vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
||||||
|
|
||||||
|
auto vulkan_pipeline = GetNextPipeline(shader->GetID());
|
||||||
|
vulkan_pipeline->name = shader->GetName();
|
||||||
|
vulkan_pipeline->pipeline = pipeLine;
|
||||||
|
vulkan_pipeline->inUse = true;
|
||||||
|
vulkan_pipeline->pipelineLayout = pipelineLayout;
|
||||||
|
vulkan_pipeline->descriptorSetLayout = descriptorSetLayout;
|
||||||
|
}
|
||||||
|
VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& index)
|
||||||
{
|
{
|
||||||
uint32_t length = (uint32_t)VAOList.size();
|
uint32_t length = (uint32_t)VAOList.size();
|
||||||
for (uint32_t i = 0; i < length; i++)
|
for (uint32_t i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
if (!VAOList[i]->inUse) {
|
if (!VAOList[i]->inUse) {
|
||||||
VAO_index = i;
|
index = i;
|
||||||
return VAOList[i];
|
return VAOList[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VAO_index = length;
|
index = length;
|
||||||
auto vao = new VulkanVAO();
|
auto vao = new VulkanVAO();
|
||||||
VAOList.push_back(vao);
|
VAOList.push_back(vao);
|
||||||
return vao;
|
return vao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VulkanPipeline* RenderVulkanAPI::GetNextPipeline(uint32_t& index)
|
||||||
|
{
|
||||||
|
uint32_t length = (uint32_t)PiPelineList.size();
|
||||||
|
for (uint32_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (!PiPelineList[i]->inUse) {
|
||||||
|
index = i;
|
||||||
|
return PiPelineList[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index = length;
|
||||||
|
auto info = new VulkanPipeline();
|
||||||
|
PiPelineList.push_back(info);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#include "render/renderapi.h"
|
#include "render/renderapi.h"
|
||||||
#include "vulkan_struct.h"
|
#include "vulkan_struct.h"
|
||||||
#include "vulkan_context.h"
|
#include "vulkan_context.h"
|
||||||
using namespace engineapi;
|
|
||||||
namespace vulkanapi
|
namespace vulkanapi
|
||||||
{
|
{
|
||||||
class RenderTarget;
|
class RenderTarget;
|
||||||
@ -14,10 +13,11 @@ namespace vulkanapi
|
|||||||
public:
|
public:
|
||||||
Backend backend;
|
Backend backend;
|
||||||
VulkanContext context;
|
VulkanContext context;
|
||||||
Swapchain* swapchain;
|
Swapchain* swapchain{nullptr};
|
||||||
vector<RenderTarget*> TargetList;
|
vector<RenderTarget*> TargetList;
|
||||||
vector<VulkanVAO*> VAOList;
|
vector<VulkanVAO*> VAOList;
|
||||||
vector<RenderPass*> PassList;
|
vector<RenderPass*> PassList;
|
||||||
|
vector<VulkanPipeline*> PiPelineList;
|
||||||
public:
|
public:
|
||||||
RenderVulkanAPI();
|
RenderVulkanAPI();
|
||||||
virtual ~RenderVulkanAPI()override;
|
virtual ~RenderVulkanAPI()override;
|
||||||
@ -36,8 +36,11 @@ namespace vulkanapi
|
|||||||
virtual void EndFrame()override;
|
virtual void EndFrame()override;
|
||||||
virtual void SetStaticMesh(Mesh* mesh)override;
|
virtual void SetStaticMesh(Mesh* mesh)override;
|
||||||
virtual void DrawStaticMesh(Mesh* mesh)override;
|
virtual void DrawStaticMesh(Mesh* mesh)override;
|
||||||
|
|
||||||
|
virtual void LoadShader(Shader* shader)override;
|
||||||
public:
|
public:
|
||||||
VulkanVAO* GetNextVAO(uint32_t& VAO_index);
|
VulkanVAO* GetNextVAO(uint32_t& index);
|
||||||
|
VulkanPipeline* GetNextPipeline(uint32_t& index);
|
||||||
public:
|
public:
|
||||||
static RenderVulkanAPI* GetSingletonPtr() {
|
static RenderVulkanAPI* GetSingletonPtr() {
|
||||||
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
||||||
|
|||||||
@ -48,9 +48,7 @@ namespace vulkanapi {
|
|||||||
}
|
}
|
||||||
VkFence CommandPool::AllocateFence()
|
VkFence CommandPool::AllocateFence()
|
||||||
{
|
{
|
||||||
VkFence fence;
|
return mDevice.CreateFence();
|
||||||
mDevice.CreateFence(fence);
|
|
||||||
return fence;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,21 +61,35 @@ namespace vulkanapi {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
bool Device::CreateFence(VkFence& fence)
|
VkFence Device::CreateFence()
|
||||||
{
|
{
|
||||||
VkFenceCreateInfo fenceInfo{};
|
VkFenceCreateInfo fenceInfo{};
|
||||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
// 创建时立刻设置为signaled状态(否则第一次永远等不到)
|
// 创建时立刻设置为signaled状态(否则第一次永远等不到)
|
||||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
VkFence fence;
|
||||||
VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence);
|
VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence);
|
||||||
return result == VK_SUCCESS;
|
return fence;
|
||||||
}
|
}
|
||||||
bool Device::CreateSemaphore(VkSemaphore& semaphore)
|
VkSemaphore Device::CreateSemaphore()
|
||||||
{
|
{
|
||||||
VkSemaphoreCreateInfo semaphoreInfo = {};
|
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
VkSemaphore semaphore;
|
||||||
VkResult result = vkCreateSemaphore(mPtr, &semaphoreInfo, nullptr, &semaphore);
|
VkResult result = vkCreateSemaphore(mPtr, &semaphoreInfo, nullptr, &semaphore);
|
||||||
return result == VK_SUCCESS;
|
return semaphore;
|
||||||
|
}
|
||||||
|
VkShaderModule Device::CreateShaderModule(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,8 @@ namespace vulkanapi {
|
|||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
Queue* GetQueue(const string& name);
|
Queue* GetQueue(const string& name);
|
||||||
bool CreateFence(VkFence& fence);
|
VkFence CreateFence();
|
||||||
bool CreateSemaphore(VkSemaphore& semaphore);
|
VkSemaphore CreateSemaphore();
|
||||||
|
VkShaderModule CreateShaderModule(vector<char> code);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -55,10 +55,10 @@ namespace vulkanapi {
|
|||||||
// components字段允许调整颜色通道的最终的映射逻辑
|
// components字段允许调整颜色通道的最终的映射逻辑
|
||||||
// 比如,我们可以将所有颜色通道映射为红色通道,以实现单色纹理,我们也可以将通道映射具体的常量数值0和1
|
// 比如,我们可以将所有颜色通道映射为红色通道,以实现单色纹理,我们也可以将通道映射具体的常量数值0和1
|
||||||
// 这里用默认的
|
// 这里用默认的
|
||||||
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
|
|
||||||
// subresourceRangle字段用于描述图像的使用目标是什么,以及可以被访问的有效区域
|
// subresourceRangle字段用于描述图像的使用目标是什么,以及可以被访问的有效区域
|
||||||
// 这个图像用作填充color还是depth stencil等
|
// 这个图像用作填充color还是depth stencil等
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "../backend.h"
|
#include "../backend.h"
|
||||||
#include "../thread/worker.h"
|
#include "../thread/worker.h"
|
||||||
|
#include "../vulkan_context.h"
|
||||||
#include "zlog.h"
|
#include "zlog.h"
|
||||||
namespace vulkanapi {
|
namespace vulkanapi {
|
||||||
Swapchain::Swapchain(SwapchainCreator& Creator)
|
Swapchain::Swapchain(SwapchainCreator& Creator)
|
||||||
@ -18,10 +19,10 @@ namespace vulkanapi {
|
|||||||
nullptr, // const void * pNext
|
nullptr, // const void * pNext
|
||||||
0, // VkSwapchainCreateFlagsKHR flags
|
0, // VkSwapchainCreateFlagsKHR flags
|
||||||
Creator.presentation_surface, // VkSurfaceKHR surface
|
Creator.presentation_surface, // VkSurfaceKHR surface
|
||||||
(uint32_t)Creator.frames, // uint32_t minImageCount
|
(uint32_t)Creator.frames, // uint32_t minImageCount
|
||||||
Creator.imageFormat, // VkFormat imageFormat
|
Creator.imageFormat, // VkFormat imageFormat
|
||||||
Creator.imageColorSpace, // VkColorSpaceKHR imageColorSpace
|
Creator.imageColorSpace, // VkColorSpaceKHR imageColorSpace
|
||||||
image_extent, // VkExtent2D imageExtent
|
image_extent, // VkExtent2D imageExtent
|
||||||
1, // uint32_t imageArrayLayers
|
1, // uint32_t imageArrayLayers
|
||||||
Creator.imageUsage, // VkImageUsageFlags imageUsage
|
Creator.imageUsage, // VkImageUsageFlags imageUsage
|
||||||
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode
|
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode
|
||||||
@ -40,30 +41,30 @@ namespace vulkanapi {
|
|||||||
vector<VkImage> swapchain_images;
|
vector<VkImage> swapchain_images;
|
||||||
Creator.CreateSwapchainImages(mPtr, swapchain_images);
|
Creator.CreateSwapchainImages(mPtr, swapchain_images);
|
||||||
auto args = Image::Make2DArgs(Creator.width, Creator.height, Creator.imageFormat, VK_SAMPLE_COUNT_8_BIT, Creator.imageUsage, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
|
auto args = Image::Make2DArgs(Creator.width, Creator.height, Creator.imageFormat, VK_SAMPLE_COUNT_8_BIT, Creator.imageUsage, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
|
||||||
args.Sharing = VK_SHARING_MODE_CONCURRENT;
|
args.Sharing = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
for (int i = 0; i < Creator.frames;i++) {
|
for (int i = 0; i < Creator.frames;i++) {
|
||||||
mSurfaces.push_back(new Image(Creator.device,"swapchain" + to_string(i), swapchain_images[i], args));
|
mSurfaces.push_back(new Image(Creator.device,"swapchain" + to_string(i), swapchain_images[i], args));
|
||||||
}
|
}
|
||||||
Creator.device.CreateSemaphore(mSemaphore);
|
mSurfaceSemaphore = Creator.device.CreateSemaphore();
|
||||||
|
mRenderSemaphore = Creator.device.CreateSemaphore();
|
||||||
}
|
}
|
||||||
uint32_t Swapchain::Aquire()
|
void Swapchain::Aquire(VulkanContext& ctx)
|
||||||
{
|
{
|
||||||
uint32_t curPresentImageIdx;
|
ctx.surfaceSemaphore = mSurfaceSemaphore;
|
||||||
VkResult result = vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, mSemaphore, VK_NULL_HANDLE, &curPresentImageIdx);
|
vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, ctx.surfaceSemaphore, VK_NULL_HANDLE, &ctx.frame);
|
||||||
return curPresentImageIdx;
|
|
||||||
}
|
}
|
||||||
void Swapchain::Present(uint32_t frame)
|
void Swapchain::Present(VulkanContext& ctx)
|
||||||
{
|
{
|
||||||
VkSwapchainKHR swapChains[] = { mPtr };
|
VkSwapchainKHR swapChains[] = { mPtr };
|
||||||
VkSemaphore waitSemaphores[] = { mSemaphore };
|
VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore };
|
||||||
VkPresentInfoKHR presentInfo = {};
|
VkPresentInfoKHR presentInfo = {};
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
presentInfo.pWaitSemaphores = waitSemaphores;
|
presentInfo.pWaitSemaphores = waitSemaphores;
|
||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pSwapchains = swapChains;
|
presentInfo.pSwapchains = swapChains;
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
presentInfo.pImageIndices = &frame;
|
presentInfo.pImageIndices = &ctx.frame;
|
||||||
presentInfo.pResults = VK_NULL_HANDLE;
|
presentInfo.pResults = VK_NULL_HANDLE;
|
||||||
Backend::PresentWorker->Present(presentInfo);
|
Backend::RenderWorker->Present(presentInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,17 +5,19 @@ namespace vulkanapi {
|
|||||||
class Image;
|
class Image;
|
||||||
class SwapchainCreator;
|
class SwapchainCreator;
|
||||||
class Device;
|
class Device;
|
||||||
|
class VulkanContext;
|
||||||
class Swapchain {
|
class Swapchain {
|
||||||
friend class SwapchainCreator;
|
friend class SwapchainCreator;
|
||||||
protected:
|
protected:
|
||||||
VkSwapchainKHR mPtr;
|
VkSwapchainKHR mPtr;
|
||||||
Device& mDevice;
|
Device& mDevice;
|
||||||
vector<Image*> mSurfaces;
|
vector<Image*> mSurfaces;
|
||||||
VkSemaphore mSemaphore;
|
VkSemaphore mSurfaceSemaphore;
|
||||||
|
VkSemaphore mRenderSemaphore;
|
||||||
public:
|
public:
|
||||||
Swapchain(SwapchainCreator& Creator);
|
Swapchain(SwapchainCreator& Creator);
|
||||||
uint32_t Aquire();
|
void Aquire(VulkanContext& ctx);
|
||||||
void Present(uint32_t frame);
|
void Present(VulkanContext& ctx);
|
||||||
vector<Image*>& GetSurface(){
|
vector<Image*>& GetSurface(){
|
||||||
return mSurfaces;
|
return mSurfaces;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace vulkanapi {
|
|||||||
, imageFormat(VK_FORMAT_B8G8R8A8_SRGB)
|
, imageFormat(VK_FORMAT_B8G8R8A8_SRGB)
|
||||||
, imageColorSpace(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
, imageColorSpace(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
, presentMode(VK_PRESENT_MODE_MAILBOX_KHR)
|
, presentMode(VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
, imageUsage(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
, imageUsage(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
||||||
, maxFrameInFlightCount(2)
|
, maxFrameInFlightCount(2)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
includes("3rdparty/xmake.lua")
|
includes("3rdparty/xmake.lua")
|
||||||
includes("xmake/**xmake.lua")
|
includes("xmake/**xmake.lua")
|
||||||
--includes("test/**xmake.lua")
|
--includes("test/**xmake.lua")
|
||||||
add_requires("assimp")
|
|
||||||
target("zengine")
|
target("zengine")
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
set_rundir(".")
|
set_rundir(".")
|
||||||
add_rules("volk.env")
|
add_rules("volk.env")
|
||||||
add_deps("zlib","zlog")
|
add_deps("zlib","zlog")
|
||||||
add_defines("VULKAN_API")
|
add_defines("VULKAN_API")
|
||||||
add_packages("vulkansdk","tinyobjloader","assimp")
|
add_packages("vulkansdk","tinyobjloader","assimp","nlohmann_json")
|
||||||
add_includedirs("src/engine")
|
add_includedirs("src/engine")
|
||||||
add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator", "src/3rdparty/template")
|
add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator", "src/3rdparty/template")
|
||||||
add_syslinks("user32")
|
add_syslinks("user32")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user