xref: /aosp_15_r20/external/deqp/modules/glshared/glsRandomShaderProgram.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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