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