update renderpass

This commit is contained in:
ouczbs 2024-03-24 11:19:06 +08:00
parent 7423dd7656
commit 8f0b9b634b
44 changed files with 474 additions and 218 deletions

View File

@ -11,8 +11,8 @@ namespace engineapi {
const char* name = "zengine";
new AssetManager();
_RenderAPI = RenderAPI::MakeInstance();
_RenderAPI->SetUpRenderPasses();
_Window = Window::MakeInstance(3, 640, 720, name);
_RenderAPI->OnInit();
auto scene_manager = new SceneManager();
scene_manager->LoadScene(path);
}

View File

@ -9,8 +9,4 @@ namespace engineapi {
Material::~Material()
{
}
void Material::Use()
{
RenderAPI::GetSingletonPtr()->UseMaterial(mId);
}
}

View File

@ -10,8 +10,5 @@ namespace engineapi {
Material(string name, uint32_t flags);
~Material();
void Use();
};
};

View File

@ -4,7 +4,6 @@ namespace engineapi {
class Texture;
class Material;
class Mesh : public Asset {
friend class RenderVulkanAPI;
protected:
uint32_t VAO = 0;
vector<Vertex> mVertices;
@ -12,5 +11,16 @@ namespace engineapi {
public:
Mesh(string name, uint32_t flags, vector<Vertex>& vertices, vector<uint32_t>& indices);
void BeginLoad()override;
public:
uint32_t& GetVAO() {
return VAO;
}
vector<Vertex>& GetVertices() {
return mVertices;
}
vector<uint32_t>& GetIndices() {
return mIndices;
}
};
};

View File

@ -13,8 +13,4 @@ namespace engineapi {
{
}
void Shader::Use()
{
RenderAPI::GetSingletonPtr()->UseShader(mId);
}
}

View File

@ -9,6 +9,5 @@ namespace engineapi {
Shader(string name, uint32_t flags);
~Shader();
void BeginLoad()override;
void Use();
};
};

View File

@ -0,0 +1,9 @@
#include "rendernode.h"
#include "../renderapi.h"
namespace engineapi {
RenderNode::RenderNode(RenderType type)
: mType(type)
{
mContext = RenderAPI::GetSingletonPtr()->GetContext();
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "../asset/material.h"
#include "../asset/mesh.h"
#include "../asset/texture.h"
#include "../render_context.h"
namespace engineapi {
enum RenderType
{
RENDER_SHADOW_GENERATION,
RENDER_FORWARD_RENDERING,
RENDER_RAY_TRACING,
RENDER_AFTER_EFFECT_RENDERING,
RENDER_UI_RENDERING,
RENDER_COUNT
};
class Camera;
class RenderNode
{
protected:
RenderType mType;
RenderContext* mContext;
public:
RenderNode(RenderType type);
~RenderNode() {};
virtual void Render(Camera& camera) = 0;
public:
RenderType GetType() {
return mType;
}
};
};

View File

@ -1,32 +1,23 @@
#include "renderpass_forward.h"
#include "rendernode_forward.h"
#include "../renderapi.h"
#include "../window.h"
#include "object/camera/camera.h"
#include "../asset/model.h"
#include "asset/asset_manager.h"
namespace engineapi {
RenderPassForwardRendering::RenderPassForwardRendering()
RenderNodeForwardRendering::RenderNodeForwardRendering()
:RenderNode(RENDER_FORWARD_RENDERING)
{
mID = 0;
mSky = AssetManager::GetSingletonPtr()->LoadAsset<Model>("assets/models/SkyBoxMesh.ply", Asset::ASSET_SHARED_FLAG | Asset::ASSET_ASYNC_FLAG);
//skyBoxMaterial = new Material(new Shader(Resources::GetAssetFullPath("Shaders/SkyBox.zxshader", true), FrameBufferType::Normal));
skyBoxRenderState = new RenderStateSetting();
skyBoxRenderState->depthTest = false;
skyBoxRenderState->depthWrite = false;
opaqueRenderState = new RenderStateSetting();
transparentRenderState = new RenderStateSetting();
transparentRenderState->depthWrite = false;
//drawCommandID = RenderAPI::GetSingletonPtr()->AllocateDrawCommand(CommandType::ForwardRendering);
}
RenderPassForwardRendering::~RenderPassForwardRendering()
RenderNodeForwardRendering::~RenderNodeForwardRendering()
{
}
void RenderPassForwardRendering::Render(Camera& camera)
void RenderNodeForwardRendering::Render(Camera& camera)
{
auto renderAPI = RenderAPI::GetSingletonPtr();
auto window = Window::GetSingletonPtr();
@ -36,9 +27,10 @@ namespace engineapi {
//FBOManager::GetInstance()->SwitchFBO("Forward");
// ViewPort设置为窗口大小
renderAPI->SetViewPort(width, height);
mContext->UsePass(mType);
mContext->UseContext();
}
void RenderPassForwardRendering::RenderSkyBox(Camera& camera)
void RenderNodeForwardRendering::RenderSkyBox(Camera& camera)
{
// 先转3x3再回4x4把相机位移信息去除
Matrix4 mat_V = Matrix4(Matrix3(camera.GetViewMatrix()));
@ -52,7 +44,7 @@ namespace engineapi {
//RenderAPI::GetInstance()->Draw(skyBox->VAO);
}
void RenderPassForwardRendering::RenderBatches(const map<uint32_t, vector<MeshRenderer*>>& batchs)
void RenderNodeForwardRendering::RenderBatches(const map<uint32_t, vector<MeshRenderer*>>& batchs)
{
}

View File

@ -1,23 +1,19 @@
#pragma once
#include "renderpass.h"
#include "rendernode.h"
#include "object/render/mesh_render.h"
namespace engineapi {
class Camera;
class Model;
class RenderPassForwardRendering : public RenderPass
class RenderNodeForwardRendering : public RenderNode
{
public:
RenderPassForwardRendering();
~RenderPassForwardRendering();
RenderNodeForwardRendering();
~RenderNodeForwardRendering();
virtual void Render(Camera& camera);
private:
uint32_t mID;
Model* mSky;
RenderStateSetting* skyBoxRenderState;
RenderStateSetting* opaqueRenderState;
RenderStateSetting* transparentRenderState;
void RenderSkyBox(Camera& camera);
void RenderBatches(const map<uint32_t, vector<MeshRenderer*>>& batchs);

View File

@ -1,43 +0,0 @@
#pragma once
#include "../asset/material.h"
#include "../asset/mesh.h"
#include "../asset/texture.h"
namespace engineapi {
enum RenderPassType
{
ZX_RENDER_PASS_SHADOW_GENERATION,
ZX_RENDER_PASS_FORWARD_RENDERING,
ZX_RENDER_PASS_RAY_TRACING,
ZX_RENDER_PASS_AFTER_EFFECT_RENDERING,
ZX_RENDER_PASS_UI_RENDERING,
ZX_RENDER_PASS_COUNT
};
class Camera;
class RenderPass
{
protected:
RenderPassType mType;
public:
RenderPass(RenderPassType type) : mType(type){};
~RenderPass() {};
virtual void Render(Camera& camera) = 0;
public:
RenderPassType GetType() {
return mType;
}
};
class RenderStateSetting
{
public:
bool depthTest = true;
bool depthWrite = true;
BlendFactor srcFactor = BlendFactor::SRC_ALPHA;
BlendFactor dstFactor = BlendFactor::ONE_MINUS_SRC_ALPHA;
Vector4 clearColor = Vector4();
float clearDepth = 1.0f;
uint32_t clearStencil = 0;
bool faceCull = true;
FaceCullOption faceCullOption = FaceCullOption::Back;
};
};

View File

@ -3,10 +3,21 @@
#include "asset/asset_render.h"
namespace engineapi
{
struct RenderContext {
uint32_t MaterialId;
uint32_t PassId;
uint32_t ShaderId;
class RenderContext {
public:
uint32_t MaterialId{ 0 };
uint32_t PassId{ 0 };
uint32_t ShaderId{ 0 };
public:
virtual void UseContext(){};
virtual void UseMaterial(uint32_t ID) {
MaterialId = ID;
};
virtual void UseShader(uint32_t ID) {
ShaderId = ID;
};
virtual void UsePass(uint32_t ID) {
PassId = ID;
};
};
}

View File

@ -1,6 +1,6 @@
#include "renderapi.h"
#include "pass/renderpass.h"
#include "pass/renderpass_forward.h"
#include "node/rendernode.h"
#include "node/rendernode_forward.h"
#ifdef VULKAN_API
#include "vulkanapi/vulkanapi.h"
#endif // VULKAN_API
@ -9,32 +9,32 @@ namespace engineapi {
{
}
void RenderAPI::SetUpRenderPasses()
void RenderAPI::OnInit()
{
mAllPasses.resize(ZX_RENDER_PASS_COUNT);
//mAllPasses[ZX_RENDER_PASS_SHADOW_GENERATION] = new RenderPassShadowGeneration();
mAllPasses[ZX_RENDER_PASS_FORWARD_RENDERING] = new RenderPassForwardRendering();
//mAllPasses[ZX_RENDER_PASS_RAY_TRACING] = new RenderPassRayTracing();
//mAllPasses[ZX_RENDER_PASS_AFTER_EFFECT_RENDERING] = new RenderPassAfterEffectRendering();
//mAllPasses[ZX_RENDER_PASS_UI_RENDERING] = new RenderPassUIRendering();
mCurPasses.clear();
InitRenderNode();
InitRenderPass();
}
void RenderAPI::InitRenderNode()
{
mAllNodes.clear();
mAllNodes.resize(RENDER_COUNT);
mAllNodes[RENDER_FORWARD_RENDERING] = new RenderNodeForwardRendering();
//mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_SHADOW_GENERATION]);
mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_FORWARD_RENDERING]);
mCurNodes.push_back(mAllNodes[RENDER_FORWARD_RENDERING]);
//mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_AFTER_EFFECT_RENDERING]);
//mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_UI_RENDERING]);
}
void RenderAPI::Render(Camera& camera)
{
for (auto pass : mCurPasses) {
pass->Render(camera);
for (auto node : mCurNodes) {
node->Render(camera);
}
}
RenderAPI* RenderAPI::MakeInstance()
{
#ifdef VULKAN_API
return new RenderVulkanAPI();
return new vulkanapi::RenderVulkanAPI();
#endif
}
}

View File

@ -5,20 +5,23 @@ namespace engineapi
{
class Mesh;
class Camera;
class RenderPass;
class RenderNode;
class RenderAPI : public Singleton<RenderAPI>
{
protected:
uint32_t mFrame;
ViewPortInfo mViewPortInfo;
RenderContext* mContext;
vector<RenderPass*> mCurPasses;
vector<RenderPass*> mAllPasses;
vector<RenderNode*> mCurNodes;
vector<RenderNode*> mAllNodes;
public:
RenderAPI();
virtual ~RenderAPI() {};
public:
virtual void SetUpRenderPasses();
virtual RenderContext* GetContext() = 0;
public:
virtual void OnInit();
virtual void InitRenderNode();
virtual void InitRenderPass() = 0;
public:
virtual void SetViewPort(uint32_t width, uint32_t height, uint32_t xOffset = 0, uint32_t yOffset = 0) = 0;
@ -29,16 +32,6 @@ namespace engineapi
virtual void DrawStaticMesh(Mesh* mesh) = 0;
virtual void SwitchContext() = 0;
virtual void UseMaterial(uint32_t ID) {
mContext->MaterialId = ID;
};
virtual void UseShader(uint32_t ID) {
mContext->PassId = ID;
};
virtual void UsePass(uint32_t ID) {
mContext->ShaderId = ID;
};
public:
static RenderAPI* MakeInstance();
};

View File

@ -7,7 +7,7 @@ namespace engineapi {
Window* Window::MakeInstance(int frames, uint32_t width, uint32_t height, const char* title)
{
#ifdef VULKAN_API
return new vulkanapi::Window(frames, width, height, title);
return new vulkanapi::VulkanWindow(frames, width, height, title);
#endif
}
Window::WindowClass::WindowClass() noexcept

View File

@ -6,6 +6,7 @@
namespace vulkanapi {
CommandWorker* Backend::TransferWorker = nullptr;
CommandWorker* Backend::RenderWorker = nullptr;
CommandWorker* Backend::PresentWorker = nullptr;
Backend::Backend(const string appName)
{
auto instanceCreator = InstanceCreator();
@ -26,6 +27,7 @@ namespace vulkanapi {
Backend::TransferWorker = GetWorker(Queue::TransferQueue);
Backend::RenderWorker = GetWorker(Queue::RenderQueue);
Backend::PresentWorker = GetWorker(Queue::PresentQueue);
}
Backend::~Backend()
{

View File

@ -27,5 +27,6 @@ namespace vulkanapi {
public:
static CommandWorker* TransferWorker;
static CommandWorker* RenderWorker;
static CommandWorker* PresentWorker;
};
};

View File

@ -1,12 +1,30 @@
#include "forwardpass.h"
#include "../wrapper/renderpass.h"
#include "../wrapper/image.h"
#include "../wrapper/framebuffer.h"
#include "target.h"
namespace vulkanapi {
void ForwardPass::Record()
{
}
ForwardPass* ForwardPass::MakePass(Device& device, GeometryBuffer& gBuffer)
void ForwardPass::InitTarget(Device& device, GeometryBuffer& gBuffer, RenderTarget* target)
{
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 normalView = gBuffer.normals[i]->View(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_VIEW_TYPE_2D);
vector<VkImageView> surfaces = { outputView, normalView };
target->frames.emplace_back(device, target, this, surfaces);
}
mClearValues.resize(2);
mClearValues[0].color = { { 0, 0, 0, 0 } };
mClearValues[1].depthStencil = { 1, 0 };
mPassBeginInfo.pClearValues = mClearValues.data();
mPassBeginInfo.clearValueCount = 2;
}
ForwardPass* ForwardPass::MakePass(Device& device, GeometryBuffer& gBuffer, RenderTarget* target)
{
VkAttachmentDescription positionAttachment{};
positionAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
@ -40,6 +58,9 @@ namespace vulkanapi {
vector<VkAttachmentDescription> attachments = { positionAttachment , normalAttachment };
vector<VkSubpassDescription> subpasses = { subpass };
vector<VkSubpassDependency> dependencies;
return new ForwardPass(device, "forward", attachments, subpasses, dependencies);
auto forwad = new ForwardPass(device, "forward", attachments, subpasses, dependencies);
forwad->InitTarget(device, gBuffer, target);
return forwad;
}
}

View File

@ -2,13 +2,15 @@
#include "../wrapper/renderpass.h"
#include "gbuffer.h"
namespace vulkanapi {
//class MaterialCache;
class RenderTarget;
class ForwardPass : public RenderPass {
//MaterialCache mMaterials;
protected:
vector<VkClearValue> mClearValues;
public:
using RenderPass::RenderPass;
void Record();
void InitTarget(Device& device, GeometryBuffer& gBuffer, RenderTarget* target);
public:
static ForwardPass* MakePass(Device& device, GeometryBuffer& gBuffer);
static ForwardPass* MakePass(Device& device, GeometryBuffer& gBuffer, RenderTarget* target);
};
}

View File

@ -9,11 +9,15 @@ namespace vulkanapi {
VkFormat normalFmt = VK_FORMAT_R8G8B8A8_UNORM;
VkFormat diffuseFmt = VK_FORMAT_R8G8B8A8_UNORM;
int usage = 1;
int usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
auto positionArgs = Image::Make2DArgs(width, height, positionFmt, VK_SAMPLE_COUNT_1_BIT, usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
auto normalArgs = Image::Make2DArgs(width, height, positionFmt, VK_SAMPLE_COUNT_1_BIT, usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
auto diffuseArgs = Image::Make2DArgs(width, height, positionFmt, VK_SAMPLE_COUNT_1_BIT, usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
for (int i = 0; i < frames; i++) {
positions.push_back(new Image(device, "position", width , height, diffuseFmt, usage));
normals.push_back(new Image(device, "normal", width, height, diffuseFmt, usage));
diffuses.push_back(new Image(device, "diffuse", width, height, diffuseFmt, usage));
string si = to_string(i);
positions.push_back(new Image(device, "position" + si, positionArgs));
normals.push_back(new Image(device, "normal" + si, normalArgs));
diffuses.push_back(new Image(device, "diffuse" + si, diffuseArgs));
}
}
GeometryBuffer::~GeometryBuffer()

View File

@ -0,0 +1,25 @@
#include "target.h"
#include "../window.h"
namespace vulkanapi {
void RenderTarget::InitSurface(Device& device, string name)
{
}
RenderTarget* RenderTarget::MakeOutputTarget()
{
auto window = VulkanWindow::GetSingletonPtr();
vector<Image*>& surfaces = window->GetSurface();
uint32_t width, height;
window->GetSize(width, height);
return new RenderTarget(width, height, surfaces);
}
RenderTarget* RenderTarget::MakeDepthTarget()
{
return nullptr;
}
RenderTarget* RenderTarget::MakeColorTarget()
{
return nullptr;
}
}

View File

@ -1,10 +1,25 @@
#pragma once
#include "../vulkan.h"
#include "../wrapper/framebuffer.h"
namespace vulkanapi {
class Image;
class Device;
class RenderTarget {
public:
uint32_t width;
uint32_t height;
uint32_t size;
vector<FrameBuffer> frames;
vector<Image*> surfaces;
public:
RenderTarget(uint32_t width, uint32_t height, uint32_t size)
:width(width), height(height), size(size) {};
RenderTarget(uint32_t width, uint32_t height, vector<Image*>& surfaces)
:width(width), height(height), size(surfaces.size()), surfaces(surfaces){};
void InitSurface(Device& device, string name);
public:
static RenderTarget* MakeOutputTarget();
static RenderTarget* MakeDepthTarget();
static RenderTarget* MakeColorTarget();
};
}

View File

@ -52,4 +52,9 @@ namespace vulkanapi {
cmd.WaitFofFence(mDevice.Ptr());
mCommandPool.Push(cmd);
}
bool CommandWorker::Present(VkPresentInfoKHR& presentInfo)
{
VkResult result = vkQueuePresentKHR(mQueue.Ptr(), &presentInfo);
return result == VK_SUCCESS;
}
}

View File

@ -25,5 +25,6 @@ namespace vulkanapi {
Buffer(mImmediateExeCmd, fn , callback);
}
void Draw(commandFn fn);
bool Present(VkPresentInfoKHR& presentInfo);
};
};

View File

@ -10,6 +10,7 @@ namespace vulkanapi {
#define Z_USE_GRAPHIC_DEBUG
class CommandBuffer;
using std::string;
using std::to_string;
using std::vector;
using std::map;
using voidFn = std::function<void()>;

View File

@ -1,9 +1,8 @@
#include "vulkan_context.h"
#include "vulkanapi.h"
namespace engineapi {
namespace vulkanapi {
void VulkanContext::UseContext()
{
Pass = API->VkPasses[PassId];
Pass = API.PassList[PassId];
}
}

View File

@ -1,11 +1,15 @@
#pragma once
#include "render/render_context.h"
#include "vulkanapi.h"
namespace engineapi {
struct VulkanContext : public RenderContext {
RenderVulkanAPI* API;
vulkanapi::RenderPass* Pass;
#include "wrapper/renderpass.h"
namespace vulkanapi {
class RenderVulkanAPI;
class VulkanContext : public engineapi::RenderContext {
public:
RenderVulkanAPI& API;
RenderPass* Pass{ nullptr };
public:
VulkanContext(RenderVulkanAPI& API):API(API){};
virtual void UseContext()override;
};
}

View File

@ -1,17 +1,20 @@
#include "vulkanapi.h"
#include "vulkanapi.h"
#include "wrapper/queue.h"
#include "wrapper/buffer.h"
#include "wrapper/commandbuffer.h"
#include "thread/worker.h"
#include "render/asset/mesh.h"
#include "object/camera/camera.h"
#include "render/pass/renderpass.h"
#include "render/node/rendernode.h"
#include "pass/forwardpass.h"
namespace engineapi {
#include "pass/target.h"
#include "wrapper/swapchain.h"
#include "window.h"
namespace vulkanapi {
RenderVulkanAPI::RenderVulkanAPI()
:backend("vulkan")
,context(*this)
{
mContext = &context;
Buffer::MakeVmaAllocator(backend);
}
RenderVulkanAPI::~RenderVulkanAPI()
@ -24,12 +27,17 @@ namespace engineapi {
}
void RenderVulkanAPI::InitRenderPass()
{
VkPasses.resize(RenderPassType::ZX_RENDER_PASS_COUNT);
swapchain = VulkanWindow::GetSingletonPtr()->GetSwapchain();
RenderTarget* output = RenderTarget::MakeOutputTarget();
TargetList.reserve(RENDER_COUNT);
TargetList.push_back(output);
PassList.resize(RENDER_COUNT);
auto gbuffer = GeometryBuffer(backend.GetDevice(), 3, 640, 720);
for (auto pass : mAllPasses) {
auto type = pass->GetType();
if (type == RenderPassType::ZX_RENDER_PASS_FORWARD_RENDERING) {
VkPasses[type] = ForwardPass::MakePass(backend.GetDevice(), gbuffer);
for (auto node : mAllNodes) {
if (!node)continue;
auto type = node->GetType();
if (type == RENDER_FORWARD_RENDERING) {
PassList[type] = ForwardPass::MakePass(backend.GetDevice(), gbuffer, output);
}
}
}
@ -42,26 +50,28 @@ namespace engineapi {
}
void RenderVulkanAPI::BeginFrame()
{
mFrame = swapchain->Aquire();
}
void RenderVulkanAPI::EndFrame()
{
swapchain->Present(mFrame);
}
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
{
auto meshBuffer = GetNextVAO(mesh->VAO);
meshBuffer->indexCount = mesh->mIndices.size();
meshBuffer->vertexCount = mesh->mVertices.size();
auto Indices = mesh->GetIndices();
auto Vertices = mesh->GetVertices();
auto meshBuffer = GetNextVAO(mesh->GetVAO());
meshBuffer->indexCount = Indices.size();
meshBuffer->vertexCount = Vertices.size();
// ----------------------------------------------- Vertex Buffer -----------------------------------------------
VkDeviceSize vertexBufferSize = sizeof(Vertex) * mesh->mVertices.size();
VkDeviceSize vertexBufferSize = sizeof(Vertex) * Vertices.size();
VmaAllocationCreateInfo vertexVmaStagingInfo = {};
VmaAllocation vertexVmaStagingAlloc;
VkBuffer vertexStagingBuffer = Buffer::CreateStageBuffer(vertexVmaStagingInfo, vertexVmaStagingAlloc, vertexBufferSize);
// 拷贝数据到StagingBuffer
Buffer::CopyData(vertexVmaStagingAlloc, mesh->mVertices.data(), vertexBufferSize);
Buffer::CopyData(vertexVmaStagingAlloc, Vertices.data(), vertexBufferSize);
VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪
VmaAllocationCreateInfo vertexVmaCreateInfo = {};
@ -69,12 +79,12 @@ namespace engineapi {
meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexCreateInfo, vertexVmaCreateInfo, meshBuffer->vertexBufferAlloc);
// ----------------------------------------------- Index Buffer -----------------------------------------------
VkDeviceSize indexBufferSize = sizeof(uint32_t) * mesh->mIndices.size();
VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size();
VmaAllocationCreateInfo indexVmaStagingInfo = {};
VmaAllocation indexVmaStagingAlloc;
VkBuffer indexStagingBuffer = Buffer::CreateStageBuffer(indexVmaStagingInfo, indexVmaStagingAlloc, vertexBufferSize);
// 拷贝数据到StagingBuffer
Buffer::CopyData(indexVmaStagingAlloc, mesh->mIndices.data(), indexBufferSize);
Buffer::CopyData(indexVmaStagingAlloc, Indices.data(), indexBufferSize);
VmaAllocationCreateInfo indexVmaCreateInfo = {};
VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
@ -99,19 +109,18 @@ namespace engineapi {
}
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
{
}
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
{
auto vulkanVAO = VAOList[mesh->VAO];
auto vulkanVAO = VAOList[mesh->GetVAO()];
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
VkCommandBuffer ptr = cmd.Ptr();
context.Pass->BeginPass(cmd);
context.Pass->BeginPass(cmd, mFrame);
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(ptr, vulkanVAO->indexCount, 1, 0, 0, 0);
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);
vkCmdDrawIndexed(ptr, vulkanVAO->indexCount, 1, 0, 0, 0);
context.Pass->EndPass(cmd);
});
}

View File

@ -2,21 +2,29 @@
#include "backend.h"
#include "wrapper/renderpass.h"
#include "render/renderapi.h"
#include "vulkan_context.h"
#include "vulkan_struct.h"
using namespace vulkanapi;
namespace engineapi
#include "vulkan_context.h"
using namespace engineapi;
namespace vulkanapi
{
class RenderTarget;
class Swapchain;
class RenderVulkanAPI : public RenderAPI
{
public:
Backend backend;
VulkanContext context;
Swapchain* swapchain;
vector<RenderTarget*> TargetList;
vector<VulkanVAO*> VAOList;
vector<vulkanapi::RenderPass*> VkPasses;
vector<RenderPass*> PassList;
public:
RenderVulkanAPI();
virtual ~RenderVulkanAPI()override;
public:
virtual RenderContext* GetContext() override {
return &context;
};
public:
virtual void SwitchContext()override;
public:

View File

@ -2,13 +2,11 @@
#include "backend.h"
#include "wrapper/instance.h"
#include "wrapper/device.h"
#include "wrapper/swapchain.h"
#include "wrapper/swapchain_creator.h"
#include "vulkanapi.h"
#include "zlog.h"
using engineapi::RenderVulkanAPI;
namespace vulkanapi {
Window::Window(int frames, uint32_t width, uint32_t height, const char* title)
VulkanWindow::VulkanWindow(int frames, uint32_t width, uint32_t height, const char* title)
:engineapi::Window(width, height , title)
, mSurfaceKHR(nullptr)
, mSwapchain(nullptr)

View File

@ -1,13 +1,25 @@
#pragma once
#include "render/window.h"
#include "wrapper/swapchain.h"
#include "vulkan.h"
namespace vulkanapi {
class Swapchain;
class Window : public engineapi::Window {
class Image;
class VulkanWindow : public engineapi::Window {
protected:
VkSurfaceKHR mSurfaceKHR;
Swapchain* mSwapchain;
public:
Window(int frames, uint32_t width, uint32_t height, const char* title);
VulkanWindow(int frames, uint32_t width, uint32_t height, const char* title);
vector<Image*>& GetSurface() {
return mSwapchain->GetSurface();
}
Swapchain* GetSwapchain() {
return mSwapchain;
}
public:
static VulkanWindow* GetSingletonPtr() {
return (VulkanWindow*)engineapi::Window::GetSingletonPtr();
}
};
};

View File

@ -69,4 +69,10 @@ namespace vulkanapi {
// 销毁StagingBuffer
vmaDestroyBuffer(vmaAllocator, buffer, bufferAlloc);
}
void Buffer::CreateImage(VkImageCreateInfo& imageInfo, VkImage& ptr, VmaAllocation& allocation, VmaMemoryUsage usage)
{
VmaAllocationCreateInfo allocationInfo = {};
allocationInfo.usage = usage;
vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &ptr, &allocation, nullptr);
}
}

View File

@ -16,5 +16,6 @@ namespace vulkanapi {
static VkBuffer CreateStageBuffer(VmaAllocationCreateInfo& allocationCreateInfo, VmaAllocation& allocation, VkDeviceSize vertexBufferSize);
static void CopyData(VmaAllocation& allocation,void* data, VkDeviceSize size);
static void DestroyBuffer(VkBuffer buffer, VmaAllocation bufferAlloc);
static void CreateImage(VkImageCreateInfo& imageInfo, VkImage& ptr, VmaAllocation& allocation, VmaMemoryUsage usage);
};
}

View File

@ -70,5 +70,12 @@ namespace vulkanapi {
VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence);
return result == VK_SUCCESS;
}
bool Device::CreateSemaphore(VkSemaphore& semaphore)
{
VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkResult result = vkCreateSemaphore(mPtr, &semaphoreInfo, nullptr, &semaphore);
return result == VK_SUCCESS;
}
}

View File

@ -23,5 +23,6 @@ namespace vulkanapi {
Queue* GetQueue(const string& name);
bool CreateFence(VkFence& fence);
bool CreateSemaphore(VkSemaphore& semaphore);
};
};

View File

@ -0,0 +1,22 @@
#include "framebuffer.h"
#include "device.h"
#include "renderpass.h"
#include "image.h"
#include "../pass/target.h"
namespace vulkanapi {
FrameBuffer::FrameBuffer(Device& device, RenderTarget* target, RenderPass* pass, vector<VkImageView>& surfaces)
: mSurfaces(surfaces)
{
uint32_t size = mSurfaces.size();
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
// 指定可以兼容的render pass(这个frame buffer和指定的render pass的attachment的数量和类型需要一致)
framebufferInfo.renderPass = pass->Ptr();
framebufferInfo.attachmentCount = size;
framebufferInfo.pAttachments = mSurfaces.data();
framebufferInfo.width = target->width;
framebufferInfo.height = target->height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device.Ptr(), &framebufferInfo, nullptr, &mPtr);
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "../vulkan.h"
namespace vulkanapi {
class Device;
class RenderPass;
class RenderTarget;
class Image;
class FrameBuffer {
protected:
VkFramebuffer mPtr;
vector<VkImageView> mSurfaces;
public:
FrameBuffer(Device& device, RenderTarget* target,RenderPass* pass, vector<VkImageView>& surfaces);
VkFramebuffer& Ptr() {
return mPtr;
}
};
}

View File

@ -1,28 +1,87 @@
#include "image.h"
#include "device.h"
#include "buffer.h"
namespace vulkanapi {
Image::Image(const Device& device, const char* name, int width, int height, VkFormat format, VkImageUsageFlags usage)
:Image(device, Args{
1,
"",
width,height,
1,1,1,
format,usage,
1,1,1,1 })
{
}
Image::Image(const Device& device, const Args& args)
Image::Image(Device& device, string name, const Args& args)
: mArgs(args)
, mName(name)
, mDevice(device)
, mPtr(nullptr)
{
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = mArgs.Type;
imageInfo.extent.width = mArgs.Width;
imageInfo.extent.height = mArgs.Height;
// 纹理第三个维度的像素数量如果不是3D纹理应该都是1
imageInfo.extent.depth = 1;
imageInfo.mipLevels = mArgs.Levels;
imageInfo.arrayLayers = mArgs.Layers;
imageInfo.format = mArgs.Format;
// VK_IMAGE_TILING_LINEAR: texel以行为主序排列为数组
// VK_IMAGE_TILING_OPTIMAL: texel按照Vulkan的具体实现来定义的一种顺序排列以实现最佳访问
// 这个和layout不一样一旦设置之后是固定的不能改如果CPU需要读取这个数据就设置为VK_IMAGE_TILING_LINEAR
// 如果只是GPU使用就设置为VK_IMAGE_TILING_OPTIMAL性能更好
imageInfo.tiling = mArgs.Tiling;
// 这里只能填VK_IMAGE_LAYOUT_UNDEFINED或者VK_IMAGE_LAYOUT_PREINITIALIZED
// VK_IMAGE_LAYOUT_UNDEFINED意味着第一次transition数据的时候数据会被丢弃
// VK_IMAGE_LAYOUT_PREINITIALIZED是第一次transition数据的时候数据会被保留
// 不是很懂这个什么意思如果是一个用来从CPU写入数据然后transfer到其它VkImage的stagingImage就要用VK_IMAGE_LAYOUT_PREINITIALIZED
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = mArgs.Usage;
imageInfo.sharingMode = mArgs.Sharing;
imageInfo.samples = mArgs.Samples;
// 这个只影响当作attachments使用的VkImage(自己创建的frame buffer才支持这个交换链用的那个默认buffer不支持)
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
Buffer::CreateImage(imageInfo, mPtr, mAllocation, mArgs.Memory);
}
Image::Image(const Device& device, VkImage ptr, const Args& args)
Image::Image(Device& device, string name, VkImage ptr, const Args& args)
: mArgs(args)
, mName(name)
, mDevice(device)
, mPtr(ptr)
{
}
VkImageView Image::View(VkFormat format, VkImageAspectFlags aspectFlags, VkImageViewType viewType)
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = mPtr;
createInfo.viewType = viewType;
createInfo.format = format;
// 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;
// subresourceRangle字段用于描述图像的使用目标是什么以及可以被访问的有效区域
// 这个图像用作填充color还是depth stencil等
createInfo.subresourceRange.aspectMask = aspectFlags;
// 默认处理所有Mipmap
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
// 默认处理所有Layers
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
VkImageView imageView;
vkCreateImageView(mDevice.Ptr(), &createInfo, nullptr, &imageView);
return imageView;
}
Image::Args Image::Make2DArgs(uint32_t width, uint32_t height, VkFormat format, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VmaMemoryUsage memory)
{
return Args{
VK_IMAGE_TYPE_2D,
width,height,
1,1,1,
format,usage,
VK_IMAGE_TILING_LINEAR,VK_SHARING_MODE_EXCLUSIVE,
samples,1,memory };
}
}

View File

@ -1,35 +1,47 @@
#pragma once
#include "../vulkan.h"
#include "vk_mem_alloc.h"
namespace vulkanapi {
class Device;
class Image {
public:
struct Args {
int Type;
const char* Key;
int Width;
int Height;
int Depth;
int Layers;
int Levels;
VkImageType Type;
uint32_t Width;
uint32_t Height;
uint32_t Depth;
uint32_t Layers;
uint32_t Levels;
VkFormat Format;
VkImageUsageFlags Usage;
int Tiling;
int Sharing;
VkImageTiling Tiling;
VkSharingMode Sharing;
VkSampleCountFlagBits Samples;
int Layout;
int Memory;
VmaMemoryUsage Memory;
};
protected:
string mName;
VkImage mPtr;
Args mArgs;
const Device& mDevice;
VmaAllocation mAllocation{nullptr};
Device& mDevice;
public:
Image(const Device& device, const char* name, int width, int height, VkFormat format, VkImageUsageFlags usage);
Image(const Device& device, const Args& args);
Image(const Device& device, VkImage ptr, const Args& args);
Image(Device& device, string name, const Args& args);
Image(Device& device, string name, VkImage ptr, const Args& args);
VkFormat Format() {
return mArgs.Format;
};
};
VkImage& Ptr() {
return mPtr;
}
VkImageView View(VkImageAspectFlags aspectFlags, VkImageViewType viewType) {
return View(mArgs.Format, aspectFlags, viewType);
};
VkImageView View(VkFormat format, VkImageAspectFlags aspectFlags, VkImageViewType viewType);
public:
static Args Make2DArgs(uint32_t width, uint32_t height, VkFormat format, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VmaMemoryUsage memory);
};
}

View File

@ -1,11 +1,14 @@
#include "renderpass.h"
#include "device.h"
#include "commandbuffer.h"
#include "../pass/target.h"
#include "framebuffer.h"
namespace vulkanapi {
RenderPass::RenderPass(Device& device, const char* name,
vector<VkAttachmentDescription>& attachments,
vector<VkSubpassDescription>& subpasses,
vector<VkSubpassDependency>& dependencies)
:mAttachments(attachments)
{
//pAttachments
VkRenderPassCreateInfo create_info{
@ -24,8 +27,9 @@ namespace vulkanapi {
mPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
mPassBeginInfo.renderPass = mPtr;
}
void RenderPass::BeginPass(CommandBuffer& cmd)
void RenderPass::BeginPass(CommandBuffer& cmd,int frame)
{
mPassBeginInfo.framebuffer = mTarget->frames.at(frame).Ptr();
vkCmdBeginRenderPass(cmd.Ptr(), &mPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
}
void RenderPass::EndPass(CommandBuffer& cmd)

View File

@ -5,21 +5,24 @@
namespace vulkanapi {
class Device;
class CommandBuffer;
class RenderTarget;
class RenderPass {
protected:
VkRenderPass mPtr;
RenderTarget* mTarget;
VkRenderPassBeginInfo mPassBeginInfo{};
vector<VkAttachmentDescription> mAttachments;
public:
RenderPass(Device& device, const char* name,
vector<VkAttachmentDescription>& attachments,
vector<VkSubpassDescription>& subpasses,
vector<VkSubpassDependency>& dependencies);
VkRenderPass& Ptr() {
return mPtr;
}
public:
void BeginPass(CommandBuffer& cmd);
void BeginPass(CommandBuffer& cmd, int frame);
void EndPass(CommandBuffer& cmd);
public:
void SetViewPort(uint32_t width, uint32_t height, int32_t xoffset, int32_t yoffset);
};

View File

@ -2,10 +2,13 @@
#include "swapchain_creator.h"
#include "device.h"
#include "image.h"
#include "../backend.h"
#include "../thread/worker.h"
#include "zlog.h"
namespace vulkanapi {
Swapchain::Swapchain(SwapchainCreator& Creator)
: mPtr(nullptr)
, mDevice(Creator.device)
{
VkSurfaceCapabilitiesKHR capabilities{};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Creator.device.GetPhysical(), Creator.presentation_surface, &capabilities);
@ -36,15 +39,31 @@ namespace vulkanapi {
}
vector<VkImage> swapchain_images;
Creator.CreateSwapchainImages(mPtr, swapchain_images);
uint32_t image_count = swapchain_images.size();
for (auto img : swapchain_images) {
mImages.push_back(new Image(Creator.device, img, Image::Args{
1,
"",
(int)Creator.width, (int)Creator.height,
1, 1, 1,
Creator.imageFormat, Creator.imageUsage,
1, 1, 1, 1}));
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;
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);
}
uint32_t Swapchain::Aquire()
{
uint32_t curPresentImageIdx;
VkResult result = vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, mSemaphore, VK_NULL_HANDLE, &curPresentImageIdx);
return curPresentImageIdx;
}
void Swapchain::Present(uint32_t frame)
{
VkSwapchainKHR swapChains[] = { mPtr };
VkSemaphore waitSemaphores[] = { mSemaphore };
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.pResults = VK_NULL_HANDLE;
Backend::PresentWorker->Present(presentInfo);
}
}

View File

@ -4,12 +4,20 @@
namespace vulkanapi {
class Image;
class SwapchainCreator;
class Device;
class Swapchain {
friend class SwapchainCreator;
protected:
VkSwapchainKHR mPtr;
vector<Image*> mImages;
Device& mDevice;
vector<Image*> mSurfaces;
VkSemaphore mSemaphore;
public:
Swapchain(SwapchainCreator& Creator);
uint32_t Aquire();
void Present(uint32_t frame);
vector<Image*>& GetSurface(){
return mSurfaces;
}
};
};

View File

@ -9,10 +9,10 @@ namespace vulkanapi {
, frames(frames)
, width(width)
, height(height)
, imageFormat(VkFormat::VK_FORMAT_B8G8R8A8_SRGB)
, imageColorSpace(VkColorSpaceKHR::VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
, presentMode(VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR)
, imageUsage(VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_DST_BIT)
, 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)
, maxFrameInFlightCount(2)
{