我想知道,如果我使用着色器渲染一个场景,我在其中传递的纹理也恰好是该场景的渲染目标会导致任何不需要的行为吗?
基本上是这样的:
texture t;
shader->SetTexture("texture",t);
device->SetRenderTarget( 0, t->surface );
shader->Begin("effect")
// do some more shader stuff
device->EndScene();
这究竟是什么原因?
如果我在渲染之前没有清除渲染目标,那么纹理是否仍然可以正常工作?我只是假设最终的更改不会被写入纹理,直到device-> End被调用?
答案 0 :(得分:3)
虽然我不能指出具体细节,但我很确定它是未定义的行为。图形卡用于着色片段的方法可以变化(一次做不同的量等),但在任何实际情况下,它一次做多个片段。这意味着您将同时阅读和写入相同的位置,从而导致竞争条件。我不认为这是推荐的。
答案 1 :(得分:3)
我假设你在谈论DirectX9。文档没有说明这个具体案例,但我可以告诉你以下内容:
我只是假设最终的更改不会被写入纹理,直到device-> End被称为
这是一个错误的假设。考虑一下,你假设你绘制的所有三角形的所有像素都将存储在“某处”并且所有纹理提取都被执行而没有任何像素被写回渲染目标。这需要任意数量的存储器,因此是不可能的。
在实践中:
所以,假设DX9没有抱怨(如果你真的想知道,请尝试它,我不再做DX9),它将未定义。
也就是说,DirectX10对此更加明确(source):
目前还有任何子资源 读书或写作(也许是 在管道的不同部分), 那些绑定点将被NULL 防止相同的子资源 同时读写 在单个渲染操作中。
因此,在DirectX10中,API将删除您的纹理设置。
答案 2 :(得分:2)
调试运行时将阻止您执行此操作并提供警告。发布运行时“可能”(但可能不会)有效。
问题来自于从纹理加载像素和使用它之间存在相当大的延迟。通过将一块纹素加载到缓存中来解决此问题。写入被缓冲并直接写入内存。因此,您可能会遇到一个问题,即可能正在读取可能已经更新的纹素,但缓存将过时。如果您只是正在阅读正在写入它的纹素“可能”有效,但实际上这些实现细节留给了IHV。他们没有义务允许这项工作。
正如其他人所说......这是非常不明确的行为。