vulkan学习笔记二十一

终于要见到三角形了:)。

这一次要填写创建这个demo时,预写的那个DrawFrame()函数了,这个函数填写完,就应该能看到三角形了吧。

在每帧的渲染过程中,一般要执行三步操作:

  1. 从交换链中取一张图像
  2. 执行渲染指令
  3. 返回渲染后的图像到交换链进行展示

现在开始,先在头文件中添加一个uint32_t类型的变量:m_currentFrame = 0;用来表示绘制时,从交换链中取出的当前帧的索引。

第一步:

先查询fence同步的状态,通过调用vkWaitForFences()函数进行查询。其参数:

第一个参数:m_device

第二个参数:fence的数量,这里为1

第三个参数:要查询的fence的指针,这里是&m_fences[m_currentFrame]

第四个参数:成功解除阻塞等待必须满足的条件,这里为VK_TRUE,表示查询的对象中,所有的fence都发出信号。

第五个参数:超时时间,系统可能会超出这个时间,单位为纳秒。这里设置为64位uint的最大值。

再从交换链中取下一张图像,调用vkAcquireNextImageKHR其参数:

第一个参数:逻辑设备对象m_device

第二个参数:要取图的交换链m_swapchain

第三个参数:超时限制,这里还是uint64的最大值。

第四个参数:对应的semaphore,这里应该是m_imageAvailableSemaphores[m_currentFrame]

第五个参数:这里为VK_NULL_HANDLE不能为m_fences[m_currentFrame],否则校验层提示fence在提交前要被重置。

第六个参数:对应的图像的ID,在提交指令时,会用到。需要用一个局部变量来记录一下这个ID,这里是 uint32_t imageIndex,传入引用&imageIndex。

取出图像后,要进行图像变换。这里执行旋转缩放平移等操作,最基础的就是执行MVP变换。这个具体的运算过程可放到顶点的shader中进行变换,但是要通过代码将变换的矩阵传给shader,这种变量在shader中定义为uniform类型的变量。所以在这个地方,先补一个函数,向shader传递具体的矩阵值:void UpdateUniformBuffer()参数就是获取到的这个图像的ID。

在这个UpdateUniformBuffer函数中,先定义一个UniformData的对象 ud = {};。通过对memset函数初始化为全0。

将ud.model数组的下标为0、5、10、15的元素赋值为1.0f。

将ud.proj数组的下标为0、5、10、11、15的元素分别赋值为:45.0f -135.0f -1.0f -1.0f 1.0f

将ud.view数组的下标为0、1、2、4、5、6、9、10、14、15的元素分别赋值为:    -0.7f   -0. 408248335f  0.577350259f  0.707106769f  -0.408248335f  0.577350259  0.816496670f  0.577350259f  -173.205078f  1.0f

然后将ud中的数据内容拷贝到GPU:

回到DrawFrame函数,调用UpdateUniformBuffer(imageIndex)。

第二步执行渲染指令:

在执行渲染指令之前,要确认一下,当前帧图象对应的fence是否已经有了,如果已经有了需要清理一下。如果没有就将之前生成好的对应的fence赋值给当前帧图像的fence,所以补充一下std::vector m_currentImageFences;其数量与m_fences一致,并且要在m_fences初始化的地方进行实始化,将VK_NULL_HANDLE初始化给m_currentImageFences。即在CreateSyncObjects函数中,m_fences初始化的后面初始化m_currentImageFences:

m_currentImageFences.resize(m_swapchainImages.size(), VK_NULL_HANDLE);

那在DrawFrame函数中继续。

在执行指令之前,要先判断一下,m_currentImageFences对应的fence是否为VK_NULL_HANDLE,如果是,说明刚开始渲染,可以将m_fences中的fence赋值给m_currentImageFences中相应图像的对象。如果不为VK_NULL_HANDLE,则说明正在绘制。需等待绘制完成后,再将m_fences中的fence赋值给m_currentImageFences中相应图像的对象。赋完值之后,就要重置m_fences中对应的fence。

vulkan学习笔记二十一_第1张图片

之后就可以提交队列了,提交队列,调用vkQueueSubmit,其参数:

第一个参数:要提交的队列,这里是m_graphicsQueue

第二个参数:是下一个参数提交信息VkSubmitInfo数组的个数

第三个参数:VkSubmitInfo数组,这里需要在vkQueueSubmit的上方补一个数据结构VkSubmitInfo submitInfo = {};

第四个参数:当前图像对应的fence,即m_fences[m_currentFrame]。

补齐第三个参数:submitInfo的数据:

submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

submitInfo.pNext = nullptr;

需要补一个VkSemaphore的数组std::vector< VkSemaphore > semaphores,意思是在队列开始前需要等待的信号量。其值为:则下面两个参数的值是:

submitInfo.waitSemaphoreCount = semaphores.size();

submitInfo.pWaitSemaphores = semaphores.data();

在这里需要将颜色输出到图像,定义一个数组VkPipelineStageFlags waitStages[]取值VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT。

submitInfo.pWaitDstStageMask = waitStages;

commandBuffer的个数,现在提交一个,所以为1

submitInfo.commandBufferCount = 1;

commandBuffer的对象imageIndex对应的m_commandBuffers[imageIndex]

submitInfo.pCommandBuffers = m_commandBuffers[imageIndex];

在指令缓冲执行完成时发出信号,所以这里使用Render信号量,m_renderFinishedSemaphores[m_currentFrame]

submitInfo.signalSemaphoreCount  = 1;

submitInfo.pSignalSemaphores = m_renderFinishedSemaphores[m_currentFrame];

对于semaphores的赋值,可以将之前生成的对应的图像信号量赋值给semaphores,所以semaphores数组中对象的数目为1,且值为m_fences[m_currentFrame]

队列提交后,需要进行呈现,将绘制的内容显示出来。可调用vkQueuePresentKHR函数进行呈现。其参数:

第一个参数:要呈现的队列,之前已取得的m_presentQueue

第二个参数:VkPresentInfoKHR类型的对象指针或引用,可以定义一个局部变量VkPresentInfoKHR presentInfo = {}其属性赋值:

presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

presentInfo.pNext = nullptr;

还使用上面写过的渲染信号量

presentInfo.waitSemaphoreCount = 1;

presentInfo.pWaitSemaphores = &m_renderFinishedSemaphores[m_currentFrame];

使用之前创建好的swapchain。

presentInfo.swapchainCount = 1;

presentInfo.pSwapchains = &m_swapchain;

图像的id

presentInfo.pImageIndices = &imageIndex;

返回的结果是个数组,数目与swapchian的数目相同,且结果也与swapchain一一对应。这里不需要这个结果,所以直接设置为nullptr。

presentInfo.pResults = nullptr;

然后对m_currentFrame的值进行更新,可以让m_currentFrame++,但是一直加下去会超出m_swapchainImages.size()这个最大值。所以还要取一下模:

m_currentFrame = m_currentFrame % m_swapchainImages.size()

函数的最后,设置一下vkQueueWaitIdle,等待指令队列执行结束。

执行程序:

vulkan学习笔记二十一_第2张图片

终于看到三角形了:)

你可能感兴趣的:(c++)