Home | History | Annotate | Download | only in glshared
      1 #ifndef _GLSSHADERRENDERCASE_HPP
      2 #define _GLSSHADERRENDERCASE_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements Quality Program OpenGL (ES) Module
      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 execute test.
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "tcuDefs.hpp"
     27 #include "tcuTestCase.hpp"
     28 #include "tcuVector.hpp"
     29 #include "tcuMatrix.hpp"
     30 #include "tcuTexture.hpp"
     31 #include "tcuSurface.hpp"
     32 #include "gluRenderContext.hpp"
     33 #include "gluContextInfo.hpp"
     34 #include "gluShaderProgram.hpp"
     35 
     36 #include <sstream>
     37 #include <string>
     38 
     39 namespace glu
     40 {
     41 class RenderContext;
     42 class Texture2D;
     43 class TextureCube;
     44 class Texture2DArray;
     45 class Texture3D;
     46 } // glu
     47 
     48 namespace deqp
     49 {
     50 namespace gls
     51 {
     52 
     53 // LineStream \todo [2011-10-17 pyry] Move to proper place!
     54 
     55 class LineStream
     56 {
     57 public:
     58 						LineStream		(int indent = 0)	{ m_indent = indent; }
     59 						~LineStream		(void)				{}
     60 
     61 	const char*			str				(void) const		{ m_string = m_stream.str(); return m_string.c_str(); }
     62 	LineStream&			operator<<		(const char* line)	{ for (int i = 0; i < m_indent; i++) { m_stream << "\t"; } m_stream << line << "\n"; return *this; }
     63 
     64 private:
     65 	int					m_indent;
     66 	std::ostringstream	m_stream;
     67 	mutable std::string	m_string;
     68 };
     69 
     70 class QuadGrid;
     71 
     72 // TextureBinding
     73 
     74 class TextureBinding
     75 {
     76 public:
     77 	enum Type
     78 	{
     79 		TYPE_NONE = 0,
     80 		TYPE_2D,
     81 		TYPE_CUBE_MAP,
     82 		TYPE_2D_ARRAY,
     83 		TYPE_3D,
     84 
     85 		TYPE_LAST
     86 	};
     87 
     88 								TextureBinding		(const glu::Texture2D* tex2D, const tcu::Sampler& sampler);
     89 								TextureBinding		(const glu::TextureCube* texCube, const tcu::Sampler& sampler);
     90 								TextureBinding		(const glu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler);
     91 								TextureBinding		(const glu::Texture3D* tex3D, const tcu::Sampler& sampler);
     92 								TextureBinding		(void);
     93 
     94 	void						setSampler			(const tcu::Sampler& sampler);
     95 	void						setTexture			(const glu::Texture2D* tex2D);
     96 	void						setTexture			(const glu::TextureCube* texCube);
     97 	void						setTexture			(const glu::Texture2DArray* tex2DArray);
     98 	void						setTexture			(const glu::Texture3D* tex3D);
     99 
    100 	Type						getType				(void) const { return m_type;		}
    101 	const tcu::Sampler&			getSampler			(void) const { return m_sampler;	}
    102 	const glu::Texture2D*		get2D				(void) const { DE_ASSERT(getType() == TYPE_2D);			return m_binding.tex2D;		}
    103 	const glu::TextureCube*		getCube				(void) const { DE_ASSERT(getType() == TYPE_CUBE_MAP);	return m_binding.texCube;	}
    104 	const glu::Texture2DArray*	get2DArray			(void) const { DE_ASSERT(getType() == TYPE_2D_ARRAY);	return m_binding.tex2DArray;}
    105 	const glu::Texture3D*		get3D				(void) const { DE_ASSERT(getType() == TYPE_3D);			return m_binding.tex3D;		}
    106 
    107 private:
    108 	Type					m_type;
    109 	tcu::Sampler			m_sampler;
    110 	union
    111 	{
    112 		const glu::Texture2D*		tex2D;
    113 		const glu::TextureCube*		texCube;
    114 		const glu::Texture2DArray*	tex2DArray;
    115 		const glu::Texture3D*		tex3D;
    116 	} m_binding;
    117 };
    118 
    119 // ShaderEvalContext.
    120 
    121 class ShaderEvalContext
    122 {
    123 public:
    124 	// Limits.
    125 	enum
    126 	{
    127 		MAX_USER_ATTRIBS	= 4,
    128 		MAX_TEXTURES		= 4,
    129 	};
    130 
    131 	struct ShaderSampler
    132 	{
    133 		tcu::Sampler				sampler;
    134 		const tcu::Texture2D*		tex2D;
    135 		const tcu::TextureCube*		texCube;
    136 		const tcu::Texture2DArray*	tex2DArray;
    137 		const tcu::Texture3D*		tex3D;
    138 
    139 		inline ShaderSampler (void)
    140 			: tex2D		(DE_NULL)
    141 			, texCube	(DE_NULL)
    142 			, tex2DArray(DE_NULL)
    143 			, tex3D		(DE_NULL)
    144 		{
    145 		}
    146 	};
    147 
    148 							ShaderEvalContext		(const QuadGrid& quadGrid);
    149 							~ShaderEvalContext		(void);
    150 
    151 	void					reset					(float sx, float sy);
    152 
    153 	// Inputs.
    154 	tcu::Vec4				coords;
    155 	tcu::Vec4				unitCoords;
    156 	tcu::Vec4				constCoords;
    157 
    158 	tcu::Vec4				in[MAX_USER_ATTRIBS];
    159 	ShaderSampler			textures[MAX_TEXTURES];
    160 
    161 	// Output.
    162 	tcu::Vec4				color;
    163 	bool					isDiscarded;
    164 
    165 	// Functions.
    166 	inline void				discard					(void)	{ isDiscarded = true; }
    167 	tcu::Vec4				texture2D				(int unitNdx, const tcu::Vec2& coords);
    168 
    169 private:
    170 	const QuadGrid&			quadGrid;
    171 };
    172 
    173 // ShaderEvalFunc.
    174 
    175 typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
    176 
    177 inline void evalCoordsPassthroughX		(ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
    178 inline void evalCoordsPassthroughXY		(ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
    179 inline void evalCoordsPassthroughXYZ	(ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
    180 inline void evalCoordsPassthrough		(ShaderEvalContext& c) { c.color = c.coords; }
    181 inline void evalCoordsSwizzleWZYX		(ShaderEvalContext& c) { c.color = c.coords.swizzle(3,2,1,0); }
    182 
    183 // ShaderEvaluator
    184 // Either inherit a class with overridden evaluate() or just pass in an evalFunc.
    185 
    186 class ShaderEvaluator
    187 {
    188 public:
    189 						ShaderEvaluator			(void);
    190 						ShaderEvaluator			(ShaderEvalFunc evalFunc);
    191 	virtual				~ShaderEvaluator		(void);
    192 
    193 	virtual void		evaluate				(ShaderEvalContext& ctx);
    194 
    195 private:
    196 						ShaderEvaluator			(const ShaderEvaluator&);	// not allowed!
    197 	ShaderEvaluator&	operator=				(const ShaderEvaluator&);	// not allowed!
    198 
    199 	ShaderEvalFunc		m_evalFunc;
    200 };
    201 
    202 // ShaderRenderCase.
    203 
    204 class ShaderRenderCase : public tcu::TestCase
    205 {
    206 public:
    207 								ShaderRenderCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc);
    208 								ShaderRenderCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, bool isVertexCase, ShaderEvaluator& evaluator);
    209 	virtual						~ShaderRenderCase		(void);
    210 
    211 	void						init					(void);
    212 	void						deinit					(void);
    213 
    214 	IterateResult				iterate					(void);
    215 
    216 protected:
    217 	virtual void				setupShaderData			(void);
    218 	virtual void				setup					(int programID);
    219 	virtual void				setupUniforms			(int programID, const tcu::Vec4& constCoords);
    220 
    221 	tcu::IVec2					getViewportSize			(void) const;
    222 
    223 	class CompileFailed : public tcu::TestError
    224 	{
    225 	public:
    226 		inline CompileFailed (const char* file, int line) : tcu::TestError("Failed to compile shader program", DE_NULL, file, line) {}
    227 	};
    228 
    229 private:
    230 								ShaderRenderCase		(const ShaderRenderCase&);		// not allowed!
    231 	ShaderRenderCase&			operator=				(const ShaderRenderCase&);		// not allowed!
    232 
    233 	void						setupDefaultInputs		(int programID);
    234 
    235 	void						render					(tcu::Surface& result, int programID, const QuadGrid& quadGrid);
    236 	void						computeVertexReference	(tcu::Surface& result, const QuadGrid& quadGrid);
    237 	void						computeFragmentReference(tcu::Surface& result, const QuadGrid& quadGrid);
    238 	bool						compareImages			(const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold);
    239 
    240 protected:
    241 	glu::RenderContext&			m_renderCtx;
    242 	const glu::ContextInfo&		m_ctxInfo;
    243 
    244 	bool						m_isVertexCase;
    245 	ShaderEvaluator				m_defaultEvaluator;
    246 	ShaderEvaluator&			m_evaluator;
    247 	std::string					m_vertShaderSource;
    248 	std::string					m_fragShaderSource;
    249 	tcu::Vec4					m_clearColor;
    250 
    251 	std::vector<tcu::Mat4>		m_userAttribTransforms;
    252 	std::vector<TextureBinding>	m_textures;
    253 
    254 	glu::ShaderProgram*			m_program;
    255 };
    256 
    257 // Helpers.
    258 // \todo [2012-04-10 pyry] Move these to separate utility?
    259 
    260 const char*		getIntUniformName			(int number);
    261 const char*		getFloatUniformName			(int number);
    262 const char*		getFloatFractionUniformName	(int number);
    263 
    264 void			setupDefaultUniforms		(const glu::RenderContext& context, deUint32 programID);
    265 
    266 } // gls
    267 } // deqp
    268 
    269 #endif // _GLSSHADERRENDERCASE_HPP
    270