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