GLSL的预处理器都有哪些规定?
GLSL的预处理器都有哪些规定?
下面的内容,英文版取自GLSLangSpec.4.60.pdf,中文版是我的翻译,只求意译准确易懂,不求直译严格匹配。
3.3. Preprocessor
There is a preprocessor that processes the source strings as part of the compilation process. Except as noted below, it behaves as the C++ standard preprocessor (see “Normative References”).
有一个预处理器preprocessor,它参与GLSL代码的编译过程。除下文所述外,此preprocessor与C++预处理器的规定相同。
The complete list of preprocessor directives is as follows.
preprocessor指令的完整列表如下:
#
#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif
#error
#pragma
#extension
#version
#line
Each number sign (#) can be preceded in its line only by spaces or horizontal tabs. It may also be followed by spaces and horizontal tabs, preceding the directive. Each directive is terminated by a new-line. Preprocessing does not change the number or relative location of new-lines in a source string. Preprocessing takes places after new-lines have been removed by the line-continuation character.
在一行里,指令前面允许出现的字符只有若干' '或'\t',不能有其他字符。指令后面也可以跟着若干' '或'\t'字符。每个指令都以换行符(\r\n或\n)标志其结束(也就是说,一个指令只能出现在同一行里)。预处理不改变源代码中各个行的相对位置(也就是说,预处理不会增删源代码中的换行符(\r\n或\n))。如果有行继续符(line-continuation character)(例如'\'),那么预处理器会先去掉换行符(即先将'\'前后2行合并为1行),再进行预处理。GLSL并没有规定行继续符(line-continuation character)必须是哪个字符,这由宿主环境决定。
The number sign (#) on a line by itself is ignored. Any directive not listed above will cause a compile-time error.
如果1行里只有1个'#'字符,它就会被忽略。如果GLSL源代码中出现了上述列表之外的指令,编译器就会报错。
#define and #undef functionality are defined as is standard for C++ preprocessors for macro definitions both with and without macro parameters.
#define和#undef的功能与C++预处理器完全相同。
The following operators are also available:
除了指令,还有下述操作符/运算符:
defined
##
The following predefined macros are available:
除了指令,还有下述由编译器预先定义的宏(macro):
__LINE__
__FILE__
__VERSION__
__LINE__ will substitute a decimal integer constant that is one more than the number of preceding new-lines in the current source string.
__LINE__表示其所在源代码的第几行(从1开始)。
__FILE__ will substitute a decimal integer constant that says which source string number is currently being processed.
__FILE__表示其所在源代码的序号。(我以为它是glShaderSource(GLuint shader, GLsizei count, string[] codes, GLint[] length)里所在codes中的序号,但试验证明不是,所有的__FILE__都是0)
__VERSION__ will substitute a decimal integer reflecting the version number of the OpenGL Shading Language. The version of the shading language described in this document will have __VERSION__ substitute the decimal integer 460.
__VERSION__表示GLSL版本号。本文档(GLSLangSpec.4.60.pdf)描述的GLSL的版本号为十进制整数460。
By convention, all macro names containing two consecutive underscores (__) are reserved for use by underlying software layers. Defining or undefining such a name in a shader does not itself result in an error, but may result in unintended behaviors that stem from having multiple definitions of the same name. All macro names prefixed with “GL_” (“GL” followed by a single underscore) are also reserved, and defining or undefining such a name results in a compile-time error.
按惯例,所有包含__的宏(macro)名称,都是被保留给底层软件用的。在GLSL中定义或取消定义这样的宏(macro)名称,本身不会导致error,但重复定义相同的宏(macro)名称可能导致意料之外的情况。所有以GL_开头的宏(macro)名称也是被保留的,如果在GLSL中定义或取消定义这样的宏(macro)名称,就会导致error。
Implementations must support macro-name lengths of up to 1024 characters. Implementations are allowed to generate an error for a macro name of length greater than 1024 characters, but are also allowed to support lengths greater than 1024.
实现(GLSL编译器)必须支持至少1024个字符的宏(macro)名称。实现(GLSL编译器)可以对超过1024个字符的宏(macro)名称生成error,也可以支持超过1024个字符的宏(macro)名称。
#if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate as is standard for C++ preprocessors except for the following:
除下述内容外,#if、#ifdef、#ifndef、#else、#elif、#endif与C++预处理器完全相同:
Expressions following #if and #elif are further restricted to expressions operating on literal integer constants, plus identifiers consumed by the defined operator.
#if、#elif后跟的表达式范围更小:只支持字面整数常量和用于defined操作符的标识符(identifier)。Character constants are not supported.
不支持字符常量。
The operators available are as follows.
可用的操作符如下表所示:
| Precedence 优先级 |
Operator class 类型 |
Operators 操作符 |
Associativity 关联性 |
|---|---|---|---|
| 1 (highest) | parenthetical grouping | ( ) | NA |
| 2 | unary | defined + - ~ ! | Right to Left |
| 3 | multiplicative | * / % | Left to Right |
| 4 | additive | + - | Left to Right |
| 5 | bit-wise shift | << >> | Left to Right |
| 6 | relational | < > <= >= | Left to Right |
| 7 | equality | == != | Left to Right |
| 8 | bit-wise and | & | Left to Right |
| 9 | bit-wise exclusive or | ^ | Left to Right |
| 10 | bit-wise inclusive or | | | Left to Right |
| 11 | logical and | && | Left to Right |
| 12 (lowest) | logical inclusive or | || | Left to Right |
The defined operator can be used in either of the following ways:
操作符defined可按下述两种方式使用:
defined identifier
defined ( identifier )
Two tokens in a macro can be concatenated into one token using the token pasting (##) operator, as is standard for C++ preprocessors. The result must be a valid single token, which will then be subject to macro expansion. That is, macro expansion happens only after token pasting. There are no other number sign based operators (e.g. no # or #@), nor is there a sizeof operator.
如果使用token粘接操作符##,一个宏(macro)里的两个token可以被连接成一个token,这与C++预处理器相同。粘接结果必须是一个有效的token,这就由宏(macro)的展开情况决定了。也就是说,宏(macro)的展开发生于token粘接之后。不存在其他基于#的操作符(例如,没有#,没有#@),也不存在sizeof操作符。
The semantics of applying operators to integer literals in the preprocessor match those standard in the C++ preprocessor, not those in the OpenGL Shading Language.
预处理器中对字面整数的计算结果,与C++预处理器相同,而未必与GLSL相同。
Preprocessor expressions will be evaluated according to the behavior of the host processor, not the processor targeted by the shader.
预处理器中的表达式由CPU计算,而不是由GPU计算。
#error will cause the implementation to put a compile-time diagnostic message into the shader object’s information log (see section 7.12 “Shader, Program and Program Pipeline Queries” of the OpenGL Specification for how to access a shader object’s information log). The message will be the tokens following the #error directive, up to the first new-line. The implementation must treat the presence of a #error directive as a compile-time error.
#error会向shader对象写入一条log(我猜就是用glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei[] length, string infoLog);得到的infoLog)。此log的内容就是#error "xxxxxxx"指令中的xxxxxxx。实现(GLSL编译器)必须将遇到#error指令视为发生了编译时error。
#pragma allows implementation-dependent compiler control. Tokens following #pragma are not subject to preprocessor macro expansion. If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma.
各个实现(GLSL编译器)可以用#pragma搞各自的控制。#pragma后跟的token不参与宏(macro)展开。如果某个实现(GLSL编译器)未能识别#pragma后跟的token,那么这个实现就会无视此#pragma。
The following pragmas are defined as part of the language.
GLSL内置了下列#pragma:
#pragma STDGL
The STDGL pragma is used to reserve pragmas for use by future revisions of this language. No implementation may use a pragma whose first token is STDGL.
这个#pragma STDGL被保留下来,是为了用于GLSL的未来版本。任何实现(GLSL编译器)均不得使用第一个token为STDGL的#pragma。
#pragma optimize(on)
#pragma optimize(off)
can be used to turn off optimizations as an aid in developing and debugging shaders. It can only be used outside function definitions. By default, optimization is turned on for all shaders.
这个optimize用于开关shader的优化选项。关闭优化,有助于开发和调试shader。它只能写到函数定义的外面。optimize的默认状态是对所有shader都开启(on)的。
#pragma debug(on)
#pragma debug(off)
The debug pragma can be used to enable compiling and annotating a shader with debug information, so that it can be used with a debugger. It can only be used outside function definitions. By default, debug is turned off.
这个debug用于开启调试信息。它只能写到函数定义的外面。debug的默认状态是关闭(off)的。
Shaders should declare the version of the language they are written to. The language version a shader is written to is specified by
shader应当声明它们使用的GLSL版本号,方式如下:
#version number profile_opt
where number must be a version of the language, following the same convention as __VERSION__ above. The directive “#version 460” is required in any shader that uses version 4.60 of the language. Any number representing a version of the language a compiler does not support will cause a compile-time error to be generated. Version 1.10 of the language does not require shaders to include this directive, and shaders that do not include a #version directive will be treated as targeting version 1.10. Shaders that specify #version 100 will be treated as targeting version 1.00 of the OpenGL ES Shading Language. Shaders that specify #version 300 will be treated as targeting version 3.00 of the OpenGL ES Shading Language. Shaders that specify #version 310 will be treated as targeting version 3.10 of the OpenGL ES Shading Language.
其中,number必须是GLSL的一个版本号,与__VERSION__遵循同样的规则。使用GLSL 4.60版的shader必须写上#version 460指令。如果编译器发现了不支持的GLSL版本号,就会报error。GLSL 1.10版不要求shader写此指令;没有写此指令的shader会被视为面向GLSL 1.10版。写了#version 100的shader会被视为面向openGL ES着色语言的1.00版。写了#version 300的shader会被视为面向openGL ES着色语言的3.00版。写了#version 310的shader会被视为面向openGL ES着色语言的3.10版。
If the optional profile argument is provided, it must be the name of an OpenGL profile. Currently, there are three choices:
如果要写可选的模式(profile)参数,那只能是一个openGL模式名称。目前,有3个模式可选:
core
compatibility
es
A profile argument can only be used with version 150 or greater. If no profile argument is provided and the version is 150 or greater, the default is core. If version 300 or 310 is specified, the profile argument is not optional and must be es, or a compile-time error results. The Language Specification for the es profile is specified in The OpenGL ES Shading Language specification.
模式(profile)参数只能用在150或更高版本。如果没有写模式(profile)参数且版本是150或更高,那就是默认使用core模式。如果指定版本为300或310,那么模式(profile)参数就不能省略,且必须是es,否则就会报编译时error。es模式的语言说明书(Specification)详见OpenGL ES Shading Language specification。
Shaders for the core or compatibility profiles that declare different versions can be linked together. However, es profile shaders cannot be linked with non-es profile shaders or with es profile shaders of a different version, or a link-time error will result. When linking shaders of versions allowed by these rules, remaining link-time errors will be given as per the linking rules in the GLSL version corresponding to the version of the context the shaders are linked under. Shader compile-time errors must still be given strictly based on the version declared (or defaulted to) within each shader.
声明不同版本的core或compatibility模式的shader,可以被链接(link)起来。但是,es模式的shader不能与非es模式的shader链接(link),也不能与不同版本的es模式的shader链接(link),否则就会报链接时error。当根据上述规则链接(link)符合版本要求的shader时,其他的链接时error将依据(shader所处上下文版本对应的GLSL版本的链接规则)进行处理。而shader的编译时error仍须严格按照每个shader内部声明的(或默认的)版本进行判定。
Unless otherwise specified, this specification is documenting the core profile, and everything specified for the core profile is also available in the compatibility profile. Features specified as belonging specifically to the compatibility profile are not available in the core profile. Compatibility-profile features are not available when generating SPIR-V.
若无其他声明,那么本文就是在介绍core模式下的情况,core模式下的情况,在compatibility模式下也适用。但只适用于在compatibility模式下的情况,在core模式下就不适用了。如果要生成SPIR-V,那么compatibility模式的特性就不可用了。
There is a built-in macro definition for each profile the implementation supports. All implementations provide the following macro:
每个模式都有一个内置的宏(macro)定义。所有的实现(GLSL编译器)都提供下述宏(macro):
#define GL_core_profile 1
Implementations providing the compatibility profile provide the following macro:
支持compatibility模式的实现(GLSL编译器),提供下述宏(macro):
#define GL_compatibility_profile 1
Implementations providing the es profile provide the following macro:
支持es模式的实现(GLSL编译器),提供下述宏(macro):
#define GL_es_profile 1
The #version directive must occur in a shader before anything else, except for comments and white space.
在一个shader里,在#version指令之前不能出现任何内容,除了注释和空白符(' '、'\t')。
By default, compilers of this language must issue compile-time syntactic, semantic, and grammatical errors for shaders that do not conform to this specification. Any extended behavior must first be enabled. Directives to control the behavior of the compiler with respect to extensions are declared with the #extension directive
默认情况下,GLSL编译器必须对shader中不符合本说明书的情况报编译时的语法/语义/文法error。任何扩展行为必须先被启用(enable)才能用。#extension指令的作用就是,控制编译器在扩展(extension)方面的行为。
#extension extension_name : behavior
#extension all : behavior
where extension_name is the name of an extension. Extension names are not documented in this specification. The token all means the behavior applies to all extensions supported by the compiler.
其中,extension_name是扩展的名字,本说明书不介绍扩展的名字的详情。all这个token的意思是,指定的行为(behavior)要作用于编译器支持的全部扩展。
The behavior can be one of the following:
可选的行为(behavior)如下表所示:
| Behavior 行为 |
Effect 效果 |
|---|---|
| require | Behave as specified by the extension extension_name. Give a compile-time error on the #extension if the extension extension_name is not supported, or if all is specified. 按照 extension_name的规定执行。如果 extension_name不被支持,或指定了all,则对#extension报error。 |
| enable | Behave as specified by the extension extension_name. Warn on the #extension if the extension extension_name is not supported. Give a compile-time error on the #extension if all is specified. 按照 extension_name的规定执行。如果 extension_name不被支持,则对#extension报warn。如果指定了 all,则对#extension报error。 |
| warn | Behave as specified by the extension extension_name, except issue warnings on any detectable use of that extension, unless such use is supported by other enabled or required extensions. If all is specified, then warn on all detectable uses of any extension used. Warn on the #extension if the extension extension_name is not supported. 按照 extension_name的规定执行,但对该扩展的使用报warn——除非这个使用被其他enable/require的扩展支持。如果指定了 all,则对所有扩展的使用报warn。如果 extension_name不被支持,则对#extension本身报warn。 |
| disable | Behave (including issuing errors and warnings) as if the extension extension_name is not part of the language definition. If all is specified, then behavior must revert back to that of the non-extended core version of the language being compiled to. Warn on the #extension if the extension extension_name is not supported. 视同 extension_name不存在。如果指定了 all,则视同使用不存在任何扩展的core版本。如果 extension_name不被支持,则对#extension本身报warn。 |
The extension directive is a simple, low-level mechanism to set the behavior for each extension. It does not define policies such as which combinations are appropriate, those must be defined elsewhere. Order of directives matters in setting the behavior for each extension: Directives that occur later override those seen earlier. The all variant sets the behavior for all extensions, overriding all previously issued extension directives, but only for the behaviors warn and disable.
#extension指令用于设置每个extension的行为,是一个简单且底层的机制。它不定义“哪个组合是恰当的”等策略(这得在其他地方定义)。各个#extension指令的先后顺序是有意义的:后出现的#extension会覆盖先出现的#extension。#extension all : warn和#extension all : disable会为所有扩展设置行为,覆盖所有先前的#extension指令。
The initial state of the compiler is as if the directive
编译器的初始状态就如同写了如下指令:
#extension all : disable
was issued, telling the compiler that all error and warning reporting must be done according to this specification, ignoring any extensions.
即,告诉编译器,要求所有错误和警告的报告必须遵循此说明书,并忽略所有扩展功能。
Each extension can define its allowed granularity of scope. If nothing is said, the granularity is a shader (that is, a single compilation unit), and the extension directives must occur before any nonpreprocessor tokens. If necessary, the linker can enforce granularities larger than a single compilation unit, in which case each involved shader will have to contain the necessary extension directive.
每个extension可以定义其允许的作用域粒度。如果什么都没说,粒度就是单个shader(即单个编译单元),且extension指令必须出现在所有非预处理器tokens之前。必要时,链接器可强制采用比单编译单元更大的粒度,此时每个相关的shader均须包含必要的extension指令。
Macro expansion is not done on lines containing #extension and #version directives.
在包含#extension或#version指令的代码行上,不会执行宏(macro)展开。
#line must have, after macro substitution, one of the following forms:
#line指令,在宏(macro)替换后,必须符合下列形式之一:
#line line
#line line source-string-number
where line and source-string-number are constant integer expressions. If these constant expressions are not integer literals then behavior is undefined. After processing this directive (including its new-line), the implementation will behave as if it is compiling at line number line and source string number source-string-number. Subsequent source strings will be numbered sequentially, until another #line directive overrides that numbering.
其中,line和source-string-number是整型常量表达式,否则其行为就是未定义的,后果是不可测的。处理了这一指令(及换行符\r\n)后,实现(GLSL编译器)将视自己在第line行和第source-string-number个源代码字符串上。后序源代码字符串将被依次编号,直到被下一个#line指令覆盖之。
Note
注意
Some implementations have allowed constant expressions in #line directives and some have not. Even where expressions are supported the grammar is ambiguous and so results are implementation dependent. For example, + #line +2 +2 // Line number set to 4, or file to 2 and line to 2
某些实现(GLSL编译器)允许在#line指令中使用常量表达式,而另一些则不允许。即使支持表达式,由于语法规则存在歧义,最终结果仍可能因实现而异。例如:#line +2 +2 // 可能被解析为行号设为4,或文件编号为2且行号为2
When shaders are compiled for OpenGL SPIR-V, the following predefined macro is available:
当shader为 OpenGL SPIR-V 编译时,以下预定义的宏(macro)可用:
#define GL_SPIRV 100
When targeting Vulkan, the following predefined macro is available:
当目标平台为 Vulkan 时,以下预定义的宏(macro)可用:
#define VULKAN 100
End
GLSL的预处理器都有哪些规定?的更多相关文章
- GLSL扩展预处理器(支持#include)
http://www.gamedev.net/topic/645610-do-you-extend-glsl/ https://github.com/ehsan/ogre/blob/master/Re ...
- 160907、CSS 预处理器-Less
CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题: 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器: ...
- CSS 即将支持嵌套,SASS/LESS 等预处理器已无用武之地?
最近,有一则非常振奋人心的消息,CSS 即将原生支持嵌套 -- Agenda+ to publish FPWD of Nesting,表示 CSS 嵌套规范即将进入规范的 FWPD 阶段. 目前对应的 ...
- 前端CSS预处理器Sass
前面的话 "CSS预处理器"(css preprocessor)的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件.SASS是一种CSS的开发工 ...
- css预处理器sass使用教程(多图预警)
css预处理器赋予了css动态语言的特性,如变量.函数.运算.继承.嵌套等,有助于更好地组织管理样式文件,以及更高效地开发项目.css预处理器可以更方便的维护和管理css代码,让整个网页变得更加灵活可 ...
- 关于前端CSS预处理器Sass的小知识!
前面的话 "CSS预处理器"(css preprocessor)的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件.SASS是一种CSS的开发工 ...
- CSS预处理器Sass、LESS 和 Stylus
CSS 预处理器技术已经非常的成熟,而且也涌现出了越来越多的 CSS 的预处理器框架.本文向你介绍使用最为普遍的三款 CSS 预处理器框架,分别是 Sass.Less CSS.Stylus. 首先我们 ...
- C#预处理器指令 ,你造吗??? (●'◡'●)
什么是c#预处理指令?? 用于在 C# 源代码中嵌入的编译器命令. C#预处理器指令有哪些?? ↓↓↓这些就是预处理器指令啦 下面我们一一道来(●'◡'●) 1.#if ,#elif,#else,en ...
- Koala – 开源的前端预处理器语言图形编译工具
koala 是一个前端预处理器语言图形编译工具,支持 Less.Sass.Compass.CoffeeScript,帮助 Web 开发者更高效地使用它们进行开发.跨平台运行,完美兼容 Windows. ...
- 为您详细比较三个 CSS 预处理器(框架):Sass、LESS 和 Stylus
CSS 预处理器技术已经非常的成熟,而且也涌现出了越来越多的 CSS 的预处理器框架.本文向你介绍使用最为普遍的三款 CSS 预处理器框架,分别是 Sass.Less CSS.Stylus. 首先我们 ...
随机推荐
- 让 LLM 来评判 | 设计你自己的评估 prompt
设计你自己的评估 prompt 这是 让 LLM 来评判 系列文章的第三篇,敬请关注系列文章: 基础概念 选择 LLM 评估模型 设计你自己的评估 prompt 评估你的评估结果 奖励模型相关内容 技 ...
- Vulnhub-Troll-1靶机-ftp匿名登录+流量包分析+hydra爆破+ssh登录脚本提权
一.靶机搭建 选择扫描虚拟机 选择路径即可 二.信息收集 扫ip 靶机ip:192.168.108.144 扫开放端口 开放了ftp服务 扫版本服务信息 信息如下 21/tcp open ftp vs ...
- Go1.24版本终于来了!各位开发者,准备好迎接这些激动人心的新功能了吗?让我们一起来探讨下Go1.24中有哪些精彩的亮点?
前言 Gopher们,Go 1.24.0 正式发布了!与 Go 1.23.0 相比,这个版本带来了众多改进.让我们一同看看 Go 1.24.0 都有哪些新变化吧! 在 Windows 下,请在 htt ...
- 在Linux系统中下载`gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu`工具链
要在Linux系统中下载gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu工具链,你可以按照以下步骤进行操作: 点击查看代码 1. **打开终端**:你 ...
- QTableView实现在表格内直接对数据库内容进行修改、新增和删除等操作
文章目录 前言 QSqlTableModel 新增 删除 修改 提交 取消 前言 本文主要利用QSqlTableModel+QTableView来实现直接在QTableView中进行对数据库数据的操作 ...
- stat() "/root/xxx/index.html" failed (13: Permission denied)
前言 在 nginx 上部署静态网页报502,于是查看 nginx 错误日志 error_log /var/log/nginx/error.log;,却没有看到任何错误信息:访问 nginx活动日志 ...
- go实现协程池管理
使用channel实现协程池 通过 Channel 实现 Goroutine Pool,缺点是会造成协程的频繁开辟和注销,但好在简单灵活通用. package main import ( " ...
- 我最常用的 Visual Studio 2022 扩展插件推荐:生产力必备工具
Visual Studio 2022作为微软推出的一款功能强大的IDE,业界称之为"宇宙第一IDE".它以出色的性能.丰富的内置功能和对多种编程语言的支持,深受开发者喜爱.然而,随 ...
- Linux+Typora+Picgo图床配置
Linux+Typora+Picgo图床配置 首先不建议安装在UbuntuStore里的版本,会有一些限制. 首先安装node.js 去官网下载编译好的源码,配置软连接,使全局都可以使用node命令. ...
- 【虚拟机】VirualBox安装macOS系统
[虚拟机]VirualBox安装macOS系统 零.创建虚拟机 类型选择 Mac OS X 版本选择 macOS 10.13 High Sierra (64-bit) 注意:这边我设置的名称为 Mac ...