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