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<deUint32> 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 deUint64 compileTimeUs; //!< Compile time in microseconds (us).
56
ShaderInfoglu::ShaderInfo57 ShaderInfo (void) : compileOk(false), compileTimeUs(0) {}
58 };
59
60 /*--------------------------------------------------------------------*//*!
61 * \brief Program information (link status, log).
62 *//*--------------------------------------------------------------------*/
63 struct ProgramInfo
64 {
65 std::string infoLog; //!< Link info log.
66 bool linkOk; //!< Did link succeed?
67 deUint64 linkTimeUs; //!< Link time in microseconds (us).
68
ProgramInfoglu::ProgramInfo69 ProgramInfo (void) : linkOk(false), linkTimeUs(0) {}
70 };
71
72 /*--------------------------------------------------------------------*//*!
73 * \brief Combined shader compilation and program linking info.
74 *//*--------------------------------------------------------------------*/
75 struct ShaderProgramInfo
76 {
77 glu::ProgramInfo program;
78 std::vector<glu::ShaderInfo> shaders;
79 };
80
81 /*--------------------------------------------------------------------*//*!
82 * \brief Shader object.
83 *//*--------------------------------------------------------------------*/
84 class Shader
85 {
86 public:
87 Shader (const glw::Functions& gl, ShaderType shaderType);
88 Shader (const RenderContext& renderCtx, ShaderType shaderType);
89 ~Shader (void);
90
91 void setSources (int numSourceStrings, const char* const* sourceStrings, const int* lengths);
92 void compile (void);
93 void specialize (const char* entryPoint, glw::GLuint numSpecializationConstants,
94 const glw::GLuint* constantIndex, const glw::GLuint* constantValue);
95
getShader(void) const96 deUint32 getShader (void) const { return m_shader; }
getInfo(void) const97 const ShaderInfo& getInfo (void) const { return m_info; }
98
getType(void) const99 glu::ShaderType getType (void) const { return getInfo().type; }
getCompileStatus(void) const100 bool getCompileStatus (void) const { return getInfo().compileOk; }
getSource(void) const101 const std::string& getSource (void) const { return getInfo().source; }
getInfoLog(void) const102 const std::string& getInfoLog (void) const { return getInfo().infoLog; }
103
operator *(void) const104 deUint32 operator* (void) const { return getShader(); }
105
106 private:
107 Shader (const Shader& other);
108 Shader& operator= (const Shader& other);
109
110 const glw::Functions& m_gl;
111 deUint32 m_shader; //!< Shader handle.
112 ShaderInfo m_info; //!< Client-side clone of state for debug / perf reasons.
113 };
114
115 /*--------------------------------------------------------------------*//*!
116 * \brief Program object.
117 *//*--------------------------------------------------------------------*/
118 class Program
119 {
120 public:
121 Program (const glw::Functions& gl);
122 Program (const RenderContext& renderCtx);
123 Program (const RenderContext& renderCtx, deUint32 program);
124 ~Program (void);
125
126 void attachShader (deUint32 shader);
127 void detachShader (deUint32 shader);
128
129 void bindAttribLocation (deUint32 location, const char* name);
130 void transformFeedbackVaryings (int count, const char* const* varyings, deUint32 bufferMode);
131
132 void link (void);
133
getProgram(void) const134 deUint32 getProgram (void) const { return m_program; }
getInfo(void) const135 const ProgramInfo& getInfo (void) const { return m_info; }
136
getLinkStatus(void) const137 bool getLinkStatus (void) const { return getInfo().linkOk; }
getInfoLog(void) const138 const std::string& getInfoLog (void) const { return getInfo().infoLog; }
139
140 bool isSeparable (void) const;
141 void setSeparable (bool separable);
142
143 int getUniformLocation (const std::string& name);
144
operator *(void) const145 deUint32 operator* (void) const { return getProgram(); }
146
147 private:
148 Program (const Program& other);
149 Program& operator= (const Program& other);
150
151 const glw::Functions& m_gl;
152 deUint32 m_program;
153 ProgramInfo m_info;
154 };
155
156
157 /*--------------------------------------------------------------------*//*!
158 * \brief Program pipeline object.
159 *//*--------------------------------------------------------------------*/
160 class ProgramPipeline
161 {
162 public:
163 ProgramPipeline (const RenderContext& renderCtx);
164 ProgramPipeline (const glw::Functions& gl);
165 ~ProgramPipeline (void);
166
getPipeline(void) const167 deUint32 getPipeline (void) const { return m_pipeline; }
168 void useProgramStages (deUint32 stages, deUint32 program);
169 void activeShaderProgram (deUint32 program);
170 bool isValid (void);
171
172 private:
173 ProgramPipeline (const ProgramPipeline& other);
174 ProgramPipeline& operator= (const ProgramPipeline& other);
175
176 const glw::Functions& m_gl;
177 deUint32 m_pipeline;
178 };
179
180 struct ProgramSources;
181 struct ProgramBinaries;
182
183 /*--------------------------------------------------------------------*//*!
184 * \brief Shader program manager.
185 *
186 * ShaderProgram manages both Shader and Program objects, and provides
187 * convenient API for constructing such programs.
188 *//*--------------------------------------------------------------------*/
189 class ShaderProgram
190 {
191 public:
192 ShaderProgram (const glw::Functions& gl, const ProgramSources& sources);
193 ShaderProgram (const glw::Functions& gl, const ProgramBinaries& binaries);
194 ShaderProgram (const RenderContext& renderCtx, const ProgramSources& sources);
195 ShaderProgram (const RenderContext& renderCtx, const ProgramBinaries& binaries);
196 ~ShaderProgram (void);
197
isOk(void) const198 bool isOk (void) const { return m_program.getLinkStatus(); }
getProgram(void) const199 deUint32 getProgram (void) const { return m_program.getProgram(); }
200
hasShader(glu::ShaderType shaderType) const201 bool hasShader (glu::ShaderType shaderType) const { return !m_shaders[shaderType].empty(); }
getShader(glu::ShaderType shaderType,int shaderNdx=0) const202 Shader* getShader (glu::ShaderType shaderType, int shaderNdx = 0) const { return m_shaders[shaderType][shaderNdx]; }
getNumShaders(glu::ShaderType shaderType) const203 int getNumShaders (glu::ShaderType shaderType) const { return (int)m_shaders[shaderType].size(); }
getShaderInfo(glu::ShaderType shaderType,int shaderNdx=0) const204 const ShaderInfo& getShaderInfo (glu::ShaderType shaderType, int shaderNdx = 0) const { return m_shaders[shaderType][shaderNdx]->getInfo(); }
getProgramInfo(void) const205 const ProgramInfo& getProgramInfo (void) const { return m_program.getInfo(); }
206
207 private:
208 ShaderProgram (const ShaderProgram& other);
209 ShaderProgram& operator= (const ShaderProgram& other);
210 void init (const glw::Functions& gl, const ProgramSources& sources);
211 void init (const glw::Functions& gl, const ProgramBinaries& binaries);
212 void setBinary (const glw::Functions& gl, std::vector<Shader*>& shaders, glw::GLenum binaryFormat, const void* binaryData, const int length);
213
214 std::vector<Shader*> m_shaders[SHADERTYPE_LAST];
215 Program m_program;
216 };
217
218 // Utilities.
219
220 deUint32 getGLShaderType (ShaderType shaderType);
221 deUint32 getGLShaderTypeBit (ShaderType shaderType);
222 qpShaderType getLogShaderType (ShaderType shaderType);
223
224 tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderInfo& shaderInfo);
225 tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgramInfo& shaderProgramInfo);
226 tcu::TestLog& operator<< (tcu::TestLog& log, const ProgramSources& sources);
227 tcu::TestLog& operator<< (tcu::TestLog& log, const Shader& shader);
228 tcu::TestLog& operator<< (tcu::TestLog& log, const ShaderProgram& program);
229
230 // ProgramSources utilities and implementation.
231
232 struct AttribLocationBinding
233 {
234 std::string name;
235 deUint32 location;
236
AttribLocationBindingglu::AttribLocationBinding237 AttribLocationBinding (void) : location(0) {}
AttribLocationBindingglu::AttribLocationBinding238 AttribLocationBinding (const std::string& name_, deUint32 location_) : name(name_), location(location_) {}
239 };
240
241 struct TransformFeedbackMode
242 {
243 deUint32 mode;
244
TransformFeedbackModeglu::TransformFeedbackMode245 TransformFeedbackMode (void) : mode(0) {}
TransformFeedbackModeglu::TransformFeedbackMode246 TransformFeedbackMode (deUint32 mode_) : mode(mode_) {}
247 };
248
249 struct TransformFeedbackVarying
250 {
251 std::string name;
252
TransformFeedbackVaryingglu::TransformFeedbackVarying253 explicit TransformFeedbackVarying (const std::string& name_) : name(name_) {}
254 };
255
256 struct ProgramSeparable
257 {
258 bool separable;
ProgramSeparableglu::ProgramSeparable259 explicit ProgramSeparable (bool separable_) : separable(separable_) {}
260 };
261
262 template<typename Iterator>
263 struct TransformFeedbackVaryings
264 {
265 Iterator begin;
266 Iterator end;
267
TransformFeedbackVaryingsglu::TransformFeedbackVaryings268 TransformFeedbackVaryings (Iterator begin_, Iterator end_) : begin(begin_), end(end_) {}
269 };
270
271 struct ShaderSource
272 {
273 ShaderType shaderType;
274 std::string source;
275
ShaderSourceglu::ShaderSource276 ShaderSource (void) : shaderType(SHADERTYPE_LAST) {}
ShaderSourceglu::ShaderSource277 ShaderSource (glu::ShaderType shaderType_, const std::string& source_) : shaderType(shaderType_), source(source_) { DE_ASSERT(!source_.empty()); }
278 };
279
280 struct VertexSource : public ShaderSource
281 {
VertexSourceglu::VertexSource282 VertexSource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_VERTEX, source_) {}
283 };
284
285 struct FragmentSource : public ShaderSource
286 {
FragmentSourceglu::FragmentSource287 FragmentSource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_FRAGMENT, source_) {}
288 };
289
290 struct GeometrySource : public ShaderSource
291 {
GeometrySourceglu::GeometrySource292 GeometrySource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_GEOMETRY, source_) {}
293 };
294
295 struct ComputeSource : public ShaderSource
296 {
ComputeSourceglu::ComputeSource297 ComputeSource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_COMPUTE, source_) {}
298 };
299
300 struct TessellationControlSource : public ShaderSource
301 {
TessellationControlSourceglu::TessellationControlSource302 TessellationControlSource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_TESSELLATION_CONTROL, source_) {}
303 };
304
305 struct TessellationEvaluationSource : public ShaderSource
306 {
TessellationEvaluationSourceglu::TessellationEvaluationSource307 TessellationEvaluationSource (const std::string& source_) : ShaderSource(glu::SHADERTYPE_TESSELLATION_EVALUATION, source_) {}
308 };
309
310 struct RaygenSource : public ShaderSource
311 {
RaygenSourceglu::RaygenSource312 RaygenSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_RAYGEN, source_) {}
313 };
314
315 struct AnyHitSource : public ShaderSource
316 {
AnyHitSourceglu::AnyHitSource317 AnyHitSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_ANY_HIT, source_) {}
318 };
319
320 struct ClosestHitSource : public ShaderSource
321 {
ClosestHitSourceglu::ClosestHitSource322 ClosestHitSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_CLOSEST_HIT, source_) {}
323 };
324
325 struct MissSource : public ShaderSource
326 {
MissSourceglu::MissSource327 MissSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_MISS, source_) {}
328 };
329
330 struct IntersectionSource : public ShaderSource
331 {
IntersectionSourceglu::IntersectionSource332 IntersectionSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_INTERSECTION, source_) {}
333 };
334
335 struct CallableSource : public ShaderSource
336 {
CallableSourceglu::CallableSource337 CallableSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_CALLABLE, source_) {}
338 };
339
340 struct ProgramSources
341 {
342 std::vector<std::string> sources[SHADERTYPE_LAST];
343 std::vector<AttribLocationBinding> attribLocationBindings;
344
345 deUint32 transformFeedbackBufferMode; //!< TF buffer mode, or GL_NONE.
346 std::vector<std::string> transformFeedbackVaryings;
347 bool separable;
348
ProgramSourcesglu::ProgramSources349 ProgramSources (void) : transformFeedbackBufferMode(0), separable(false) {}
350
operator <<glu::ProgramSources351 ProgramSources& operator<< (const AttribLocationBinding& binding) { attribLocationBindings.push_back(binding); return *this; }
operator <<glu::ProgramSources352 ProgramSources& operator<< (const TransformFeedbackMode& mode) { transformFeedbackBufferMode = mode.mode; return *this; }
operator <<glu::ProgramSources353 ProgramSources& operator<< (const TransformFeedbackVarying& varying) { transformFeedbackVaryings.push_back(varying.name); return *this; }
operator <<glu::ProgramSources354 ProgramSources& operator<< (const ShaderSource& shaderSource) { sources[shaderSource.shaderType].push_back(shaderSource.source); return *this; }
operator <<glu::ProgramSources355 ProgramSources& operator<< (const ProgramSeparable& progSeparable) { separable = progSeparable.separable; return *this; }
356
357 template<typename Iterator>
358 ProgramSources& operator<< (const TransformFeedbackVaryings<Iterator>& varyings);
359 };
360
361 struct SpecializationData
362 {
363 deUint32 index;
364 deUint32 value;
365
SpecializationDataglu::SpecializationData366 SpecializationData (void) : index(0), value(0) {}
SpecializationDataglu::SpecializationData367 SpecializationData (const deUint32 index_, const deUint32 value_) : index(index_), value(value_) {}
368 };
369
370 struct ShaderBinary
371 {
372 ShaderBinaryDataType binary;
373 std::vector<ShaderType> shaderTypes;
374 std::vector<std::string> shaderEntryPoints;
375 std::vector<deUint32> specializationIndices;
376 std::vector<deUint32> specializationValues;
377
ShaderBinaryglu::ShaderBinary378 ShaderBinary (void) {}
ShaderBinaryglu::ShaderBinary379 ShaderBinary (const ShaderBinaryDataType binary_) : binary(binary_)
380 {
381 DE_ASSERT(!binary_.empty());
382 }
ShaderBinaryglu::ShaderBinary383 ShaderBinary (const ShaderBinaryDataType binary_, glu::ShaderType shaderType_) : binary(binary_)
384 {
385 DE_ASSERT(!binary_.empty());
386 shaderTypes.push_back(shaderType_);
387 shaderEntryPoints.push_back("main");
388 }
389
operator <<glu::ShaderBinary390 ShaderBinary& operator<< (const ShaderType& shaderType)
391 {
392 shaderTypes.push_back(shaderType);
393 return *this;
394 }
395
operator <<glu::ShaderBinary396 ShaderBinary& operator<< (const std::string& entryPoint)
397 {
398 shaderEntryPoints.push_back(entryPoint);
399 return *this;
400 }
401
operator <<glu::ShaderBinary402 ShaderBinary& operator<< (const SpecializationData& specData)
403 {
404 specializationIndices.push_back(specData.index);
405 specializationValues.push_back(specData.value);
406 return *this;
407 }
408 };
409
410 struct VertexBinary : public ShaderBinary
411 {
VertexBinaryglu::VertexBinary412 VertexBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_VERTEX) {}
413 };
414
415 struct FragmentBinary : public ShaderBinary
416 {
FragmentBinaryglu::FragmentBinary417 FragmentBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_FRAGMENT) {}
418 };
419
420 struct GeometryBinary : public ShaderBinary
421 {
GeometryBinaryglu::GeometryBinary422 GeometryBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_GEOMETRY) {}
423 };
424
425 struct ComputeBinary : public ShaderBinary
426 {
ComputeBinaryglu::ComputeBinary427 ComputeBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_COMPUTE) {}
428 };
429
430 struct TessellationControlBinary : public ShaderBinary
431 {
TessellationControlBinaryglu::TessellationControlBinary432 TessellationControlBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_CONTROL) {}
433 };
434
435 struct TessellationEvaluationBinary : public ShaderBinary
436 {
TessellationEvaluationBinaryglu::TessellationEvaluationBinary437 TessellationEvaluationBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_EVALUATION) {}
438 };
439
440 struct ProgramBinaries
441 {
442 std::vector<ShaderBinary> binaries;
443
444 glw::GLenum binaryFormat;
445
ProgramBinariesglu::ProgramBinaries446 ProgramBinaries (void) : binaryFormat(GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {}
ProgramBinariesglu::ProgramBinaries447 ProgramBinaries (glw::GLenum binaryFormat_) : binaryFormat(binaryFormat_) {}
448
operator <<glu::ProgramBinaries449 ProgramBinaries& operator<< (const ShaderBinary& shaderBinary) { binaries.push_back(shaderBinary); return *this; }
450 };
451
452 template<typename Iterator>
operator <<(const TransformFeedbackVaryings<Iterator> & varyings)453 inline ProgramSources& ProgramSources::operator<< (const TransformFeedbackVaryings<Iterator>& varyings)
454 {
455 for (Iterator cur = varyings.begin; cur != varyings.end; ++cur)
456 transformFeedbackVaryings.push_back(*cur);
457 return *this;
458 }
459
460 //! Helper for constructing vertex-fragment source pair.
makeVtxFragSources(const std::string & vertexSrc,const std::string & fragmentSrc)461 inline ProgramSources makeVtxFragSources (const std::string& vertexSrc, const std::string& fragmentSrc)
462 {
463 ProgramSources sources;
464 sources.sources[SHADERTYPE_VERTEX].push_back(vertexSrc);
465 sources.sources[SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
466 return sources;
467 }
468
469 } // glu
470
471 #endif // _GLUSHADERPROGRAM_HPP
472