Vulkan 每帧更新描述符
Vulkan update descriptor every frame
我想将我的场景渲染为纹理,然后在着色器中使用该纹理,因此我使用 imageview 创建了一个 frambuffer 并为此记录了一个命令缓冲区。我在gpu上成功上传并执行了命令缓冲区,但是imageview的描述符是黑色的。我在渲染循环之前从 imageview 创建一个描述符。它是黑色的,因为我在将任何内容渲染到帧缓冲区之前创建它吗?如果是这样,我将不得不每帧更新描述符。我是否必须每帧从 imageview 创建一个新的描述符?还是有其他方法可以做到这一点?
我已阅读有关此标题的其他主题。不要将其标记为重复,因为线程是关于纹理的,而这是来自图像视图的纹理。
谢谢。
@IAS0601 我将通过答案回答您的评论中的问题,因为它允许编写更长的文本,并且其格式更好。我希望这也能回答您原来的问题,但您不必像回答一样对待。正如我所写,我不确定你在问什么。
1) 在几乎所有情况下,GPU 都是通过图像视图来访问图像的。它们指定了额外的参数来定义如何访问图像(例如访问图像的哪一部分),但仍然是原始图像被访问。图片视图,顾名思义,就是一个视图,访问参数的列表。它没有绑定任何内存,不包含任何数据(除了在图像视图创建期间指定的参数)。
因此,当您创建一个帧缓冲区并将其渲染到其中时,您将渲染到原始图像中,或者更具体地说,渲染到图像视图中指定的原始图像的那些部分。例如,您有一个包含 3 个数组层的 2D 纹理。您为中间(第二)层创建一个 2D 图像视图。然后在创建帧缓冲区期间使用此图像视图。现在当你渲染到这个帧缓冲区时,实际上你正在渲染到原始二维纹理数组的第二层。
另一件事 - 当您稍后访问相同的图像,并且当您使用相同的图像视图时,您仍然可以访问原始图像。如果您将某些内容渲染到图像中,那么您将获得更新的数据(前提是您已正确完成所有操作,例如执行适当的同步操作、必要时进行布局转换等)。我希望这就是您所说的更新图像视图。
2) 我不确定您所说的更新描述符集是什么意思。在 Vulkan 中,当我们更新描述符集时,这意味着我们指定了应该通过给定描述符集使用的 Vulkan 资源句柄。
如果我理解正确的话 - 你想将某些东西渲染成图像。您为该图像创建一个图像视图,并在帧缓冲区创建期间提供该图像视图。然后你将一些东西渲染到那个帧缓冲区中。现在您想从该图像中读取数据。你有两个选择。如果您只想访问一个与片段着色器位置关联的样本位置,您可以通过同一渲染通道的下一个子通道中的输入附件来实现。但是这样你只能执行不需要访问多个纹素的操作,例如颜色校正。
但是如果你想做一些更高级的事情,比如模糊或阴影贴图,如果你需要访问多个纹素,你必须结束一个渲染通道并开始另一个渲染通道。在这第二个渲染过程中,您可以通过描述符集从原始图像中读取数据。创建和更新此描述符集的时间并不重要(指定图像视图的句柄时)。如果您不更改资源句柄 - 也就是说,如果您不创建新图像或新图像视图,您可以使用相同的描述符集,并且您将访问在第一个渲染通道中渲染的数据。
如果您在访问数据时遇到问题,例如(如您所写)您只得到黑色,这表明您没有正确执行所有操作 - 渲染传递加载或存储操作不正确,或者初始和最终布局不正确。或者未正确执行同步。不幸的是,无法访问您的项目,我们无法确定问题所在。
我想将我的场景渲染为纹理,然后在着色器中使用该纹理,因此我使用 imageview 创建了一个 frambuffer 并为此记录了一个命令缓冲区。我在gpu上成功上传并执行了命令缓冲区,但是imageview的描述符是黑色的。我在渲染循环之前从 imageview 创建一个描述符。它是黑色的,因为我在将任何内容渲染到帧缓冲区之前创建它吗?如果是这样,我将不得不每帧更新描述符。我是否必须每帧从 imageview 创建一个新的描述符?还是有其他方法可以做到这一点?
我已阅读有关此标题的其他主题。不要将其标记为重复,因为线程是关于纹理的,而这是来自图像视图的纹理。
谢谢。
@IAS0601 我将通过答案回答您的评论中的问题,因为它允许编写更长的文本,并且其格式更好。我希望这也能回答您原来的问题,但您不必像回答一样对待。正如我所写,我不确定你在问什么。
1) 在几乎所有情况下,GPU 都是通过图像视图来访问图像的。它们指定了额外的参数来定义如何访问图像(例如访问图像的哪一部分),但仍然是原始图像被访问。图片视图,顾名思义,就是一个视图,访问参数的列表。它没有绑定任何内存,不包含任何数据(除了在图像视图创建期间指定的参数)。
因此,当您创建一个帧缓冲区并将其渲染到其中时,您将渲染到原始图像中,或者更具体地说,渲染到图像视图中指定的原始图像的那些部分。例如,您有一个包含 3 个数组层的 2D 纹理。您为中间(第二)层创建一个 2D 图像视图。然后在创建帧缓冲区期间使用此图像视图。现在当你渲染到这个帧缓冲区时,实际上你正在渲染到原始二维纹理数组的第二层。
另一件事 - 当您稍后访问相同的图像,并且当您使用相同的图像视图时,您仍然可以访问原始图像。如果您将某些内容渲染到图像中,那么您将获得更新的数据(前提是您已正确完成所有操作,例如执行适当的同步操作、必要时进行布局转换等)。我希望这就是您所说的更新图像视图。
2) 我不确定您所说的更新描述符集是什么意思。在 Vulkan 中,当我们更新描述符集时,这意味着我们指定了应该通过给定描述符集使用的 Vulkan 资源句柄。
如果我理解正确的话 - 你想将某些东西渲染成图像。您为该图像创建一个图像视图,并在帧缓冲区创建期间提供该图像视图。然后你将一些东西渲染到那个帧缓冲区中。现在您想从该图像中读取数据。你有两个选择。如果您只想访问一个与片段着色器位置关联的样本位置,您可以通过同一渲染通道的下一个子通道中的输入附件来实现。但是这样你只能执行不需要访问多个纹素的操作,例如颜色校正。
但是如果你想做一些更高级的事情,比如模糊或阴影贴图,如果你需要访问多个纹素,你必须结束一个渲染通道并开始另一个渲染通道。在这第二个渲染过程中,您可以通过描述符集从原始图像中读取数据。创建和更新此描述符集的时间并不重要(指定图像视图的句柄时)。如果您不更改资源句柄 - 也就是说,如果您不创建新图像或新图像视图,您可以使用相同的描述符集,并且您将访问在第一个渲染通道中渲染的数据。
如果您在访问数据时遇到问题,例如(如您所写)您只得到黑色,这表明您没有正确执行所有操作 - 渲染传递加载或存储操作不正确,或者初始和最终布局不正确。或者未正确执行同步。不幸的是,无法访问您的项目,我们无法确定问题所在。