在Vulkan中,执行依赖是否不足以确保正确的顺序



我很难理解为什么我们为管道屏障和访问掩码指定管道的阶段。用管道阶段指定屏障的目的是给出指令,使某个阶段之前的所有命令都发生在某个阶段之后的所有阶段之前。因此,根据这个推理,假设我想将数据从暂存缓冲区传输到设备本地缓冲区。在我从着色器读取缓冲区之前,我需要有一个屏障,说明传输阶段必须在着色器读取阶段之前发生。我可以使用:

srcstage=VK_PIPELINE_STAGE_TRANSFER_BIT;dststage=VK_PIPELINE_STAGE_FRAGMENT_BIT;

这意味着屏障之前的所有命令必须在屏障之后的所有命令启动片段着色器阶段之前完成传输阶段。

然而,我不理解进入面具的概念,也不理解我们为什么要把它和舞台面具一起使用。显然,舞台面具并不能确保";可见性";或";可用性"???那么,这是否意味着,尽管传输阶段将在片段阶段开始之前完成,但无法保证着色器将读取正确的数据?因为缓存可能没有被刷新,也不可见/不可用?

如果是这种情况,我们需要指定访问掩码,例如:

srcaccessmask=VK_ACCESS_MEMORY_WRITE_BIT;dstaccessmask=VK_ACCESS_MEMORY_READ_BIT;

那么,如果阶段还不够,那么指定阶段又有什么意义呢?

访问掩码确保可见性,但您不能对尚未可用的内容进行可见性(即:您无法看到尚未发生的内容(。可见性和可用性对于内存屏障都是必要的,但单独使用它们是不够的。

毕竟,严格来说,执行障碍并不需要内存障碍。读后写屏障不需要确保可见性。它只需要确保在写入之后不会发生读取;纯粹的执行障碍就足够了。但是,如果您正在进行一次又一次的写入或一次接一次的读取,那么除了可用性之外,还需要确保可见性

执行依赖性不足以确保正确的顺序,因为Vulkan的内存模型需要手动\显式内存屏障。

换句话说,执行屏障只包括执行,而不包括执行的副作用。因此,当你需要副作用连贯一致时,你也需要记忆屏障。

如果以另一种方式满足一致性,那么访问掩码实际上是不必要的:

semaphore_wait.pWaitDstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// we need to order our stuff after the semaphore wait, so:
barrier.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// semaphore already includes all device memory access, so nothing here:
barrier.srcAccessMask = 0;
barrier.oldLayout = COOL_LAYOUT;
barrier.newLayout = EVEN_BETTER_LAYOUT;

只使用访问掩码(没有阶段(是不明确的。访问掩码可以限制驱动程序需要执行的内存一致性工作的数量:

// make available the storage writes from fragment shader,
// but do not bother with storage writes
// from compute, vertex, tessellation, geometry, raytracing, or mesh shader:
barrier.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;

VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT隐含地包括顶点、镶嵌和几何着色器阶段。但仅用于执行依赖性,用于内存依赖性:

注意

在命令的第一同步作用域中包括特定流水线阶段隐含地包括同步作用域的逻辑上较早的流水线阶段。类似地,第二同步范围包括逻辑上较晚的流水线阶段。

但是,请注意,访问范围不会受到这种影响——只有指定的精确阶段才被视为每个访问范围的一部分。

最新更新