着色概述
OpenGL 着色语言实际上是几种密切相关的语言。这些语言用于为 API 处理管道中包含的每个可编程处理器创建着色器。目前,这些处理器是顶点、细分控制、细分评估、几何、片段和计算处理器。
除非本文另有说明,否则语言特性适用于所有语言,并且通常用法会将这些语言称为单一语言。特定语言将以它们所针对的处理器的名称来指代:顶点、细分控制、细分评估、几何、片段或计算。
大多数 API 状态不会被跟踪或提供给着色器。通常,用户定义的变量将用于在 API 管道的不同阶段之间进行通信。但是,仍然会跟踪少量状态并自动提供给着色器,并且有一些内置变量用于 API 管道的不同阶段之间的接口。
顶点处理器
顶点处理器是一个可编程单元,它对传入的顶点及其关联数据进行操作。用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为顶点着色器。当一组顶点着色器成功编译和链接时,它们会生成一个在顶点处理器上运行的顶点着色器可执行文件。
顶点处理器一次操作一个顶点。它不会取代需要同时了解多个顶点的图形操作。
细分控制处理器
细分控制处理器是一个可编程单元,它对传入的顶点补丁及其关联数据进行操作,并发出一个新的输出补丁。用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为细分控制着色器。当一组细分控制着色器成功编译和链接时,它们会生成一个在细分控制处理器上运行的细分控制着色器可执行文件。
细分控制着色器为输出补丁的每个顶点调用。每次调用都可以读取输入或输出补丁中任何顶点的属性,但只能为相应的输出补丁顶点写入每个顶点的属性。着色器调用共同为输出补丁生成一组每个补丁的属性。
在所有细分控制着色器调用完成后,输出顶点和每个补丁的属性被组装成一个补丁,供后续管道阶段使用。
细分控制着色器调用主要独立运行,具有未定义的相对执行顺序。但是,内置函数 barrier() 可用于通过同步调用来控制执行顺序,有效地将细分控制着色器执行划分为一组阶段。如果一个调用在同一阶段的任何时间点从另一个调用写入的每个顶点或每个补丁属性中读取,或者如果两个调用尝试在单个阶段将不同的值写入同一每个补丁输出的 32 位组件,则细分控制着色器将获得未定义的结果。
细分评估处理器
细分评估处理器是一个可编程单元,它使用传入的顶点补丁及其关联数据,评估细分图元生成器生成的顶点的位置和其他属性。用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为细分评估着色器。当一组细分评估着色器成功编译和链接时,它们会生成一个在细分评估处理器上运行的细分评估着色器可执行文件。
每次调用细分评估可执行文件都会计算细分图元生成器生成的单个顶点的位置和属性。可执行文件可以读取输入补丁中任何顶点的属性,以及细分坐标,它是被细分的图元中顶点的相对位置。可执行文件写入顶点的位置和其他属性。
几何处理器
几何处理器是一个可编程单元,它对顶点处理后组装的图元的传入顶点数据进行操作,并输出形成输出图元的顶点序列。用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为几何着色器。当一组几何着色器成功编译和链接时,它们会生成一个在几何处理器上运行的几何着色器可执行文件。
在几何处理器上对几何着色器可执行文件的单个调用将对具有固定数量顶点的已声明的输入图元进行操作。此单个调用可以发出可变数量的顶点,这些顶点被组装成已声明的输出图元类型的图元,并传递到后续的管道阶段。
片段处理器
片段处理器是一个可编程单元,它对片段值及其关联数据进行操作。用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为片段着色器。当一组片段着色器成功编译和链接时,它们会生成一个在片段处理器上运行的片段着色器可执行文件。
片元着色器不能改变片元的 (x, y) 位置。不允许访问相邻片元。片元着色器计算出的值最终用于更新帧缓冲内存或纹理内存,具体取决于当前的 API 状态和导致生成片元的 API 命令。
计算处理器
计算处理器是一个可编程单元,独立于其他着色器处理器运行。使用 OpenGL 着色语言编写的、在此处理器上运行的编译单元称为计算着色器。当一组计算着色器成功编译和链接后,它们会生成一个在计算处理器上运行的计算着色器可执行程序。
计算着色器可以访问许多与片元着色器和其他着色器处理器相同的资源,例如纹理、缓冲区、图像变量和原子计数器。它没有固定功能的输出。它不是图形管道的一部分,其可见的副作用是通过更改图像、存储缓冲区和原子计数器来实现的。
计算着色器在一个称为工作组的工作项组上操作。工作组是执行相同代码(可能并行执行)的着色器调用集合。工作组内的调用可以通过共享变量与其他工作组成员共享数据,并发出内存和控制流屏障以与同一工作组的其他成员同步。