support renderdoc

This commit is contained in:
ouczbs 2024-03-26 10:14:40 +08:00
parent 13aaa8cd63
commit c39c997c8d
34 changed files with 582 additions and 74 deletions

42
engine/3rdparty/json/xmake.lua vendored Normal file
View 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)

View File

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

View File

@ -1,7 +0,0 @@
#version 450
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0, 1.0, 0.0, 1.0);
}

Binary file not shown.

View File

View File

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec4 inColor;
layout(location = 0) out vec4 outFragColor;
void main()
{
outFragColor = inColor;
}

View File

@ -1,7 +0,0 @@
#version 450
layout (location = 0) in vec3 inPosition;
void main() {
gl_Position = vec4(inPosition, 1.0);
}

Binary file not shown.

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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)
{
}
}

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -48,9 +48,7 @@ namespace vulkanapi {
} }
VkFence CommandPool::AllocateFence() VkFence CommandPool::AllocateFence()
{ {
VkFence fence; return mDevice.CreateFence();
mDevice.CreateFence(fence);
return fence;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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