我想问下PushConstant的作用,在Opengl之前感觉没有见过,它跟UBO的区别是什么?更新频率更快么?有没有更加详细的例子说明下?UBO在某种情况下也能更新,如果是新特性,为什么不直接优化UBO,而要新增一个特性?
我想问下PushConstant的作用,在Opengl之前感觉没有见过,它跟UBO的区别是什么?更新频率更快么?有没有更加详细的例子说明下?UBO在某种情况下也能更新,如果是新特性,为什么不直接优化UBO,而要新增一个特性?
Push Constants 是一种快速将少量统一数据提供给着色器的方式。它应该比使用 Uniform Buffer Objects (UBOs) 快得多,但有一个巨大的限制是数据的大小——规范要求为一个 Push Constant 范围提供至少 128 字节的空间。硬件供应商可能会支持更大的大小,但与其他方法相比,这仍然是非常小的(例如 256 字节)。
由于 Push Constants 比其他描述符(我们通过这些资源向着色器提供数据)快得多,因此它们非常适合用于在绘制调用之间变化的数据,比如变换矩阵。
从着色器的角度来看,Push Constants 通过 layout( push_constant ) 限定符和一个统一数据块来声明。例如:
layout( push_constant ) uniform ColorBlock {
vec4 Color;
} PushConstant;
从应用程序的角度来看,如果着色器想要使用 Push Constants,它们必须在创建管线布局时指定。然后必须将 vkCmdPushConstants() 命令记录到命令缓冲区中。此函数需要一个指向内存的指针,从中将数据复制到 Push Constant 范围。
同一管线的不同着色器阶段可以使用相同的 Push Constant 数据块(类似于 UBOs),或者使用整个范围的一部分。但是,重要的是,每个着色器阶段只能使用一个 Push Constant 数据块。它可以包含多个成员。另一个重要的点是,所有使用 Push Constants 的着色器阶段的总数据大小必须适合大小限制。因此,这个限制不是针对每个阶段,而是针对整个范围。
Vulkan Cookbook 的仓库中有一个示例展示了简单的 Push Constants 使用场景。Sascha Willems 的 Vulkan 示例也包含了一个展示如何使用 Push Constants 的样本。
在Vulkan中,Push Constants是一种快速访问内存的方式,用于将少量数据传递给着色器。它们主要用于传递需要频繁更改的数据,如渲染管线的状态信息、着色器程序参数等。
Push Constant vs UBO(Uniform Buffer Object)
Push Constant:
Uniform Buffer Object (UBO):
更新频率
为什么需要Push Constants
虽然UBO也可以更新,但它们的设计初衷是为了传递相对静态的数据。对于需要频繁更新的小数据集,UBO的更新过程可能会引入不必要的开销。因此,Push Constants提供了一种更高效的方式来处理这类数据。
示例代码
以下是一个简单的Vulkan Push Constant使用的示例:
// 定义Push Constant结构体
struct PushConstants {
float scale;
float offset;
};
// 创建Pipeline Layout
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pSetLayouts = nullptr;
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(PushConstants);
VkPipelineLayout pipelineLayout;
vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout);
// 在渲染命令中设置Push Constant
vkCmdPushConstants(
commandBuffer,
pipelineLayout,
VK_SHADER_STAGE_VERTEX_BIT,
0,
sizeof(PushConstants),
&pushConstants
);
在这个示例中,PushConstants
结构体包含两个浮点数,用于传递缩放和偏移值。在渲染命令中,我们使用 vkCmdPushConstants
函数将这些值直接推送到GPU。
总结
Push Constants提供了一种高效的方式来传递频繁更新的小数据集。它们在设计上与UBO有所不同,适用于不同的场景。虽然UBO也可以更新,但对于需要频繁更改的数据,Push Constants提供了更低的开销和更简洁的API。