Fix flakiness in mailbox.display_timing
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsRandomShaderProgram.cpp
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
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
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
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
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
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
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
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
155 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
169 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
248 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