2

我想知道,如果我使用着色器渲染场景,我传入的纹理也恰好是该场景的渲染目标,它会导致任何不需要的行为吗?

所以基本上:

texture t;

shader->SetTexture("texture",t);

device->SetRenderTarget( 0, t->surface );

shader->Begin("effect")
// do some more shader stuff

device->EndScene();

这究竟会导致什么?

如果我在渲染之前不清除渲染目标,纹理仍然可以正常工作吗?我只是假设在调用 device->End 之前,最终的更改不会写入纹理?

4

3 回答 3

3

我假设您在谈论 DirectX9。文档没有说明这个具体案例,但我可以告诉你以下内容:

我只是假设在调用 device->End 之前,最终的更改不会写入纹理

这是一个错误的假设。想一想,您假设您绘制的所有三角形的所有像素都将存储在“某处”,并且您的所有纹理提取都将执行,而没有任何像素被写回渲染目标。这需要任意数量的内存,因此是不可能的。

在实践中:

  • 硬件通常会在三角形出现时处理它们,一次处理很多
  • 假设不存在竞争条件,它会在需要时更新帧缓冲区(在您的情况下是纹理内存支持)

所以,假设 DX9 没有抱怨(如果你真的想知道就试试吧,我不再做 DX9),它将未定义的。

也就是说,DirectX10 对此更加明确(来源):

如果任何子资源当前也被绑定用于读取或写入(可能在管道的不同部分),则这些绑定点将被 NULL'ed out 以防止在单个渲染操作中同时读取和写入相同的子资源。

因此,在 DirectX10 中,您的纹理设置将被 API 删除。

于 2009-10-25T18:08:09.840 回答
3

虽然我无法指出具体细节,但我很确定这是未定义的行为。显卡用于着色片段的方法可能会有所不同(一次处理不同的数量等),但在任何实际情况下,它一次处理多个片段。这意味着您将同时读取和写入相同的位置,从而导致竞争条件。我不认为这是推荐的。

于 2009-10-25T05:41:06.563 回答
2

调试运行时将阻止您执行此操作并提供警告。发布运行时“可能”(但可能不会)工作。

问题来自这样一个事实,即从纹理加载像素和使用它之间存在相当大的延迟。这是通过将一块纹素加载到缓存中来解决的。写入被缓冲并直接写入内存。因此,您可能最终会遇到一个问题,即读取可能已经更新但缓存已过期的纹素。如果您只阅读正在写入它的纹素“可能”工作,但实际上这些实现细节留给 IHV。他们没有义务允许这个工作。

正如其他人所说......这是非常不确定的行为。

于 2009-10-26T12:07:43.843 回答