使用查询系统测量片段着色器执行时间:需指定哪些管线阶段?
如何用Vulkan时间戳查询仅跟踪片段着色器执行时间
嘿,这个问题我刚好研究过,咱们来一步步拆解清楚~
要仅跟踪片段着色器的执行时间,你需要精准选择对应的管线阶段,配合正确的命令顺序来捕获片段着色器的开始和结束时间点:
核心管线阶段选择
你需要使用两个关键的管线阶段枚举值,分别对应片段着色器执行的起始前一刻和完成时刻:
- 第一个时间戳(片段着色器开始前):指定
VK_PIPELINE_STAGE_RASTERIZATION_BIT
这个阶段是片段着色器的直接前置阶段,当光栅化完成后,片段着色器就会立即开始执行。用这个阶段作为时间戳的触发条件,能精准捕获片段着色器启动前的时间点。 - 第二个时间戳(片段着色器完成后):指定
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
这个阶段就是片段着色器本身的执行阶段,当所有先前命令(也就是你的绘制命令)完成该阶段后,时间戳会被写入,对应片段着色器执行完毕的时间点。
正确的命令序列
要让时间戳准确工作,你需要按以下顺序组织命令:
// 1. 完成所有前置状态设置(绑定管线、视图port、资源等) vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, yourPipeline); vkCmdSetViewport(cmdBuf, ...); // ... 其他必要的状态配置 // 2. 执行触发片段着色器的绘制命令 vkCmdDraw(cmdBuf, ...); // 这个命令会执行从顶点到片段的完整图形管线 // 3. 插入第一个时间戳:捕获光栅化完成(片段着色器即将开始)的时间 vkCmdWriteTimestamp(cmdBuf, VK_PIPELINE_STAGE_RASTERIZATION_BIT, yourQueryPool, 0); // 4. 插入第二个时间戳:捕获片段着色器完成的时间 vkCmdWriteTimestamp(cmdBuf, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, yourQueryPool, 1);
后续获取并计算时间
当时间戳写入完成后,你可以通过vkGetQueryPoolResults接口从查询池中读取两个时间戳的值。然后用以下步骤计算实际执行时间:
- 计算两个时间戳的差值:
timestampDiff = timestamp1 - timestamp0 - 使用物理设备的
timestampPeriod(通过vkGetPhysicalDeviceProperties获取,单位为纳秒每时间戳单位)转换为实际时间:executionTimeNs = timestampDiff * physicalDeviceProperties.limits.timestampPeriod
注意事项
- 确保你的设备支持时间戳查询特性(
VK_FEATURE_TIMESTAMP_QUERY_BIT),可以在设备创建前通过vkGetPhysicalDeviceFeatures检查。 - 查询池创建时,
queryType必须设置为VK_QUERY_TYPE_TIMESTAMP,且queryCount至少为2。 - 部分GPU可能对管线阶段的支持有细微差异,建议先检查设备的
pipelineStageProperties确认阶段是否支持时间戳查询。
内容的提问来源于stack exchange,提问作者Maik Klein
相关产品推荐
相关产品推荐

