ULRE/src/RenderDevice/Vulkan/VKRenderTarget.cpp

152 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<hgl/graph/vulkan/VKRenderTarget.h>
#include<hgl/graph/vulkan/VKDevice.h>
#include<hgl/graph/vulkan/VKSwapchain.h>
#include<hgl/graph/vulkan/VKSemaphore.h>
VK_NAMESPACE_BEGIN
namespace
{
const VkPipelineStageFlags pipe_stage_flags=VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
}//namespace
SubmitQueue::SubmitQueue(Device *dev,VkQueue q,const uint32_t fence_count)
{
device=dev;
queue=q;
for(uint32_t i=0;i<fence_count;i++)
fence_list.Add(device->CreateFence(true));
current_fence=0;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
//submit_info.waitSemaphoreCount = 1;
//submit_info.pWaitSemaphores = *present_complete_semaphore;
submit_info.pWaitDstStageMask = &pipe_stage_flags;
//submit_info.signalSemaphoreCount = 1;
//submit_info.pSignalSemaphores = *render_complete_semaphore;
}
SubmitQueue::~SubmitQueue()
{
fence_list.Clear();
}
bool SubmitQueue::Wait(const bool wait_all,uint64_t time_out)
{
VkFence fence=*fence_list[current_fence];
VkResult result;
result=vkWaitForFences(device->GetDevice(),1,&fence,wait_all,time_out);
result=vkResetFences(device->GetDevice(),1,&fence);
return(true);
}
bool SubmitQueue::Submit(VkCommandBuffer &cmd_buf,vulkan::Semaphore *wait_sem,vulkan::Semaphore *complete_sem)
{
VkSemaphore ws=*wait_sem;
VkSemaphore cs=*complete_sem;
submit_info.waitSemaphoreCount =1;
submit_info.pWaitSemaphores =&ws;
submit_info.commandBufferCount =1;
submit_info.pCommandBuffers =&cmd_buf;
submit_info.signalSemaphoreCount=1;
submit_info.pSignalSemaphores =&cs;
VkFence fence=*fence_list[current_fence];
VkResult result=vkQueueSubmit(queue,1,&submit_info,fence);
if(++current_fence==fence_list.GetCount())
current_fence=0;
//不在这里立即等待fence完成是因为有可能queue submit需要久一点工作时间我们这个时间可以去干别的。等在AcquireNextImage时再去等待fence而且是另一帧的fence。这样有利于异步处理
return(result==VK_SUCCESS);
}
RenderTarget::RenderTarget(Device *dev,Framebuffer *_fb,const uint32_t fence_count):SubmitQueue(dev,dev->GetGraphicsQueue(),fence_count)
{
fb=_fb;
}
SwapchainRenderTarget::SwapchainRenderTarget(Device *dev,Swapchain *sc):RenderTarget(dev,nullptr,sc->GetImageCount())
{
swapchain=sc;
vk_swapchain=swapchain->GetSwapchain();
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.pNext = nullptr;
present_info.waitSemaphoreCount = 0;
present_info.pWaitSemaphores = nullptr;
present_info.swapchainCount = 1;
present_info.pResults = nullptr;
present_info.pSwapchains = &vk_swapchain;
Texture2D **sc_color=swapchain->GetColorTextures();
Texture2D *sc_depth=swapchain->GetDepthTexture();
main_rp=device->CreateRenderPass((*sc_color)->GetFormat(),sc_depth->GetFormat());
swap_chain_count=swapchain->GetImageCount();
extent=swapchain->GetExtent();
for(uint i=0;i<swap_chain_count;i++)
{
render_frame.Add(vulkan::CreateFramebuffer(device,main_rp,(*sc_color)->GetImageView(),sc_depth->GetImageView()));
++sc_color;
}
current_frame=0;
}
SwapchainRenderTarget::~SwapchainRenderTarget()
{
render_frame.Clear();
delete main_rp;
}
int SwapchainRenderTarget::AcquireNextImage(vulkan::Semaphore *present_complete_semaphore)
{
VkSemaphore sem=*present_complete_semaphore;
if(vkAcquireNextImageKHR(device->GetDevice(),vk_swapchain,UINT64_MAX,sem,VK_NULL_HANDLE,&current_frame)==VK_SUCCESS)
return current_frame;
return -1;
}
bool SwapchainRenderTarget::PresentBackbuffer(vulkan::Semaphore *render_complete_semaphore)
{
VkSemaphore sem=*render_complete_semaphore;
present_info.waitSemaphoreCount=1;
present_info.pWaitSemaphores=&sem;
present_info.pImageIndices=&current_frame;
VkResult result=vkQueuePresentKHR(queue,&present_info);
if (!((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)))
{
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
// Swap chain is no longer compatible with the surface and needs to be recreated
return false;
}
}
result=vkQueueWaitIdle(queue);
if(result!=VK_SUCCESS)
return(false);
return(true);
}
VK_NAMESPACE_END