Skip to content

Commit f651079

Browse files
authored
Add support for handling WebGL built-in preprocessor variables when custom preprocessor is in use (emscripten-core#19226)
* Add support for handling WebGL built-in preprocessor variables GL_ES and __VERSION__, and add a note of __FILE__ and __LINE__ not being handled (since there is no apparent benefit/uses of these, and adding them would just increase code size). Add a unit test for these variables. * Address review
1 parent 9757ac1 commit f651079

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

src/library_webgl.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3038,9 +3038,19 @@ var LibraryGL = {
30383038
#if GL_DEBUG
30393039
dbg('Input shader source: ' + source);
30403040
#endif
3041+
3042+
#if ASSERTIONS
3043+
// These are not expected to be meaningful in WebGL, but issue a warning if they are present, to give some diagnostics about if they are present.
3044+
if (source.includes('__FILE__')) warnOnce(`When compiling shader: ${source}: Preprocessor variable __FILE__ is not handled by -sGL_EXPLICIT_UNIFORM_LOCATION/-sGL_EXPLICIT_UNIFORM_BINDING options!`);
3045+
if (source.includes('__LINE__')) warnOnce(`When compiling shader: ${source}: Preprocessor variable __LINE__ is not handled by -sGL_EXPLICIT_UNIFORM_LOCATION/-sGL_EXPLICIT_UNIFORM_BINDING options!`);
3046+
#endif
30413047
// Remove comments and C-preprocess the input shader first, so that we can appropriately
30423048
// parse the layout location directives.
3043-
source = preprocess_c_code(remove_cpp_comments_in_shaders(source), { 'GL_FRAGMENT_PRECISION_HIGH': function() { return 1; }});
3049+
source = preprocess_c_code(remove_cpp_comments_in_shaders(source), {
3050+
'GL_FRAGMENT_PRECISION_HIGH': () => 1,
3051+
'GL_ES': () => 1,
3052+
'__VERSION__': () => source.includes('#version 300') ? 300 : 100
3053+
});
30443054
#if GL_DEBUG
30453055
dbg('Shader source after preprocessing: ' + source);
30463056
#endif

test/test_browser.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,6 +2724,16 @@ def test_html5_webgl_api(self):
27242724
continue
27252725
self.btest_exit(test_file('html5_webgl.c'), args=['-sMAX_WEBGL_VERSION=2', '-lGL'] + mode)
27262726

2727+
@parameterized({
2728+
'webgl1': (['-DWEBGL_VERSION=1'],),
2729+
'webgl2': (['-sMAX_WEBGL_VERSION=2', '-DWEBGL_VERSION=2'],),
2730+
'webgl1_extensions': (['-DWEBGL_VERSION=1', '-sGL_EXPLICIT_UNIFORM_LOCATION'],),
2731+
'webgl2_extensions': (['-sMAX_WEBGL_VERSION=2', '-DWEBGL_VERSION=2', '-sGL_EXPLICIT_UNIFORM_LOCATION', '-sGL_EXPLICIT_UNIFORM_BINDING'],),
2732+
})
2733+
@requires_graphics_hardware
2734+
def test_webgl_preprocessor_variables(self, opts):
2735+
self.btest_exit(test_file('webgl_preprocessor_variables.c'), args=['-lGL'] + opts)
2736+
27272737
@requires_graphics_hardware
27282738
def test_webgl2_ubos(self):
27292739
self.btest_exit(test_file('webgl2_ubos.cpp'), args=['-sMAX_WEBGL_VERSION=2', '-lGL'])
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include <emscripten/html5_webgl.h>
2+
#include <emscripten/html5.h>
3+
#include <webgl/webgl2.h>
4+
#include <stdlib.h>
5+
#include <assert.h>
6+
#include <stdio.h>
7+
#include <string.h>
8+
9+
void test(const char *src)
10+
{
11+
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
12+
glShaderSource(shader, 1, &src, NULL);
13+
glCompileShader(shader);
14+
printf("%s\n", emscripten_webgl_get_shader_info_log_utf8(shader));
15+
assert(emscripten_webgl_get_shader_parameter_d(shader, GL_COMPILE_STATUS) == 1);
16+
}
17+
18+
int main()
19+
{
20+
EmscriptenWebGLContextAttributes attrs;
21+
emscripten_webgl_init_context_attributes(&attrs);
22+
attrs.majorVersion = WEBGL_VERSION;
23+
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context("#canvas", &attrs);
24+
emscripten_webgl_make_context_current(context);
25+
26+
// Test the presence of GL_FRAGMENT_PRECISION_HIGH built-in preprocessor
27+
test("#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
28+
"void main() {}\n"
29+
"#endif");
30+
test("#if GL_FRAGMENT_PRECISION_HIGH == 1\n"
31+
"void main() {}\n"
32+
"#endif");
33+
34+
// Test GL_ES built-in preprocessor directive
35+
test("#ifdef GL_ES\n"
36+
"void main() {}\n"
37+
"#endif");
38+
test("#if GL_ES == 1\n"
39+
"void main() {}\n"
40+
"#endif");
41+
test("#if GL_ES != 1\n" // Also check negation, i.e. that #if is not tautologically true
42+
"error!\n"
43+
"#else\n"
44+
"void main() {}\n"
45+
"#endif");
46+
47+
// Test __VERSION__ built-in preprocessor directive.
48+
// Note that when WebGL 2 contexts are created, shaders
49+
// still default to #version 100, unless explicit
50+
// "#version 300 es" is specified.
51+
test("#ifdef __VERSION__\n"
52+
"void main() {}\n"
53+
"#endif");
54+
test("#if __VERSION__ == 100\n"
55+
"void main() {}\n"
56+
"#endif");
57+
test("#if defined(GL_ES) && __VERSION__ < 300\n"
58+
"void main() {}\n"
59+
"#endif");
60+
test("#if !defined(GL_ES) || __VERSION__ >= 300\n" // for good measure, check via negation
61+
"error!\n"
62+
"#else\n"
63+
"void main() {}\n"
64+
"#endif");
65+
66+
#if WEBGL_VERSION >= 2
67+
test("#version 100\n"
68+
"#if __VERSION__ == 300\n"
69+
"error!\n"
70+
"#endif\n"
71+
"void main() {}");
72+
test("#version 300 es\n"
73+
"#if __VERSION__ == 300\n"
74+
"void main() {}\n"
75+
"#endif");
76+
#endif
77+
78+
return 0;
79+
}

0 commit comments

Comments
 (0)