1 #ifndef _GLUSHADERPROGRAM_HPP
2 #define _GLUSHADERPROGRAM_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL ES Utilities
5 * ------------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Shader and Program helpers.
24 *//*--------------------------------------------------------------------*/
25
26 #include "gluDefs.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "glwEnums.hpp"
29 #include "qpTestLog.h"
30
31 #include <string>
32 #include <vector>
33
34 namespace tcu
35 {
36 class TestLog;
37 }
38
39 namespace glu
40 {
41
42 class RenderContext;
43
44 typedef std::vector<uint32_t> ShaderBinaryDataType;
45
46 /*--------------------------------------------------------------------*//*!
47 * \brief Shader information (compile status, log, etc.).
48 *//*--------------------------------------------------------------------*/
49 struct ShaderInfo
50 {
51 ShaderType type; //!< Shader type.
52 std::string source; //!< Shader source.
53 std::string infoLog; //!< Compile info log.
54 bool compileOk; //!< Did compilation succeed?
55 uint64_t compileTimeUs; //!< Compile time in microseconds (us).
56
ShaderInfoglu::ShaderInfo57 ShaderInfo(void) : type(SHADERTYPE_LAST), compileOk(false), compileTimeUs(0)
58 {
59 }
60 };
61
62 /*--------------------------------------------------------------------*//*!
63 * \brief Program information (link status, log).
64 *//*--------------------------------------------------------------------*/
65 struct ProgramInfo
66 {
67 std::string infoLog; //!< Link info log.
68 bool linkOk; //!< Did link succeed?
69 uint64_t linkTimeUs; //!< Link time in microseconds (us).
70
ProgramInfoglu::ProgramInfo71 ProgramInfo(void) : linkOk(false), linkTimeUs(0)
72 {
73 }
74 };
75
76 /*--------------------------------------------------------------------*//*!
77 * \brief Combined shader compilation and program linking info.
78 *//*--------------------------------------------------------------------*/
79 struct ShaderProgramInfo
80 {
81 glu::ProgramInfo program;
82 std::vector<glu::ShaderInfo> shaders;
83 };
84
85 /*--------------------------------------------------------------------*//*!
86 * \brief Shader object.
87 *//*--------------------------------------------------------------------*/
88 class Shader
89 {
90 public:
91 Shader(const glw::Functions &gl, ShaderType shaderType);
92 Shader(const RenderContext &renderCtx, ShaderType shaderType);
93 ~Shader(void);
94
95 void setSources(int numSourceStrings, const char *const *sourceStrings, const int *lengths);
96 void compile(void);
97 void specialize(const char *entryPoint, glw::GLuint numSpecializationConstants, const glw::GLuint *constantIndex,
98 const glw::GLuint *constantValue);
99
getShader(void) const100 uint32_t getShader(void) const
101 {
102 return m_shader;
103 }
getInfo(void) const104 const ShaderInfo &getInfo(void) const
105 {
106 return m_info;
107 }
108
getType(void) const109 glu::ShaderType getType(void) const
110 {
111 return getInfo().type;
112 }
getCompileStatus(void) const113 bool getCompileStatus(void) const
114 {
115 return getInfo().compileOk;
116 }
getSource(void) const117 const std::string &getSource(void) const
118 {
119 return getInfo().source;
120 }
getInfoLog(void) const121 const std::string &getInfoLog(void) const
122 {
123 return getInfo().infoLog;
124 }
125
operator *(void) const126 uint32_t operator*(void) const
127 {
128 return getShader();
129 }
130
131 private:
132 Shader(const Shader &other);
133 Shader &operator=(const Shader &other);
134
135 const glw::Functions &m_gl;
136 uint32_t m_shader; //!< Shader handle.
137 ShaderInfo m_info; //!< Client-side clone of state for debug / perf reasons.
138 };
139
140 /*--------------------------------------------------------------------*//*!
141 * \brief Program object.
142 *//*--------------------------------------------------------------------*/
143 class Program
144 {
145 public:
146 Program(const glw::Functions &gl);
147 Program(const RenderContext &renderCtx);
148 Program(const RenderContext &renderCtx, uint32_t program);
149 ~Program(void);
150
151 void attachShader(uint32_t shader);
152 void detachShader(uint32_t shader);
153
154 void bindAttribLocation(uint32_t location, const char *name);
155 void transformFeedbackVaryings(int count, const char *const *varyings, uint32_t bufferMode);
156
157 void link(void);
158
getProgram(void) const159 uint32_t getProgram(void) const
160 {
161 return m_program;
162 }
getInfo(void) const163 const ProgramInfo &getInfo(void) const
164 {
165 return m_info;
166 }
167
getLinkStatus(void) const168 bool getLinkStatus(void) const
169 {
170 return getInfo().linkOk;
171 }
getInfoLog(void) const172 const std::string &getInfoLog(void) const
173 {
174 return getInfo().infoLog;
175 }
176
177 bool isSeparable(void) const;
178 void setSeparable(bool separable);
179
180 int getUniformLocation(const std::string &name);
181
operator *(void) const182 uint32_t operator*(void) const
183 {
184 return getProgram();
185 }
186
187 private:
188 Program(const Program &other);
189 Program &operator=(const Program &other);
190
191 const glw::Functions &m_gl;
192 uint32_t m_program;
193 ProgramInfo m_info;
194 };
195
196 /*--------------------------------------------------------------------*//*!
197 * \brief Program pipeline object.
198 *//*--------------------------------------------------------------------*/
199 class ProgramPipeline
200 {
201 public:
202 ProgramPipeline(const RenderContext &renderCtx);
203 ProgramPipeline(const glw::Functions &gl);
204 ~ProgramPipeline(void);
205
getPipeline(void) const206 uint32_t getPipeline(void) const
207 {
208 return m_pipeline;
209 }
210 void useProgramStages(uint32_t stages, uint32_t program);
211 void activeShaderProgram(uint32_t program);
212 bool isValid(void);
213
214 private:
215 ProgramPipeline(const ProgramPipeline &other);
216 ProgramPipeline &operator=(const ProgramPipeline &other);
217
218 const glw::Functions &m_gl;
219 uint32_t m_pipeline;
220 };
221
222 struct ProgramSources;
223 struct ProgramBinaries;
224
225 /*--------------------------------------------------------------------*//*!
226 * \brief Shader program manager.
227 *
228 * ShaderProgram manages both Shader and Program objects, and provides
229 * convenient API for constructing such programs.
230 *//*--------------------------------------------------------------------*/
231 class ShaderProgram
232 {
233 public:
234 ShaderProgram(const glw::Functions &gl, const ProgramSources &sources);
235 ShaderProgram(const glw::Functions &gl, const ProgramBinaries &binaries);
236 ShaderProgram(const RenderContext &renderCtx, const ProgramSources &sources);
237 ShaderProgram(const RenderContext &renderCtx, const ProgramBinaries &binaries);
238 ~ShaderProgram(void);
239
isOk(void) const240 bool isOk(void) const
241 {
242 return m_program.getLinkStatus();
243 }
getProgram(void) const244 uint32_t getProgram(void) const
245 {
246 return m_program.getProgram();
247 }
248
hasShader(glu::ShaderType shaderType) const249 bool hasShader(glu::ShaderType shaderType) const
250 {
251 return !m_shaders[shaderType].empty();
252 }
getShader(glu::ShaderType shaderType,int shaderNdx=0) const253 Shader *getShader(glu::ShaderType shaderType, int shaderNdx = 0) const
254 {
255 return m_shaders[shaderType][shaderNdx];
256 }
getNumShaders(glu::ShaderType shaderType) const257 int getNumShaders(glu::ShaderType shaderType) const
258 {
259 return (int)m_shaders[shaderType].size();
260 }
getShaderInfo(glu::ShaderType shaderType,int shaderNdx=0) const261 const ShaderInfo &getShaderInfo(glu::ShaderType shaderType, int shaderNdx = 0) const
262 {
263 return m_shaders[shaderType][shaderNdx]->getInfo();
264 }
getProgramInfo(void) const265 const ProgramInfo &getProgramInfo(void) const
266 {
267 return m_program.getInfo();
268 }
269
270 private:
271 ShaderProgram(const ShaderProgram &other);
272 ShaderProgram &operator=(const ShaderProgram &other);
273 void init(const glw::Functions &gl, const ProgramSources &sources);
274 void init(const glw::Functions &gl, const ProgramBinaries &binaries);
275 void setBinary(const glw::Functions &gl, std::vector<Shader *> &shaders, glw::GLenum binaryFormat,
276 const void *binaryData, const int length);
277
278 std::vector<Shader *> m_shaders[SHADERTYPE_LAST];
279 Program m_program;
280 };
281
282 // Utilities.
283
284 uint32_t getGLShaderType(ShaderType shaderType);
285 uint32_t getGLShaderTypeBit(ShaderType shaderType);
286 qpShaderType getLogShaderType(ShaderType shaderType);
287
288 tcu::TestLog &operator<<(tcu::TestLog &log, const ShaderInfo &shaderInfo);
289 tcu::TestLog &operator<<(tcu::TestLog &log, const ShaderProgramInfo &shaderProgramInfo);
290 tcu::TestLog &operator<<(tcu::TestLog &log, const ProgramSources &sources);
291 tcu::TestLog &operator<<(tcu::TestLog &log, const Shader &shader);
292 tcu::TestLog &operator<<(tcu::TestLog &log, const ShaderProgram &program);
293
294 // ProgramSources utilities and implementation.
295
296 struct AttribLocationBinding
297 {
298 std::string name;
299 uint32_t location;
300
AttribLocationBindingglu::AttribLocationBinding301 AttribLocationBinding(void) : location(0)
302 {
303 }
AttribLocationBindingglu::AttribLocationBinding304 AttribLocationBinding(const std::string &name_, uint32_t location_) : name(name_), location(location_)
305 {
306 }
307 };
308
309 struct TransformFeedbackMode
310 {
311 uint32_t mode;
312
TransformFeedbackModeglu::TransformFeedbackMode313 TransformFeedbackMode(void) : mode(0)
314 {
315 }
TransformFeedbackModeglu::TransformFeedbackMode316 TransformFeedbackMode(uint32_t mode_) : mode(mode_)
317 {
318 }
319 };
320
321 struct TransformFeedbackVarying
322 {
323 std::string name;
324
TransformFeedbackVaryingglu::TransformFeedbackVarying325 explicit TransformFeedbackVarying(const std::string &name_) : name(name_)
326 {
327 }
328 };
329
330 struct ProgramSeparable
331 {
332 bool separable;
ProgramSeparableglu::ProgramSeparable333 explicit ProgramSeparable(bool separable_) : separable(separable_)
334 {
335 }
336 };
337
338 template <typename Iterator>
339 struct TransformFeedbackVaryings
340 {
341 Iterator begin;
342 Iterator end;
343
TransformFeedbackVaryingsglu::TransformFeedbackVaryings344 TransformFeedbackVaryings(Iterator begin_, Iterator end_) : begin(begin_), end(end_)
345 {
346 }
347 };
348
349 struct ShaderSource
350 {
351 ShaderType shaderType;
352 std::string source;
353
ShaderSourceglu::ShaderSource354 ShaderSource(void) : shaderType(SHADERTYPE_LAST)
355 {
356 }
ShaderSourceglu::ShaderSource357 ShaderSource(glu::ShaderType shaderType_, const std::string &source_) : shaderType(shaderType_), source(source_)
358 {
359 DE_ASSERT(!source_.empty());
360 }
361 };
362
363 struct VertexSource : public ShaderSource
364 {
VertexSourceglu::VertexSource365 VertexSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_VERTEX, source_)
366 {
367 }
368 };
369
370 struct FragmentSource : public ShaderSource
371 {
FragmentSourceglu::FragmentSource372 FragmentSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_FRAGMENT, source_)
373 {
374 }
375 };
376
377 struct GeometrySource : public ShaderSource
378 {
GeometrySourceglu::GeometrySource379 GeometrySource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_GEOMETRY, source_)
380 {
381 }
382 };
383
384 struct ComputeSource : public ShaderSource
385 {
ComputeSourceglu::ComputeSource386 ComputeSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_COMPUTE, source_)
387 {
388 }
389 };
390
391 struct TessellationControlSource : public ShaderSource
392 {
TessellationControlSourceglu::TessellationControlSource393 TessellationControlSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_TESSELLATION_CONTROL, source_)
394 {
395 }
396 };
397
398 struct TessellationEvaluationSource : public ShaderSource
399 {
TessellationEvaluationSourceglu::TessellationEvaluationSource400 TessellationEvaluationSource(const std::string &source_)
401 : ShaderSource(glu::SHADERTYPE_TESSELLATION_EVALUATION, source_)
402 {
403 }
404 };
405
406 struct RaygenSource : public ShaderSource
407 {
RaygenSourceglu::RaygenSource408 RaygenSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_RAYGEN, source_)
409 {
410 }
411 };
412
413 struct AnyHitSource : public ShaderSource
414 {
AnyHitSourceglu::AnyHitSource415 AnyHitSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_ANY_HIT, source_)
416 {
417 }
418 };
419
420 struct ClosestHitSource : public ShaderSource
421 {
ClosestHitSourceglu::ClosestHitSource422 ClosestHitSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_CLOSEST_HIT, source_)
423 {
424 }
425 };
426
427 struct MissSource : public ShaderSource
428 {
MissSourceglu::MissSource429 MissSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_MISS, source_)
430 {
431 }
432 };
433
434 struct IntersectionSource : public ShaderSource
435 {
IntersectionSourceglu::IntersectionSource436 IntersectionSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_INTERSECTION, source_)
437 {
438 }
439 };
440
441 struct CallableSource : public ShaderSource
442 {
CallableSourceglu::CallableSource443 CallableSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_CALLABLE, source_)
444 {
445 }
446 };
447
448 struct TaskSource : public ShaderSource
449 {
TaskSourceglu::TaskSource450 TaskSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_TASK, source_)
451 {
452 }
453 };
454
455 struct MeshSource : public ShaderSource
456 {
MeshSourceglu::MeshSource457 MeshSource(const std::string &source_) : ShaderSource(glu::SHADERTYPE_MESH, source_)
458 {
459 }
460 };
461
462 struct ProgramSources
463 {
464 std::vector<std::string> sources[SHADERTYPE_LAST];
465 std::vector<AttribLocationBinding> attribLocationBindings;
466
467 uint32_t transformFeedbackBufferMode; //!< TF buffer mode, or GL_NONE.
468 std::vector<std::string> transformFeedbackVaryings;
469 bool separable;
470
ProgramSourcesglu::ProgramSources471 ProgramSources(void) : transformFeedbackBufferMode(0), separable(false)
472 {
473 }
474
operator <<glu::ProgramSources475 ProgramSources &operator<<(const AttribLocationBinding &binding)
476 {
477 attribLocationBindings.push_back(binding);
478 return *this;
479 }
operator <<glu::ProgramSources480 ProgramSources &operator<<(const TransformFeedbackMode &mode)
481 {
482 transformFeedbackBufferMode = mode.mode;
483 return *this;
484 }
operator <<glu::ProgramSources485 ProgramSources &operator<<(const TransformFeedbackVarying &varying)
486 {
487 transformFeedbackVaryings.push_back(varying.name);
488 return *this;
489 }
operator <<glu::ProgramSources490 ProgramSources &operator<<(const ShaderSource &shaderSource)
491 {
492 sources[shaderSource.shaderType].push_back(shaderSource.source);
493 return *this;
494 }
operator <<glu::ProgramSources495 ProgramSources &operator<<(const ProgramSeparable &progSeparable)
496 {
497 separable = progSeparable.separable;
498 return *this;
499 }
500
501 template <typename Iterator>
502 ProgramSources &operator<<(const TransformFeedbackVaryings<Iterator> &varyings);
503 };
504
505 struct SpecializationData
506 {
507 uint32_t index;
508 uint32_t value;
509
SpecializationDataglu::SpecializationData510 SpecializationData(void) : index(0), value(0)
511 {
512 }
SpecializationDataglu::SpecializationData513 SpecializationData(const uint32_t index_, const uint32_t value_) : index(index_), value(value_)
514 {
515 }
516 };
517
518 struct ShaderBinary
519 {
520 ShaderBinaryDataType binary;
521 std::vector<ShaderType> shaderTypes;
522 std::vector<std::string> shaderEntryPoints;
523 std::vector<uint32_t> specializationIndices;
524 std::vector<uint32_t> specializationValues;
525
ShaderBinaryglu::ShaderBinary526 ShaderBinary(void)
527 {
528 }
ShaderBinaryglu::ShaderBinary529 ShaderBinary(const ShaderBinaryDataType binary_) : binary(binary_)
530 {
531 DE_ASSERT(!binary_.empty());
532 }
ShaderBinaryglu::ShaderBinary533 ShaderBinary(const ShaderBinaryDataType binary_, glu::ShaderType shaderType_) : binary(binary_)
534 {
535 DE_ASSERT(!binary_.empty());
536 shaderTypes.push_back(shaderType_);
537 shaderEntryPoints.push_back("main");
538 }
539
operator <<glu::ShaderBinary540 ShaderBinary &operator<<(const ShaderType &shaderType)
541 {
542 shaderTypes.push_back(shaderType);
543 return *this;
544 }
545
operator <<glu::ShaderBinary546 ShaderBinary &operator<<(const std::string &entryPoint)
547 {
548 shaderEntryPoints.push_back(entryPoint);
549 return *this;
550 }
551
operator <<glu::ShaderBinary552 ShaderBinary &operator<<(const SpecializationData &specData)
553 {
554 specializationIndices.push_back(specData.index);
555 specializationValues.push_back(specData.value);
556 return *this;
557 }
558 };
559
560 struct VertexBinary : public ShaderBinary
561 {
VertexBinaryglu::VertexBinary562 VertexBinary(const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_VERTEX)
563 {
564 }
565 };
566
567 struct FragmentBinary : public ShaderBinary
568 {
FragmentBinaryglu::FragmentBinary569 FragmentBinary(const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_FRAGMENT)
570 {
571 }
572 };
573
574 struct GeometryBinary : public ShaderBinary
575 {
GeometryBinaryglu::GeometryBinary576 GeometryBinary(const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_GEOMETRY)
577 {
578 }
579 };
580
581 struct ComputeBinary : public ShaderBinary
582 {
ComputeBinaryglu::ComputeBinary583 ComputeBinary(const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_COMPUTE)
584 {
585 }
586 };
587
588 struct TessellationControlBinary : public ShaderBinary
589 {
TessellationControlBinaryglu::TessellationControlBinary590 TessellationControlBinary(const ShaderBinaryDataType binary_)
591 : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_CONTROL)
592 {
593 }
594 };
595
596 struct TessellationEvaluationBinary : public ShaderBinary
597 {
TessellationEvaluationBinaryglu::TessellationEvaluationBinary598 TessellationEvaluationBinary(const ShaderBinaryDataType binary_)
599 : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_EVALUATION)
600 {
601 }
602 };
603
604 struct ProgramBinaries
605 {
606 std::vector<ShaderBinary> binaries;
607
608 glw::GLenum binaryFormat;
609
ProgramBinariesglu::ProgramBinaries610 ProgramBinaries(void) : binaryFormat(GL_SHADER_BINARY_FORMAT_SPIR_V_ARB)
611 {
612 }
ProgramBinariesglu::ProgramBinaries613 ProgramBinaries(glw::GLenum binaryFormat_) : binaryFormat(binaryFormat_)
614 {
615 }
616
operator <<glu::ProgramBinaries617 ProgramBinaries &operator<<(const ShaderBinary &shaderBinary)
618 {
619 binaries.push_back(shaderBinary);
620 return *this;
621 }
622 };
623
624 template <typename Iterator>
operator <<(const TransformFeedbackVaryings<Iterator> & varyings)625 inline ProgramSources &ProgramSources::operator<<(const TransformFeedbackVaryings<Iterator> &varyings)
626 {
627 for (Iterator cur = varyings.begin; cur != varyings.end; ++cur)
628 transformFeedbackVaryings.push_back(*cur);
629 return *this;
630 }
631
632 //! Helper for constructing vertex-fragment source pair.
makeVtxFragSources(const std::string & vertexSrc,const std::string & fragmentSrc)633 inline ProgramSources makeVtxFragSources(const std::string &vertexSrc, const std::string &fragmentSrc)
634 {
635 ProgramSources sources;
636 sources.sources[SHADERTYPE_VERTEX].push_back(vertexSrc);
637 sources.sources[SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
638 return sources;
639 }
640
641 } // namespace glu
642
643 #endif // _GLUSHADERPROGRAM_HPP
644