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