1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "util/shader_utils.h"
8
9 #include <cstring>
10 #include <fstream>
11 #include <iostream>
12 #include <vector>
13
14 #include "common/utilities.h"
15 #include "util/test_utils.h"
16
17 namespace
18 {
CompileProgramInternal(const char * vsSource,const char * tcsSource,const char * tesSource,const char * gsSource,const char * fsSource,const std::function<void (GLuint)> & preLinkCallback)19 GLuint CompileProgramInternal(const char *vsSource,
20 const char *tcsSource,
21 const char *tesSource,
22 const char *gsSource,
23 const char *fsSource,
24 const std::function<void(GLuint)> &preLinkCallback)
25 {
26 GLuint program = glCreateProgram();
27
28 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
29 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
30
31 if (vs == 0 || fs == 0)
32 {
33 glDeleteShader(fs);
34 glDeleteShader(vs);
35 glDeleteProgram(program);
36 return 0;
37 }
38
39 glAttachShader(program, vs);
40 glDeleteShader(vs);
41
42 glAttachShader(program, fs);
43 glDeleteShader(fs);
44
45 GLuint tcs = 0;
46 GLuint tes = 0;
47 GLuint gs = 0;
48
49 if (strlen(tcsSource) > 0)
50 {
51 tcs = CompileShader(GL_TESS_CONTROL_SHADER_EXT, tcsSource);
52 if (tcs == 0)
53 {
54 glDeleteShader(vs);
55 glDeleteShader(fs);
56 glDeleteProgram(program);
57 return 0;
58 }
59
60 glAttachShader(program, tcs);
61 glDeleteShader(tcs);
62 }
63
64 if (strlen(tesSource) > 0)
65 {
66 tes = CompileShader(GL_TESS_EVALUATION_SHADER_EXT, tesSource);
67 if (tes == 0)
68 {
69 glDeleteShader(vs);
70 glDeleteShader(fs);
71 glDeleteShader(tcs);
72 glDeleteProgram(program);
73 return 0;
74 }
75
76 glAttachShader(program, tes);
77 glDeleteShader(tes);
78 }
79
80 if (strlen(gsSource) > 0)
81 {
82 gs = CompileShader(GL_GEOMETRY_SHADER_EXT, gsSource);
83 if (gs == 0)
84 {
85 glDeleteShader(vs);
86 glDeleteShader(fs);
87 glDeleteShader(tcs);
88 glDeleteShader(tes);
89 glDeleteProgram(program);
90 return 0;
91 }
92
93 glAttachShader(program, gs);
94 glDeleteShader(gs);
95 }
96
97 if (preLinkCallback)
98 {
99 preLinkCallback(program);
100 }
101
102 glLinkProgram(program);
103
104 return CheckLinkStatusAndReturnProgram(program, true);
105 }
106
107 const void *gCallbackChainUserParam;
108
DebugMessageCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)109 void KHRONOS_APIENTRY DebugMessageCallback(GLenum source,
110 GLenum type,
111 GLuint id,
112 GLenum severity,
113 GLsizei length,
114 const GLchar *message,
115 const void *userParam)
116 {
117 std::string sourceText = gl::GetDebugMessageSourceString(source);
118 std::string typeText = gl::GetDebugMessageTypeString(type);
119 std::string severityText = gl::GetDebugMessageSeverityString(severity);
120 std::cerr << sourceText << ", " << typeText << ", " << severityText << ": " << message << "\n";
121
122 GLDEBUGPROC callbackChain = reinterpret_cast<GLDEBUGPROC>(const_cast<void *>(userParam));
123 if (callbackChain)
124 {
125 callbackChain(source, type, id, severity, length, message, gCallbackChainUserParam);
126 }
127 }
128
GetPerfCounterValue(const CounterNameToIndexMap & counterIndexMap,std::vector<angle::PerfMonitorTriplet> & triplets,const char * name,GLuint64 * counterOut)129 void GetPerfCounterValue(const CounterNameToIndexMap &counterIndexMap,
130 std::vector<angle::PerfMonitorTriplet> &triplets,
131 const char *name,
132 GLuint64 *counterOut)
133 {
134 auto iter = counterIndexMap.find(name);
135 ASSERT(iter != counterIndexMap.end());
136 GLuint counterIndex = iter->second;
137
138 for (const angle::PerfMonitorTriplet &triplet : triplets)
139 {
140 ASSERT(triplet.group == 0);
141 if (triplet.counter == counterIndex)
142 {
143 *counterOut = triplet.value;
144 return;
145 }
146 }
147
148 UNREACHABLE();
149 }
150 } // namespace
151
CompileShader(GLenum type,const char * source)152 GLuint CompileShader(GLenum type, const char *source)
153 {
154 GLuint shader = glCreateShader(type);
155
156 const char *sourceArray[1] = {source};
157 glShaderSource(shader, 1, sourceArray, nullptr);
158 glCompileShader(shader);
159
160 GLint compileResult;
161 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
162
163 if (compileResult == 0)
164 {
165 GLint infoLogLength;
166 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
167
168 // Info log length includes the null terminator, so 1 means that the info log is an empty
169 // string.
170 if (infoLogLength > 1)
171 {
172 std::vector<GLchar> infoLog(infoLogLength);
173 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
174 std::cerr << "shader compilation failed: " << &infoLog[0];
175 }
176 else
177 {
178 std::cerr << "shader compilation failed. <Empty log message>";
179 }
180
181 std::cerr << std::endl;
182
183 glDeleteShader(shader);
184 shader = 0;
185 }
186
187 return shader;
188 }
189
CompileShaderFromFile(GLenum type,const std::string & sourcePath)190 GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
191 {
192 std::string source;
193 if (!angle::ReadEntireFileToString(sourcePath.c_str(), &source))
194 {
195 std::cerr << "Error reading shader file: " << sourcePath << "\n";
196 return 0;
197 }
198
199 return CompileShader(type, source.c_str());
200 }
201
CheckLinkStatusAndReturnProgram(GLuint program,bool outputErrorMessages)202 GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
203 {
204 if (glGetError() != GL_NO_ERROR)
205 return 0;
206
207 GLint linkStatus;
208 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
209 if (linkStatus == 0)
210 {
211 if (outputErrorMessages)
212 {
213 GLint infoLogLength;
214 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
215
216 // Info log length includes the null terminator, so 1 means that the info log is an
217 // empty string.
218 if (infoLogLength > 1)
219 {
220 std::vector<GLchar> infoLog(infoLogLength);
221 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
222 &infoLog[0]);
223
224 std::cerr << "program link failed: " << &infoLog[0];
225 }
226 else
227 {
228 std::cerr << "program link failed. <Empty log message>";
229 }
230 }
231
232 glDeleteProgram(program);
233 return 0;
234 }
235
236 return program;
237 }
238
GetProgramShader(GLuint program,GLint requestedType)239 GLuint GetProgramShader(GLuint program, GLint requestedType)
240 {
241 static constexpr GLsizei kMaxShaderCount = 16;
242 GLuint attachedShaders[kMaxShaderCount] = {0u};
243 GLsizei count = 0;
244 glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders);
245 for (int i = 0; i < count; ++i)
246 {
247 GLint type = 0;
248 glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type);
249 if (type == requestedType)
250 {
251 return attachedShaders[i];
252 }
253 }
254
255 return 0;
256 }
257
CompileProgramWithTransformFeedback(const char * vsSource,const char * fsSource,const std::vector<std::string> & transformFeedbackVaryings,GLenum bufferMode)258 GLuint CompileProgramWithTransformFeedback(
259 const char *vsSource,
260 const char *fsSource,
261 const std::vector<std::string> &transformFeedbackVaryings,
262 GLenum bufferMode)
263 {
264 auto preLink = [&](GLuint program) {
265 if (transformFeedbackVaryings.size() > 0)
266 {
267 std::vector<const char *> constCharTFVaryings;
268
269 for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
270 {
271 constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
272 }
273
274 glTransformFeedbackVaryings(program,
275 static_cast<GLsizei>(transformFeedbackVaryings.size()),
276 &constCharTFVaryings[0], bufferMode);
277 }
278 };
279
280 return CompileProgramInternal(vsSource, "", "", "", fsSource, preLink);
281 }
282
CompileProgram(const char * vsSource,const char * fsSource)283 GLuint CompileProgram(const char *vsSource, const char *fsSource)
284 {
285 return CompileProgramInternal(vsSource, "", "", "", fsSource, nullptr);
286 }
287
CompileProgram(const char * vsSource,const char * fsSource,const std::function<void (GLuint)> & preLinkCallback)288 GLuint CompileProgram(const char *vsSource,
289 const char *fsSource,
290 const std::function<void(GLuint)> &preLinkCallback)
291 {
292 return CompileProgramInternal(vsSource, "", "", "", fsSource, preLinkCallback);
293 }
294
CompileProgramWithGS(const char * vsSource,const char * gsSource,const char * fsSource)295 GLuint CompileProgramWithGS(const char *vsSource, const char *gsSource, const char *fsSource)
296 {
297 return CompileProgramInternal(vsSource, "", "", gsSource, fsSource, nullptr);
298 }
299
CompileProgramWithTESS(const char * vsSource,const char * tcsSource,const char * tesSource,const char * fsSource)300 GLuint CompileProgramWithTESS(const char *vsSource,
301 const char *tcsSource,
302 const char *tesSource,
303 const char *fsSource)
304 {
305 return CompileProgramInternal(vsSource, tcsSource, tesSource, "", fsSource, nullptr);
306 }
307
CompileProgramFromFiles(const std::string & vsPath,const std::string & fsPath)308 GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
309 {
310 std::string vsSource;
311 if (!angle::ReadEntireFileToString(vsPath.c_str(), &vsSource))
312 {
313 std::cerr << "Error reading shader: " << vsPath << "\n";
314 return 0;
315 }
316
317 std::string fsSource;
318 if (!angle::ReadEntireFileToString(fsPath.c_str(), &fsSource))
319 {
320 std::cerr << "Error reading shader: " << fsPath << "\n";
321 return 0;
322 }
323
324 return CompileProgram(vsSource.c_str(), fsSource.c_str());
325 }
326
CompileComputeProgram(const char * csSource,bool outputErrorMessages)327 GLuint CompileComputeProgram(const char *csSource, bool outputErrorMessages)
328 {
329 GLuint program = glCreateProgram();
330
331 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
332 if (cs == 0)
333 {
334 glDeleteProgram(program);
335 return 0;
336 }
337
338 glAttachShader(program, cs);
339
340 glLinkProgram(program);
341
342 return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
343 }
344
LoadBinaryProgramOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)345 GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
346 {
347 GLuint program = glCreateProgram();
348 glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
349 return CheckLinkStatusAndReturnProgram(program, true);
350 }
351
LoadBinaryProgramES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)352 GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
353 {
354 GLuint program = glCreateProgram();
355 glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
356 return CheckLinkStatusAndReturnProgram(program, true);
357 }
358
LinkAttachedProgram(GLuint program)359 bool LinkAttachedProgram(GLuint program)
360 {
361 glLinkProgram(program);
362 return (CheckLinkStatusAndReturnProgram(program, true) != 0);
363 }
364
EnableDebugCallback(GLDEBUGPROC callbackChain,const void * userParam)365 void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam)
366 {
367 gCallbackChainUserParam = userParam;
368
369 glEnable(GL_DEBUG_OUTPUT);
370 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
371 // Enable medium and high priority messages.
372 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr,
373 GL_TRUE);
374 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr,
375 GL_TRUE);
376 // Disable low and notification priority messages.
377 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr,
378 GL_FALSE);
379 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
380 GL_FALSE);
381 // Disable performance messages to reduce spam.
382 glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, 0, nullptr,
383 GL_FALSE);
384 glDebugMessageCallbackKHR(DebugMessageCallback, reinterpret_cast<const void *>(callbackChain));
385 }
386
BuildCounterNameToIndexMap()387 CounterNameToIndexMap BuildCounterNameToIndexMap()
388 {
389 GLint numCounters = 0;
390 glGetPerfMonitorCountersAMD(0, &numCounters, nullptr, 0, nullptr);
391 if (glGetError() != GL_NO_ERROR)
392 {
393 return {};
394 }
395
396 std::vector<GLuint> counterIndexes(numCounters, 0);
397 glGetPerfMonitorCountersAMD(0, nullptr, nullptr, numCounters, counterIndexes.data());
398 if (glGetError() != GL_NO_ERROR)
399 {
400 return {};
401 }
402
403 CounterNameToIndexMap indexMap;
404
405 for (GLuint counterIndex : counterIndexes)
406 {
407 static constexpr size_t kBufSize = 1000;
408 char buffer[kBufSize] = {};
409 glGetPerfMonitorCounterStringAMD(0, counterIndex, kBufSize, nullptr, buffer);
410 if (glGetError() != GL_NO_ERROR)
411 {
412 return {};
413 }
414
415 indexMap[buffer] = counterIndex;
416 }
417
418 return indexMap;
419 }
420
GetPerfMonitorTriplets()421 std::vector<angle::PerfMonitorTriplet> GetPerfMonitorTriplets()
422 {
423 GLuint resultSize = 0;
424 glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_SIZE_AMD, sizeof(GLuint), &resultSize,
425 nullptr);
426 if (glGetError() != GL_NO_ERROR || resultSize == 0)
427 {
428 return {};
429 }
430
431 std::vector<angle::PerfMonitorTriplet> perfResults(resultSize /
432 sizeof(angle::PerfMonitorTriplet));
433 glGetPerfMonitorCounterDataAMD(
434 0, GL_PERFMON_RESULT_AMD, static_cast<GLsizei>(perfResults.size() * sizeof(perfResults[0])),
435 &perfResults.data()->group, nullptr);
436
437 if (glGetError() != GL_NO_ERROR)
438 {
439 return {};
440 }
441
442 return perfResults;
443 }
444
GetPerfCounters(const CounterNameToIndexMap & indexMap)445 angle::VulkanPerfCounters GetPerfCounters(const CounterNameToIndexMap &indexMap)
446 {
447 std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
448
449 angle::VulkanPerfCounters counters;
450
451 #define ANGLE_UNPACK_PERF_COUNTER(COUNTER) \
452 GetPerfCounterValue(indexMap, perfResults, #COUNTER, &counters.COUNTER);
453
454 ANGLE_VK_PERF_COUNTERS_X(ANGLE_UNPACK_PERF_COUNTER)
455
456 #undef ANGLE_UNPACK_PERF_COUNTER
457
458 return counters;
459 }
460
BuildCounterNameToValueMap()461 CounterNameToValueMap BuildCounterNameToValueMap()
462 {
463 CounterNameToIndexMap indexMap = BuildCounterNameToIndexMap();
464 std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
465
466 CounterNameToValueMap valueMap;
467
468 for (const auto &iter : indexMap)
469 {
470 const std::string &name = iter.first;
471 GLuint index = iter.second;
472
473 valueMap[name] = perfResults[index].value;
474 }
475
476 return valueMap;
477 }
478
479 namespace angle
480 {
481
482 namespace essl1_shaders
483 {
484
PositionAttrib()485 const char *PositionAttrib()
486 {
487 return "a_position";
488 }
ColorUniform()489 const char *ColorUniform()
490 {
491 return "u_color";
492 }
493
Texture2DUniform()494 const char *Texture2DUniform()
495 {
496 return "u_tex2D";
497 }
498
499 namespace vs
500 {
501
502 // A shader that sets gl_Position to zero.
Zero()503 const char *Zero()
504 {
505 return R"(void main()
506 {
507 gl_Position = vec4(0);
508 })";
509 }
510
511 // A shader that sets gl_Position to attribute a_position.
Simple()512 const char *Simple()
513 {
514 return R"(precision highp float;
515 attribute vec4 a_position;
516
517 void main()
518 {
519 gl_Position = a_position;
520 })";
521 }
522
523 // A shader that sets gl_Position to attribute a_position, and sets gl_PointSize to 1.
SimpleForPoints()524 const char *SimpleForPoints()
525 {
526 return R"(precision highp float;
527 attribute vec4 a_position;
528
529 void main()
530 {
531 gl_Position = a_position;
532 gl_PointSize = 1.0;
533 })";
534 }
535
536 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
537 // v_position.
Passthrough()538 const char *Passthrough()
539 {
540 return R"(precision highp float;
541 attribute vec4 a_position;
542 varying vec4 v_position;
543
544 void main()
545 {
546 gl_Position = a_position;
547 v_position = a_position;
548 })";
549 }
550
551 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
552 // texcoord.
Texture2D()553 const char *Texture2D()
554 {
555 return R"(precision highp float;
556 attribute vec4 a_position;
557 varying vec2 v_texCoord;
558
559 void main()
560 {
561 gl_Position = a_position;
562 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
563 })";
564 }
565
Texture2DArray()566 const char *Texture2DArray()
567 {
568 return R"(#version 300 es
569 out vec2 v_texCoord;
570 in vec4 a_position;
571 void main()
572 {
573 gl_Position = vec4(a_position.xy, 0.0, 1.0);
574 v_texCoord = (a_position.xy * 0.5) + 0.5;
575 })";
576 }
577
578 } // namespace vs
579
580 namespace fs
581 {
582
583 // A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
584 // different colors. Needs varying v_position.
Checkered()585 const char *Checkered()
586 {
587 return R"(precision highp float;
588 varying vec4 v_position;
589
590 void main()
591 {
592 bool isLeft = v_position.x < 0.0;
593 bool isTop = v_position.y < 0.0;
594 if (isLeft)
595 {
596 if (isTop)
597 {
598 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
599 }
600 else
601 {
602 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
603 }
604 }
605 else
606 {
607 if (isTop)
608 {
609 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
610 }
611 else
612 {
613 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
614 }
615 }
616 })";
617 }
618
619 // A shader that fills with color taken from uniform named "color".
UniformColor()620 const char *UniformColor()
621 {
622 return R"(uniform mediump vec4 u_color;
623 void main(void)
624 {
625 gl_FragColor = u_color;
626 })";
627 }
628
629 // A shader that fills with 100% opaque red.
Red()630 const char *Red()
631 {
632 return R"(precision mediump float;
633
634 void main()
635 {
636 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
637 })";
638 }
639
640 // A shader that fills with 100% opaque green.
Green()641 const char *Green()
642 {
643 return R"(precision mediump float;
644
645 void main()
646 {
647 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
648 })";
649 }
650
651 // A shader that fills with 100% opaque blue.
Blue()652 const char *Blue()
653 {
654 return R"(precision mediump float;
655
656 void main()
657 {
658 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
659 })";
660 }
661
662 // A shader that samples the texture.
Texture2D()663 const char *Texture2D()
664 {
665 return R"(precision mediump float;
666 uniform sampler2D u_tex2D;
667 varying vec2 v_texCoord;
668
669 void main()
670 {
671 gl_FragColor = texture2D(u_tex2D, v_texCoord);
672 })";
673 }
674
Texture2DArray()675 const char *Texture2DArray()
676 {
677 return R"(#version 300 es
678 precision highp float;
679 uniform highp sampler2DArray tex2DArray;
680 uniform int slice;
681 in vec2 v_texCoord;
682 out vec4 fragColor;
683 void main()
684 {
685 fragColor = texture(tex2DArray, vec3(v_texCoord, float(slice)));
686 })";
687 }
688
689 } // namespace fs
690 } // namespace essl1_shaders
691
692 namespace essl3_shaders
693 {
694
PositionAttrib()695 const char *PositionAttrib()
696 {
697 return "a_position";
698 }
Texture2DUniform()699 const char *Texture2DUniform()
700 {
701 return "u_tex2D";
702 }
LodUniform()703 const char *LodUniform()
704 {
705 return "u_lod";
706 }
707
708 namespace vs
709 {
710
711 // A shader that sets gl_Position to zero.
Zero()712 const char *Zero()
713 {
714 return R"(#version 300 es
715 void main()
716 {
717 gl_Position = vec4(0);
718 })";
719 }
720
721 // A shader that sets gl_Position to attribute a_position.
Simple()722 const char *Simple()
723 {
724 return R"(#version 300 es
725 in vec4 a_position;
726 void main()
727 {
728 gl_Position = a_position;
729 })";
730 }
731
732 // A shader that sets gl_Position to attribute a_position, and sets gl_PointSize to 1.
SimpleForPoints()733 const char *SimpleForPoints()
734 {
735 return R"(#version 300 es
736 in vec4 a_position;
737 void main()
738 {
739 gl_Position = a_position;
740 gl_PointSize = 1.0;
741 })";
742 }
743
744 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
745 // v_position.
Passthrough()746 const char *Passthrough()
747 {
748 return R"(#version 300 es
749 in vec4 a_position;
750 out vec4 v_position;
751 void main()
752 {
753 gl_Position = a_position;
754 v_position = a_position;
755 })";
756 }
757
758 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
759 // texcoord.
Texture2DLod()760 const char *Texture2DLod()
761 {
762 return R"(#version 300 es
763 in vec4 a_position;
764 out vec2 v_texCoord;
765
766 void main()
767 {
768 gl_Position = vec4(a_position.xy, 0.0, 1.0);
769 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
770 })";
771 }
772
773 } // namespace vs
774
775 namespace fs
776 {
777
778 // A shader that fills with 100% opaque red.
Red()779 const char *Red()
780 {
781 return R"(#version 300 es
782 precision highp float;
783 out vec4 my_FragColor;
784 void main()
785 {
786 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
787 })";
788 }
789
790 // A shader that fills with 100% opaque green.
Green()791 const char *Green()
792 {
793 return R"(#version 300 es
794 precision highp float;
795 out vec4 my_FragColor;
796 void main()
797 {
798 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
799 })";
800 }
801
802 // A shader that fills with 100% opaque blue.
Blue()803 const char *Blue()
804 {
805 return R"(#version 300 es
806 precision highp float;
807 out vec4 my_FragColor;
808 void main()
809 {
810 my_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
811 })";
812 }
813
814 // A shader that samples the texture at a given lod.
Texture2DLod()815 const char *Texture2DLod()
816 {
817 return R"(#version 300 es
818 precision mediump float;
819 uniform sampler2D u_tex2D;
820 uniform float u_lod;
821 in vec2 v_texCoord;
822 out vec4 my_FragColor;
823
824 void main()
825 {
826 my_FragColor = textureLod(u_tex2D, v_texCoord, u_lod);
827 })";
828 }
829
830 } // namespace fs
831 } // namespace essl3_shaders
832
833 namespace essl31_shaders
834 {
835
PositionAttrib()836 const char *PositionAttrib()
837 {
838 return "a_position";
839 }
840
841 namespace vs
842 {
843
844 // A shader that sets gl_Position to zero.
Zero()845 const char *Zero()
846 {
847 return R"(#version 310 es
848 void main()
849 {
850 gl_Position = vec4(0);
851 })";
852 }
853
854 // A shader that sets gl_Position to attribute a_position.
Simple()855 const char *Simple()
856 {
857 return R"(#version 310 es
858 in vec4 a_position;
859 void main()
860 {
861 gl_Position = a_position;
862 })";
863 }
864
865 // A shader that simply passes through attribute a_position, setting it to gl_Position and varying
866 // v_position.
Passthrough()867 const char *Passthrough()
868 {
869 return R"(#version 310 es
870 in vec4 a_position;
871 out vec4 v_position;
872 void main()
873 {
874 gl_Position = a_position;
875 v_position = a_position;
876 })";
877 }
878
879 } // namespace vs
880
881 namespace fs
882 {
883
884 // A shader that fills with 100% opaque red.
Red()885 const char *Red()
886 {
887 return R"(#version 310 es
888 precision highp float;
889 out vec4 my_FragColor;
890 void main()
891 {
892 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
893 })";
894 }
895
896 // A shader that fills with 100% opaque green.
Green()897 const char *Green()
898 {
899 return R"(#version 310 es
900 precision highp float;
901 out vec4 my_FragColor;
902 void main()
903 {
904 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
905 })";
906 }
907
908 // A shader that renders a simple gradient of red to green. Needs varying v_position.
RedGreenGradient()909 const char *RedGreenGradient()
910 {
911 return R"(#version 310 es
912 precision highp float;
913 in vec4 v_position;
914 out vec4 my_FragColor;
915
916 void main()
917 {
918 my_FragColor = vec4(v_position.xy * 0.5 + vec2(0.5), 0.0, 1.0);
919 })";
920 }
921
922 } // namespace fs
923 } // namespace essl31_shaders
924 } // namespace angle
925