cg:顶点输出结构被不同的成员顺序破坏了?违反配置文件或cg错误



我一直在为Retrarch修改cg着色器,我在cg Toolkit的编译器或代码生成器中遇到了一个奇怪的错误。。。或者什么的。考虑一下这里找到的模拟CRT电视的三遍着色器:https://github.com/libretro/common-shaders/tree/master/crt/crt-interlaced-halation

特别要考虑最后一道:https://github.com/libretro/common-shaders/blob/master/crt/crt-interlaced-halation/crt-interlaced-halation-pass2.cg

目前,着色器输出按预期工作。如果注释掉该文件顶部的"#define CURVATURE"(模拟CRT电视的曲率),着色器输出也会按预期工作。然而,这里的顶点着色器输出结构的成员顺序非常特殊:

struct out_vertex {
    float4 position : POSITION;
    float4 color : COLOR;
    float2 texCoord : TEXCOORD0;
        float2 one;
        float mod_factor;
        float2 ilfac;
        float3 stretch;
        float2 sinangle;
        float2 cosangle;
};

如果你重新排列顺序如下,你会得到损坏的输出:

struct out_vertex {
    float4 position : POSITION;
    float4 color : COLOR;
    float2 texCoord : TEXCOORD0;
        float2 cosangle;
        float2 one;
        float mod_factor;
        float2 ilfac;
        float3 stretch;
        float2 sinangle;
};

我的台式机的nvidia卡给了我一个带有该顺序的黑屏,而我的笔记本电脑的ATI卡则给了我奇怪的伪影,纹理坐标似乎被破坏了(也许)。因此,错误的确切性质取决于GPU或驱动程序,但错误的存在与供应商/驱动程序无关。。。因此,这似乎是cg编译器中的一个错误,导致各种属性损坏。你能得到的腐败几乎没有尽头。例如,其他成员的重新排列会破坏诸如"mod_factor"变量(存储输出的x像素坐标)之类的东西,这会导致交替的品红色/绿色像素色调粘在一个或另一个上,从而用相同的色调覆盖整个图像。还有一些会导致黑屏,除了光晕/开花等。

如果重新启用"#define CURVATURE",该问题不会出现在该特定着色器中,但它与"平面"代码路径中的错误无关:事实上,在"#ifdef CURVAURE"块内的片段着色器部分,您实际上可以将最终值替换为"xy=VAR.texCourd;"(与未服务版本使用的值相同),并且您将获得没有任何错误的平坦输出。(编辑:糟糕的是,这个特定的着色器实际上不是这样,但它是在我自己的版本中。在对这个"简化"的示例进行同样的评估之前,我应该先检查一下。)事实上,平面代码路径触发了损坏,但弯曲代码路径似乎并不表明它与弯曲代码路径读取碎片着色器中更多变化的属性有关(可能读取顺序或用法也很重要…?),但我还没有找到它的韵律或理由。我有自己完全不同的分叉WIP,同样奇怪的问题也会影响弯曲的代码路径,但我宁愿把它留给自己,直到它准备好为止。

所以,我想我有几个问题:

  • 其他人见过这样的东西吗
  • 这种不确定性只是在没有与任何语义显式关联的输出结构成员中预期的吗
  • 这种损坏可能来自我不知道的cg着色器配置文件限制吗?我不知道Retrarch编译的着色器配置文件是什么,但我可以看到,如果顶点输出结构的大小超过了允许的最大大小,就会发生这种损坏
  • 还有其他我可能忽略的可能性吗?我考虑过驱动程序错误,但当我意识到它影响了nvidia和ATI硬件时,这就消失了。尽管如此,我还是想在通知nvidia Cg Toolkit似乎有一个bug之前做好功课

感谢您的真知灼见!:)

事实证明,这个问题与依赖cg的自动分配语义有关。我将从上面复制/粘贴我的评论:

我开始觉得这个问题可能与依赖cg自动分配语义:例如,如果cg关联将具有完全浮动范围的值钳制为[0.0,1.0],这显然会引起问题。mod_factor、ilfac和stretch都属于这一类,sinangle和cosangle可能在[-1,1]中,所以这可能也适用于它们。这个语义的分配可能会受到死代码的影响消除,这将解释有无差异"#define CURVATURE。"不过,我必须检验这个假设。。。

根据配置文件的不同,可用的语义数量有限(请参阅本规范),并且(我可能错了)Retrarch似乎使用了较低的配置文件,其中只有以下可用:

  • POSITION:必须设置为片段空间顶点位置,这不仅是因为它通知光栅化器,而且因为它显然甚至无法从片段着色器中读取
  • COLOR0和COLOR1:值被钳制在[0,1]范围内
  • TEXCOORD0-7:对于任何标量或矢量浮点值都是安全的
  • FOG:对于任何标量浮点值都是安全的

BCOL0/BCOL1语义可能也包含在支持它们的概要文件中,而PSIZE和CLP0-5可能没有。总的教训似乎是,让cg编译器为[0,1]范围之外的值自动分配语义就像玩俄罗斯轮盘赌,因为你永远不知道它们最终是否会与钳制语义相关联,并且自动分配会根据着色器代码的具体情况而改变。出于这个原因,您需要仔细管理语义,以便可能在[0,1]之外的值与TEXCOORD0-7或FOG(用于标量浮点)之类的值配对。

最新更新