细分控制着色器执行模式与大多数其他着色器阶段不同;它与计算着色器最相似。与几何着色器每个调用都可以输出多个图元不同,每个细分控制着色器调用只负责生成输出面片中的单个顶点。
对于渲染期间提供的每个面片,将执行n次细分控制着色器调用,其中n是输出面片中的顶点数。因此,如果一个绘制命令绘制了20个面片,并且每个输出有4个顶点,那么总共将有80个单独的细分控制着色器调用。
为同一面片提供数据的不同调用是相互连接的。这些调用都共享它们的输出值。它们可以读取同一面片的其他调用写入的输出值。但是为了做到这一点,他们必须使用同步机制(barrier)来确保细分控制着色器的所有其他调用至少已经执行了写入。
因此,细分控制着色器不同调用可以共享数据并彼此通信。
输出面片的顶点数量可以通过布局限定符(layout)来设置,也即设置了控制着色器执行的次数:
layout(vertices = patch_size) out;
patch_size 的大小不是必须与输入面片顶点的大小(glPatchParameteri(GL_PATCH_VERTICES, n))匹配。
细分控制着色器的输出变量直接传递到细分计算着色器,而不需要任何形式的插值(这是细分计算着色器的主要工作)。这些可以是逐顶点输出或逐面片输出。
下面来测试下执行的次数:
// 创建原子计数器缓存
glGenBuffers(1, &atomic_counter_buffer);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomic_counter_buffer);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_READ);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_counter_buffer);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_counter_buffer);
GLuint* data = (GLuint *)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY);
data[0] = 0;
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
//设置输入面片的顶点数
glPatchParameteri(GL_PATCH_VERTICES, 3);
//绘制六个顶点
glDrawArrays(GL_PATCHES, 0