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