Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL Shared Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Shared shader constant expression test components
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsShaderConstExprTests.hpp"
     25 #include "glsShaderLibrary.hpp"
     26 #include "glsShaderLibraryCase.hpp"
     27 
     28 #include "tcuStringTemplate.hpp"
     29 
     30 #include "deStringUtil.hpp"
     31 #include "deMath.h"
     32 
     33 namespace deqp
     34 {
     35 namespace gls
     36 {
     37 namespace ShaderConstExpr
     38 {
     39 
     40 static void addOutputVar (glu::sl::ValueBlock* dst, glu::DataType type, float output)
     41 {
     42 	dst->outputs.push_back(glu::sl::Value());
     43 
     44 	{
     45 		glu::sl::Value&	value	= dst->outputs.back();
     46 
     47 		value.name	= "out0";
     48 		value.type	= glu::VarType(type, glu::PRECISION_LAST);
     49 		value.elements.resize(1);
     50 
     51 		switch (type)
     52 		{
     53 			case glu::TYPE_INT:
     54 				value.elements[0].int32 = (int)output;
     55 				break;
     56 
     57 			case glu::TYPE_UINT:
     58 				value.elements[0].int32 = (unsigned int)output;
     59 				break;
     60 
     61 			case glu::TYPE_BOOL:
     62 				value.elements[0].bool32 = output!=0.0f;
     63 				break;
     64 
     65 			case glu::TYPE_FLOAT:
     66 				value.elements[0].float32 = output;
     67 				break;
     68 
     69 			default:
     70 				DE_ASSERT(false);
     71 		}
     72 	}
     73 }
     74 
     75 std::vector<tcu::TestNode*> createTests (tcu::TestContext&			testContext,
     76 										 glu::RenderContext&		renderContext,
     77 										 const glu::ContextInfo&	contextInfo,
     78 										 const TestParams*			cases,
     79 										 int						numCases,
     80 										 glu::GLSLVersion			version,
     81 										 TestShaderStage			testStage)
     82 {
     83 	using std::string;
     84 	using std::vector;
     85 	using gls::ShaderLibraryCase;
     86 
     87 	// Needed for autogenerating shader code for increased component counts
     88 	DE_STATIC_ASSERT(glu::TYPE_FLOAT+1 == glu::TYPE_FLOAT_VEC2);
     89 	DE_STATIC_ASSERT(glu::TYPE_FLOAT+2 == glu::TYPE_FLOAT_VEC3);
     90 	DE_STATIC_ASSERT(glu::TYPE_FLOAT+3 == glu::TYPE_FLOAT_VEC4);
     91 
     92 	DE_STATIC_ASSERT(glu::TYPE_INT+1 == glu::TYPE_INT_VEC2);
     93 	DE_STATIC_ASSERT(glu::TYPE_INT+2 == glu::TYPE_INT_VEC3);
     94 	DE_STATIC_ASSERT(glu::TYPE_INT+3 == glu::TYPE_INT_VEC4);
     95 
     96 	DE_STATIC_ASSERT(glu::TYPE_UINT+1 == glu::TYPE_UINT_VEC2);
     97 	DE_STATIC_ASSERT(glu::TYPE_UINT+2 == glu::TYPE_UINT_VEC3);
     98 	DE_STATIC_ASSERT(glu::TYPE_UINT+3 == glu::TYPE_UINT_VEC4);
     99 
    100 	DE_STATIC_ASSERT(glu::TYPE_BOOL+1 == glu::TYPE_BOOL_VEC2);
    101 	DE_STATIC_ASSERT(glu::TYPE_BOOL+2 == glu::TYPE_BOOL_VEC3);
    102 	DE_STATIC_ASSERT(glu::TYPE_BOOL+3 == glu::TYPE_BOOL_VEC4);
    103 
    104 	DE_ASSERT(testStage);
    105 
    106 	const char* shaderTemplateSrc =
    107 		"#version ${GLES_VERSION}\n"
    108 		"precision highp float;\n"
    109 		"precision highp int;\n"
    110 		"${DECLARATIONS}\n"
    111 		"void main()\n"
    112 		"{\n"
    113 		"	const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n"
    114 		"	out0 = cval;\n"
    115 		"	${OUTPUT}\n"
    116 		"}\n";
    117 
    118 	const tcu::StringTemplate	shaderTemplate	(shaderTemplateSrc);
    119 	vector<tcu::TestNode*>		ret;
    120 
    121 	for (int caseNdx = 0; caseNdx < numCases; caseNdx++)
    122 	{
    123 		std::map<string, string>	shaderTemplateParams;
    124 		const int					minComponents	= cases[caseNdx].minComponents;
    125 		const int					maxComponents	= cases[caseNdx].maxComponents;
    126 		const DataType				inType			= cases[caseNdx].inType;
    127 		const DataType				outType			= cases[caseNdx].outType;
    128 		const string				expression		= cases[caseNdx].expression;
    129 		// Check for presence of func(vec, scalar) style specialization, use as gatekeeper for applying said specialization
    130 		const bool					alwaysScalar	= expression.find("${MT}")!=string::npos;
    131 
    132 		shaderTemplateParams["GLES_VERSION"]	= version == glu::GLSL_VERSION_300_ES ? "300 es" : "100";
    133 		shaderTemplateParams["CASE_BASE_TYPE"]	= glu::getDataTypeName(outType);
    134 		shaderTemplateParams["DECLARATIONS"]	= "${DECLARATIONS}";
    135 		shaderTemplateParams["OUTPUT"]			= "${OUTPUT}";
    136 
    137 		for (int compCount = minComponents-1; compCount < maxComponents; compCount++)
    138 		{
    139 			vector<tcu::TestNode*>		children;
    140 			std::map<string, string>	expressionTemplateParams;
    141 			string						typeName			= glu::getDataTypeName((glu::DataType)(inType + compCount)); // results in float, vec2, vec3, vec4 progression (same for other primitive types)
    142 			const char*					componentAccess[]	= {"", ".y", ".z", ".w"};
    143 			const tcu::StringTemplate	expressionTemplate	(expression);
    144 			// Add type to case name if we are generating multiple versions
    145 			const string				caseName			= string(cases[caseNdx].name) + (minComponents==maxComponents ? "" : ("_" + typeName));
    146 
    147 			// ${T} => final type, ${MT} => final type but with scalar version usable even when T is a vector
    148 			expressionTemplateParams["T"]			= typeName;
    149 			expressionTemplateParams["MT"]			= typeName;
    150 
    151 			shaderTemplateParams["CASE_EXPRESSION"]	= expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount]; // Add vector access to expression as needed
    152 
    153 			{
    154 				const string mapped = shaderTemplate.specialize(shaderTemplateParams);
    155 
    156 				if (testStage & SHADER_VERTEX)
    157 				{
    158 					glu::sl::ShaderCaseSpecification	spec;
    159 
    160 					spec.targetVersion	= version;
    161 					spec.expectResult	= glu::sl::EXPECT_PASS;
    162 					spec.caseType		= glu::sl::CASETYPE_VERTEX_ONLY;
    163 					spec.programs.resize(1);
    164 
    165 					spec.programs[0].sources << glu::VertexSource(mapped);
    166 
    167 					addOutputVar(&spec.values, outType, cases[caseNdx].output);
    168 
    169 					ret.push_back(new ShaderLibraryCase(testContext,
    170 														renderContext,
    171 														contextInfo,
    172 														(caseName + "_vertex").c_str(),
    173 														"",
    174 														spec));
    175 				}
    176 
    177 				if (testStage & SHADER_FRAGMENT)
    178 				{
    179 					glu::sl::ShaderCaseSpecification	spec;
    180 
    181 					spec.targetVersion	= version;
    182 					spec.expectResult	= glu::sl::EXPECT_PASS;
    183 					spec.caseType		= glu::sl::CASETYPE_FRAGMENT_ONLY;
    184 					spec.programs.resize(1);
    185 
    186 					spec.programs[0].sources << glu::FragmentSource(mapped);
    187 
    188 					addOutputVar(&spec.values, outType, cases[caseNdx].output);
    189 
    190 					ret.push_back(new ShaderLibraryCase(testContext,
    191 														renderContext,
    192 														contextInfo,
    193 														(caseName + "_fragment").c_str(),
    194 														"",
    195 														spec));
    196 				}
    197 			}
    198 
    199 			// Deal with functions that allways accept one ore more scalar parameters even when others are vectors
    200 			if (alwaysScalar && compCount > 0)
    201 			{
    202 				const string	scalarCaseName	= string(cases[caseNdx].name) + "_" + typeName + "_" + glu::getDataTypeName(inType);
    203 
    204 				expressionTemplateParams["MT"] = glu::getDataTypeName(inType);
    205 				shaderTemplateParams["CASE_EXPRESSION"]	= expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount];
    206 
    207 				{
    208 					const string mapped = shaderTemplate.specialize(shaderTemplateParams);
    209 
    210 					if (testStage & SHADER_VERTEX)
    211 					{
    212 						glu::sl::ShaderCaseSpecification	spec;
    213 
    214 						spec.targetVersion	= version;
    215 						spec.expectResult	= glu::sl::EXPECT_PASS;
    216 						spec.caseType		= glu::sl::CASETYPE_VERTEX_ONLY;
    217 						spec.programs.resize(1);
    218 
    219 						spec.programs[0].sources << glu::VertexSource(mapped);
    220 
    221 						addOutputVar(&spec.values, outType, cases[caseNdx].output);
    222 
    223 						ret.push_back(new ShaderLibraryCase(testContext,
    224 															renderContext,
    225 															contextInfo,
    226 															(scalarCaseName + "_vertex").c_str(),
    227 															"",
    228 															spec));
    229 					}
    230 
    231 					if (testStage & SHADER_FRAGMENT)
    232 					{
    233 						glu::sl::ShaderCaseSpecification	spec;
    234 
    235 						spec.targetVersion	= version;
    236 						spec.expectResult	= glu::sl::EXPECT_PASS;
    237 						spec.caseType		= glu::sl::CASETYPE_FRAGMENT_ONLY;
    238 						spec.programs.resize(1);
    239 
    240 						spec.programs[0].sources << glu::FragmentSource(mapped);
    241 
    242 						addOutputVar(&spec.values, outType, cases[caseNdx].output);
    243 
    244 						ret.push_back(new ShaderLibraryCase(testContext,
    245 															renderContext,
    246 															contextInfo,
    247 															(scalarCaseName + "_fragment").c_str(),
    248 															"",
    249 															spec));
    250 					}
    251 				}
    252 			}
    253 		}
    254 	}
    255 
    256 	return ret;
    257 }
    258 
    259 } // ShaderConstExpr
    260 } // gls
    261 } // deqp
    262