vulkan bugfix
This commit is contained in:
parent
6975d71a19
commit
70f66ab7b9
@ -20,6 +20,9 @@ namespace engineapi
|
||||
constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) {}
|
||||
void Init();
|
||||
void Clear() { res = nullptr; };
|
||||
Res* Ptr() {
|
||||
return (Res*)res;
|
||||
}
|
||||
Res* operator->() { if (!res && guid) Init(); return (Res*)res; }
|
||||
Res& operator*() { if (!res && guid) Init(); return *(Res*)res; }
|
||||
operator bool() { if (!res && guid) Init(); return res; }
|
||||
|
||||
@ -31,10 +31,10 @@ namespace engineapi {
|
||||
}
|
||||
void Scene::Render()
|
||||
{
|
||||
RenderAPI::GetSingletonPtr()->Render(*mCamera);
|
||||
RenderAPI::GetSingletonPtr()->Render(mCamera);
|
||||
auto& meshs = actor1->Ptr().GetMeshs();
|
||||
for (auto it : meshs) {
|
||||
RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
|
||||
RenderAPI::GetSingletonPtr()->DrawStaticMesh(it.Ptr());
|
||||
}
|
||||
}
|
||||
void Scene::AddGameObject(GameObject* gameObject)
|
||||
|
||||
@ -54,10 +54,10 @@ namespace openglapi {
|
||||
window->Present();
|
||||
GL_CHECK();
|
||||
}
|
||||
void RenderOpenGLApi::SetStaticMesh(Mesh& mesh)
|
||||
void RenderOpenGLApi::SetStaticMesh(Mesh* mesh)
|
||||
{
|
||||
auto Indices = mesh.GetIndices();
|
||||
auto Vertices = mesh.GetVertices();
|
||||
auto Indices = mesh->GetIndices();
|
||||
auto Vertices = mesh->GetVertices();
|
||||
unsigned int VBO, VAO, EBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
@ -90,28 +90,28 @@ namespace openglapi {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// 解绑VAO
|
||||
glBindVertexArray(0);
|
||||
VAOTable[mesh.GetGuid()] = OpenGLPtr{ VAO };
|
||||
VAOTable[mesh->GetGuid()] = OpenGLPtr{ VAO };
|
||||
}
|
||||
void RenderOpenGLApi::DrawStaticMesh(Mesh& mesh)
|
||||
void RenderOpenGLApi::DrawStaticMesh(Mesh* mesh)
|
||||
{
|
||||
OpenGLPtr& shaderPtr = ShaderTable[mesh.GetShaderGuid()];
|
||||
OpenGLPtr& shaderPtr = ShaderTable[mesh->GetShaderGuid()];
|
||||
glUseProgram(shaderPtr);
|
||||
OpenGLPtr& meshPtr = VAOTable[mesh.GetGuid()];
|
||||
OpenGLPtr& meshPtr = VAOTable[mesh->GetGuid()];
|
||||
glBindVertexArray(meshPtr);
|
||||
glDrawElements(GL_TRIANGLES, mesh.GetIndices().size(), GL_UNSIGNED_INT, 0);
|
||||
glDrawElements(GL_TRIANGLES, mesh->GetIndices().size(), GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
void RenderOpenGLApi::LoadShader(Shader& shader)
|
||||
void RenderOpenGLApi::LoadShader(Shader* shader)
|
||||
{
|
||||
auto vertModule = shader.GetVertHandle<glShaderProgram>()->Ptr();
|
||||
auto fragModule = shader.GetFragHandle<glShaderProgram>()->Ptr();
|
||||
auto vertModule = shader->GetVertHandle<glShaderProgram>()->Ptr();
|
||||
auto fragModule = shader->GetFragHandle<glShaderProgram>()->Ptr();
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertModule);
|
||||
glAttachShader(shaderProgram, fragModule);
|
||||
glLinkProgram(shaderProgram);
|
||||
glDeleteShader(vertModule);
|
||||
glDeleteShader(fragModule);
|
||||
ShaderTable[shader.GetGuid()] = OpenGLPtr{shaderProgram};
|
||||
ShaderTable[shader->GetGuid()] = OpenGLPtr{shaderProgram};
|
||||
Backend::CheckShaderProgram(shaderProgram);
|
||||
}
|
||||
}
|
||||
@ -31,9 +31,9 @@ namespace openglapi {
|
||||
|
||||
void BeginFrame()override;
|
||||
void EndFrame()override;
|
||||
void SetStaticMesh(Mesh& mesh)override;
|
||||
void DrawStaticMesh(Mesh& mesh)override;
|
||||
void SetStaticMesh(Mesh* mesh)override;
|
||||
void DrawStaticMesh(Mesh* mesh)override;
|
||||
|
||||
void LoadShader(Shader& shader)override;
|
||||
void LoadShader(Shader* shader)override;
|
||||
};
|
||||
}
|
||||
@ -7,6 +7,6 @@ namespace engineapi {
|
||||
void Mesh::BeginLoad()
|
||||
{
|
||||
mMaterial->BeginLoad();
|
||||
RenderAPI::GetSingletonPtr()->SetStaticMesh(*this);
|
||||
RenderAPI::GetSingletonPtr()->SetStaticMesh(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,6 @@ namespace engineapi {
|
||||
}
|
||||
void Shader::BeginLoad()
|
||||
{
|
||||
RenderAPI::GetSingletonPtr()->LoadShader(*this);
|
||||
RenderAPI::GetSingletonPtr()->LoadShader(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ namespace engineapi {
|
||||
RenderNode(RenderType type);
|
||||
~RenderNode() {};
|
||||
|
||||
virtual void Render(Camera& camera) = 0;
|
||||
virtual void Render(Camera* camera) = 0;
|
||||
public:
|
||||
RenderType GetType() {
|
||||
return mType;
|
||||
|
||||
@ -16,7 +16,7 @@ namespace engineapi {
|
||||
RenderNodeForwardRendering::~RenderNodeForwardRendering()
|
||||
{
|
||||
}
|
||||
void RenderNodeForwardRendering::Render(Camera& camera)
|
||||
void RenderNodeForwardRendering::Render(Camera* camera)
|
||||
{
|
||||
auto renderAPI = RenderAPI::GetSingletonPtr();
|
||||
auto window = Window::GetSingletonPtr();
|
||||
@ -29,11 +29,11 @@ namespace engineapi {
|
||||
mContext->UsePass(mType);
|
||||
mContext->UseContext();
|
||||
}
|
||||
void RenderNodeForwardRendering::RenderSkyBox(Camera& camera)
|
||||
void RenderNodeForwardRendering::RenderSkyBox(Camera* camera)
|
||||
{
|
||||
// 先转3x3再回4x4,把相机位移信息去除
|
||||
Matrix4 mat_V = Matrix4(Matrix3(camera.GetViewMatrix()));
|
||||
Matrix4 mat_P = camera.GetProjectionMatrix();
|
||||
Matrix4 mat_V = Matrix4(Matrix3(camera->GetViewMatrix()));
|
||||
Matrix4 mat_P = camera->GetProjectionMatrix();
|
||||
|
||||
mSky->Use();
|
||||
//skyBoxMaterial->Use();
|
||||
|
||||
@ -10,12 +10,12 @@ namespace engineapi {
|
||||
RenderNodeForwardRendering();
|
||||
~RenderNodeForwardRendering();
|
||||
|
||||
virtual void Render(Camera& camera);
|
||||
virtual void Render(Camera* camera);
|
||||
|
||||
private:
|
||||
Model* mSky;
|
||||
|
||||
void RenderSkyBox(Camera& camera);
|
||||
void RenderSkyBox(Camera* camera);
|
||||
void RenderBatches(const table<uint32_t, vector<MeshRenderer*>>& batchs);
|
||||
};
|
||||
}
|
||||
@ -29,7 +29,7 @@ namespace engineapi {
|
||||
//mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_AFTER_EFFECT_RENDERING]);
|
||||
//mCurPasses.push_back(mAllPasses[ZX_RENDER_PASS_UI_RENDERING]);
|
||||
}
|
||||
void RenderAPI::Render(Camera& camera)
|
||||
void RenderAPI::Render(Camera* camera)
|
||||
{
|
||||
for (auto node : mCurNodes) {
|
||||
node->Render(camera);
|
||||
|
||||
@ -30,12 +30,12 @@ namespace engineapi
|
||||
virtual void OnWindowSizeChange(uint32_t width, uint32_t height) = 0;
|
||||
virtual void SetViewPort(uint32_t width, uint32_t height, uint32_t xOffset = 0, uint32_t yOffset = 0) = 0;
|
||||
virtual void BeginFrame() = 0;
|
||||
virtual void Render(Camera& camera);
|
||||
virtual void Render(Camera* camera);
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void SetStaticMesh(Mesh& mesh) = 0;
|
||||
virtual void DrawStaticMesh(Mesh& mesh) = 0;
|
||||
virtual void SetStaticMesh(Mesh* mesh) = 0;
|
||||
virtual void DrawStaticMesh(Mesh* mesh) = 0;
|
||||
|
||||
virtual void LoadShader(Shader& shader) = 0;
|
||||
virtual void LoadShader(Shader* shader) = 0;
|
||||
virtual void SwitchContext() = 0;
|
||||
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ namespace vulkanapi {
|
||||
|
||||
Backend::TransferWorker = GetWorker(Queue::TransferQueue);
|
||||
Backend::RenderWorker = GetWorker(Queue::RenderQueue);
|
||||
Backend::PresentWorker = GetWorker(Queue::PresentQueue);
|
||||
//Backend::PresentWorker = GetWorker(Queue::PresentQueue);
|
||||
|
||||
auto poolSizes = DescriptorPool::DefaultDescriptorPoolSize();
|
||||
mPool = new DescriptorPool(*mDevice, poolSizes, 1000);
|
||||
|
||||
@ -20,14 +20,14 @@ namespace vulkanapi {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
void CommandThreadWorker::Invoke(voidFn fn)
|
||||
void CommandThreadWorker::Invoke(const voidFn& fn)
|
||||
{
|
||||
mChannel.release(fn);
|
||||
}
|
||||
|
||||
void CommandThreadWorker::SyncInvoke(voidFn fn)
|
||||
void CommandThreadWorker::SyncInvoke(const voidFn& fn)
|
||||
{
|
||||
Invoke([=]() {
|
||||
Invoke([=,this]() {
|
||||
fn();
|
||||
mSemaphore.release();
|
||||
});
|
||||
|
||||
@ -15,7 +15,7 @@ namespace vulkanapi {
|
||||
CommandThreadWorker(const string name, int buffer);
|
||||
~CommandThreadWorker();
|
||||
|
||||
void Invoke(voidFn fn);
|
||||
void SyncInvoke(voidFn fn);
|
||||
void Invoke(const voidFn& fn);
|
||||
void SyncInvoke(const voidFn& fn);
|
||||
};
|
||||
};
|
||||
|
||||
@ -8,49 +8,36 @@ namespace vulkanapi {
|
||||
,mQueue(queue)
|
||||
,mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
|
||||
,mWork(name, 64)
|
||||
,mImmediateExeCmd(mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)
|
||||
,mImmediateExeCmd(mCommandPool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))
|
||||
{
|
||||
mImmediateExeCmd.Fence() = mCommandPool.AllocateFence();
|
||||
}
|
||||
void CommandWorker::Invoke(voidFn fn)
|
||||
void CommandWorker::Invoke(const voidFn& fn)
|
||||
{
|
||||
mWork.Invoke(fn);
|
||||
}
|
||||
|
||||
void CommandWorker::InvokeBuffer(commandFn fn, voidFn callback)
|
||||
void CommandWorker::InvokeBuffer(const commandFn& fn, const voidFn& callback)
|
||||
{
|
||||
mWork.Invoke([=]() {
|
||||
mWork.Invoke([=, this]() {
|
||||
CommandBuffer cmd = mCommandPool.Pop();
|
||||
Buffer(cmd, fn, callback);
|
||||
mCommandPool.Push(cmd);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandWorker::Buffer(CommandBuffer& cmd, commandFn fn, voidFn callback)
|
||||
void CommandWorker::Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback)
|
||||
{
|
||||
cmd.Reset();
|
||||
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
fn(cmd);
|
||||
cmd.EndRecord();
|
||||
cmd.Submit(mQueue.Ptr());
|
||||
cmd.WaitFofFence(mDevice.Ptr());
|
||||
VkFence fence = mDevice.PopFence();
|
||||
cmd.Submit(mQueue.Ptr(), fence);
|
||||
mDevice.PushWaitFence(fence);
|
||||
callback();
|
||||
}
|
||||
|
||||
void CommandWorker::Flush()
|
||||
{
|
||||
mWork.SyncInvoke([]() {});
|
||||
}
|
||||
void CommandWorker::Draw(commandFn fn)
|
||||
{
|
||||
CommandBuffer cmd = mCommandPool.Pop();
|
||||
cmd.Reset();
|
||||
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
fn(cmd);
|
||||
cmd.EndRecord();
|
||||
cmd.Submit(mQueue.Ptr());
|
||||
cmd.WaitFofFence(mDevice.Ptr());
|
||||
mCommandPool.Push(cmd);
|
||||
mWork.SyncInvoke([]{});
|
||||
}
|
||||
bool CommandWorker::Present(VkPresentInfoKHR& presentInfo)
|
||||
{
|
||||
|
||||
@ -16,15 +16,19 @@ namespace vulkanapi {
|
||||
CommandBuffer mImmediateExeCmd;
|
||||
public:
|
||||
CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags);
|
||||
|
||||
void Invoke(voidFn fn);
|
||||
void InvokeBuffer(commandFn fn, voidFn callback);
|
||||
void Buffer(CommandBuffer& cmd,commandFn fn, voidFn callback);
|
||||
CommandPool& GetCommandPool() {
|
||||
return mCommandPool;
|
||||
}
|
||||
Queue& GetQueue() {
|
||||
return mQueue;
|
||||
}
|
||||
void Invoke(const voidFn& fn);
|
||||
void InvokeBuffer(const commandFn& fn, const voidFn& callback);
|
||||
void Buffer(CommandBuffer& cmd, const commandFn& fn, const voidFn& callback);
|
||||
void Flush();
|
||||
void ImmediatelyExecute(commandFn fn, voidFn callback) {
|
||||
void ImmediatelyExecute(const commandFn& fn, const voidFn callback) {
|
||||
Buffer(mImmediateExeCmd, fn , callback);
|
||||
}
|
||||
void Draw(commandFn fn);
|
||||
bool Present(VkPresentInfoKHR& presentInfo);
|
||||
};
|
||||
};
|
||||
@ -13,6 +13,7 @@ namespace vulkanapi {
|
||||
uint32_t presentFrame{0};
|
||||
VkFence surfaceFence;
|
||||
VkSemaphore surfaceSemaphore;
|
||||
VkCommandBuffer drawCommand;
|
||||
public:
|
||||
VulkanContext(RenderVulkanAPI* _API){
|
||||
API = _API;
|
||||
|
||||
@ -68,11 +68,11 @@ namespace vulkanapi {
|
||||
{
|
||||
swapchain->Present(context);
|
||||
}
|
||||
void RenderVulkanAPI::SetStaticMesh(Mesh& mesh)
|
||||
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
|
||||
{
|
||||
auto Indices = mesh.GetIndices();
|
||||
auto Vertices = mesh.GetVertices();
|
||||
VulkanVAO& meshBuffer = VAOTable[mesh.GetGuid()];
|
||||
auto Indices = mesh->GetIndices();
|
||||
auto Vertices = mesh->GetVertices();
|
||||
VulkanVAO& meshBuffer = VAOTable[mesh->GetGuid()];
|
||||
meshBuffer.indexCount = Indices.size();
|
||||
meshBuffer.vertexCount = Vertices.size();
|
||||
|
||||
@ -102,7 +102,7 @@ namespace vulkanapi {
|
||||
VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
meshBuffer.indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer.vertexBufferAlloc);
|
||||
|
||||
auto fn = [=](CommandBuffer& cmd) {
|
||||
auto fn = [=, &meshBuffer](CommandBuffer& cmd) {
|
||||
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer.vertexBuffer, vertexBufferSize);
|
||||
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer.indexBuffer, indexBufferSize);
|
||||
};
|
||||
@ -119,48 +119,52 @@ namespace vulkanapi {
|
||||
Backend::TransferWorker->ImmediatelyExecute(fn, callback);
|
||||
}
|
||||
}
|
||||
void RenderVulkanAPI::DrawStaticMesh(Mesh& mesh)
|
||||
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
|
||||
{
|
||||
VulkanVAO& vulkanVAO = VAOTable[mesh.GetGuid()];
|
||||
VulkanPipeline& pipeline = PipelineTable[mesh.GetShaderGuid()];
|
||||
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, frame);
|
||||
VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer };
|
||||
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);
|
||||
VkFence fence{ context.surfaceFence};
|
||||
CommandBuffer cmd(context.drawCommand);
|
||||
VkCommandBuffer ptr = cmd.Ptr();
|
||||
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
|
||||
VkRect2D scissor = {};
|
||||
scissor.offset = { mViewPortInfo.xOffset, mViewPortInfo.yOffset };
|
||||
scissor.extent = { mViewPortInfo.width, mViewPortInfo.height };
|
||||
vkCmdSetScissor(ptr, 0, 1, &scissor);
|
||||
context.Pass->BeginPass(cmd, frame);
|
||||
VulkanVAO& vulkanVAO = VAOTable[mesh->GetGuid()];
|
||||
VulkanPipeline& pipeline = PipelineTable[mesh->GetShaderGuid()];
|
||||
VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer };
|
||||
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);
|
||||
|
||||
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, &pipeline.descriptorSet, 0, VK_NULL_HANDLE);
|
||||
vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0);
|
||||
context.Pass->EndPass(cmd);
|
||||
});
|
||||
Backend::RenderWorker->Flush();
|
||||
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, &pipeline.descriptorSet, 0, VK_NULL_HANDLE);
|
||||
vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0);
|
||||
|
||||
context.Pass->EndPass(cmd);
|
||||
cmd.EndRecord();
|
||||
cmd.Submit(Backend::RenderWorker->GetQueue().Ptr(), fence);
|
||||
}
|
||||
void RenderVulkanAPI::LoadShader(Shader& shader)
|
||||
void RenderVulkanAPI::LoadShader(Shader* shader)
|
||||
{
|
||||
vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
|
||||
auto device = backend.GetDevice();
|
||||
auto vertModule = shader.GetVertHandle<vkShaderProgram>()->Ptr();
|
||||
auto& device = backend.GetDevice();
|
||||
auto vertModule = shader->GetVertHandle<vkShaderProgram>()->Ptr();
|
||||
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
|
||||
auto fragModule = shader.GetFragHandle<vkShaderProgram>()->Ptr();
|
||||
auto fragModule = shader->GetFragHandle<vkShaderProgram>()->Ptr();
|
||||
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
@ -171,7 +175,7 @@ namespace vulkanapi {
|
||||
shaderStageInfo.pName = "main";
|
||||
shaderStages.push_back(shaderStageInfo);
|
||||
}
|
||||
auto it = refl::UClass::MetaTable.find(shader.Name());
|
||||
auto it = refl::UClass::MetaTable.find(shader->Name());
|
||||
auto meta = it->second->vtable.GetMeta("vkMeta");
|
||||
// 设置顶点输入格式
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||
@ -281,7 +285,7 @@ namespace vulkanapi {
|
||||
depthStencilInfo.front = {};
|
||||
depthStencilInfo.back = {};
|
||||
|
||||
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader.GetInfo());
|
||||
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo());
|
||||
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||
@ -309,8 +313,8 @@ namespace vulkanapi {
|
||||
for (auto& shaderModule : shaderModules)
|
||||
vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
||||
|
||||
VulkanPipeline& vulkan_pipeline = PipelineTable[shader.GetGuid()];
|
||||
vulkan_pipeline.name = shader.Name();
|
||||
VulkanPipeline& vulkan_pipeline = PipelineTable[shader->GetGuid()];
|
||||
vulkan_pipeline.name = shader->Name();
|
||||
vulkan_pipeline.pipeline = pipeLine;
|
||||
vulkan_pipeline.inUse = true;
|
||||
vulkan_pipeline.pipelineLayout = pipelineLayout;
|
||||
|
||||
@ -38,10 +38,10 @@ namespace vulkanapi
|
||||
|
||||
void BeginFrame()override;
|
||||
void EndFrame()override;
|
||||
void SetStaticMesh(Mesh& mesh)override;
|
||||
void DrawStaticMesh(Mesh& mesh)override;
|
||||
void SetStaticMesh(Mesh* mesh)override;
|
||||
void DrawStaticMesh(Mesh* mesh)override;
|
||||
|
||||
void LoadShader(Shader& shader)override;
|
||||
void LoadShader(Shader* shader)override;
|
||||
public:
|
||||
static RenderVulkanAPI* GetSingletonPtr() {
|
||||
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
||||
|
||||
@ -1,37 +1,8 @@
|
||||
#include "commandbuffer.h"
|
||||
#include "commandpool.h"
|
||||
#include "device.h"
|
||||
namespace vulkanapi {
|
||||
CommandBuffer::CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level)
|
||||
:mPool(commandPool)
|
||||
,mPtr(commandPool.AllocateBuffer(level))
|
||||
,mFence(commandPool.AllocateFence())
|
||||
{
|
||||
|
||||
}
|
||||
CommandBuffer::~CommandBuffer()
|
||||
{
|
||||
//zlog::info("CommandBuffer Destruct {:#x} isNull = {}", (uint64_t)this, mPtr == nullptr || mFence == nullptr);
|
||||
if (mPtr) {
|
||||
mPool.FreeBuffer(mPtr);
|
||||
}
|
||||
if (mFence) {
|
||||
mPool.FreeFence(mFence);
|
||||
}
|
||||
}
|
||||
CommandBuffer::CommandBuffer(CommandBuffer&& other)noexcept
|
||||
: mPtr(other.mPtr)
|
||||
, mFence(other.mFence)
|
||||
, mPool(other.mPool)
|
||||
{
|
||||
other.mPtr = nullptr;
|
||||
other.mFence = nullptr;
|
||||
//zlog::info("CommandBuffer MoveConstruct {:#x} => {:#x}", (uint64_t)&other, (uint64_t)this);
|
||||
}
|
||||
void CommandBuffer::Reset()
|
||||
{
|
||||
vkResetCommandBuffer(mPtr, VkCommandBufferResetFlagBits::VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
mPool.ResetFence(mFence);
|
||||
}
|
||||
void CommandBuffer::BeginRecord(VkCommandBufferUsageFlags flag)
|
||||
{
|
||||
@ -54,17 +25,13 @@ namespace vulkanapi {
|
||||
copy.size = size;
|
||||
vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, ©);
|
||||
}
|
||||
void CommandBuffer::Submit(VkQueue& queue)
|
||||
void CommandBuffer::Submit(VkQueue& queue, VkFence fence)
|
||||
{
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &mPtr;
|
||||
vkQueueSubmit(queue, 1, &submitInfo, mFence);
|
||||
}
|
||||
void CommandBuffer::WaitFofFence(VkDevice& device)
|
||||
{
|
||||
vkWaitForFences(device, 1, &mFence, VK_TRUE, UINT64_MAX);
|
||||
vkQueueSubmit(queue, 1, &submitInfo, fence);
|
||||
}
|
||||
void CommandBuffer::BindVertexBuffer(VkBuffer buffer, uint32_t offset)
|
||||
{
|
||||
|
||||
@ -1,30 +1,19 @@
|
||||
#pragma once
|
||||
#include "../vulkan.h"
|
||||
namespace vulkanapi {
|
||||
class Device;
|
||||
class CommandPool;
|
||||
class CommandBuffer {
|
||||
protected:
|
||||
CommandPool& mPool;
|
||||
VkCommandBuffer mPtr;
|
||||
VkFence mFence;
|
||||
public:
|
||||
CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level);
|
||||
~CommandBuffer();
|
||||
CommandBuffer(CommandBuffer* other)noexcept:CommandBuffer(std::forward<CommandBuffer>(*other)) {};
|
||||
CommandBuffer(CommandBuffer&& other)noexcept;
|
||||
CommandBuffer(VkCommandBuffer ptr) : mPtr(ptr) {};
|
||||
VkCommandBuffer& Ptr() {
|
||||
return mPtr;
|
||||
};
|
||||
VkFence& Fence() {
|
||||
return mFence;
|
||||
};
|
||||
void Reset();
|
||||
void BeginRecord(VkCommandBufferUsageFlags flag);
|
||||
void EndRecord();
|
||||
void CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
||||
void Submit(VkQueue& queue);
|
||||
void WaitFofFence(VkDevice& device);
|
||||
void Submit(VkQueue& queue,VkFence fence);
|
||||
|
||||
void BindVertexBuffer(VkBuffer buffer, uint32_t offset);
|
||||
void BindIndexBuffers(VkBuffer buffer, uint32_t offset, VkIndexType type);
|
||||
|
||||
@ -7,9 +7,6 @@ namespace vulkanapi {
|
||||
CommandPool::CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex)
|
||||
:mPtr(nullptr)
|
||||
,mDevice(device)
|
||||
,mPool([=]()->CommandBuffer {
|
||||
return std::move(CommandBuffer(*this, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
|
||||
}, 256)
|
||||
{
|
||||
VkCommandPoolCreateInfo pCreateInfo{
|
||||
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
@ -19,6 +16,13 @@ namespace vulkanapi {
|
||||
};
|
||||
vkCreateCommandPool(device.Ptr(), &pCreateInfo, nullptr, &mPtr);
|
||||
}
|
||||
CommandPool::~CommandPool()
|
||||
{
|
||||
for (auto cb : mPool) {
|
||||
FreeBuffer(cb.Ptr());
|
||||
}
|
||||
mPool.clear();
|
||||
}
|
||||
VkCommandBuffer CommandPool::AllocateBuffer(VkCommandBufferLevel level)
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocInfo{
|
||||
@ -37,18 +41,19 @@ namespace vulkanapi {
|
||||
vkFreeCommandBuffers(mDevice.Ptr(), mPtr, 1, &buf);
|
||||
buf = nullptr;
|
||||
}
|
||||
void CommandPool::FreeFence(VkFence& fence)
|
||||
CommandBuffer CommandPool::Pop()
|
||||
{
|
||||
vkDestroyFence(mDevice.Ptr(), fence, NULL);
|
||||
fence = nullptr;
|
||||
if (mPool.empty()) {
|
||||
return AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||
}
|
||||
CommandBuffer buffer = mPool.back();
|
||||
mPool.pop_back();
|
||||
return buffer;
|
||||
}
|
||||
void CommandPool::ResetFence(VkFence& fence)
|
||||
void CommandPool::Push(CommandBuffer& cmd)
|
||||
{
|
||||
vkResetFences(mDevice.Ptr(), 1, &fence);
|
||||
}
|
||||
VkFence CommandPool::AllocateFence()
|
||||
{
|
||||
return mDevice.CreateFence();
|
||||
cmd.Reset();
|
||||
mPool.push_back(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,25 +9,16 @@ namespace vulkanapi {
|
||||
protected:
|
||||
VkCommandPool mPtr;
|
||||
Device& mDevice;
|
||||
zstd::pool<CommandBuffer> mPool;
|
||||
std::vector<CommandBuffer> mPool;
|
||||
public:
|
||||
CommandPool(Device& device, VkCommandPoolCreateFlags queueFlags, uint32_t queueIndex);
|
||||
|
||||
~CommandPool();
|
||||
VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level);
|
||||
void FreeBuffer(VkCommandBuffer& buf);
|
||||
void FreeFence(VkFence& fence);
|
||||
void ResetFence(VkFence& fence);
|
||||
VkFence AllocateFence();
|
||||
VkCommandPool& Ptr() {
|
||||
return mPtr;
|
||||
};
|
||||
CommandBuffer Pop()
|
||||
{
|
||||
return mPool.acquire();
|
||||
}
|
||||
void Push(CommandBuffer& cmd)
|
||||
{
|
||||
mPool.release(&cmd);
|
||||
}
|
||||
CommandBuffer Pop();
|
||||
void Push(CommandBuffer& cmd);
|
||||
};
|
||||
}
|
||||
@ -52,6 +52,20 @@ namespace vulkanapi {
|
||||
delete queue.second;
|
||||
}
|
||||
mQueueMap.clear();
|
||||
for (auto& fence : mFencePool) {
|
||||
vkDestroyFence(mPtr, fence, nullptr);
|
||||
}
|
||||
mFencePool.clear();
|
||||
}
|
||||
VkFence Device::CreateFence(VkFenceCreateFlags flags)
|
||||
{
|
||||
VkFenceCreateInfo fenceInfo{};
|
||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
// 创建时立刻设置为signaled状态(否则第一次永远等不到)
|
||||
fenceInfo.flags = flags;
|
||||
VkFence fence;
|
||||
VkResult result = vkCreateFence(mPtr, &fenceInfo, nullptr, &fence);
|
||||
return fence;
|
||||
}
|
||||
Queue* Device::GetQueue(const string& name)
|
||||
{
|
||||
@ -61,16 +75,23 @@ namespace vulkanapi {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
VkFence Device::CreateFence()
|
||||
VkFence Device::PopFence()
|
||||
{
|
||||
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);
|
||||
if (mFencePool.empty()) {
|
||||
return CreateFence(0);
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mFenceMutex);
|
||||
VkFence fence = mFencePool.back();
|
||||
mFencePool.pop_back();
|
||||
return fence;
|
||||
}
|
||||
void Device::PushWaitFence(VkFence fence)
|
||||
{
|
||||
vkWaitForFences(mPtr, 1, &fence, VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(mPtr, 1, &fence);
|
||||
std::lock_guard<std::mutex> lock(mFenceMutex);
|
||||
mFencePool.push_back(fence);
|
||||
}
|
||||
VkSemaphore Device::CreateSemaphore()
|
||||
{
|
||||
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "../vulkan.h"
|
||||
|
||||
#include "zstd/pool.h"
|
||||
#include <mutex>
|
||||
namespace vulkanapi {
|
||||
class DeviceCreator;
|
||||
class Queue;
|
||||
@ -10,6 +11,8 @@ namespace vulkanapi {
|
||||
VkDevice mPtr{ NULL };
|
||||
VkPhysicalDevice mPhysical{NULL};
|
||||
table<const string*, Queue*> mQueueMap;
|
||||
vector<VkFence> mFencePool;
|
||||
std::mutex mFenceMutex;
|
||||
public:
|
||||
VkDevice& Ptr() {
|
||||
return mPtr;
|
||||
@ -20,9 +23,10 @@ namespace vulkanapi {
|
||||
public:
|
||||
Device(DeviceCreator& Creator);
|
||||
~Device();
|
||||
|
||||
VkFence CreateFence(VkFenceCreateFlags flags);
|
||||
Queue* GetQueue(const string& name);
|
||||
VkFence CreateFence();
|
||||
VkFence PopFence();
|
||||
void PushWaitFence(VkFence fence);
|
||||
VkSemaphore CreateSemaphore();
|
||||
VkShaderModule CreateShaderModule(vector<char> code);
|
||||
VkShaderModule CreateShaderModule(vector<uint32_t> code);
|
||||
|
||||
@ -22,6 +22,7 @@ namespace vulkanapi {
|
||||
VkPhysicalDeviceType desiredPhysicalDeviceType;
|
||||
vector<string> desiredExtensions;
|
||||
vector<DesiredQueue> desiredQueues;
|
||||
int fencePoolCount = 256;
|
||||
public:
|
||||
Instance& instance;
|
||||
|
||||
|
||||
@ -42,26 +42,31 @@ namespace vulkanapi {
|
||||
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_EXCLUSIVE;
|
||||
auto& pool = Backend::RenderWorker->GetCommandPool();
|
||||
for (int i = 0; i < Creator.frames;i++) {
|
||||
mSurfaces.push_back(new Image(Creator.device,"swapchain" + to_string(i), swapchain_images[i], args));
|
||||
mSemaphores.push_back(Creator.device.CreateSemaphore());
|
||||
mFences.push_back(Creator.device.CreateFence());
|
||||
mFences.push_back(Creator.device.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
|
||||
mCommands.push_back(pool.AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
|
||||
}
|
||||
mFrames = Creator.frames;
|
||||
}
|
||||
void Swapchain::Aquire(VulkanContext& ctx)
|
||||
{
|
||||
ctx.drawCommand = mCommands[ctx.frame];
|
||||
ctx.surfaceFence = mFences[ctx.frame];
|
||||
ctx.surfaceSemaphore = mSemaphores[ctx.frame];
|
||||
//if (vkWaitForFences(mDevice.Ptr(), 1, &ctx.surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS)
|
||||
//throw std::runtime_error("Failed to wait for fence!");
|
||||
if (vkWaitForFences(mDevice.Ptr(), 1, &ctx.surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS)
|
||||
throw std::runtime_error("Failed to wait for fence!");
|
||||
CommandBuffer cmd(ctx.drawCommand);
|
||||
cmd.Reset();//surfaceSemaphore unsignaled state = > signaled state
|
||||
vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, ctx.surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame);
|
||||
vkResetFences(mDevice.Ptr(), 1, &ctx.surfaceFence);
|
||||
}
|
||||
void Swapchain::Present(VulkanContext& ctx)
|
||||
{
|
||||
VkSwapchainKHR swapChains[] = { mPtr };
|
||||
VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore };
|
||||
VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore };//wait signaled state
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.pWaitSemaphores = waitSemaphores;
|
||||
|
||||
@ -13,6 +13,7 @@ namespace vulkanapi {
|
||||
Device& mDevice;
|
||||
int mFrames;
|
||||
vector<Image*> mSurfaces;
|
||||
vector<VkCommandBuffer> mCommands;
|
||||
vector<VkFence> mFences;
|
||||
vector<VkSemaphore> mSemaphores;
|
||||
public:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user