摘要
我希望能够在GPU上测量整个图形管道的毫秒级已经流逝的时间,目的是为了在优化代码之前/之后保存基准测试,以查看改进。在OpenGL中实现这一点非常简单,但我对Vulkan很新,并需要一些帮助。
我已经浏览了相关的现有答案(这里和这里),但它们并没有多大帮助。我无法在任何地方找到代码示例,所以我敢在这里问。
通过文档页面,我发现了一些我认为应该使用的函数,因此我已经像这样放置了一些内容:
1:创建查询池
void CreateQueryPool()
{
VkQueryPoolCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
createInfo.pNext = nullptr; // Optional
createInfo.flags = 0; // Reserved for future use, must be 0!
createInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
createInfo.queryCount = mCommandBuffers.size() * 2; // REVIEW
VkResult result = vkCreateQueryPool(mDevice, &createInfo, nullptr, &mTimeQueryPool);
if (result != VK_SUCCESS)
{
throw std::runtime_error("Failed to create time query pool!");
}
}
我想到了queryCount = mCommandBuffers.size() * 2
的主意,以便在渲染之前和之后有单独的查询时间戳空间,但我不知道这个假设是否正确。
2:记录命令缓冲区
// recording command buffer i:
vkCmdWriteTimestamp(mCommandBuffers[i], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mTimeQueryPool, i);
// render pass ...
vkCmdWriteTimestamp(mCommandBuffers[i], VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, mTimeQueryPool, i);
vkCmdCopyQueryPoolResults(/* many parameters here */);
我想要澄清一下几个问题:
- 向同一个查询索引写入的后果是什么?我需要两个单独的查询池-一个用于渲染前,另一个用于渲染后吗?
- 我应该如何处理同步?我假设每个命令缓冲区都有一个单独的查询。
- 对于包含查询结果的目标缓冲区,将其存储在具有“主机可见位”(host visible bit)的位置是否足够好,还是需要“仅设备可见”的分段内存?我对这个也有点迷茫。
我没有找到任何关于如何测量渲染时间的在线示例,但我认为这是如此常见的任务,一定有类似的示例存在。