From c39c997c8dd7506f64459aa21577130ccf01d737 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Tue, 26 Mar 2024 10:14:40 +0800 Subject: [PATCH] support renderdoc --- engine/3rdparty/json/xmake.lua | 42 ++++ engine/3rdparty/xmake.lua | 4 +- engine/assets/shader/simple.frag | 7 - engine/assets/shader/simple.frag.spv | Bin 0 -> 452 bytes engine/assets/shader/simple.json | 0 engine/assets/shader/simple.ps.glsl | 11 + engine/assets/shader/simple.vert | 7 - engine/assets/shader/simple.vert.spv | Bin 0 -> 1408 bytes engine/assets/shader/simple.vs.glsl | 22 ++ engine/src/engine/asset/asset.h | 4 +- engine/src/engine/asset/asset_manager.cpp | 25 +- engine/src/engine/asset/asset_manager.h | 3 + engine/src/engine/render/asset/material.cpp | 3 +- engine/src/engine/render/asset/material.h | 5 +- engine/src/engine/render/asset/shader.cpp | 16 +- engine/src/engine/render/asset/shader.h | 10 + engine/src/engine/render/renderapi.h | 4 + engine/src/engine/render/window.cpp | 7 +- .../src/engine/vulkanapi/pass/forwardpass.cpp | 6 +- .../engine/vulkanapi/tool/spirv_compiler.cpp | 33 +++ .../engine/vulkanapi/tool/spirv_compiler.h | 16 ++ engine/src/engine/vulkanapi/vulkan.h | 2 + .../src/engine/vulkanapi/vulkan_context.cpp | 98 +++++++- engine/src/engine/vulkanapi/vulkan_context.h | 18 +- engine/src/engine/vulkanapi/vulkanapi.cpp | 227 +++++++++++++++++- engine/src/engine/vulkanapi/vulkanapi.h | 9 +- .../engine/vulkanapi/wrapper/commandpool.cpp | 4 +- .../src/engine/vulkanapi/wrapper/device.cpp | 22 +- engine/src/engine/vulkanapi/wrapper/device.h | 5 +- engine/src/engine/vulkanapi/wrapper/image.cpp | 8 +- .../engine/vulkanapi/wrapper/swapchain.cpp | 25 +- .../src/engine/vulkanapi/wrapper/swapchain.h | 8 +- .../vulkanapi/wrapper/swapchain_creator.cpp | 2 +- engine/xmake.lua | 3 +- 34 files changed, 582 insertions(+), 74 deletions(-) create mode 100644 engine/3rdparty/json/xmake.lua delete mode 100644 engine/assets/shader/simple.frag create mode 100644 engine/assets/shader/simple.frag.spv create mode 100644 engine/assets/shader/simple.json create mode 100644 engine/assets/shader/simple.ps.glsl delete mode 100644 engine/assets/shader/simple.vert create mode 100644 engine/assets/shader/simple.vert.spv create mode 100644 engine/assets/shader/simple.vs.glsl create mode 100644 engine/src/engine/vulkanapi/tool/spirv_compiler.cpp create mode 100644 engine/src/engine/vulkanapi/tool/spirv_compiler.h diff --git a/engine/3rdparty/json/xmake.lua b/engine/3rdparty/json/xmake.lua new file mode 100644 index 0000000..581a008 --- /dev/null +++ b/engine/3rdparty/json/xmake.lua @@ -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) diff --git a/engine/3rdparty/xmake.lua b/engine/3rdparty/xmake.lua index 2a0b652..64086c2 100644 --- a/engine/3rdparty/xmake.lua +++ b/engine/3rdparty/xmake.lua @@ -2,4 +2,6 @@ includes("**/xmake.lua") add_requires("spdlog") add_requires("tinyobjloader") -add_requires("vulkansdk") \ No newline at end of file +add_requires("vulkansdk") +add_requires("assimp") +add_requires("nlohmann_json") \ No newline at end of file diff --git a/engine/assets/shader/simple.frag b/engine/assets/shader/simple.frag deleted file mode 100644 index 650b7d5..0000000 --- a/engine/assets/shader/simple.frag +++ /dev/null @@ -1,7 +0,0 @@ -#version 450 - -layout(location = 0) out vec4 outColor; - -void main() { - outColor = vec4(1.0, 1.0, 0.0, 1.0); -} \ No newline at end of file diff --git a/engine/assets/shader/simple.frag.spv b/engine/assets/shader/simple.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..a1a14e51e7982bb704a49f55c4a7daea39b2b844 GIT binary patch literal 452 zcmYk2PfNo<5XHx)X>03W1ieYcd-0$m6upSePhjwceQDr>*ecXRaCX0p<|v?wq0)nED?+(WK0J(N1mc{#5&cxT)ey zdhP_qf2#jTnOA|I|6)AgsE?I(_5V5;PqlBr(y%7?XI3abwh|f#8FRASx1Nd{{^%;OnsNHfzIVW|`^r_T+E# zSNS4%zMkoIdnl^v)ak13)6;J4FB)^fteDH@(9~<)w1gO83&AJ-v;I-#M@LVeJ%O=m z+JOjXP5W3K+4;cb#2{B?w`9Ard$Rko1KDF)TVG55w;FWJvPt@Ba&nUN->1XLB(409 z%%+*kZ8~zL9eVfG!dsf-xqO&SNArZP81rZ7>g+3;G0xIcTYj>ox8Ictt#M*%MdiFJ za-oZX&z%D9a)0K2YBGE38fRARICGPCuJVI?XlFGPp*GF3S*@#k*6JA3)rTgNI8ZSd z8WmH2Tx3P5P)H|ersMi)X+w^Fc~PDZvbv6znm)F<4|R0?X5ILUuR@N-pNrg9@*jkt z11tK7)o;w}|L1W>c-$xQh{4b|QH2;@B7{5f#w_yq<}s&+F@rjHA&>jH3pq2Wa~JY@ zRww)~Gxc($vNS&xWgYIyzwicXtE(gkB>sR*Jgvs&9JQoqi5u8HyHg- zr55MCE@MA@>gf7bebMlyjCbU%Uh5>}@Hq$C-I1YN?7!Dwax?61gK>^Hb6+uBYCRb< O>Cc-{`zs}0$o>JX5^5m; literal 0 HcmV?d00001 diff --git a/engine/assets/shader/simple.vs.glsl b/engine/assets/shader/simple.vs.glsl new file mode 100644 index 0000000..82258bc --- /dev/null +++ b/engine/assets/shader/simple.vs.glsl @@ -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); +} \ No newline at end of file diff --git a/engine/src/engine/asset/asset.h b/engine/src/engine/asset/asset.h index 8159eb8..f7e127b 100644 --- a/engine/src/engine/asset/asset.h +++ b/engine/src/engine/asset/asset.h @@ -33,7 +33,9 @@ namespace engineapi mFlags &= ~ASSET_LOADING_FLAG; mFlags |= ASSET_LOADED_FLAG; }; - + string& GetName() { + return mName; + } public: inline bool IsShared() { return mFlags & ASSET_SHARED_FLAG; diff --git a/engine/src/engine/asset/asset_manager.cpp b/engine/src/engine/asset/asset_manager.cpp index c19ec7e..02356da 100644 --- a/engine/src/engine/asset/asset_manager.cpp +++ b/engine/src/engine/asset/asset_manager.cpp @@ -41,8 +41,10 @@ namespace engineapi { { // ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区 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); + return vector(); + } // 使用读取位置来确定文件的大小并分配缓冲区 size_t fileSize = (size_t)file.tellg(); @@ -55,4 +57,25 @@ namespace engineapi { 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; + } } diff --git a/engine/src/engine/asset/asset_manager.h b/engine/src/engine/asset/asset_manager.h index 8ff4e87..040ca5f 100644 --- a/engine/src/engine/asset/asset_manager.h +++ b/engine/src/engine/asset/asset_manager.h @@ -5,6 +5,8 @@ #include #include "asset.h" #include "singleton.h" +#include +using json = nlohmann::json; namespace engineapi { class AssetManager : public Singleton @@ -50,6 +52,7 @@ namespace engineapi public: static string LoadTextFile(const string& path); static vector LoadBinaryFile(const string& path); + static json LoadJsonFile(const string& path); }; } template<> diff --git a/engine/src/engine/render/asset/material.cpp b/engine/src/engine/render/asset/material.cpp index c1dcb6f..2c9d04c 100644 --- a/engine/src/engine/render/asset/material.cpp +++ b/engine/src/engine/render/asset/material.cpp @@ -1,11 +1,12 @@ #include "material.h" +#include "shader.h" #include "asset/asset_manager.h" #include "../renderapi.h" namespace engineapi { Material::Material(string name, uint32_t flags) :Asset(name, flags) { - auto vertShader = AssetManager::LoadBinaryFile(name); + mShader = new Shader(name, flags); } Material::~Material() { diff --git a/engine/src/engine/render/asset/material.h b/engine/src/engine/render/asset/material.h index c028a88..1d00d34 100644 --- a/engine/src/engine/render/asset/material.h +++ b/engine/src/engine/render/asset/material.h @@ -2,10 +2,11 @@ #include "asset_render.h" namespace engineapi { + class Shader; class Material : public Asset { protected: - uint32_t mId; - + uint32_t mId{0}; + Shader* mShader; public: Material(string name, uint32_t flags); ~Material(); diff --git a/engine/src/engine/render/asset/shader.cpp b/engine/src/engine/render/asset/shader.cpp index e6da9f7..bec4038 100644 --- a/engine/src/engine/render/asset/shader.cpp +++ b/engine/src/engine/render/asset/shader.cpp @@ -1,16 +1,28 @@ #include "shader.h" +#include "asset/asset_manager.h" #include "../renderapi.h" namespace engineapi { Shader::Shader(string name, uint32_t flags) :Asset(name, flags) { - + BeginLoad(); } Shader::~Shader() { } void Shader::BeginLoad() { - + json data = AssetManager::LoadJsonFile(mName + ".json"); + RenderAPI::GetSingletonPtr()->LoadShader(this); + //ShaderProperty + //mInfo.vertProperties.baseProperties.push_back + } + vector Shader::GetVertData() + { + return AssetManager::LoadBinaryFile(mName + ".vert.spv"); + } + vector Shader::GetFragData() + { + return AssetManager::LoadBinaryFile(mName + ".frag.spv"); } } diff --git a/engine/src/engine/render/asset/shader.h b/engine/src/engine/render/asset/shader.h index fa008b3..b11884f 100644 --- a/engine/src/engine/render/asset/shader.h +++ b/engine/src/engine/render/asset/shader.h @@ -5,9 +5,19 @@ namespace engineapi { class Shader : public Asset { protected: uint32_t mId; + ShaderInfo mInfo; public: Shader(string name, uint32_t flags); ~Shader(); void BeginLoad()override; + + uint32_t& GetID() { + return mId; + } + ShaderInfo& GetInfo() { + return mInfo; + } + vector GetVertData(); + vector GetFragData(); }; }; \ No newline at end of file diff --git a/engine/src/engine/render/renderapi.h b/engine/src/engine/render/renderapi.h index 1518fb3..36b50e8 100644 --- a/engine/src/engine/render/renderapi.h +++ b/engine/src/engine/render/renderapi.h @@ -4,6 +4,7 @@ namespace engineapi { class Mesh; + class Shader; class Camera; class RenderNode; class RenderAPI : public Singleton @@ -31,7 +32,10 @@ namespace engineapi virtual void SetStaticMesh(Mesh* mesh) = 0; virtual void DrawStaticMesh(Mesh* mesh) = 0; + virtual void LoadShader(Shader* shader) = 0; virtual void SwitchContext() = 0; + + public: static RenderAPI* MakeInstance(); }; diff --git a/engine/src/engine/render/window.cpp b/engine/src/engine/render/window.cpp index 66c5095..341e256 100644 --- a/engine/src/engine/render/window.cpp +++ b/engine/src/engine/render/window.cpp @@ -31,10 +31,13 @@ namespace engineapi { :mWidth(width), mHeight(height) { RECT wr{}; - wr.left = 100; + wr.left = 0; wr.right = width + wr.left; - wr.top = 100; + wr.top = 0; 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( WindowClass::GetName(), title, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, diff --git a/engine/src/engine/vulkanapi/pass/forwardpass.cpp b/engine/src/engine/vulkanapi/pass/forwardpass.cpp index be81fe6..df63d7c 100644 --- a/engine/src/engine/vulkanapi/pass/forwardpass.cpp +++ b/engine/src/engine/vulkanapi/pass/forwardpass.cpp @@ -13,7 +13,7 @@ namespace vulkanapi { mTarget = target; target->frames.reserve(target->size); 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); vector surfaces = { outputView, normalView }; target->frames.emplace_back(device, target, this, surfaces); @@ -28,13 +28,13 @@ namespace vulkanapi { { VkAttachmentDescription positionAttachment{}; 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.storeOp = VK_ATTACHMENT_STORE_OP_STORE; positionAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; positionAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 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{}; normalAttachment.samples = VK_SAMPLE_COUNT_1_BIT; diff --git a/engine/src/engine/vulkanapi/tool/spirv_compiler.cpp b/engine/src/engine/vulkanapi/tool/spirv_compiler.cpp new file mode 100644 index 0000000..44dc34d --- /dev/null +++ b/engine/src/engine/vulkanapi/tool/spirv_compiler.cpp @@ -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) + { + + } +} \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/tool/spirv_compiler.h b/engine/src/engine/vulkanapi/tool/spirv_compiler.h new file mode 100644 index 0000000..0df915b --- /dev/null +++ b/engine/src/engine/vulkanapi/tool/spirv_compiler.h @@ -0,0 +1,16 @@ +#pragma once +#include "../vulkan.h" +#include +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); + }; +} \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan.h b/engine/src/engine/vulkanapi/vulkan.h index d9c7f38..7ecc24e 100644 --- a/engine/src/engine/vulkanapi/vulkan.h +++ b/engine/src/engine/vulkanapi/vulkan.h @@ -9,10 +9,12 @@ namespace vulkanapi { #define Z_USE_GRAPHIC_DEBUG class CommandBuffer; +using std::array; using std::string; using std::to_string; using std::vector; using std::map; +using std::make_pair; using voidFn = std::function; using commandFn = std::function; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan_context.cpp b/engine/src/engine/vulkanapi/vulkan_context.cpp index c297c8c..de5c7ff 100644 --- a/engine/src/engine/vulkanapi/vulkan_context.cpp +++ b/engine/src/engine/vulkanapi/vulkan_context.cpp @@ -1,8 +1,104 @@ #include "vulkan_context.h" #include "vulkanapi.h" +#include "zlog.h" namespace vulkanapi { + RenderVulkanAPI* VulkanContext::API = nullptr; void VulkanContext::UseContext() { - Pass = API.PassList[PassId]; + Pass = API->PassList[PassId]; } + + VkDescriptorSetLayout VulkanContext::CreateDescriptorSetLayout(const ShaderInfo& info) + { + vector 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& bindings) + { + VkDescriptorSetLayout descriptorSetLayout = {}; + VkDescriptorSetLayoutCreateInfo layoutInfo = {}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.pBindings = bindings.data(); + layoutInfo.bindingCount = static_cast(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& descriptorSetLayouts, const vector& pushConstantRanges) + { + VkPipelineLayout pipelineLayout = {}; + VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); + pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); + pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data(); + pipelineLayoutInfo.pushConstantRangeCount = static_cast(pushConstantRanges.size()); + if (vkCreatePipelineLayout(API->backend.GetDevice().Ptr(), &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) + zlog::error("failed to create pipeline layout!"); + + return pipelineLayout; + } } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkan_context.h b/engine/src/engine/vulkanapi/vulkan_context.h index e8396ac..6d9d02f 100644 --- a/engine/src/engine/vulkanapi/vulkan_context.h +++ b/engine/src/engine/vulkanapi/vulkan_context.h @@ -1,15 +1,27 @@ #pragma once #include "render/render_context.h" +#include "render/asset/shader.h" #include "wrapper/renderpass.h" +using namespace engineapi; namespace vulkanapi { class RenderVulkanAPI; class VulkanContext : public engineapi::RenderContext { public: - RenderVulkanAPI& API; + static RenderVulkanAPI* API; RenderPass* Pass{ nullptr }; + uint32_t frame; + VkSemaphore surfaceSemaphore; + VkSemaphore renderSemaphore; + public: + VulkanContext(RenderVulkanAPI* _API){ + API = _API; + }; + virtual void UseContext()override; public: - VulkanContext(RenderVulkanAPI& API):API(API){}; - virtual void UseContext()override; + static VkDescriptorSetLayout CreateDescriptorSetLayout(const ShaderInfo& info); + static VkDescriptorSetLayout CreateDescriptorSetLayout(const vector& bindings); + + static VkPipelineLayout CreatePipelineLayout(const vector& descriptorSetLayouts, const vector& pushConstantRanges); }; } \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/vulkanapi.cpp b/engine/src/engine/vulkanapi/vulkanapi.cpp index bbaa3fa..f9f9251 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.cpp +++ b/engine/src/engine/vulkanapi/vulkanapi.cpp @@ -3,17 +3,17 @@ #include "wrapper/buffer.h" #include "wrapper/commandbuffer.h" #include "thread/worker.h" -#include "render/asset/mesh.h" #include "object/camera/camera.h" #include "render/node/rendernode.h" #include "pass/forwardpass.h" #include "pass/target.h" #include "wrapper/swapchain.h" +#include "render/asset/mesh.h" #include "window.h" namespace vulkanapi { RenderVulkanAPI::RenderVulkanAPI() :backend("vulkan") - ,context(*this) + ,context(this) { Buffer::MakeVmaAllocator(backend); } @@ -50,11 +50,11 @@ namespace vulkanapi { } void RenderVulkanAPI::BeginFrame() { - mFrame = swapchain->Aquire(); + swapchain->Aquire(context); } void RenderVulkanAPI::EndFrame() { - swapchain->Present(mFrame); + swapchain->Present(context); } void RenderVulkanAPI::SetStaticMesh(Mesh* mesh) { @@ -110,35 +110,244 @@ namespace vulkanapi { void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh) { 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); Backend::RenderWorker->Draw([=](CommandBuffer& cmd) { VkCommandBuffer ptr = cmd.Ptr(); - context.Pass->BeginPass(cmd, mFrame); + context.Pass->BeginPass(cmd, frame); VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer }; VkDeviceSize offsets[] = { 0 }; + VkViewport viewport = {}; + viewport.x = static_cast(mViewPortInfo.xOffset); + viewport.y = static_cast(mViewPortInfo.yOffset); + viewport.width = static_cast(mViewPortInfo.width); + viewport.height = static_cast(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); vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32); 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); context.Pass->EndPass(cmd); }); + Backend::RenderWorker->Flush(); } - VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& VAO_index) + void RenderVulkanAPI::LoadShader(Shader* shader) + { + vector shaderStages; + map 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 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(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 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(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(); for (uint32_t i = 0; i < length; i++) { if (!VAOList[i]->inUse) { - VAO_index = i; + index = i; return VAOList[i]; } } - VAO_index = length; + index = length; auto vao = new VulkanVAO(); VAOList.push_back(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; + } + } diff --git a/engine/src/engine/vulkanapi/vulkanapi.h b/engine/src/engine/vulkanapi/vulkanapi.h index 3c651ac..4558d57 100644 --- a/engine/src/engine/vulkanapi/vulkanapi.h +++ b/engine/src/engine/vulkanapi/vulkanapi.h @@ -4,7 +4,6 @@ #include "render/renderapi.h" #include "vulkan_struct.h" #include "vulkan_context.h" -using namespace engineapi; namespace vulkanapi { class RenderTarget; @@ -14,10 +13,11 @@ namespace vulkanapi public: Backend backend; VulkanContext context; - Swapchain* swapchain; + Swapchain* swapchain{nullptr}; vector TargetList; vector VAOList; vector PassList; + vector PiPelineList; public: RenderVulkanAPI(); virtual ~RenderVulkanAPI()override; @@ -36,8 +36,11 @@ namespace vulkanapi virtual void EndFrame()override; virtual void SetStaticMesh(Mesh* mesh)override; virtual void DrawStaticMesh(Mesh* mesh)override; + + virtual void LoadShader(Shader* shader)override; public: - VulkanVAO* GetNextVAO(uint32_t& VAO_index); + VulkanVAO* GetNextVAO(uint32_t& index); + VulkanPipeline* GetNextPipeline(uint32_t& index); public: static RenderVulkanAPI* GetSingletonPtr() { return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr(); diff --git a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp index a81ede3..df0cefd 100644 --- a/engine/src/engine/vulkanapi/wrapper/commandpool.cpp +++ b/engine/src/engine/vulkanapi/wrapper/commandpool.cpp @@ -48,9 +48,7 @@ namespace vulkanapi { } VkFence CommandPool::AllocateFence() { - VkFence fence; - mDevice.CreateFence(fence); - return fence; + return mDevice.CreateFence(); } } diff --git a/engine/src/engine/vulkanapi/wrapper/device.cpp b/engine/src/engine/vulkanapi/wrapper/device.cpp index a7b0379..8bd3f6f 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.cpp +++ b/engine/src/engine/vulkanapi/wrapper/device.cpp @@ -61,21 +61,35 @@ namespace vulkanapi { } return nullptr; } - bool Device::CreateFence(VkFence& fence) + VkFence Device::CreateFence() { VkFenceCreateInfo fenceInfo{}; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; // 创建时立刻设置为signaled状态(否则第一次永远等不到) fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + VkFence fence; VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence); - return result == VK_SUCCESS; + return fence; } - bool Device::CreateSemaphore(VkSemaphore& semaphore) + VkSemaphore Device::CreateSemaphore() { VkSemaphoreCreateInfo semaphoreInfo = {}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + VkSemaphore semaphore; VkResult result = vkCreateSemaphore(mPtr, &semaphoreInfo, nullptr, &semaphore); - return result == VK_SUCCESS; + return semaphore; + } + VkShaderModule Device::CreateShaderModule(vector 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(code.data()); + VkShaderModule module; + VkResult result = vkCreateShaderModule(mPtr, &createInfo, nullptr, &module); + return module; } } diff --git a/engine/src/engine/vulkanapi/wrapper/device.h b/engine/src/engine/vulkanapi/wrapper/device.h index 7f73132..5a18f1c 100644 --- a/engine/src/engine/vulkanapi/wrapper/device.h +++ b/engine/src/engine/vulkanapi/wrapper/device.h @@ -22,7 +22,8 @@ namespace vulkanapi { ~Device(); Queue* GetQueue(const string& name); - bool CreateFence(VkFence& fence); - bool CreateSemaphore(VkSemaphore& semaphore); + VkFence CreateFence(); + VkSemaphore CreateSemaphore(); + VkShaderModule CreateShaderModule(vector code); }; }; \ No newline at end of file diff --git a/engine/src/engine/vulkanapi/wrapper/image.cpp b/engine/src/engine/vulkanapi/wrapper/image.cpp index 0c70d91..749078e 100644 --- a/engine/src/engine/vulkanapi/wrapper/image.cpp +++ b/engine/src/engine/vulkanapi/wrapper/image.cpp @@ -55,10 +55,10 @@ namespace vulkanapi { // components字段允许调整颜色通道的最终的映射逻辑 // 比如,我们可以将所有颜色通道映射为红色通道,以实现单色纹理,我们也可以将通道映射具体的常量数值0和1 // 这里用默认的 - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.r = VK_COMPONENT_SWIZZLE_R; + createInfo.components.g = VK_COMPONENT_SWIZZLE_G; + createInfo.components.b = VK_COMPONENT_SWIZZLE_B; + createInfo.components.a = VK_COMPONENT_SWIZZLE_A; // subresourceRangle字段用于描述图像的使用目标是什么,以及可以被访问的有效区域 // 这个图像用作填充color还是depth stencil等 diff --git a/engine/src/engine/vulkanapi/wrapper/swapchain.cpp b/engine/src/engine/vulkanapi/wrapper/swapchain.cpp index 224e02d..ac6eede 100644 --- a/engine/src/engine/vulkanapi/wrapper/swapchain.cpp +++ b/engine/src/engine/vulkanapi/wrapper/swapchain.cpp @@ -4,6 +4,7 @@ #include "image.h" #include "../backend.h" #include "../thread/worker.h" +#include "../vulkan_context.h" #include "zlog.h" namespace vulkanapi { Swapchain::Swapchain(SwapchainCreator& Creator) @@ -18,10 +19,10 @@ namespace vulkanapi { nullptr, // const void * pNext 0, // VkSwapchainCreateFlagsKHR flags Creator.presentation_surface, // VkSurfaceKHR surface - (uint32_t)Creator.frames, // uint32_t minImageCount + (uint32_t)Creator.frames, // uint32_t minImageCount Creator.imageFormat, // VkFormat imageFormat Creator.imageColorSpace, // VkColorSpaceKHR imageColorSpace - image_extent, // VkExtent2D imageExtent + image_extent, // VkExtent2D imageExtent 1, // uint32_t imageArrayLayers Creator.imageUsage, // VkImageUsageFlags imageUsage VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode @@ -40,30 +41,30 @@ namespace vulkanapi { vector 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); - args.Sharing = VK_SHARING_MODE_CONCURRENT; + args.Sharing = VK_SHARING_MODE_EXCLUSIVE; for (int i = 0; i < Creator.frames;i++) { 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; - VkResult result = vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, mSemaphore, VK_NULL_HANDLE, &curPresentImageIdx); - return curPresentImageIdx; + ctx.surfaceSemaphore = mSurfaceSemaphore; + vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, ctx.surfaceSemaphore, VK_NULL_HANDLE, &ctx.frame); } - void Swapchain::Present(uint32_t frame) + void Swapchain::Present(VulkanContext& ctx) { VkSwapchainKHR swapChains[] = { mPtr }; - VkSemaphore waitSemaphores[] = { mSemaphore }; + VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore }; VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.pWaitSemaphores = waitSemaphores; presentInfo.waitSemaphoreCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.swapchainCount = 1; - presentInfo.pImageIndices = &frame; + presentInfo.pImageIndices = &ctx.frame; presentInfo.pResults = VK_NULL_HANDLE; - Backend::PresentWorker->Present(presentInfo); + Backend::RenderWorker->Present(presentInfo); } } diff --git a/engine/src/engine/vulkanapi/wrapper/swapchain.h b/engine/src/engine/vulkanapi/wrapper/swapchain.h index 7654879..20c4259 100644 --- a/engine/src/engine/vulkanapi/wrapper/swapchain.h +++ b/engine/src/engine/vulkanapi/wrapper/swapchain.h @@ -5,17 +5,19 @@ namespace vulkanapi { class Image; class SwapchainCreator; class Device; + class VulkanContext; class Swapchain { friend class SwapchainCreator; protected: VkSwapchainKHR mPtr; Device& mDevice; vector mSurfaces; - VkSemaphore mSemaphore; + VkSemaphore mSurfaceSemaphore; + VkSemaphore mRenderSemaphore; public: Swapchain(SwapchainCreator& Creator); - uint32_t Aquire(); - void Present(uint32_t frame); + void Aquire(VulkanContext& ctx); + void Present(VulkanContext& ctx); vector& GetSurface(){ return mSurfaces; } diff --git a/engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp b/engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp index aad55b6..ecea1a7 100644 --- a/engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp +++ b/engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp @@ -12,7 +12,7 @@ namespace vulkanapi { , imageFormat(VK_FORMAT_B8G8R8A8_SRGB) , imageColorSpace(VK_COLOR_SPACE_SRGB_NONLINEAR_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) { diff --git a/engine/xmake.lua b/engine/xmake.lua index 8e22197..dd66dd5 100644 --- a/engine/xmake.lua +++ b/engine/xmake.lua @@ -1,14 +1,13 @@ includes("3rdparty/xmake.lua") includes("xmake/**xmake.lua") --includes("test/**xmake.lua") -add_requires("assimp") target("zengine") set_kind("binary") set_rundir(".") add_rules("volk.env") add_deps("zlib","zlog") add_defines("VULKAN_API") - add_packages("vulkansdk","tinyobjloader","assimp") + add_packages("vulkansdk","tinyobjloader","assimp","nlohmann_json") add_includedirs("src/engine") add_includedirs("src/3rdparty/volk", "src/3rdparty/vulkan-memory-allocator", "src/3rdparty/template") add_syslinks("user32")