1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) 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 sglr-rsg adaptation.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "glsRandomShaderProgram.hpp"
25 #include "rsgShader.hpp"
26 
27 namespace deqp
28 {
29 namespace gls
30 {
31 
32 using std::vector;
33 
mapToGenericVecType(const rsg::VariableType & varType)34 static rr::GenericVecType mapToGenericVecType (const rsg::VariableType& varType)
35 {
36 	if (varType.isFloatOrVec())
37 		return rr::GENERICVECTYPE_FLOAT;
38 	else if (varType.isIntOrVec())
39 		return rr::GENERICVECTYPE_INT32;
40 	else
41 	{
42 		DE_ASSERT(false);
43 		return rr::GENERICVECTYPE_LAST;
44 	}
45 }
46 
mapToBasicType(const rsg::VariableType & varType)47 static glu::DataType mapToBasicType (const rsg::VariableType& varType)
48 {
49 	if (varType.isFloatOrVec() || varType.isIntOrVec() || varType.isBoolOrVec())
50 	{
51 		const glu::DataType		scalarType		= varType.isFloatOrVec()	? glu::TYPE_FLOAT	:
52 												  varType.isIntOrVec()		? glu::TYPE_INT		:
53 												  varType.isBoolOrVec()		? glu::TYPE_BOOL	: glu::TYPE_LAST;
54 		const int				numComps		= varType.getNumElements();
55 
56 		DE_ASSERT(de::inRange(numComps, 1, 4));
57 		return glu::DataType(scalarType + numComps - 1);
58 	}
59 	else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_2D)
60 		return glu::TYPE_SAMPLER_2D;
61 	else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_CUBE)
62 		return glu::TYPE_SAMPLER_CUBE;
63 	else
64 	{
65 		DE_ASSERT(false);
66 		return glu::TYPE_LAST;
67 	}
68 }
69 
generateProgramDeclaration(sglr::pdec::ShaderProgramDeclaration & decl,const rsg::Shader & vertexShader,const rsg::Shader & fragmentShader,int numUnifiedUniforms,const rsg::ShaderInput * const * unifiedUniforms)70 static void generateProgramDeclaration (sglr::pdec::ShaderProgramDeclaration& decl, const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
71 {
72 	decl << sglr::pdec::VertexSource(vertexShader.getSource())
73 		 << sglr::pdec::FragmentSource(fragmentShader.getSource());
74 
75 	for (vector<rsg::ShaderInput*>::const_iterator vtxInIter = vertexShader.getInputs().begin(); vtxInIter != vertexShader.getInputs().end(); ++vtxInIter)
76 	{
77 		const rsg::ShaderInput*	vertexInput	= *vtxInIter;
78 		decl << sglr::pdec::VertexAttribute(vertexInput->getVariable()->getName(), mapToGenericVecType(vertexInput->getVariable()->getType()));
79 	}
80 
81 	for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
82 	{
83 		const rsg::ShaderInput*	fragInput	= *fragInIter;
84 		decl << sglr::pdec::VertexToFragmentVarying(mapToGenericVecType(fragInput->getVariable()->getType()));
85 	}
86 
87 	for (int uniformNdx = 0; uniformNdx < numUnifiedUniforms; uniformNdx++)
88 	{
89 		const rsg::ShaderInput*	uniform	= unifiedUniforms[uniformNdx];
90 		decl << sglr::pdec::Uniform(uniform->getVariable()->getName(), mapToBasicType(uniform->getVariable()->getType()));
91 	}
92 
93 	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
94 }
95 
generateProgramDeclaration(const rsg::Shader & vertexShader,const rsg::Shader & fragmentShader,int numUnifiedUniforms,const rsg::ShaderInput * const * unifiedUniforms)96 static sglr::pdec::ShaderProgramDeclaration generateProgramDeclaration (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
97 {
98 	sglr::pdec::ShaderProgramDeclaration decl;
99 	generateProgramDeclaration(decl, vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms);
100 	return decl;
101 }
102 
findShaderOutputByName(const rsg::Shader & shader,const char * name)103 static const rsg::Variable* findShaderOutputByName (const rsg::Shader& shader, const char* name)
104 {
105 	vector<const rsg::Variable*> outputs;
106 	shader.getOutputs(outputs);
107 
108 	for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); ++iter)
109 	{
110 		if (deStringEqual((*iter)->getName(), name))
111 			return *iter;
112 	}
113 
114 	return DE_NULL;
115 }
116 
findShaderOutputByLocation(const rsg::Shader & shader,int location)117 static const rsg::Variable* findShaderOutputByLocation (const rsg::Shader& shader, int location)
118 {
119 	vector<const rsg::Variable*> outputs;
120 	shader.getOutputs(outputs);
121 
122 	for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); iter++)
123 	{
124 		if ((*iter)->getLayoutLocation() == location)
125 			return *iter;
126 	}
127 
128 	return DE_NULL;
129 }
130 
RandomShaderProgram(const rsg::Shader & vertexShader,const rsg::Shader & fragmentShader,int numUnifiedUniforms,const rsg::ShaderInput * const * unifiedUniforms)131 RandomShaderProgram::RandomShaderProgram (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
132 	: sglr::ShaderProgram	(generateProgramDeclaration(vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms))
133 	, m_vertexShader		(vertexShader)
134 	, m_fragmentShader		(fragmentShader)
135 	, m_numUnifiedUniforms	(numUnifiedUniforms)
136 	, m_unifiedUniforms		(unifiedUniforms)
137 	, m_positionVar			(findShaderOutputByName(vertexShader, "gl_Position"))
138 	, m_fragColorVar		(findShaderOutputByLocation(fragmentShader, 0))
139 	, m_execCtx				(m_sampler2DMap, m_samplerCubeMap)
140 {
141 	TCU_CHECK_INTERNAL(m_positionVar && m_positionVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_positionVar->getType().getNumElements() == 4);
142 	TCU_CHECK_INTERNAL(m_fragColorVar && m_fragColorVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_fragColorVar->getType().getNumElements() == 4);
143 
144 	// Build list of vertex outputs.
145 	for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
146 	{
147 		const rsg::ShaderInput*	fragInput		= *fragInIter;
148 		const rsg::Variable*	vertexOutput	= findShaderOutputByName(vertexShader, fragInput->getVariable()->getName());
149 
150 		TCU_CHECK_INTERNAL(vertexOutput);
151 		m_vertexOutputs.push_back(vertexOutput);
152 	}
153 }
154 
refreshUniforms(void) const155 void RandomShaderProgram::refreshUniforms (void) const
156 {
157 	DE_ASSERT(m_numUnifiedUniforms == (int)m_uniforms.size());
158 
159 	for (int uniformNdx = 0; uniformNdx < m_numUnifiedUniforms; uniformNdx++)
160 	{
161 		const rsg::Variable*		uniformVar	= m_unifiedUniforms[uniformNdx]->getVariable();
162 		const rsg::VariableType&	uniformType	= uniformVar->getType();
163 		const sglr::UniformSlot&	uniformSlot	= m_uniforms[uniformNdx];
164 
165 		m_execCtx.getValue(uniformVar) = rsg::ConstValueAccess(uniformType, (const rsg::Scalar*)&uniformSlot.value).value();
166 	}
167 }
168 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const169 void RandomShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
170 {
171 	// \todo [2013-12-13 pyry] Do only when necessary.
172 	refreshUniforms();
173 
174 	int packetOffset = 0;
175 
176 	while (packetOffset < numPackets)
177 	{
178 		const int	numToExecute	= de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH);
179 
180 		// Fetch attributes.
181 		for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
182 		{
183 			const rsg::Variable*		attribVar		= m_vertexShader.getInputs()[attribNdx]->getVariable();
184 			const rsg::VariableType&	attribType		= attribVar->getType();
185 			const int					numComponents	= attribType.getNumElements();
186 			rsg::ExecValueAccess		access			= m_execCtx.getValue(attribVar);
187 
188 			DE_ASSERT(attribType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
189 
190 			for (int ndx = 0; ndx < numToExecute; ndx++)
191 			{
192 				const int				packetNdx	= ndx+packetOffset;
193 				const rr::VertexPacket*	packet		= packets[packetNdx];
194 				const tcu::Vec4			attribValue	= rr::readVertexAttribFloat(inputs[attribNdx], packet->instanceNdx, packet->vertexNdx);
195 
196 										access.component(0).asFloat(ndx) = attribValue[0];
197 				if (numComponents >= 2)	access.component(1).asFloat(ndx) = attribValue[1];
198 				if (numComponents >= 3)	access.component(2).asFloat(ndx) = attribValue[2];
199 				if (numComponents >= 4)	access.component(3).asFloat(ndx) = attribValue[3];
200 			}
201 		}
202 
203 		m_vertexShader.execute(m_execCtx);
204 
205 		// Store position
206 		{
207 			const rsg::ExecConstValueAccess	access	= m_execCtx.getValue(m_positionVar);
208 
209 			for (int ndx = 0; ndx < numToExecute; ndx++)
210 			{
211 				const int			packetNdx	= ndx+packetOffset;
212 				rr::VertexPacket*	packet		= packets[packetNdx];
213 
214 				packet->position[0] = access.component(0).asFloat(ndx);
215 				packet->position[1] = access.component(1).asFloat(ndx);
216 				packet->position[2] = access.component(2).asFloat(ndx);
217 				packet->position[3] = access.component(3).asFloat(ndx);
218 			}
219 		}
220 
221 		// Other varyings
222 		for (int varNdx = 0; varNdx < (int)m_vertexOutputs.size(); varNdx++)
223 		{
224 			const rsg::Variable*			var				= m_vertexOutputs[varNdx];
225 			const rsg::VariableType&		varType			= var->getType();
226 			const int						numComponents	= varType.getNumElements();
227 			const rsg::ExecConstValueAccess	access			= m_execCtx.getValue(var);
228 
229 			DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
230 
231 			for (int ndx = 0; ndx < numToExecute; ndx++)
232 			{
233 				const int				packetNdx	= ndx+packetOffset;
234 				rr::VertexPacket* const	packet		= packets[packetNdx];
235 				float* const			dst			= packet->outputs[varNdx].getAccess<float>();
236 
237 										dst[0] = access.component(0).asFloat(ndx);
238 				if (numComponents >= 2) dst[1] = access.component(1).asFloat(ndx);
239 				if (numComponents >= 3) dst[2] = access.component(2).asFloat(ndx);
240 				if (numComponents >= 4) dst[3] = access.component(3).asFloat(ndx);
241 			}
242 		}
243 
244 		packetOffset += numToExecute;
245 	}
246 }
247 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const248 void RandomShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
249 {
250 	const rsg::ExecConstValueAccess	fragColorAccess	= m_execCtx.getValue(m_fragColorVar);
251 	int								packetOffset	= 0;
252 
253 	DE_STATIC_ASSERT(rsg::EXEC_VEC_WIDTH % rr::NUM_FRAGMENTS_PER_PACKET == 0);
254 
255 	while (packetOffset < numPackets)
256 	{
257 		const int	numPacketsToExecute	= de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH / (int)rr::NUM_FRAGMENTS_PER_PACKET);
258 
259 		// Interpolate varyings.
260 		for (int varNdx = 0; varNdx < (int)m_fragmentShader.getInputs().size(); ++varNdx)
261 		{
262 			const rsg::Variable*		var				= m_fragmentShader.getInputs()[varNdx]->getVariable();
263 			const rsg::VariableType&	varType			= var->getType();
264 			const int					numComponents	= varType.getNumElements();
265 			rsg::ExecValueAccess		access			= m_execCtx.getValue(var);
266 
267 			DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
268 
269 			for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
270 			{
271 				const rr::FragmentPacket&	packet		= packets[packetOffset+packetNdx];
272 
273 				for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
274 				{
275 					const tcu::Vec4		varValue	= rr::readVarying<float>(packet, context, varNdx, fragNdx);
276 					const int			dstNdx		= packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
277 
278 											access.component(0).asFloat(dstNdx) = varValue[0];
279 					if (numComponents >= 2)	access.component(1).asFloat(dstNdx) = varValue[1];
280 					if (numComponents >= 3)	access.component(2).asFloat(dstNdx) = varValue[2];
281 					if (numComponents >= 4)	access.component(3).asFloat(dstNdx) = varValue[3];
282 				}
283 			}
284 		}
285 
286 		m_fragmentShader.execute(m_execCtx);
287 
288 		// Store color
289 		for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
290 		{
291 			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
292 			{
293 				const int		srcNdx	= packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
294 				const tcu::Vec4 color	(fragColorAccess.component(0).asFloat(srcNdx),
295 										 fragColorAccess.component(1).asFloat(srcNdx),
296 										 fragColorAccess.component(2).asFloat(srcNdx),
297 										 fragColorAccess.component(3).asFloat(srcNdx));
298 
299 				rr::writeFragmentOutput(context, packetOffset+packetNdx, fragNdx, 0, color);
300 			}
301 		}
302 
303 		packetOffset += numPacketsToExecute;
304 	}
305 }
306 
307 } // gls
308 } // deqp
309