仅为一个输出顶点设置gl_TessLevel?

时间:2016-08-11 09:16:14

标签: opengl glsl shader tesselation

在互联网上,我找到了一些TCS代码示例,其中gl_TessLevel*变量仅针对一个输出补丁顶点设置

// first code snippet
if ( gl_InvocationID == 0 ) // set tessellation level, can do only for one vertex
{
    gl_TessLevelOuter [0] = foo
    gl_TessLevelOuter [1] = bar;
}

而不仅仅是

// second code snippet
gl_TessLevelOuter [0] = foo;
gl_TessLevelOuter [1] = bar;

在有条件检查和无条件检查的情况下它的工作方式类似,但我在OpenGL wiki上找不到任何关于此类用法的内容。

如果要逻辑思考,只在一个TCS调用中设置这些变量应该可以,并且根据gl_InvocationID将它们设置为不同的值会很奇怪。所以我的问题是:

  1. 这种设置gl_TessLevel*的方式是否正确,是否可能导致某些平台出现错误或崩溃?
  2. 如果它是正确的,是否应该一直使用?这是惯用的吗?
  3. 最后,两个片段如何影响性能?由于分支,可能是第一个片段放缓的表现?可能第二个片段导致后续流水线阶段的冗余和/或空闲调用,也会降低性能?

1 个答案:

答案 0 :(得分:3)

你在这里看到的是着色器的作者试图建立一个类似于激发其他原始类型使用的顶点的约定。

  

OpenGL Shading Language 4.50 - 2.2曲面细分控制处理器 - p。 7

     
    

Tessellation控件着色器调用主要独立运行, 未定义相对执行顺序。     但是,内置函数barrier()可用于通过同步调用来控制执行顺序,从而有效地将细分控制着色器执行划分为一组阶段。

         

如果一次调用在同一阶段中的任何时刻读取由另一个调用写入的每顶点或每个补丁属性,则曲面细分控制着色器将获得未定义结果,或 if两次调用尝试写不同的     在单个阶段中,每个补丁输出的值相同。

  

鉴于着色器伪代码,foobar在所有TCS调用中是否一致,目前还不清楚。如果不是,则第二个着色器片段由于未定义的相对排序而调用未定义的行为。

任意决定第一次调用是唯一允许编写每个补丁属性的解决方案,解决了这个问题,类似于第一个顶点激发约定。最后一个顶点约定可以很容易地实现,因为所有调用都知道补丁顶点的数量。

如果你知道foobar是不变的,那么这一切都不是必需的。