diff --git a/example/Basic/rf_test.cpp b/example/Basic/rf_test.cpp index d1efee0c..66632a7e 100644 --- a/example/Basic/rf_test.cpp +++ b/example/Basic/rf_test.cpp @@ -80,8 +80,15 @@ private: public: - TestApp(RenderFramework *rf):WorkObject(rf) + TestApp(RenderFramework *rf):WorkObject() { + Join(rf,rf->GetSwapchainRenderTarget()); + } + + void Join(RenderFramework *rf,IRenderTarget *rt) + { + WorkObject::Join(rf,rt); + if(!InitAutoMaterial()) return; @@ -95,31 +102,21 @@ public: void Tick(double)override {} - void Render(double) + void Render(double delta_time,graph::RenderCmdBuffer *cmd) { - //WorkObject是工作对象,不是渲染对象,所以不应该直接自动指定RenderTarget,更不能直接指定RenderCmdBuffer + if(!cmd) + return; - //目前这里只是为了测试,所以这样写 + //这个使用完全不合理,录制CMD和推送swapchain是两回事,需要分开操作。 + //比如场景有的物件分静态和动态 - RenderFramework *rf=GetRenderFramework(); - SwapchainModule *sm=rf->GetSwapchainModule(); + //可能静态物件就全部一次性录制好,而动态物件则是每帧录制 - RenderCmdBuffer *cb=sm->BeginRender(); //这里会有AcquireNextImage操作 - if(cb) - { - //这个使用完全不合理,录制CMD和推送swapchain是两回事,需要分开操作。 - //比如场景有的物件分静态和动态 + cmd->SetClearColor(0,clear_color); - //可能静态物件就全部一次性录制好,而动态物件则是每帧录制 - - cb->SetClearColor(0,clear_color); - - cb->BeginRenderPass(); - cb->Render(render_obj); - cb->EndRenderPass(); - - sm->EndRender(); //这里会Submit和PresentBackbuffer - } + cmd->BeginRenderPass(); + cmd->Render(render_obj); + cmd->EndRenderPass(); } };//class TestApp:public VulkanApplicationFramework @@ -130,7 +127,20 @@ int main(int,char **) if(!rf.Init(SCREEN_WIDTH,SCREEN_HEIGHT)) return(-1); - WorkManager wm(&rf); + // RenderFramework存在于外部,提供的是整体的渲染控制。 - wm.Start(new TestApp(&rf)); + // WorkManager是提供一个工作业务管理,但开发者并不一定要使用它,所以我们不将它们整合在一起。 + + SwapchainWorkManager wm(&rf); + + wm.Run(new TestApp(&rf)); + + // WorkObject被定义为工作对象,所有的渲染控制都需要被写在WorkObject的Render函数下。 + + // 但我们认为游戏开发者不应该关注如何控制渲染,而应该关注如何处理游戏逻辑. + // 所以我们在WorkObject的基础上再提供RenderWorkObject派生类,用于直接封装好的渲染场景树控制。 + // + // 开发者仅需要将要渲染的物件放置于场景树即可。 + + // 但开发者也可以直接使用WorkObject,自行管理这些事。 } diff --git a/example/common/WorkManager.cpp b/example/common/WorkManager.cpp index 4c17d939..220ebba6 100644 --- a/example/common/WorkManager.cpp +++ b/example/common/WorkManager.cpp @@ -1,5 +1,6 @@ #pragma once #include"WorkManager.h" +#include namespace hgl { @@ -18,17 +19,33 @@ namespace hgl { double delta_time=cur_time-last_render_time; - if(delta_time>=frame_time) + if(delta_time>=frame_time||wo->IsRenderDirty()) { last_render_time=cur_time; wo->Render(delta_time); } } - void WorkManager::Run() + void SwapchainWorkManager::Render(WorkObject *wo) { - if(!cur_work_object) - return; + graph::IRenderTarget *rt=swpachain_module->AcquireNextImage(); + + wo->MarkRenderDirty(); //临时的,未来会被更好的机制替代 + WorkManager::Render(wo); + + rt->WaitQueue(); + rt->WaitFence(); + } + + void WorkManager::Run(WorkObject *wo) + { + if(!wo)return; + + last_update_time=last_render_time=0; + + cur_work_object=wo; + + wo->Join(render_framework,render_framework->GetSwapchainRenderTarget()); Window *win=render_framework->GetWindow(); graph::GPUDevice *dev=render_framework->GetDevice(); @@ -50,17 +67,4 @@ namespace hgl break; } } - - void WorkManager::Start(WorkObject *wo) - { - if(!wo)return; - - last_update_time=last_render_time=0; - - cur_work_object=wo; - - wo->Join(render_framework); - - Run(); - } }//namespcae hgl diff --git a/example/common/WorkManager.h b/example/common/WorkManager.h index 2695d3af..531c820e 100644 --- a/example/common/WorkManager.h +++ b/example/common/WorkManager.h @@ -3,6 +3,9 @@ namespace hgl { + /** + * 工作管理器,管理一个序列的WorkObject
+ */ class WorkManager { graph::RenderFramework *render_framework; @@ -35,10 +38,24 @@ namespace hgl } void Tick(WorkObject *wo); - void Render(WorkObject *wo); - void Run(); + virtual void Render(WorkObject *wo); - void Start(WorkObject *wo); + void Run(WorkObject *wo); };//class WorkManager + + class SwapchainWorkManager:public WorkManager + { + graph::SwapchainModule *swpachain_module; + + public: + + SwapchainWorkManager(graph::RenderFramework *rf):WorkManager(rf) + { + swpachain_module=rf->GetSwapchainModule(); + } + ~SwapchainWorkManager()=default; + + void Render(WorkObject *wo) override; + }; }//namespcae hgl diff --git a/example/common/WorkObject.h b/example/common/WorkObject.h index 1cc7b246..39181fa8 100644 --- a/example/common/WorkObject.h +++ b/example/common/WorkObject.h @@ -2,18 +2,25 @@ #include #include #include +#include #include #include +//#include namespace hgl { + /** + * 工作对象

+ */ class WorkObject:public TickObject { graph::RenderFramework *render_framework=nullptr; + graph::IRenderTarget *cur_render_target=nullptr; bool destroy_flag=false; bool renderable=true; + bool render_dirty=true; protected: @@ -29,27 +36,58 @@ namespace hgl const bool IsDestroy()const{return destroy_flag;} const bool IsRenderable()const{return renderable;} + const bool IsRenderDirty()const{return render_dirty;} void MarkDestory(){destroy_flag=true;} void SetRenderable(bool r){renderable=r;} + void MarkRenderDirty(){render_dirty=true;} public: - WorkObject(graph::RenderFramework *rf) - { - Join(rf); - } + WorkObject()=default; virtual ~WorkObject()=default; - virtual void Join(graph::RenderFramework *rf) + virtual void Join(graph::RenderFramework *rf,graph::IRenderTarget *rt) { if(!rf)return; if(render_framework==rf)return; render_framework=rf; + cur_render_target=rt; db=rf->GetRenderResource(); } - virtual void Render(double delta_time)=0; + virtual void Render(double delta_time,graph::RenderCmdBuffer *cmd)=0; + + virtual void Render(double delta_time) + { + if(!cur_render_target) + { + //std::cerr<<"WorkObject::Render,cur_render_target=nullptr"<BeginRender(); + + if(!cmd) + { + //std::cerr<<"WorkObject::Render,cur_render_target->BeginRender()=nullptr"<EndRender(); + cur_render_target->Submit(); + + render_dirty=false; + } + + //std::cout<<"WorkObject::Render End"< @@ -31,8 +31,16 @@ public: VkResult Present(const VkPresentInfoKHR *pi){return vkQueuePresentKHR(queue,pi);} + /** + * 等待Submit的队列完成操作。这个操作会阻塞当前线程,所以在Submit后请不要立即使用它。而是在下一次队列提交前再做这个操作。 + */ bool WaitQueue(); + + /** + * 等待Queue命令执行完成的fence信号 + */ bool WaitFence(const bool wait_all=true,const uint64_t time_out=HGL_NANO_SEC_PER_SEC); + bool Submit(const VkCommandBuffer *cmd_buf,const uint32_t count,Semaphore *wait_sem,Semaphore *complete_sem); bool Submit(GPUCmdBuffer *cmd_buf,Semaphore *wait_sem,Semaphore *complete_sem); };//class DeviceQueue diff --git a/inc/hgl/graph/VKRenderTarget.h b/inc/hgl/graph/VKRenderTarget.h index 19ec6ba4..494a0eda 100644 --- a/inc/hgl/graph/VKRenderTarget.h +++ b/inc/hgl/graph/VKRenderTarget.h @@ -7,6 +7,7 @@ #include #include #include +//#include VK_NAMESPACE_BEGIN /** @@ -54,6 +55,9 @@ public: // Command Buffer virtual bool WaitQueue ()=0; virtual bool WaitFence ()=0; + + virtual RenderCmdBuffer * BeginRender ()=0; + virtual void EndRender ()=0; };//class IRenderTarget struct RenderTargetData @@ -136,6 +140,26 @@ public: // Command Buffer bool WaitQueue ()override{return data->queue->WaitQueue();} bool WaitFence ()override{return data->queue->WaitFence();} + +public: + + virtual RenderCmdBuffer *BeginRender()override + { + if(!data->cmd_buf) + return(nullptr); + + data->cmd_buf->Begin(); + data->cmd_buf->BindFramebuffer(data->fbo); + return data->cmd_buf; + } + + virtual void EndRender() override + { + if(!data->cmd_buf) + return; + + data->cmd_buf->End(); + } };//class RenderTarget /** @@ -212,6 +236,20 @@ public: // Command Buffer bool WaitQueue ()override{return rt_list[current_frame]->WaitQueue();} bool WaitFence ()override{return rt_list[current_frame]->WaitFence();} + +public: + + virtual RenderCmdBuffer *BeginRender()override + { + //std::cout<<"Begin Render frame="<BeginRender(); + } + + virtual void EndRender() override + { + //std::cout<<"End Render frame="<EndRender(); + } };//class MFRenderTarget /** @@ -238,13 +276,8 @@ public: public: - RenderCmdBuffer *AcquireNextImage(); ///<获取下一帧的索引 + IRenderTarget *AcquireNextImage(); ///<获取下一帧的索引 - bool PresentBackbuffer(); ///<推送后台画面到前台 - - bool Submit()override - { - return rt_list[current_frame]->Submit(present_complete_semaphore); - } + bool Submit()override; ///<提交当前帧的渲染,交推送到前台 };//class SwapchainRenderTarget:public RenderTarget VK_NAMESPACE_END diff --git a/inc/hgl/graph/module/SwapchainModule.h b/inc/hgl/graph/module/SwapchainModule.h index 49d0b025..7c8fc8bf 100644 --- a/inc/hgl/graph/module/SwapchainModule.h +++ b/inc/hgl/graph/module/SwapchainModule.h @@ -33,9 +33,9 @@ public: SwapchainModule(GPUDevice *,TextureManager *tm,RenderTargetManager *rtm,RenderPassManager *rpm); virtual ~SwapchainModule(); - RenderCmdBuffer *BeginRender(); +// RenderCmdBuffer *BeginRender(); - void EndRender(); + //void EndRender(); public: @@ -44,6 +44,7 @@ public: const VkExtent2D & GetSwapchainSize()const{return sc_render_target->GetExtent();} SwapchainRenderTarget * GetRenderTarget ()const{return sc_render_target;} + IRenderTarget * AcquireNextImage()const{return sc_render_target->AcquireNextImage();} };//class SwapchainModule:public GraphModule VK_NAMESPACE_END diff --git a/res b/res index e1a36d78..475d8ad4 160000 --- a/res +++ b/res @@ -1 +1 @@ -Subproject commit e1a36d78f0eead5f6bb65493432c4690637b991d +Subproject commit 475d8ad43ceee084cd24f5d0bed59de9f6aa36fd diff --git a/src/SceneGraph/Vulkan/VKQueue.cpp b/src/SceneGraph/Vulkan/VKQueue.cpp index 7af7f758..6846133d 100644 --- a/src/SceneGraph/Vulkan/VKQueue.cpp +++ b/src/SceneGraph/Vulkan/VKQueue.cpp @@ -67,6 +67,10 @@ bool DeviceQueue::Submit(const VkCommandBuffer *cmd_buf,const uint32_t cb_count, submit_info.pWaitSemaphores =nullptr; } + // wait 信号的意思是等待这个Image有效 + // signal 则是这个queue已执行完成,和fence功能类似。 + // 所以Wait信号一般是上一次的signal信号 + if(complete_sem) { cs=*complete_sem; diff --git a/src/SceneGraph/Vulkan/VKSwapchainRenderTarget.cpp b/src/SceneGraph/Vulkan/VKSwapchainRenderTarget.cpp index 4d6e684f..9b46022a 100644 --- a/src/SceneGraph/Vulkan/VKSwapchainRenderTarget.cpp +++ b/src/SceneGraph/Vulkan/VKSwapchainRenderTarget.cpp @@ -1,6 +1,7 @@ #include #include #include +//#include VK_NAMESPACE_BEGIN SwapchainRenderTarget::SwapchainRenderTarget(VkDevice dev,Swapchain *sc,Semaphore *pcs,RenderTarget **rtl):MFRenderTarget(sc->image_count,rtl) @@ -16,6 +17,10 @@ SwapchainRenderTarget::SwapchainRenderTarget(VkDevice dev,Swapchain *sc,Semaphor present_info.pSwapchains = &(swapchain->swap_chain); present_complete_semaphore=pcs; + + VkSemaphore sem=*present_complete_semaphore; + +// std::cout<<"present complete semaphore : "<swap_chain, UINT64_MAX, - *present_complete_semaphore, + sem, VK_NULL_HANDLE, ¤t_frame)!=VK_SUCCESS) return(nullptr); - SwapchainImage *sc_image=&(swapchain->sc_image[current_frame]); + //std::cerr<<"AcquireNextImage current_frame="<cmd_buf->Begin(); - sc_image->cmd_buf->BindFramebuffer(sc_image->fbo); - - return sc_image->cmd_buf; + return rt_list[current_frame]; } -bool SwapchainRenderTarget::PresentBackbuffer() +bool SwapchainRenderTarget::Submit() { + IRenderTarget *rt=rt_list[current_frame]; + + //std::cout<<"submit frame="<Submit(present_complete_semaphore)) + return(false); + DeviceQueue *queue=GetQueue(); - VkSemaphore wait_semaphores=*GetRenderCompleteSemaphore(); + VkSemaphore wait_semaphores=*rt->GetRenderCompleteSemaphore(); present_info.waitSemaphoreCount =1; present_info.pWaitSemaphores =&wait_semaphores; present_info.pImageIndices =¤t_frame; +// std::cout<<"present frame="<Present(&present_info); if (!((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) diff --git a/src/SceneGraph/module/SwapchainModule.cpp b/src/SceneGraph/module/SwapchainModule.cpp index 9f3c3e88..804ed539 100644 --- a/src/SceneGraph/module/SwapchainModule.cpp +++ b/src/SceneGraph/module/SwapchainModule.cpp @@ -6,6 +6,7 @@ #include #include #include +#include VK_NAMESPACE_BEGIN namespace @@ -266,18 +267,18 @@ void SwapchainModule::OnResize(const VkExtent2D &extent) CreateSwapchainRenderTarget(); } - -RenderCmdBuffer *SwapchainModule::BeginRender() -{ - return sc_render_target->AcquireNextImage(); -} - -void SwapchainModule::EndRender() -{ - sc_render_target->Submit(); - sc_render_target->PresentBackbuffer(); - sc_render_target->WaitQueue(); - sc_render_target->WaitFence(); -} +// +//RenderCmdBuffer *SwapchainModule::BeginRender() +//{ +// return sc_render_target->AcquireNextImage(); +//} +// +//void SwapchainModule::EndRender() +//{ +// sc_render_target->Submit(); +// sc_render_target->PresentBackbuffer(); +// sc_render_target->WaitQueue(); +// sc_render_target->WaitFence(); +//} VK_NAMESPACE_END