xref: /aosp_15_r20/external/deqp/modules/glshared/glsShaderExecUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL (ES) Module
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Shader execution utilities.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "glsShaderExecUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluProgramInterfaceQuery.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker #include <map>
42*35238bceSAndroid Build Coastguard Worker 
43*35238bceSAndroid Build Coastguard Worker namespace deqp
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker namespace gls
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker 
48*35238bceSAndroid Build Coastguard Worker namespace ShaderExecUtil
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker 
51*35238bceSAndroid Build Coastguard Worker using std::vector;
52*35238bceSAndroid Build Coastguard Worker 
isExtensionSupported(const glu::RenderContext & renderCtx,const std::string & extension)53*35238bceSAndroid Build Coastguard Worker static bool isExtensionSupported(const glu::RenderContext &renderCtx, const std::string &extension)
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = renderCtx.getFunctions();
56*35238bceSAndroid Build Coastguard Worker     int numExts              = 0;
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_NUM_EXTENSIONS, &numExts);
59*35238bceSAndroid Build Coastguard Worker 
60*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numExts; ndx++)
61*35238bceSAndroid Build Coastguard Worker     {
62*35238bceSAndroid Build Coastguard Worker         const char *curExt = (const char *)gl.getStringi(GL_EXTENSIONS, ndx);
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker         if (extension == curExt)
65*35238bceSAndroid Build Coastguard Worker             return true;
66*35238bceSAndroid Build Coastguard Worker     }
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker     return false;
69*35238bceSAndroid Build Coastguard Worker }
70*35238bceSAndroid Build Coastguard Worker 
checkExtension(const glu::RenderContext & renderCtx,const std::string & extension)71*35238bceSAndroid Build Coastguard Worker static void checkExtension(const glu::RenderContext &renderCtx, const std::string &extension)
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker     if (!isExtensionSupported(renderCtx, extension))
74*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError(extension + " is not supported");
75*35238bceSAndroid Build Coastguard Worker }
76*35238bceSAndroid Build Coastguard Worker 
checkLimit(const glu::RenderContext & renderCtx,uint32_t pname,int required)77*35238bceSAndroid Build Coastguard Worker static void checkLimit(const glu::RenderContext &renderCtx, uint32_t pname, int required)
78*35238bceSAndroid Build Coastguard Worker {
79*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = renderCtx.getFunctions();
80*35238bceSAndroid Build Coastguard Worker     int implementationLimit  = -1;
81*35238bceSAndroid Build Coastguard Worker     uint32_t error;
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(pname, &implementationLimit);
84*35238bceSAndroid Build Coastguard Worker     error = gl.getError();
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker     if (error != GL_NO_ERROR)
87*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("Failed to query " + de::toString(glu::getGettableStateStr(pname)) + " - got " +
88*35238bceSAndroid Build Coastguard Worker                              de::toString(glu::getErrorStr(error)));
89*35238bceSAndroid Build Coastguard Worker     if (implementationLimit < required)
90*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(pname)) +
91*35238bceSAndroid Build Coastguard Worker                                      " >= " + de::toString(required) + ", got " + de::toString(implementationLimit));
92*35238bceSAndroid Build Coastguard Worker }
93*35238bceSAndroid Build Coastguard Worker 
94*35238bceSAndroid Build Coastguard Worker // Shader utilities
95*35238bceSAndroid Build Coastguard Worker 
generateVertexShader(const ShaderSpec & shaderSpec,const std::string & inputPrefix,const std::string & outputPrefix)96*35238bceSAndroid Build Coastguard Worker static std::string generateVertexShader(const ShaderSpec &shaderSpec, const std::string &inputPrefix,
97*35238bceSAndroid Build Coastguard Worker                                         const std::string &outputPrefix)
98*35238bceSAndroid Build Coastguard Worker {
99*35238bceSAndroid Build Coastguard Worker     const bool usesInout = glu::glslVersionUsesInOutQualifiers(shaderSpec.version);
100*35238bceSAndroid Build Coastguard Worker     const char *in       = usesInout ? "in" : "attribute";
101*35238bceSAndroid Build Coastguard Worker     const char *out      = usesInout ? "out" : "varying";
102*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
103*35238bceSAndroid Build Coastguard Worker 
104*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
107*35238bceSAndroid Build Coastguard Worker 
108*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
109*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker     src << in << " highp vec4 a_position;\n";
112*35238bceSAndroid Build Coastguard Worker 
113*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
114*35238bceSAndroid Build Coastguard Worker         src << in << " " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
115*35238bceSAndroid Build Coastguard Worker 
116*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
117*35238bceSAndroid Build Coastguard Worker          ++output)
118*35238bceSAndroid Build Coastguard Worker     {
119*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(output->varType.isBasicType());
120*35238bceSAndroid Build Coastguard Worker 
121*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
122*35238bceSAndroid Build Coastguard Worker         {
123*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
124*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
125*35238bceSAndroid Build Coastguard Worker             const glu::VarType intType(intBaseType, glu::PRECISION_HIGHP);
126*35238bceSAndroid Build Coastguard Worker 
127*35238bceSAndroid Build Coastguard Worker             src << "flat " << out << " " << glu::declare(intType, outputPrefix + output->name) << ";\n";
128*35238bceSAndroid Build Coastguard Worker         }
129*35238bceSAndroid Build Coastguard Worker         else
130*35238bceSAndroid Build Coastguard Worker             src << "flat " << out << " " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
131*35238bceSAndroid Build Coastguard Worker     }
132*35238bceSAndroid Build Coastguard Worker 
133*35238bceSAndroid Build Coastguard Worker     src << "\n"
134*35238bceSAndroid Build Coastguard Worker         << "void main (void)\n"
135*35238bceSAndroid Build Coastguard Worker         << "{\n"
136*35238bceSAndroid Build Coastguard Worker         << "    gl_Position = a_position;\n"
137*35238bceSAndroid Build Coastguard Worker         << "    gl_PointSize = 1.0;\n\n";
138*35238bceSAndroid Build Coastguard Worker 
139*35238bceSAndroid Build Coastguard Worker     // Declare & fetch local input variables
140*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
141*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker     // Declare local output variables
144*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
145*35238bceSAndroid Build Coastguard Worker          ++output)
146*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(output->varType, output->name) << ";\n";
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker     // Operation - indented to correct level.
149*35238bceSAndroid Build Coastguard Worker     {
150*35238bceSAndroid Build Coastguard Worker         std::istringstream opSrc(shaderSpec.source);
151*35238bceSAndroid Build Coastguard Worker         std::string line;
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker         while (std::getline(opSrc, line))
154*35238bceSAndroid Build Coastguard Worker             src << "\t" << line << "\n";
155*35238bceSAndroid Build Coastguard Worker     }
156*35238bceSAndroid Build Coastguard Worker 
157*35238bceSAndroid Build Coastguard Worker     // Assignments to outputs.
158*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
159*35238bceSAndroid Build Coastguard Worker          ++output)
160*35238bceSAndroid Build Coastguard Worker     {
161*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
162*35238bceSAndroid Build Coastguard Worker         {
163*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
164*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "("
167*35238bceSAndroid Build Coastguard Worker                 << output->name << ");\n";
168*35238bceSAndroid Build Coastguard Worker         }
169*35238bceSAndroid Build Coastguard Worker         else
170*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
171*35238bceSAndroid Build Coastguard Worker     }
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker     src << "}\n";
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker     return src.str();
176*35238bceSAndroid Build Coastguard Worker }
177*35238bceSAndroid Build Coastguard Worker 
generateGeometryShader(const ShaderSpec & shaderSpec,const std::string & inputPrefix,const std::string & outputPrefix)178*35238bceSAndroid Build Coastguard Worker static std::string generateGeometryShader(const ShaderSpec &shaderSpec, const std::string &inputPrefix,
179*35238bceSAndroid Build Coastguard Worker                                           const std::string &outputPrefix)
180*35238bceSAndroid Build Coastguard Worker {
181*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
182*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
187*35238bceSAndroid Build Coastguard Worker 
188*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
189*35238bceSAndroid Build Coastguard Worker         src << "#extension GL_EXT_geometry_shader : require\n";
190*35238bceSAndroid Build Coastguard Worker 
191*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
192*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker     src << "layout(points) in;\n"
195*35238bceSAndroid Build Coastguard Worker         << "layout(points, max_vertices = 1) out;\n";
196*35238bceSAndroid Build Coastguard Worker 
197*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
198*35238bceSAndroid Build Coastguard Worker         src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n";
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
201*35238bceSAndroid Build Coastguard Worker          ++output)
202*35238bceSAndroid Build Coastguard Worker     {
203*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(output->varType.isBasicType());
204*35238bceSAndroid Build Coastguard Worker 
205*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
206*35238bceSAndroid Build Coastguard Worker         {
207*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
208*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
209*35238bceSAndroid Build Coastguard Worker             const glu::VarType intType(intBaseType, glu::PRECISION_HIGHP);
210*35238bceSAndroid Build Coastguard Worker 
211*35238bceSAndroid Build Coastguard Worker             src << "flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
212*35238bceSAndroid Build Coastguard Worker         }
213*35238bceSAndroid Build Coastguard Worker         else
214*35238bceSAndroid Build Coastguard Worker             src << "flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
215*35238bceSAndroid Build Coastguard Worker     }
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker     src << "\n"
218*35238bceSAndroid Build Coastguard Worker         << "void main (void)\n"
219*35238bceSAndroid Build Coastguard Worker         << "{\n"
220*35238bceSAndroid Build Coastguard Worker         << "    gl_Position = gl_in[0].gl_Position;\n\n";
221*35238bceSAndroid Build Coastguard Worker 
222*35238bceSAndroid Build Coastguard Worker     // Fetch input variables
223*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
224*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n";
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker     // Declare local output variables.
227*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
228*35238bceSAndroid Build Coastguard Worker          ++output)
229*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(output->varType, output->name) << ";\n";
230*35238bceSAndroid Build Coastguard Worker 
231*35238bceSAndroid Build Coastguard Worker     src << "\n";
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker     // Operation - indented to correct level.
234*35238bceSAndroid Build Coastguard Worker     {
235*35238bceSAndroid Build Coastguard Worker         std::istringstream opSrc(shaderSpec.source);
236*35238bceSAndroid Build Coastguard Worker         std::string line;
237*35238bceSAndroid Build Coastguard Worker 
238*35238bceSAndroid Build Coastguard Worker         while (std::getline(opSrc, line))
239*35238bceSAndroid Build Coastguard Worker             src << "\t" << line << "\n";
240*35238bceSAndroid Build Coastguard Worker     }
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker     // Assignments to outputs.
243*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
244*35238bceSAndroid Build Coastguard Worker          ++output)
245*35238bceSAndroid Build Coastguard Worker     {
246*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
247*35238bceSAndroid Build Coastguard Worker         {
248*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
249*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "("
252*35238bceSAndroid Build Coastguard Worker                 << output->name << ");\n";
253*35238bceSAndroid Build Coastguard Worker         }
254*35238bceSAndroid Build Coastguard Worker         else
255*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker     src << "    EmitVertex();\n"
259*35238bceSAndroid Build Coastguard Worker         << "    EndPrimitive();\n"
260*35238bceSAndroid Build Coastguard Worker         << "}\n";
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker     return src.str();
263*35238bceSAndroid Build Coastguard Worker }
264*35238bceSAndroid Build Coastguard Worker 
generateEmptyFragmentSource(glu::GLSLVersion version)265*35238bceSAndroid Build Coastguard Worker static std::string generateEmptyFragmentSource(glu::GLSLVersion version)
266*35238bceSAndroid Build Coastguard Worker {
267*35238bceSAndroid Build Coastguard Worker     const bool customOut = glu::glslVersionUsesInOutQualifiers(version);
268*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(version) << "\n";
271*35238bceSAndroid Build Coastguard Worker 
272*35238bceSAndroid Build Coastguard Worker     // \todo [2013-08-05 pyry] Do we need one unused output?
273*35238bceSAndroid Build Coastguard Worker 
274*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n{\n";
275*35238bceSAndroid Build Coastguard Worker     if (!customOut)
276*35238bceSAndroid Build Coastguard Worker         src << "    gl_FragColor = vec4(0.0);\n";
277*35238bceSAndroid Build Coastguard Worker     src << "}\n";
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker     return src.str();
280*35238bceSAndroid Build Coastguard Worker }
281*35238bceSAndroid Build Coastguard Worker 
generatePassthroughVertexShader(const ShaderSpec & shaderSpec,const std::string & inputPrefix,const std::string & outputPrefix)282*35238bceSAndroid Build Coastguard Worker static std::string generatePassthroughVertexShader(const ShaderSpec &shaderSpec, const std::string &inputPrefix,
283*35238bceSAndroid Build Coastguard Worker                                                    const std::string &outputPrefix)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker     // flat qualifier is not present in earlier versions?
286*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
287*35238bceSAndroid Build Coastguard Worker 
288*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"
291*35238bceSAndroid Build Coastguard Worker         << "in highp vec4 a_position;\n";
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
294*35238bceSAndroid Build Coastguard Worker     {
295*35238bceSAndroid Build Coastguard Worker         src << "in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"
296*35238bceSAndroid Build Coastguard Worker             << "flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n";
297*35238bceSAndroid Build Coastguard Worker     }
298*35238bceSAndroid Build Coastguard Worker 
299*35238bceSAndroid Build Coastguard Worker     src << "\nvoid main (void)\n{\n"
300*35238bceSAndroid Build Coastguard Worker         << "    gl_Position = a_position;\n"
301*35238bceSAndroid Build Coastguard Worker         << "    gl_PointSize = 1.0;\n";
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
304*35238bceSAndroid Build Coastguard Worker         src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n";
305*35238bceSAndroid Build Coastguard Worker 
306*35238bceSAndroid Build Coastguard Worker     src << "}\n";
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker     return src.str();
309*35238bceSAndroid Build Coastguard Worker }
310*35238bceSAndroid Build Coastguard Worker 
generateFragShaderOutputDecl(std::ostream & src,const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & outputPrefix)311*35238bceSAndroid Build Coastguard Worker static void generateFragShaderOutputDecl(std::ostream &src, const ShaderSpec &shaderSpec, bool useIntOutputs,
312*35238bceSAndroid Build Coastguard Worker                                          const std::map<std::string, int> &outLocationMap,
313*35238bceSAndroid Build Coastguard Worker                                          const std::string &outputPrefix)
314*35238bceSAndroid Build Coastguard Worker {
315*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
316*35238bceSAndroid Build Coastguard Worker 
317*35238bceSAndroid Build Coastguard Worker     for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx)
318*35238bceSAndroid Build Coastguard Worker     {
319*35238bceSAndroid Build Coastguard Worker         const Symbol &output         = shaderSpec.outputs[outNdx];
320*35238bceSAndroid Build Coastguard Worker         const int location           = de::lookup(outLocationMap, output.name);
321*35238bceSAndroid Build Coastguard Worker         const std::string outVarName = outputPrefix + output.name;
322*35238bceSAndroid Build Coastguard Worker         glu::VariableDeclaration decl(output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST,
323*35238bceSAndroid Build Coastguard Worker                                       glu::Layout(location));
324*35238bceSAndroid Build Coastguard Worker 
325*35238bceSAndroid Build Coastguard Worker         TCU_CHECK_INTERNAL(output.varType.isBasicType());
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker         if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType()))
328*35238bceSAndroid Build Coastguard Worker         {
329*35238bceSAndroid Build Coastguard Worker             const int vecSize                 = glu::getDataTypeScalarSize(output.varType.getBasicType());
330*35238bceSAndroid Build Coastguard Worker             const glu::DataType uintBasicType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
331*35238bceSAndroid Build Coastguard Worker             const glu::VarType uintType(uintBasicType, glu::PRECISION_HIGHP);
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker             decl.varType = uintType;
334*35238bceSAndroid Build Coastguard Worker             src << decl << ";\n";
335*35238bceSAndroid Build Coastguard Worker         }
336*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType()))
337*35238bceSAndroid Build Coastguard Worker         {
338*35238bceSAndroid Build Coastguard Worker             const int vecSize                = glu::getDataTypeScalarSize(output.varType.getBasicType());
339*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBasicType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
340*35238bceSAndroid Build Coastguard Worker             const glu::VarType intType(intBasicType, glu::PRECISION_HIGHP);
341*35238bceSAndroid Build Coastguard Worker 
342*35238bceSAndroid Build Coastguard Worker             decl.varType = intType;
343*35238bceSAndroid Build Coastguard Worker             src << decl << ";\n";
344*35238bceSAndroid Build Coastguard Worker         }
345*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeMatrix(output.varType.getBasicType()))
346*35238bceSAndroid Build Coastguard Worker         {
347*35238bceSAndroid Build Coastguard Worker             const int vecSize                 = glu::getDataTypeMatrixNumRows(output.varType.getBasicType());
348*35238bceSAndroid Build Coastguard Worker             const int numVecs                 = glu::getDataTypeMatrixNumColumns(output.varType.getBasicType());
349*35238bceSAndroid Build Coastguard Worker             const glu::DataType uintBasicType = glu::getDataTypeUintVec(vecSize);
350*35238bceSAndroid Build Coastguard Worker             const glu::VarType uintType(uintBasicType, glu::PRECISION_HIGHP);
351*35238bceSAndroid Build Coastguard Worker 
352*35238bceSAndroid Build Coastguard Worker             decl.varType = uintType;
353*35238bceSAndroid Build Coastguard Worker             for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
354*35238bceSAndroid Build Coastguard Worker             {
355*35238bceSAndroid Build Coastguard Worker                 decl.name            = outVarName + "_" + de::toString(vecNdx);
356*35238bceSAndroid Build Coastguard Worker                 decl.layout.location = location + vecNdx;
357*35238bceSAndroid Build Coastguard Worker                 src << decl << ";\n";
358*35238bceSAndroid Build Coastguard Worker             }
359*35238bceSAndroid Build Coastguard Worker         }
360*35238bceSAndroid Build Coastguard Worker         else
361*35238bceSAndroid Build Coastguard Worker             src << decl << ";\n";
362*35238bceSAndroid Build Coastguard Worker     }
363*35238bceSAndroid Build Coastguard Worker }
364*35238bceSAndroid Build Coastguard Worker 
generateFragShaderOutAssign(std::ostream & src,const ShaderSpec & shaderSpec,bool useIntOutputs,const std::string & valuePrefix,const std::string & outputPrefix)365*35238bceSAndroid Build Coastguard Worker static void generateFragShaderOutAssign(std::ostream &src, const ShaderSpec &shaderSpec, bool useIntOutputs,
366*35238bceSAndroid Build Coastguard Worker                                         const std::string &valuePrefix, const std::string &outputPrefix)
367*35238bceSAndroid Build Coastguard Worker {
368*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
369*35238bceSAndroid Build Coastguard Worker          ++output)
370*35238bceSAndroid Build Coastguard Worker     {
371*35238bceSAndroid Build Coastguard Worker         if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType()))
372*35238bceSAndroid Build Coastguard Worker             src << "    o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n";
373*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeMatrix(output->varType.getBasicType()))
374*35238bceSAndroid Build Coastguard Worker         {
375*35238bceSAndroid Build Coastguard Worker             const int numVecs = glu::getDataTypeMatrixNumColumns(output->varType.getBasicType());
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker             for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
378*35238bceSAndroid Build Coastguard Worker                 if (useIntOutputs)
379*35238bceSAndroid Build Coastguard Worker                     src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix
380*35238bceSAndroid Build Coastguard Worker                         << output->name << "[" << vecNdx << "]);\n";
381*35238bceSAndroid Build Coastguard Worker                 else
382*35238bceSAndroid Build Coastguard Worker                     src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name
383*35238bceSAndroid Build Coastguard Worker                         << "[" << vecNdx << "];\n";
384*35238bceSAndroid Build Coastguard Worker         }
385*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
386*35238bceSAndroid Build Coastguard Worker         {
387*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
388*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
389*35238bceSAndroid Build Coastguard Worker 
390*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "("
391*35238bceSAndroid Build Coastguard Worker                 << valuePrefix << output->name << ");\n";
392*35238bceSAndroid Build Coastguard Worker         }
393*35238bceSAndroid Build Coastguard Worker         else
394*35238bceSAndroid Build Coastguard Worker             src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n";
395*35238bceSAndroid Build Coastguard Worker     }
396*35238bceSAndroid Build Coastguard Worker }
397*35238bceSAndroid Build Coastguard Worker 
generateFragmentShader(const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & inputPrefix,const std::string & outputPrefix)398*35238bceSAndroid Build Coastguard Worker static std::string generateFragmentShader(const ShaderSpec &shaderSpec, bool useIntOutputs,
399*35238bceSAndroid Build Coastguard Worker                                           const std::map<std::string, int> &outLocationMap,
400*35238bceSAndroid Build Coastguard Worker                                           const std::string &inputPrefix, const std::string &outputPrefix)
401*35238bceSAndroid Build Coastguard Worker {
402*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
403*35238bceSAndroid Build Coastguard Worker 
404*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
409*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
410*35238bceSAndroid Build Coastguard Worker 
411*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
412*35238bceSAndroid Build Coastguard Worker         src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker     generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker     src << "\nvoid main (void)\n{\n";
417*35238bceSAndroid Build Coastguard Worker 
418*35238bceSAndroid Build Coastguard Worker     // Declare & fetch local input variables
419*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
420*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
421*35238bceSAndroid Build Coastguard Worker 
422*35238bceSAndroid Build Coastguard Worker     // Declare output variables
423*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
424*35238bceSAndroid Build Coastguard Worker          ++output)
425*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(output->varType, output->name) << ";\n";
426*35238bceSAndroid Build Coastguard Worker 
427*35238bceSAndroid Build Coastguard Worker     // Operation - indented to correct level.
428*35238bceSAndroid Build Coastguard Worker     {
429*35238bceSAndroid Build Coastguard Worker         std::istringstream opSrc(shaderSpec.source);
430*35238bceSAndroid Build Coastguard Worker         std::string line;
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker         while (std::getline(opSrc, line))
433*35238bceSAndroid Build Coastguard Worker             src << "\t" << line << "\n";
434*35238bceSAndroid Build Coastguard Worker     }
435*35238bceSAndroid Build Coastguard Worker 
436*35238bceSAndroid Build Coastguard Worker     generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix);
437*35238bceSAndroid Build Coastguard Worker 
438*35238bceSAndroid Build Coastguard Worker     src << "}\n";
439*35238bceSAndroid Build Coastguard Worker 
440*35238bceSAndroid Build Coastguard Worker     return src.str();
441*35238bceSAndroid Build Coastguard Worker }
442*35238bceSAndroid Build Coastguard Worker 
generatePassthroughFragmentShader(const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & inputPrefix,const std::string & outputPrefix)443*35238bceSAndroid Build Coastguard Worker static std::string generatePassthroughFragmentShader(const ShaderSpec &shaderSpec, bool useIntOutputs,
444*35238bceSAndroid Build Coastguard Worker                                                      const std::map<std::string, int> &outLocationMap,
445*35238bceSAndroid Build Coastguard Worker                                                      const std::string &inputPrefix, const std::string &outputPrefix)
446*35238bceSAndroid Build Coastguard Worker {
447*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
448*35238bceSAndroid Build Coastguard Worker 
449*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
450*35238bceSAndroid Build Coastguard Worker 
451*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
452*35238bceSAndroid Build Coastguard Worker 
453*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
454*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
455*35238bceSAndroid Build Coastguard Worker 
456*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end();
457*35238bceSAndroid Build Coastguard Worker          ++output)
458*35238bceSAndroid Build Coastguard Worker     {
459*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
460*35238bceSAndroid Build Coastguard Worker         {
461*35238bceSAndroid Build Coastguard Worker             const int vecSize               = glu::getDataTypeScalarSize(output->varType.getBasicType());
462*35238bceSAndroid Build Coastguard Worker             const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
463*35238bceSAndroid Build Coastguard Worker             const glu::VarType intType(intBaseType, glu::PRECISION_HIGHP);
464*35238bceSAndroid Build Coastguard Worker 
465*35238bceSAndroid Build Coastguard Worker             src << "flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n";
466*35238bceSAndroid Build Coastguard Worker         }
467*35238bceSAndroid Build Coastguard Worker         else
468*35238bceSAndroid Build Coastguard Worker             src << "flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n";
469*35238bceSAndroid Build Coastguard Worker     }
470*35238bceSAndroid Build Coastguard Worker 
471*35238bceSAndroid Build Coastguard Worker     generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
472*35238bceSAndroid Build Coastguard Worker 
473*35238bceSAndroid Build Coastguard Worker     src << "\nvoid main (void)\n{\n";
474*35238bceSAndroid Build Coastguard Worker 
475*35238bceSAndroid Build Coastguard Worker     generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix);
476*35238bceSAndroid Build Coastguard Worker 
477*35238bceSAndroid Build Coastguard Worker     src << "}\n";
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker     return src.str();
480*35238bceSAndroid Build Coastguard Worker }
481*35238bceSAndroid Build Coastguard Worker 
482*35238bceSAndroid Build Coastguard Worker // ShaderExecutor
483*35238bceSAndroid Build Coastguard Worker 
ShaderExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)484*35238bceSAndroid Build Coastguard Worker ShaderExecutor::ShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
485*35238bceSAndroid Build Coastguard Worker     : m_renderCtx(renderCtx)
486*35238bceSAndroid Build Coastguard Worker     , m_inputs(shaderSpec.inputs)
487*35238bceSAndroid Build Coastguard Worker     , m_outputs(shaderSpec.outputs)
488*35238bceSAndroid Build Coastguard Worker {
489*35238bceSAndroid Build Coastguard Worker }
490*35238bceSAndroid Build Coastguard Worker 
~ShaderExecutor(void)491*35238bceSAndroid Build Coastguard Worker ShaderExecutor::~ShaderExecutor(void)
492*35238bceSAndroid Build Coastguard Worker {
493*35238bceSAndroid Build Coastguard Worker }
494*35238bceSAndroid Build Coastguard Worker 
useProgram(void)495*35238bceSAndroid Build Coastguard Worker void ShaderExecutor::useProgram(void)
496*35238bceSAndroid Build Coastguard Worker {
497*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isOk());
498*35238bceSAndroid Build Coastguard Worker     m_renderCtx.getFunctions().useProgram(getProgram());
499*35238bceSAndroid Build Coastguard Worker }
500*35238bceSAndroid Build Coastguard Worker 
501*35238bceSAndroid Build Coastguard Worker // FragmentOutExecutor
502*35238bceSAndroid Build Coastguard Worker 
503*35238bceSAndroid Build Coastguard Worker struct FragmentOutputLayout
504*35238bceSAndroid Build Coastguard Worker {
505*35238bceSAndroid Build Coastguard Worker     std::vector<const Symbol *> locationSymbols; //! Symbols by location
506*35238bceSAndroid Build Coastguard Worker     std::map<std::string, int> locationMap;      //! Map from symbol name to start location
507*35238bceSAndroid Build Coastguard Worker };
508*35238bceSAndroid Build Coastguard Worker 
509*35238bceSAndroid Build Coastguard Worker class FragmentOutExecutor : public ShaderExecutor
510*35238bceSAndroid Build Coastguard Worker {
511*35238bceSAndroid Build Coastguard Worker public:
512*35238bceSAndroid Build Coastguard Worker     FragmentOutExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
513*35238bceSAndroid Build Coastguard Worker     ~FragmentOutExecutor(void);
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker     void execute(int numValues, const void *const *inputs, void *const *outputs);
516*35238bceSAndroid Build Coastguard Worker 
517*35238bceSAndroid Build Coastguard Worker protected:
518*35238bceSAndroid Build Coastguard Worker     const FragmentOutputLayout m_outputLayout;
519*35238bceSAndroid Build Coastguard Worker };
520*35238bceSAndroid Build Coastguard Worker 
computeFragmentOutputLayout(const std::vector<Symbol> & symbols)521*35238bceSAndroid Build Coastguard Worker static FragmentOutputLayout computeFragmentOutputLayout(const std::vector<Symbol> &symbols)
522*35238bceSAndroid Build Coastguard Worker {
523*35238bceSAndroid Build Coastguard Worker     FragmentOutputLayout ret;
524*35238bceSAndroid Build Coastguard Worker     int location = 0;
525*35238bceSAndroid Build Coastguard Worker 
526*35238bceSAndroid Build Coastguard Worker     for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it)
527*35238bceSAndroid Build Coastguard Worker     {
528*35238bceSAndroid Build Coastguard Worker         const int numLocations = glu::getDataTypeNumLocations(it->varType.getBasicType());
529*35238bceSAndroid Build Coastguard Worker 
530*35238bceSAndroid Build Coastguard Worker         TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name));
531*35238bceSAndroid Build Coastguard Worker         de::insert(ret.locationMap, it->name, location);
532*35238bceSAndroid Build Coastguard Worker         location += numLocations;
533*35238bceSAndroid Build Coastguard Worker 
534*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < numLocations; ++ndx)
535*35238bceSAndroid Build Coastguard Worker             ret.locationSymbols.push_back(&*it);
536*35238bceSAndroid Build Coastguard Worker     }
537*35238bceSAndroid Build Coastguard Worker 
538*35238bceSAndroid Build Coastguard Worker     return ret;
539*35238bceSAndroid Build Coastguard Worker }
540*35238bceSAndroid Build Coastguard Worker 
hasFloatRenderTargets(const glu::RenderContext & renderCtx)541*35238bceSAndroid Build Coastguard Worker inline bool hasFloatRenderTargets(const glu::RenderContext &renderCtx)
542*35238bceSAndroid Build Coastguard Worker {
543*35238bceSAndroid Build Coastguard Worker     glu::ContextType type = renderCtx.getType();
544*35238bceSAndroid Build Coastguard Worker     return glu::isContextTypeGLCore(type);
545*35238bceSAndroid Build Coastguard Worker }
546*35238bceSAndroid Build Coastguard Worker 
FragmentOutExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)547*35238bceSAndroid Build Coastguard Worker FragmentOutExecutor::FragmentOutExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
548*35238bceSAndroid Build Coastguard Worker     : ShaderExecutor(renderCtx, shaderSpec)
549*35238bceSAndroid Build Coastguard Worker     , m_outputLayout(computeFragmentOutputLayout(m_outputs))
550*35238bceSAndroid Build Coastguard Worker {
551*35238bceSAndroid Build Coastguard Worker }
552*35238bceSAndroid Build Coastguard Worker 
~FragmentOutExecutor(void)553*35238bceSAndroid Build Coastguard Worker FragmentOutExecutor::~FragmentOutExecutor(void)
554*35238bceSAndroid Build Coastguard Worker {
555*35238bceSAndroid Build Coastguard Worker }
556*35238bceSAndroid Build Coastguard Worker 
queryInt(const glw::Functions & gl,uint32_t pname)557*35238bceSAndroid Build Coastguard Worker inline int queryInt(const glw::Functions &gl, uint32_t pname)
558*35238bceSAndroid Build Coastguard Worker {
559*35238bceSAndroid Build Coastguard Worker     int value = 0;
560*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(pname, &value);
561*35238bceSAndroid Build Coastguard Worker     return value;
562*35238bceSAndroid Build Coastguard Worker }
563*35238bceSAndroid Build Coastguard Worker 
getRenderbufferFormatForOutput(const glu::VarType & outputType,bool useIntOutputs)564*35238bceSAndroid Build Coastguard Worker static tcu::TextureFormat getRenderbufferFormatForOutput(const glu::VarType &outputType, bool useIntOutputs)
565*35238bceSAndroid Build Coastguard Worker {
566*35238bceSAndroid Build Coastguard Worker     const tcu::TextureFormat::ChannelOrder channelOrderMap[] = {tcu::TextureFormat::R, tcu::TextureFormat::RG,
567*35238bceSAndroid Build Coastguard Worker                                                                 tcu::TextureFormat::RGBA, // No RGB variants available.
568*35238bceSAndroid Build Coastguard Worker                                                                 tcu::TextureFormat::RGBA};
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker     const glu::DataType basicType = outputType.getBasicType();
571*35238bceSAndroid Build Coastguard Worker     const int numComps            = glu::getDataTypeNumComponents(basicType);
572*35238bceSAndroid Build Coastguard Worker     tcu::TextureFormat::ChannelType channelType;
573*35238bceSAndroid Build Coastguard Worker 
574*35238bceSAndroid Build Coastguard Worker     switch (glu::getDataTypeScalarType(basicType))
575*35238bceSAndroid Build Coastguard Worker     {
576*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_UINT:
577*35238bceSAndroid Build Coastguard Worker         channelType = tcu::TextureFormat::UNSIGNED_INT32;
578*35238bceSAndroid Build Coastguard Worker         break;
579*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_INT:
580*35238bceSAndroid Build Coastguard Worker         channelType = tcu::TextureFormat::SIGNED_INT32;
581*35238bceSAndroid Build Coastguard Worker         break;
582*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_BOOL:
583*35238bceSAndroid Build Coastguard Worker         channelType = tcu::TextureFormat::SIGNED_INT32;
584*35238bceSAndroid Build Coastguard Worker         break;
585*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_FLOAT:
586*35238bceSAndroid Build Coastguard Worker         channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT;
587*35238bceSAndroid Build Coastguard Worker         break;
588*35238bceSAndroid Build Coastguard Worker     default:
589*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Invalid output type");
590*35238bceSAndroid Build Coastguard Worker     }
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap)));
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker     return tcu::TextureFormat(channelOrderMap[numComps - 1], channelType);
595*35238bceSAndroid Build Coastguard Worker }
596*35238bceSAndroid Build Coastguard Worker 
execute(int numValues,const void * const * inputs,void * const * outputs)597*35238bceSAndroid Build Coastguard Worker void FragmentOutExecutor::execute(int numValues, const void *const *inputs, void *const *outputs)
598*35238bceSAndroid Build Coastguard Worker {
599*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl      = m_renderCtx.getFunctions();
600*35238bceSAndroid Build Coastguard Worker     const bool useIntOutputs      = !hasFloatRenderTargets(m_renderCtx);
601*35238bceSAndroid Build Coastguard Worker     const int maxRenderbufferSize = queryInt(gl, GL_MAX_RENDERBUFFER_SIZE);
602*35238bceSAndroid Build Coastguard Worker     const int framebufferW        = de::min(maxRenderbufferSize, numValues);
603*35238bceSAndroid Build Coastguard Worker     const int framebufferH        = (numValues / framebufferW) + ((numValues % framebufferW != 0) ? 1 : 0);
604*35238bceSAndroid Build Coastguard Worker 
605*35238bceSAndroid Build Coastguard Worker     glu::Framebuffer framebuffer(m_renderCtx);
606*35238bceSAndroid Build Coastguard Worker     glu::RenderbufferVector renderbuffers(m_renderCtx, m_outputLayout.locationSymbols.size());
607*35238bceSAndroid Build Coastguard Worker 
608*35238bceSAndroid Build Coastguard Worker     vector<glu::VertexArrayBinding> vertexArrays;
609*35238bceSAndroid Build Coastguard Worker     vector<tcu::Vec2> positions(numValues);
610*35238bceSAndroid Build Coastguard Worker 
611*35238bceSAndroid Build Coastguard Worker     if (framebufferH > maxRenderbufferSize)
612*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Value count is too high for maximum supported renderbuffer size");
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     // Compute positions - 1px points are used to drive fragment shading.
615*35238bceSAndroid Build Coastguard Worker     for (int valNdx = 0; valNdx < numValues; valNdx++)
616*35238bceSAndroid Build Coastguard Worker     {
617*35238bceSAndroid Build Coastguard Worker         const int ix   = valNdx % framebufferW;
618*35238bceSAndroid Build Coastguard Worker         const int iy   = valNdx / framebufferW;
619*35238bceSAndroid Build Coastguard Worker         const float fx = -1.0f + 2.0f * ((float(ix) + 0.5f) / float(framebufferW));
620*35238bceSAndroid Build Coastguard Worker         const float fy = -1.0f + 2.0f * ((float(iy) + 0.5f) / float(framebufferH));
621*35238bceSAndroid Build Coastguard Worker 
622*35238bceSAndroid Build Coastguard Worker         positions[valNdx] = tcu::Vec2(fx, fy);
623*35238bceSAndroid Build Coastguard Worker     }
624*35238bceSAndroid Build Coastguard Worker 
625*35238bceSAndroid Build Coastguard Worker     // Vertex inputs.
626*35238bceSAndroid Build Coastguard Worker     vertexArrays.push_back(glu::va::Float("a_position", 2, numValues, 0, (const float *)&positions[0]));
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker     for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++)
629*35238bceSAndroid Build Coastguard Worker     {
630*35238bceSAndroid Build Coastguard Worker         const Symbol &symbol          = m_inputs[inputNdx];
631*35238bceSAndroid Build Coastguard Worker         const std::string attribName  = "a_" + symbol.name;
632*35238bceSAndroid Build Coastguard Worker         const void *ptr               = inputs[inputNdx];
633*35238bceSAndroid Build Coastguard Worker         const glu::DataType basicType = symbol.varType.getBasicType();
634*35238bceSAndroid Build Coastguard Worker         const int vecSize             = glu::getDataTypeScalarSize(basicType);
635*35238bceSAndroid Build Coastguard Worker 
636*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeFloatOrVec(basicType))
637*35238bceSAndroid Build Coastguard Worker             vertexArrays.push_back(glu::va::Float(attribName, vecSize, numValues, 0, (const float *)ptr));
638*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeIntOrIVec(basicType))
639*35238bceSAndroid Build Coastguard Worker             vertexArrays.push_back(glu::va::Int32(attribName, vecSize, numValues, 0, (const int32_t *)ptr));
640*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeUintOrUVec(basicType))
641*35238bceSAndroid Build Coastguard Worker             vertexArrays.push_back(glu::va::Uint32(attribName, vecSize, numValues, 0, (const uint32_t *)ptr));
642*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeMatrix(basicType))
643*35238bceSAndroid Build Coastguard Worker         {
644*35238bceSAndroid Build Coastguard Worker             int numRows = glu::getDataTypeMatrixNumRows(basicType);
645*35238bceSAndroid Build Coastguard Worker             int numCols = glu::getDataTypeMatrixNumColumns(basicType);
646*35238bceSAndroid Build Coastguard Worker             int stride  = numRows * numCols * (int)sizeof(float);
647*35238bceSAndroid Build Coastguard Worker 
648*35238bceSAndroid Build Coastguard Worker             for (int colNdx = 0; colNdx < numCols; ++colNdx)
649*35238bceSAndroid Build Coastguard Worker                 vertexArrays.push_back(glu::va::Float(attribName, colNdx, numRows, numValues, stride,
650*35238bceSAndroid Build Coastguard Worker                                                       ((const float *)ptr) + colNdx * numRows));
651*35238bceSAndroid Build Coastguard Worker         }
652*35238bceSAndroid Build Coastguard Worker         else
653*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
654*35238bceSAndroid Build Coastguard Worker     }
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker     // Construct framebuffer.
657*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
658*35238bceSAndroid Build Coastguard Worker 
659*35238bceSAndroid Build Coastguard Worker     for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx)
660*35238bceSAndroid Build Coastguard Worker     {
661*35238bceSAndroid Build Coastguard Worker         const Symbol &output        = *m_outputLayout.locationSymbols[outNdx];
662*35238bceSAndroid Build Coastguard Worker         const uint32_t renderbuffer = renderbuffers[outNdx];
663*35238bceSAndroid Build Coastguard Worker         const uint32_t format = glu::getInternalFormat(getRenderbufferFormatForOutput(output.varType, useIntOutputs));
664*35238bceSAndroid Build Coastguard Worker 
665*35238bceSAndroid Build Coastguard Worker         gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
666*35238bceSAndroid Build Coastguard Worker         gl.renderbufferStorage(GL_RENDERBUFFER, format, framebufferW, framebufferH);
667*35238bceSAndroid Build Coastguard Worker         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + outNdx, GL_RENDERBUFFER, renderbuffer);
668*35238bceSAndroid Build Coastguard Worker     }
669*35238bceSAndroid Build Coastguard Worker     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
670*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up framebuffer object");
671*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
672*35238bceSAndroid Build Coastguard Worker 
673*35238bceSAndroid Build Coastguard Worker     {
674*35238bceSAndroid Build Coastguard Worker         vector<uint32_t> drawBuffers(m_outputLayout.locationSymbols.size());
675*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < (int)m_outputLayout.locationSymbols.size(); ndx++)
676*35238bceSAndroid Build Coastguard Worker             drawBuffers[ndx] = GL_COLOR_ATTACHMENT0 + ndx;
677*35238bceSAndroid Build Coastguard Worker         gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]);
678*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffers()");
679*35238bceSAndroid Build Coastguard Worker     }
680*35238bceSAndroid Build Coastguard Worker 
681*35238bceSAndroid Build Coastguard Worker     // Render
682*35238bceSAndroid Build Coastguard Worker     gl.viewport(0, 0, framebufferW, framebufferH);
683*35238bceSAndroid Build Coastguard Worker     glu::draw(m_renderCtx, this->getProgram(), (int)vertexArrays.size(), &vertexArrays[0], glu::pr::Points(numValues));
684*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw");
685*35238bceSAndroid Build Coastguard Worker 
686*35238bceSAndroid Build Coastguard Worker     // Read back pixels.
687*35238bceSAndroid Build Coastguard Worker     {
688*35238bceSAndroid Build Coastguard Worker         tcu::TextureLevel tmpBuf;
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker         // \todo [2013-08-07 pyry] Some fast-paths could be added here.
691*35238bceSAndroid Build Coastguard Worker 
692*35238bceSAndroid Build Coastguard Worker         for (int outNdx = 0; outNdx < (int)m_outputs.size(); ++outNdx)
693*35238bceSAndroid Build Coastguard Worker         {
694*35238bceSAndroid Build Coastguard Worker             const Symbol &output            = m_outputs[outNdx];
695*35238bceSAndroid Build Coastguard Worker             const int outSize               = output.varType.getScalarSize();
696*35238bceSAndroid Build Coastguard Worker             const int outVecSize            = glu::getDataTypeNumComponents(output.varType.getBasicType());
697*35238bceSAndroid Build Coastguard Worker             const int outNumLocs            = glu::getDataTypeNumLocations(output.varType.getBasicType());
698*35238bceSAndroid Build Coastguard Worker             uint32_t *dstPtrBase            = static_cast<uint32_t *>(outputs[outNdx]);
699*35238bceSAndroid Build Coastguard Worker             const tcu::TextureFormat format = getRenderbufferFormatForOutput(output.varType, useIntOutputs);
700*35238bceSAndroid Build Coastguard Worker             const tcu::TextureFormat readFormat(tcu::TextureFormat::RGBA, format.type);
701*35238bceSAndroid Build Coastguard Worker             const int outLocation = de::lookup(m_outputLayout.locationMap, output.name);
702*35238bceSAndroid Build Coastguard Worker 
703*35238bceSAndroid Build Coastguard Worker             tmpBuf.setStorage(readFormat, framebufferW, framebufferH);
704*35238bceSAndroid Build Coastguard Worker 
705*35238bceSAndroid Build Coastguard Worker             for (int locNdx = 0; locNdx < outNumLocs; ++locNdx)
706*35238bceSAndroid Build Coastguard Worker             {
707*35238bceSAndroid Build Coastguard Worker                 gl.readBuffer(GL_COLOR_ATTACHMENT0 + outLocation + locNdx);
708*35238bceSAndroid Build Coastguard Worker                 glu::readPixels(m_renderCtx, 0, 0, tmpBuf.getAccess());
709*35238bceSAndroid Build Coastguard Worker                 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels");
710*35238bceSAndroid Build Coastguard Worker 
711*35238bceSAndroid Build Coastguard Worker                 if (outSize == 4 && outNumLocs == 1)
712*35238bceSAndroid Build Coastguard Worker                     deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues * outVecSize * sizeof(uint32_t));
713*35238bceSAndroid Build Coastguard Worker                 else
714*35238bceSAndroid Build Coastguard Worker                 {
715*35238bceSAndroid Build Coastguard Worker                     for (int valNdx = 0; valNdx < numValues; valNdx++)
716*35238bceSAndroid Build Coastguard Worker                     {
717*35238bceSAndroid Build Coastguard Worker                         const uint32_t *srcPtr = (const uint32_t *)tmpBuf.getAccess().getDataPtr() + valNdx * 4;
718*35238bceSAndroid Build Coastguard Worker                         uint32_t *dstPtr       = &dstPtrBase[outSize * valNdx + outVecSize * locNdx];
719*35238bceSAndroid Build Coastguard Worker                         deMemcpy(dstPtr, srcPtr, outVecSize * sizeof(uint32_t));
720*35238bceSAndroid Build Coastguard Worker                     }
721*35238bceSAndroid Build Coastguard Worker                 }
722*35238bceSAndroid Build Coastguard Worker             }
723*35238bceSAndroid Build Coastguard Worker         }
724*35238bceSAndroid Build Coastguard Worker     }
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker     // \todo [2013-08-07 pyry] Clear draw buffers & viewport?
727*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
728*35238bceSAndroid Build Coastguard Worker }
729*35238bceSAndroid Build Coastguard Worker 
730*35238bceSAndroid Build Coastguard Worker // VertexShaderExecutor
731*35238bceSAndroid Build Coastguard Worker 
732*35238bceSAndroid Build Coastguard Worker class VertexShaderExecutor : public FragmentOutExecutor
733*35238bceSAndroid Build Coastguard Worker {
734*35238bceSAndroid Build Coastguard Worker public:
735*35238bceSAndroid Build Coastguard Worker     VertexShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
736*35238bceSAndroid Build Coastguard Worker     ~VertexShaderExecutor(void);
737*35238bceSAndroid Build Coastguard Worker 
isOk(void) const738*35238bceSAndroid Build Coastguard Worker     bool isOk(void) const
739*35238bceSAndroid Build Coastguard Worker     {
740*35238bceSAndroid Build Coastguard Worker         return m_program.isOk();
741*35238bceSAndroid Build Coastguard Worker     }
log(tcu::TestLog & dst) const742*35238bceSAndroid Build Coastguard Worker     void log(tcu::TestLog &dst) const
743*35238bceSAndroid Build Coastguard Worker     {
744*35238bceSAndroid Build Coastguard Worker         dst << m_program;
745*35238bceSAndroid Build Coastguard Worker     }
getProgram(void) const746*35238bceSAndroid Build Coastguard Worker     uint32_t getProgram(void) const
747*35238bceSAndroid Build Coastguard Worker     {
748*35238bceSAndroid Build Coastguard Worker         return m_program.getProgram();
749*35238bceSAndroid Build Coastguard Worker     }
750*35238bceSAndroid Build Coastguard Worker 
751*35238bceSAndroid Build Coastguard Worker protected:
752*35238bceSAndroid Build Coastguard Worker     const glu::ShaderProgram m_program;
753*35238bceSAndroid Build Coastguard Worker };
754*35238bceSAndroid Build Coastguard Worker 
VertexShaderExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)755*35238bceSAndroid Build Coastguard Worker VertexShaderExecutor::VertexShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
756*35238bceSAndroid Build Coastguard Worker     : FragmentOutExecutor(renderCtx, shaderSpec)
757*35238bceSAndroid Build Coastguard Worker     , m_program(renderCtx, glu::ProgramSources()
758*35238bceSAndroid Build Coastguard Worker                                << glu::VertexSource(generateVertexShader(shaderSpec, "a_", "vtx_out_"))
759*35238bceSAndroid Build Coastguard Worker                                << glu::FragmentSource(
760*35238bceSAndroid Build Coastguard Worker                                       generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx),
761*35238bceSAndroid Build Coastguard Worker                                                                         m_outputLayout.locationMap, "vtx_out_", "o_")))
762*35238bceSAndroid Build Coastguard Worker {
763*35238bceSAndroid Build Coastguard Worker }
764*35238bceSAndroid Build Coastguard Worker 
~VertexShaderExecutor(void)765*35238bceSAndroid Build Coastguard Worker VertexShaderExecutor::~VertexShaderExecutor(void)
766*35238bceSAndroid Build Coastguard Worker {
767*35238bceSAndroid Build Coastguard Worker }
768*35238bceSAndroid Build Coastguard Worker 
769*35238bceSAndroid Build Coastguard Worker // GeometryShaderExecutor
770*35238bceSAndroid Build Coastguard Worker 
771*35238bceSAndroid Build Coastguard Worker class GeometryShaderExecutor : public FragmentOutExecutor
772*35238bceSAndroid Build Coastguard Worker {
773*35238bceSAndroid Build Coastguard Worker public:
774*35238bceSAndroid Build Coastguard Worker     static GeometryShaderExecutor *create(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
775*35238bceSAndroid Build Coastguard Worker 
776*35238bceSAndroid Build Coastguard Worker     ~GeometryShaderExecutor(void);
777*35238bceSAndroid Build Coastguard Worker 
isOk(void) const778*35238bceSAndroid Build Coastguard Worker     bool isOk(void) const
779*35238bceSAndroid Build Coastguard Worker     {
780*35238bceSAndroid Build Coastguard Worker         return m_program.isOk();
781*35238bceSAndroid Build Coastguard Worker     }
log(tcu::TestLog & dst) const782*35238bceSAndroid Build Coastguard Worker     void log(tcu::TestLog &dst) const
783*35238bceSAndroid Build Coastguard Worker     {
784*35238bceSAndroid Build Coastguard Worker         dst << m_program;
785*35238bceSAndroid Build Coastguard Worker     }
getProgram(void) const786*35238bceSAndroid Build Coastguard Worker     uint32_t getProgram(void) const
787*35238bceSAndroid Build Coastguard Worker     {
788*35238bceSAndroid Build Coastguard Worker         return m_program.getProgram();
789*35238bceSAndroid Build Coastguard Worker     }
790*35238bceSAndroid Build Coastguard Worker 
791*35238bceSAndroid Build Coastguard Worker protected:
792*35238bceSAndroid Build Coastguard Worker     const glu::ShaderProgram m_program;
793*35238bceSAndroid Build Coastguard Worker 
794*35238bceSAndroid Build Coastguard Worker private:
795*35238bceSAndroid Build Coastguard Worker     GeometryShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
796*35238bceSAndroid Build Coastguard Worker };
797*35238bceSAndroid Build Coastguard Worker 
create(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)798*35238bceSAndroid Build Coastguard Worker GeometryShaderExecutor *GeometryShaderExecutor::create(const glu::RenderContext &renderCtx,
799*35238bceSAndroid Build Coastguard Worker                                                        const ShaderSpec &shaderSpec)
800*35238bceSAndroid Build Coastguard Worker {
801*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES &&
802*35238bceSAndroid Build Coastguard Worker         !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5)))
803*35238bceSAndroid Build Coastguard Worker         checkExtension(renderCtx, "GL_EXT_geometry_shader");
804*35238bceSAndroid Build Coastguard Worker 
805*35238bceSAndroid Build Coastguard Worker     return new GeometryShaderExecutor(renderCtx, shaderSpec);
806*35238bceSAndroid Build Coastguard Worker }
807*35238bceSAndroid Build Coastguard Worker 
GeometryShaderExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)808*35238bceSAndroid Build Coastguard Worker GeometryShaderExecutor::GeometryShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
809*35238bceSAndroid Build Coastguard Worker     : FragmentOutExecutor(renderCtx, shaderSpec)
810*35238bceSAndroid Build Coastguard Worker     , m_program(renderCtx, glu::ProgramSources()
811*35238bceSAndroid Build Coastguard Worker                                << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_"))
812*35238bceSAndroid Build Coastguard Worker                                << glu::GeometrySource(generateGeometryShader(shaderSpec, "vtx_out_", "geom_out_"))
813*35238bceSAndroid Build Coastguard Worker                                << glu::FragmentSource(
814*35238bceSAndroid Build Coastguard Worker                                       generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx),
815*35238bceSAndroid Build Coastguard Worker                                                                         m_outputLayout.locationMap, "geom_out_", "o_")))
816*35238bceSAndroid Build Coastguard Worker {
817*35238bceSAndroid Build Coastguard Worker }
818*35238bceSAndroid Build Coastguard Worker 
~GeometryShaderExecutor(void)819*35238bceSAndroid Build Coastguard Worker GeometryShaderExecutor::~GeometryShaderExecutor(void)
820*35238bceSAndroid Build Coastguard Worker {
821*35238bceSAndroid Build Coastguard Worker }
822*35238bceSAndroid Build Coastguard Worker 
823*35238bceSAndroid Build Coastguard Worker // FragmentShaderExecutor
824*35238bceSAndroid Build Coastguard Worker 
825*35238bceSAndroid Build Coastguard Worker class FragmentShaderExecutor : public FragmentOutExecutor
826*35238bceSAndroid Build Coastguard Worker {
827*35238bceSAndroid Build Coastguard Worker public:
828*35238bceSAndroid Build Coastguard Worker     FragmentShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
829*35238bceSAndroid Build Coastguard Worker     ~FragmentShaderExecutor(void);
830*35238bceSAndroid Build Coastguard Worker 
isOk(void) const831*35238bceSAndroid Build Coastguard Worker     bool isOk(void) const
832*35238bceSAndroid Build Coastguard Worker     {
833*35238bceSAndroid Build Coastguard Worker         return m_program.isOk();
834*35238bceSAndroid Build Coastguard Worker     }
log(tcu::TestLog & dst) const835*35238bceSAndroid Build Coastguard Worker     void log(tcu::TestLog &dst) const
836*35238bceSAndroid Build Coastguard Worker     {
837*35238bceSAndroid Build Coastguard Worker         dst << m_program;
838*35238bceSAndroid Build Coastguard Worker     }
getProgram(void) const839*35238bceSAndroid Build Coastguard Worker     uint32_t getProgram(void) const
840*35238bceSAndroid Build Coastguard Worker     {
841*35238bceSAndroid Build Coastguard Worker         return m_program.getProgram();
842*35238bceSAndroid Build Coastguard Worker     }
843*35238bceSAndroid Build Coastguard Worker 
844*35238bceSAndroid Build Coastguard Worker protected:
845*35238bceSAndroid Build Coastguard Worker     const glu::ShaderProgram m_program;
846*35238bceSAndroid Build Coastguard Worker };
847*35238bceSAndroid Build Coastguard Worker 
FragmentShaderExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)848*35238bceSAndroid Build Coastguard Worker FragmentShaderExecutor::FragmentShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
849*35238bceSAndroid Build Coastguard Worker     : FragmentOutExecutor(renderCtx, shaderSpec)
850*35238bceSAndroid Build Coastguard Worker     , m_program(
851*35238bceSAndroid Build Coastguard Worker           renderCtx, glu::ProgramSources()
852*35238bceSAndroid Build Coastguard Worker                          << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_"))
853*35238bceSAndroid Build Coastguard Worker                          << glu::FragmentSource(generateFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx),
854*35238bceSAndroid Build Coastguard Worker                                                                        m_outputLayout.locationMap, "vtx_out_", "o_")))
855*35238bceSAndroid Build Coastguard Worker {
856*35238bceSAndroid Build Coastguard Worker }
857*35238bceSAndroid Build Coastguard Worker 
~FragmentShaderExecutor(void)858*35238bceSAndroid Build Coastguard Worker FragmentShaderExecutor::~FragmentShaderExecutor(void)
859*35238bceSAndroid Build Coastguard Worker {
860*35238bceSAndroid Build Coastguard Worker }
861*35238bceSAndroid Build Coastguard Worker 
862*35238bceSAndroid Build Coastguard Worker // Shared utilities for compute and tess executors
863*35238bceSAndroid Build Coastguard Worker 
getVecStd430ByteAlignment(glu::DataType type)864*35238bceSAndroid Build Coastguard Worker static uint32_t getVecStd430ByteAlignment(glu::DataType type)
865*35238bceSAndroid Build Coastguard Worker {
866*35238bceSAndroid Build Coastguard Worker     switch (glu::getDataTypeScalarSize(type))
867*35238bceSAndroid Build Coastguard Worker     {
868*35238bceSAndroid Build Coastguard Worker     case 1:
869*35238bceSAndroid Build Coastguard Worker         return 4u;
870*35238bceSAndroid Build Coastguard Worker     case 2:
871*35238bceSAndroid Build Coastguard Worker         return 8u;
872*35238bceSAndroid Build Coastguard Worker     case 3:
873*35238bceSAndroid Build Coastguard Worker         return 16u;
874*35238bceSAndroid Build Coastguard Worker     case 4:
875*35238bceSAndroid Build Coastguard Worker         return 16u;
876*35238bceSAndroid Build Coastguard Worker     default:
877*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
878*35238bceSAndroid Build Coastguard Worker         return 0u;
879*35238bceSAndroid Build Coastguard Worker     }
880*35238bceSAndroid Build Coastguard Worker }
881*35238bceSAndroid Build Coastguard Worker 
882*35238bceSAndroid Build Coastguard Worker class BufferIoExecutor : public ShaderExecutor
883*35238bceSAndroid Build Coastguard Worker {
884*35238bceSAndroid Build Coastguard Worker public:
885*35238bceSAndroid Build Coastguard Worker     BufferIoExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec,
886*35238bceSAndroid Build Coastguard Worker                      const glu::ProgramSources &sources);
887*35238bceSAndroid Build Coastguard Worker     ~BufferIoExecutor(void);
888*35238bceSAndroid Build Coastguard Worker 
isOk(void) const889*35238bceSAndroid Build Coastguard Worker     bool isOk(void) const
890*35238bceSAndroid Build Coastguard Worker     {
891*35238bceSAndroid Build Coastguard Worker         return m_program.isOk();
892*35238bceSAndroid Build Coastguard Worker     }
log(tcu::TestLog & dst) const893*35238bceSAndroid Build Coastguard Worker     void log(tcu::TestLog &dst) const
894*35238bceSAndroid Build Coastguard Worker     {
895*35238bceSAndroid Build Coastguard Worker         dst << m_program;
896*35238bceSAndroid Build Coastguard Worker     }
getProgram(void) const897*35238bceSAndroid Build Coastguard Worker     uint32_t getProgram(void) const
898*35238bceSAndroid Build Coastguard Worker     {
899*35238bceSAndroid Build Coastguard Worker         return m_program.getProgram();
900*35238bceSAndroid Build Coastguard Worker     }
901*35238bceSAndroid Build Coastguard Worker 
902*35238bceSAndroid Build Coastguard Worker protected:
903*35238bceSAndroid Build Coastguard Worker     enum
904*35238bceSAndroid Build Coastguard Worker     {
905*35238bceSAndroid Build Coastguard Worker         INPUT_BUFFER_BINDING  = 0,
906*35238bceSAndroid Build Coastguard Worker         OUTPUT_BUFFER_BINDING = 1,
907*35238bceSAndroid Build Coastguard Worker     };
908*35238bceSAndroid Build Coastguard Worker 
909*35238bceSAndroid Build Coastguard Worker     void initBuffers(int numValues);
getInputBuffer(void) const910*35238bceSAndroid Build Coastguard Worker     uint32_t getInputBuffer(void) const
911*35238bceSAndroid Build Coastguard Worker     {
912*35238bceSAndroid Build Coastguard Worker         return *m_inputBuffer;
913*35238bceSAndroid Build Coastguard Worker     }
getOutputBuffer(void) const914*35238bceSAndroid Build Coastguard Worker     uint32_t getOutputBuffer(void) const
915*35238bceSAndroid Build Coastguard Worker     {
916*35238bceSAndroid Build Coastguard Worker         return *m_outputBuffer;
917*35238bceSAndroid Build Coastguard Worker     }
getInputStride(void) const918*35238bceSAndroid Build Coastguard Worker     uint32_t getInputStride(void) const
919*35238bceSAndroid Build Coastguard Worker     {
920*35238bceSAndroid Build Coastguard Worker         return getLayoutStride(m_inputLayout);
921*35238bceSAndroid Build Coastguard Worker     }
getOutputStride(void) const922*35238bceSAndroid Build Coastguard Worker     uint32_t getOutputStride(void) const
923*35238bceSAndroid Build Coastguard Worker     {
924*35238bceSAndroid Build Coastguard Worker         return getLayoutStride(m_outputLayout);
925*35238bceSAndroid Build Coastguard Worker     }
926*35238bceSAndroid Build Coastguard Worker 
927*35238bceSAndroid Build Coastguard Worker     void uploadInputBuffer(const void *const *inputPtrs, int numValues);
928*35238bceSAndroid Build Coastguard Worker     void readOutputBuffer(void *const *outputPtrs, int numValues);
929*35238bceSAndroid Build Coastguard Worker 
930*35238bceSAndroid Build Coastguard Worker     static void declareBufferBlocks(std::ostream &src, const ShaderSpec &spec);
931*35238bceSAndroid Build Coastguard Worker     static void generateExecBufferIo(std::ostream &src, const ShaderSpec &spec, const char *invocationNdxName);
932*35238bceSAndroid Build Coastguard Worker 
933*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram m_program;
934*35238bceSAndroid Build Coastguard Worker 
935*35238bceSAndroid Build Coastguard Worker private:
936*35238bceSAndroid Build Coastguard Worker     struct VarLayout
937*35238bceSAndroid Build Coastguard Worker     {
938*35238bceSAndroid Build Coastguard Worker         uint32_t offset;
939*35238bceSAndroid Build Coastguard Worker         uint32_t stride;
940*35238bceSAndroid Build Coastguard Worker         uint32_t matrixStride;
941*35238bceSAndroid Build Coastguard Worker 
VarLayoutdeqp::gls::ShaderExecUtil::BufferIoExecutor::VarLayout942*35238bceSAndroid Build Coastguard Worker         VarLayout(void) : offset(0), stride(0), matrixStride(0)
943*35238bceSAndroid Build Coastguard Worker         {
944*35238bceSAndroid Build Coastguard Worker         }
945*35238bceSAndroid Build Coastguard Worker     };
946*35238bceSAndroid Build Coastguard Worker 
947*35238bceSAndroid Build Coastguard Worker     void resizeInputBuffer(int newSize);
948*35238bceSAndroid Build Coastguard Worker     void resizeOutputBuffer(int newSize);
949*35238bceSAndroid Build Coastguard Worker 
950*35238bceSAndroid Build Coastguard Worker     static void computeVarLayout(const std::vector<Symbol> &symbols, std::vector<VarLayout> *layout);
951*35238bceSAndroid Build Coastguard Worker     static uint32_t getLayoutStride(const vector<VarLayout> &layout);
952*35238bceSAndroid Build Coastguard Worker 
953*35238bceSAndroid Build Coastguard Worker     static void copyToBuffer(const glu::VarType &varType, const VarLayout &layout, int numValues,
954*35238bceSAndroid Build Coastguard Worker                              const void *srcBasePtr, void *dstBasePtr);
955*35238bceSAndroid Build Coastguard Worker     static void copyFromBuffer(const glu::VarType &varType, const VarLayout &layout, int numValues,
956*35238bceSAndroid Build Coastguard Worker                                const void *srcBasePtr, void *dstBasePtr);
957*35238bceSAndroid Build Coastguard Worker 
958*35238bceSAndroid Build Coastguard Worker     glu::Buffer m_inputBuffer;
959*35238bceSAndroid Build Coastguard Worker     glu::Buffer m_outputBuffer;
960*35238bceSAndroid Build Coastguard Worker 
961*35238bceSAndroid Build Coastguard Worker     vector<VarLayout> m_inputLayout;
962*35238bceSAndroid Build Coastguard Worker     vector<VarLayout> m_outputLayout;
963*35238bceSAndroid Build Coastguard Worker };
964*35238bceSAndroid Build Coastguard Worker 
BufferIoExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec,const glu::ProgramSources & sources)965*35238bceSAndroid Build Coastguard Worker BufferIoExecutor::BufferIoExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec,
966*35238bceSAndroid Build Coastguard Worker                                    const glu::ProgramSources &sources)
967*35238bceSAndroid Build Coastguard Worker     : ShaderExecutor(renderCtx, shaderSpec)
968*35238bceSAndroid Build Coastguard Worker     , m_program(renderCtx, sources)
969*35238bceSAndroid Build Coastguard Worker     , m_inputBuffer(renderCtx)
970*35238bceSAndroid Build Coastguard Worker     , m_outputBuffer(renderCtx)
971*35238bceSAndroid Build Coastguard Worker {
972*35238bceSAndroid Build Coastguard Worker     computeVarLayout(m_inputs, &m_inputLayout);
973*35238bceSAndroid Build Coastguard Worker     computeVarLayout(m_outputs, &m_outputLayout);
974*35238bceSAndroid Build Coastguard Worker }
975*35238bceSAndroid Build Coastguard Worker 
~BufferIoExecutor(void)976*35238bceSAndroid Build Coastguard Worker BufferIoExecutor::~BufferIoExecutor(void)
977*35238bceSAndroid Build Coastguard Worker {
978*35238bceSAndroid Build Coastguard Worker }
979*35238bceSAndroid Build Coastguard Worker 
resizeInputBuffer(int newSize)980*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::resizeInputBuffer(int newSize)
981*35238bceSAndroid Build Coastguard Worker {
982*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
983*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_inputBuffer);
984*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
985*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate input buffer");
986*35238bceSAndroid Build Coastguard Worker }
987*35238bceSAndroid Build Coastguard Worker 
resizeOutputBuffer(int newSize)988*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::resizeOutputBuffer(int newSize)
989*35238bceSAndroid Build Coastguard Worker {
990*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
991*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_outputBuffer);
992*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
993*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate output buffer");
994*35238bceSAndroid Build Coastguard Worker }
995*35238bceSAndroid Build Coastguard Worker 
initBuffers(int numValues)996*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::initBuffers(int numValues)
997*35238bceSAndroid Build Coastguard Worker {
998*35238bceSAndroid Build Coastguard Worker     const uint32_t inputStride  = getLayoutStride(m_inputLayout);
999*35238bceSAndroid Build Coastguard Worker     const uint32_t outputStride = getLayoutStride(m_outputLayout);
1000*35238bceSAndroid Build Coastguard Worker     const int inputBufferSize   = numValues * inputStride;
1001*35238bceSAndroid Build Coastguard Worker     const int outputBufferSize  = numValues * outputStride;
1002*35238bceSAndroid Build Coastguard Worker 
1003*35238bceSAndroid Build Coastguard Worker     resizeInputBuffer(inputBufferSize);
1004*35238bceSAndroid Build Coastguard Worker     resizeOutputBuffer(outputBufferSize);
1005*35238bceSAndroid Build Coastguard Worker }
1006*35238bceSAndroid Build Coastguard Worker 
computeVarLayout(const std::vector<Symbol> & symbols,std::vector<VarLayout> * layout)1007*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::computeVarLayout(const std::vector<Symbol> &symbols, std::vector<VarLayout> *layout)
1008*35238bceSAndroid Build Coastguard Worker {
1009*35238bceSAndroid Build Coastguard Worker     uint32_t maxAlignment = 0;
1010*35238bceSAndroid Build Coastguard Worker     uint32_t curOffset    = 0;
1011*35238bceSAndroid Build Coastguard Worker 
1012*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(layout->empty());
1013*35238bceSAndroid Build Coastguard Worker     layout->resize(symbols.size());
1014*35238bceSAndroid Build Coastguard Worker 
1015*35238bceSAndroid Build Coastguard Worker     for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++)
1016*35238bceSAndroid Build Coastguard Worker     {
1017*35238bceSAndroid Build Coastguard Worker         const Symbol &symbol          = symbols[varNdx];
1018*35238bceSAndroid Build Coastguard Worker         const glu::DataType basicType = symbol.varType.getBasicType();
1019*35238bceSAndroid Build Coastguard Worker         VarLayout &layoutEntry        = (*layout)[varNdx];
1020*35238bceSAndroid Build Coastguard Worker 
1021*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeScalarOrVector(basicType))
1022*35238bceSAndroid Build Coastguard Worker         {
1023*35238bceSAndroid Build Coastguard Worker             const uint32_t alignment = getVecStd430ByteAlignment(basicType);
1024*35238bceSAndroid Build Coastguard Worker             const uint32_t size      = (uint32_t)glu::getDataTypeScalarSize(basicType) * (int)sizeof(uint32_t);
1025*35238bceSAndroid Build Coastguard Worker 
1026*35238bceSAndroid Build Coastguard Worker             curOffset    = (uint32_t)deAlign32((int)curOffset, (int)alignment);
1027*35238bceSAndroid Build Coastguard Worker             maxAlignment = de::max(maxAlignment, alignment);
1028*35238bceSAndroid Build Coastguard Worker 
1029*35238bceSAndroid Build Coastguard Worker             layoutEntry.offset       = curOffset;
1030*35238bceSAndroid Build Coastguard Worker             layoutEntry.matrixStride = 0;
1031*35238bceSAndroid Build Coastguard Worker 
1032*35238bceSAndroid Build Coastguard Worker             curOffset += size;
1033*35238bceSAndroid Build Coastguard Worker         }
1034*35238bceSAndroid Build Coastguard Worker         else if (glu::isDataTypeMatrix(basicType))
1035*35238bceSAndroid Build Coastguard Worker         {
1036*35238bceSAndroid Build Coastguard Worker             const int numVecs           = glu::getDataTypeMatrixNumColumns(basicType);
1037*35238bceSAndroid Build Coastguard Worker             const glu::DataType vecType = glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType));
1038*35238bceSAndroid Build Coastguard Worker             const uint32_t vecAlignment = getVecStd430ByteAlignment(vecType);
1039*35238bceSAndroid Build Coastguard Worker 
1040*35238bceSAndroid Build Coastguard Worker             curOffset    = (uint32_t)deAlign32((int)curOffset, (int)vecAlignment);
1041*35238bceSAndroid Build Coastguard Worker             maxAlignment = de::max(maxAlignment, vecAlignment);
1042*35238bceSAndroid Build Coastguard Worker 
1043*35238bceSAndroid Build Coastguard Worker             layoutEntry.offset       = curOffset;
1044*35238bceSAndroid Build Coastguard Worker             layoutEntry.matrixStride = vecAlignment;
1045*35238bceSAndroid Build Coastguard Worker 
1046*35238bceSAndroid Build Coastguard Worker             curOffset += vecAlignment * numVecs;
1047*35238bceSAndroid Build Coastguard Worker         }
1048*35238bceSAndroid Build Coastguard Worker         else
1049*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1050*35238bceSAndroid Build Coastguard Worker     }
1051*35238bceSAndroid Build Coastguard Worker 
1052*35238bceSAndroid Build Coastguard Worker     {
1053*35238bceSAndroid Build Coastguard Worker         const uint32_t totalSize = (uint32_t)deAlign32(curOffset, maxAlignment);
1054*35238bceSAndroid Build Coastguard Worker 
1055*35238bceSAndroid Build Coastguard Worker         for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter)
1056*35238bceSAndroid Build Coastguard Worker             varIter->stride = totalSize;
1057*35238bceSAndroid Build Coastguard Worker     }
1058*35238bceSAndroid Build Coastguard Worker }
1059*35238bceSAndroid Build Coastguard Worker 
getLayoutStride(const vector<VarLayout> & layout)1060*35238bceSAndroid Build Coastguard Worker inline uint32_t BufferIoExecutor::getLayoutStride(const vector<VarLayout> &layout)
1061*35238bceSAndroid Build Coastguard Worker {
1062*35238bceSAndroid Build Coastguard Worker     return layout.empty() ? 0 : layout[0].stride;
1063*35238bceSAndroid Build Coastguard Worker }
1064*35238bceSAndroid Build Coastguard Worker 
copyToBuffer(const glu::VarType & varType,const VarLayout & layout,int numValues,const void * srcBasePtr,void * dstBasePtr)1065*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::copyToBuffer(const glu::VarType &varType, const VarLayout &layout, int numValues,
1066*35238bceSAndroid Build Coastguard Worker                                     const void *srcBasePtr, void *dstBasePtr)
1067*35238bceSAndroid Build Coastguard Worker {
1068*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType())
1069*35238bceSAndroid Build Coastguard Worker     {
1070*35238bceSAndroid Build Coastguard Worker         const glu::DataType basicType = varType.getBasicType();
1071*35238bceSAndroid Build Coastguard Worker         const bool isMatrix           = glu::isDataTypeMatrix(basicType);
1072*35238bceSAndroid Build Coastguard Worker         const int scalarSize          = glu::getDataTypeScalarSize(basicType);
1073*35238bceSAndroid Build Coastguard Worker         const int numVecs             = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
1074*35238bceSAndroid Build Coastguard Worker         const int numComps            = scalarSize / numVecs;
1075*35238bceSAndroid Build Coastguard Worker 
1076*35238bceSAndroid Build Coastguard Worker         for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
1077*35238bceSAndroid Build Coastguard Worker         {
1078*35238bceSAndroid Build Coastguard Worker             for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1079*35238bceSAndroid Build Coastguard Worker             {
1080*35238bceSAndroid Build Coastguard Worker                 const int srcOffset = (int)sizeof(uint32_t) * (elemNdx * scalarSize + vecNdx * numComps);
1081*35238bceSAndroid Build Coastguard Worker                 const int dstOffset =
1082*35238bceSAndroid Build Coastguard Worker                     layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
1083*35238bceSAndroid Build Coastguard Worker                 const uint8_t *srcPtr = (const uint8_t *)srcBasePtr + srcOffset;
1084*35238bceSAndroid Build Coastguard Worker                 uint8_t *dstPtr       = (uint8_t *)dstBasePtr + dstOffset;
1085*35238bceSAndroid Build Coastguard Worker 
1086*35238bceSAndroid Build Coastguard Worker                 deMemcpy(dstPtr, srcPtr, sizeof(uint32_t) * numComps);
1087*35238bceSAndroid Build Coastguard Worker             }
1088*35238bceSAndroid Build Coastguard Worker         }
1089*35238bceSAndroid Build Coastguard Worker     }
1090*35238bceSAndroid Build Coastguard Worker     else
1091*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Unsupported type");
1092*35238bceSAndroid Build Coastguard Worker }
1093*35238bceSAndroid Build Coastguard Worker 
copyFromBuffer(const glu::VarType & varType,const VarLayout & layout,int numValues,const void * srcBasePtr,void * dstBasePtr)1094*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::copyFromBuffer(const glu::VarType &varType, const VarLayout &layout, int numValues,
1095*35238bceSAndroid Build Coastguard Worker                                       const void *srcBasePtr, void *dstBasePtr)
1096*35238bceSAndroid Build Coastguard Worker {
1097*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType())
1098*35238bceSAndroid Build Coastguard Worker     {
1099*35238bceSAndroid Build Coastguard Worker         const glu::DataType basicType = varType.getBasicType();
1100*35238bceSAndroid Build Coastguard Worker         const bool isMatrix           = glu::isDataTypeMatrix(basicType);
1101*35238bceSAndroid Build Coastguard Worker         const int scalarSize          = glu::getDataTypeScalarSize(basicType);
1102*35238bceSAndroid Build Coastguard Worker         const int numVecs             = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
1103*35238bceSAndroid Build Coastguard Worker         const int numComps            = scalarSize / numVecs;
1104*35238bceSAndroid Build Coastguard Worker 
1105*35238bceSAndroid Build Coastguard Worker         for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
1106*35238bceSAndroid Build Coastguard Worker         {
1107*35238bceSAndroid Build Coastguard Worker             for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1108*35238bceSAndroid Build Coastguard Worker             {
1109*35238bceSAndroid Build Coastguard Worker                 const int srcOffset =
1110*35238bceSAndroid Build Coastguard Worker                     layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
1111*35238bceSAndroid Build Coastguard Worker                 const int dstOffset   = (int)sizeof(uint32_t) * (elemNdx * scalarSize + vecNdx * numComps);
1112*35238bceSAndroid Build Coastguard Worker                 const uint8_t *srcPtr = (const uint8_t *)srcBasePtr + srcOffset;
1113*35238bceSAndroid Build Coastguard Worker                 uint8_t *dstPtr       = (uint8_t *)dstBasePtr + dstOffset;
1114*35238bceSAndroid Build Coastguard Worker 
1115*35238bceSAndroid Build Coastguard Worker                 deMemcpy(dstPtr, srcPtr, sizeof(uint32_t) * numComps);
1116*35238bceSAndroid Build Coastguard Worker             }
1117*35238bceSAndroid Build Coastguard Worker         }
1118*35238bceSAndroid Build Coastguard Worker     }
1119*35238bceSAndroid Build Coastguard Worker     else
1120*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Unsupported type");
1121*35238bceSAndroid Build Coastguard Worker }
1122*35238bceSAndroid Build Coastguard Worker 
uploadInputBuffer(const void * const * inputPtrs,int numValues)1123*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::uploadInputBuffer(const void *const *inputPtrs, int numValues)
1124*35238bceSAndroid Build Coastguard Worker {
1125*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl   = m_renderCtx.getFunctions();
1126*35238bceSAndroid Build Coastguard Worker     const uint32_t buffer      = *m_inputBuffer;
1127*35238bceSAndroid Build Coastguard Worker     const uint32_t inputStride = getLayoutStride(m_inputLayout);
1128*35238bceSAndroid Build Coastguard Worker     const int inputBufferSize  = inputStride * numValues;
1129*35238bceSAndroid Build Coastguard Worker 
1130*35238bceSAndroid Build Coastguard Worker     if (inputBufferSize == 0)
1131*35238bceSAndroid Build Coastguard Worker         return; // No inputs
1132*35238bceSAndroid Build Coastguard Worker 
1133*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1134*35238bceSAndroid Build Coastguard Worker     void *mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, inputBufferSize, GL_MAP_WRITE_BIT);
1135*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
1136*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(mapPtr);
1137*35238bceSAndroid Build Coastguard Worker 
1138*35238bceSAndroid Build Coastguard Worker     try
1139*35238bceSAndroid Build Coastguard Worker     {
1140*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_inputs.size() == m_inputLayout.size());
1141*35238bceSAndroid Build Coastguard Worker         for (size_t inputNdx = 0; inputNdx < m_inputs.size(); ++inputNdx)
1142*35238bceSAndroid Build Coastguard Worker         {
1143*35238bceSAndroid Build Coastguard Worker             const glu::VarType &varType = m_inputs[inputNdx].varType;
1144*35238bceSAndroid Build Coastguard Worker             const VarLayout &layout     = m_inputLayout[inputNdx];
1145*35238bceSAndroid Build Coastguard Worker 
1146*35238bceSAndroid Build Coastguard Worker             copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], mapPtr);
1147*35238bceSAndroid Build Coastguard Worker         }
1148*35238bceSAndroid Build Coastguard Worker     }
1149*35238bceSAndroid Build Coastguard Worker     catch (...)
1150*35238bceSAndroid Build Coastguard Worker     {
1151*35238bceSAndroid Build Coastguard Worker         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1152*35238bceSAndroid Build Coastguard Worker         throw;
1153*35238bceSAndroid Build Coastguard Worker     }
1154*35238bceSAndroid Build Coastguard Worker 
1155*35238bceSAndroid Build Coastguard Worker     gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1156*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
1157*35238bceSAndroid Build Coastguard Worker }
1158*35238bceSAndroid Build Coastguard Worker 
readOutputBuffer(void * const * outputPtrs,int numValues)1159*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::readOutputBuffer(void *const *outputPtrs, int numValues)
1160*35238bceSAndroid Build Coastguard Worker {
1161*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl    = m_renderCtx.getFunctions();
1162*35238bceSAndroid Build Coastguard Worker     const uint32_t buffer       = *m_outputBuffer;
1163*35238bceSAndroid Build Coastguard Worker     const uint32_t outputStride = getLayoutStride(m_outputLayout);
1164*35238bceSAndroid Build Coastguard Worker     const int outputBufferSize  = numValues * outputStride;
1165*35238bceSAndroid Build Coastguard Worker 
1166*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(outputBufferSize > 0); // At least some outputs are required.
1167*35238bceSAndroid Build Coastguard Worker 
1168*35238bceSAndroid Build Coastguard Worker     gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1169*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
1170*35238bceSAndroid Build Coastguard Worker     void *mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSize, GL_MAP_READ_BIT);
1171*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
1172*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(mapPtr);
1173*35238bceSAndroid Build Coastguard Worker 
1174*35238bceSAndroid Build Coastguard Worker     try
1175*35238bceSAndroid Build Coastguard Worker     {
1176*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_outputs.size() == m_outputLayout.size());
1177*35238bceSAndroid Build Coastguard Worker         for (size_t outputNdx = 0; outputNdx < m_outputs.size(); ++outputNdx)
1178*35238bceSAndroid Build Coastguard Worker         {
1179*35238bceSAndroid Build Coastguard Worker             const glu::VarType &varType = m_outputs[outputNdx].varType;
1180*35238bceSAndroid Build Coastguard Worker             const VarLayout &layout     = m_outputLayout[outputNdx];
1181*35238bceSAndroid Build Coastguard Worker 
1182*35238bceSAndroid Build Coastguard Worker             copyFromBuffer(varType, layout, numValues, mapPtr, outputPtrs[outputNdx]);
1183*35238bceSAndroid Build Coastguard Worker         }
1184*35238bceSAndroid Build Coastguard Worker     }
1185*35238bceSAndroid Build Coastguard Worker     catch (...)
1186*35238bceSAndroid Build Coastguard Worker     {
1187*35238bceSAndroid Build Coastguard Worker         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1188*35238bceSAndroid Build Coastguard Worker         throw;
1189*35238bceSAndroid Build Coastguard Worker     }
1190*35238bceSAndroid Build Coastguard Worker 
1191*35238bceSAndroid Build Coastguard Worker     gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1192*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
1193*35238bceSAndroid Build Coastguard Worker }
1194*35238bceSAndroid Build Coastguard Worker 
declareBufferBlocks(std::ostream & src,const ShaderSpec & spec)1195*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::declareBufferBlocks(std::ostream &src, const ShaderSpec &spec)
1196*35238bceSAndroid Build Coastguard Worker {
1197*35238bceSAndroid Build Coastguard Worker     // Input struct
1198*35238bceSAndroid Build Coastguard Worker     if (!spec.inputs.empty())
1199*35238bceSAndroid Build Coastguard Worker     {
1200*35238bceSAndroid Build Coastguard Worker         glu::StructType inputStruct("Inputs");
1201*35238bceSAndroid Build Coastguard Worker         for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
1202*35238bceSAndroid Build Coastguard Worker             inputStruct.addMember(symIter->name.c_str(), symIter->varType);
1203*35238bceSAndroid Build Coastguard Worker         src << glu::declare(&inputStruct) << ";\n";
1204*35238bceSAndroid Build Coastguard Worker     }
1205*35238bceSAndroid Build Coastguard Worker 
1206*35238bceSAndroid Build Coastguard Worker     // Output struct
1207*35238bceSAndroid Build Coastguard Worker     {
1208*35238bceSAndroid Build Coastguard Worker         glu::StructType outputStruct("Outputs");
1209*35238bceSAndroid Build Coastguard Worker         for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1210*35238bceSAndroid Build Coastguard Worker             outputStruct.addMember(symIter->name.c_str(), symIter->varType);
1211*35238bceSAndroid Build Coastguard Worker         src << glu::declare(&outputStruct) << ";\n";
1212*35238bceSAndroid Build Coastguard Worker     }
1213*35238bceSAndroid Build Coastguard Worker 
1214*35238bceSAndroid Build Coastguard Worker     src << "\n";
1215*35238bceSAndroid Build Coastguard Worker 
1216*35238bceSAndroid Build Coastguard Worker     if (!spec.inputs.empty())
1217*35238bceSAndroid Build Coastguard Worker     {
1218*35238bceSAndroid Build Coastguard Worker         src << "layout(binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n"
1219*35238bceSAndroid Build Coastguard Worker             << "{\n"
1220*35238bceSAndroid Build Coastguard Worker             << "    Inputs inputs[];\n"
1221*35238bceSAndroid Build Coastguard Worker             << "};\n";
1222*35238bceSAndroid Build Coastguard Worker     }
1223*35238bceSAndroid Build Coastguard Worker 
1224*35238bceSAndroid Build Coastguard Worker     src << "layout(binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n"
1225*35238bceSAndroid Build Coastguard Worker         << "{\n"
1226*35238bceSAndroid Build Coastguard Worker         << "    Outputs outputs[];\n"
1227*35238bceSAndroid Build Coastguard Worker         << "};\n"
1228*35238bceSAndroid Build Coastguard Worker         << "\n";
1229*35238bceSAndroid Build Coastguard Worker }
1230*35238bceSAndroid Build Coastguard Worker 
generateExecBufferIo(std::ostream & src,const ShaderSpec & spec,const char * invocationNdxName)1231*35238bceSAndroid Build Coastguard Worker void BufferIoExecutor::generateExecBufferIo(std::ostream &src, const ShaderSpec &spec, const char *invocationNdxName)
1232*35238bceSAndroid Build Coastguard Worker {
1233*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
1234*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]."
1235*35238bceSAndroid Build Coastguard Worker             << symIter->name << ";\n";
1236*35238bceSAndroid Build Coastguard Worker 
1237*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1238*35238bceSAndroid Build Coastguard Worker         src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n";
1239*35238bceSAndroid Build Coastguard Worker 
1240*35238bceSAndroid Build Coastguard Worker     src << "\n";
1241*35238bceSAndroid Build Coastguard Worker 
1242*35238bceSAndroid Build Coastguard Worker     {
1243*35238bceSAndroid Build Coastguard Worker         std::istringstream opSrc(spec.source);
1244*35238bceSAndroid Build Coastguard Worker         std::string line;
1245*35238bceSAndroid Build Coastguard Worker 
1246*35238bceSAndroid Build Coastguard Worker         while (std::getline(opSrc, line))
1247*35238bceSAndroid Build Coastguard Worker             src << "\t" << line << "\n";
1248*35238bceSAndroid Build Coastguard Worker     }
1249*35238bceSAndroid Build Coastguard Worker 
1250*35238bceSAndroid Build Coastguard Worker     src << "\n";
1251*35238bceSAndroid Build Coastguard Worker     for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1252*35238bceSAndroid Build Coastguard Worker         src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n";
1253*35238bceSAndroid Build Coastguard Worker }
1254*35238bceSAndroid Build Coastguard Worker 
1255*35238bceSAndroid Build Coastguard Worker // ComputeShaderExecutor
1256*35238bceSAndroid Build Coastguard Worker 
1257*35238bceSAndroid Build Coastguard Worker class ComputeShaderExecutor : public BufferIoExecutor
1258*35238bceSAndroid Build Coastguard Worker {
1259*35238bceSAndroid Build Coastguard Worker public:
1260*35238bceSAndroid Build Coastguard Worker     ComputeShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
1261*35238bceSAndroid Build Coastguard Worker     ~ComputeShaderExecutor(void);
1262*35238bceSAndroid Build Coastguard Worker 
1263*35238bceSAndroid Build Coastguard Worker     void execute(int numValues, const void *const *inputs, void *const *outputs);
1264*35238bceSAndroid Build Coastguard Worker 
1265*35238bceSAndroid Build Coastguard Worker protected:
1266*35238bceSAndroid Build Coastguard Worker     static std::string generateComputeShader(const ShaderSpec &spec);
1267*35238bceSAndroid Build Coastguard Worker 
1268*35238bceSAndroid Build Coastguard Worker     tcu::IVec3 m_maxWorkSize;
1269*35238bceSAndroid Build Coastguard Worker };
1270*35238bceSAndroid Build Coastguard Worker 
generateComputeShader(const ShaderSpec & spec)1271*35238bceSAndroid Build Coastguard Worker std::string ComputeShaderExecutor::generateComputeShader(const ShaderSpec &spec)
1272*35238bceSAndroid Build Coastguard Worker {
1273*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1274*35238bceSAndroid Build Coastguard Worker 
1275*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(spec.version) << "\n";
1276*35238bceSAndroid Build Coastguard Worker 
1277*35238bceSAndroid Build Coastguard Worker     if (!spec.globalDeclarations.empty())
1278*35238bceSAndroid Build Coastguard Worker         src << spec.globalDeclarations << "\n";
1279*35238bceSAndroid Build Coastguard Worker 
1280*35238bceSAndroid Build Coastguard Worker     src << "layout(local_size_x = 1) in;\n"
1281*35238bceSAndroid Build Coastguard Worker         << "\n";
1282*35238bceSAndroid Build Coastguard Worker 
1283*35238bceSAndroid Build Coastguard Worker     declareBufferBlocks(src, spec);
1284*35238bceSAndroid Build Coastguard Worker 
1285*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n"
1286*35238bceSAndroid Build Coastguard Worker         << "{\n"
1287*35238bceSAndroid Build Coastguard Worker         << "    uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n"
1288*35238bceSAndroid Build Coastguard Worker         << "                       + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n";
1289*35238bceSAndroid Build Coastguard Worker 
1290*35238bceSAndroid Build Coastguard Worker     generateExecBufferIo(src, spec, "invocationNdx");
1291*35238bceSAndroid Build Coastguard Worker 
1292*35238bceSAndroid Build Coastguard Worker     src << "}\n";
1293*35238bceSAndroid Build Coastguard Worker 
1294*35238bceSAndroid Build Coastguard Worker     return src.str();
1295*35238bceSAndroid Build Coastguard Worker }
1296*35238bceSAndroid Build Coastguard Worker 
ComputeShaderExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)1297*35238bceSAndroid Build Coastguard Worker ComputeShaderExecutor::ComputeShaderExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
1298*35238bceSAndroid Build Coastguard Worker     : BufferIoExecutor(renderCtx, shaderSpec,
1299*35238bceSAndroid Build Coastguard Worker                        glu::ProgramSources() << glu::ComputeSource(generateComputeShader(shaderSpec)))
1300*35238bceSAndroid Build Coastguard Worker {
1301*35238bceSAndroid Build Coastguard Worker     m_maxWorkSize = tcu::IVec3(128, 128, 64); // Minimum in 3plus
1302*35238bceSAndroid Build Coastguard Worker }
1303*35238bceSAndroid Build Coastguard Worker 
~ComputeShaderExecutor(void)1304*35238bceSAndroid Build Coastguard Worker ComputeShaderExecutor::~ComputeShaderExecutor(void)
1305*35238bceSAndroid Build Coastguard Worker {
1306*35238bceSAndroid Build Coastguard Worker }
1307*35238bceSAndroid Build Coastguard Worker 
execute(int numValues,const void * const * inputs,void * const * outputs)1308*35238bceSAndroid Build Coastguard Worker void ComputeShaderExecutor::execute(int numValues, const void *const *inputs, void *const *outputs)
1309*35238bceSAndroid Build Coastguard Worker {
1310*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl         = m_renderCtx.getFunctions();
1311*35238bceSAndroid Build Coastguard Worker     const int maxValuesPerInvocation = m_maxWorkSize[0];
1312*35238bceSAndroid Build Coastguard Worker     const uint32_t inputStride       = getInputStride();
1313*35238bceSAndroid Build Coastguard Worker     const uint32_t outputStride      = getOutputStride();
1314*35238bceSAndroid Build Coastguard Worker 
1315*35238bceSAndroid Build Coastguard Worker     initBuffers(numValues);
1316*35238bceSAndroid Build Coastguard Worker 
1317*35238bceSAndroid Build Coastguard Worker     // Setup input buffer & copy data
1318*35238bceSAndroid Build Coastguard Worker     uploadInputBuffer(inputs, numValues);
1319*35238bceSAndroid Build Coastguard Worker 
1320*35238bceSAndroid Build Coastguard Worker     // Perform compute invocations
1321*35238bceSAndroid Build Coastguard Worker     {
1322*35238bceSAndroid Build Coastguard Worker         int curOffset = 0;
1323*35238bceSAndroid Build Coastguard Worker         while (curOffset < numValues)
1324*35238bceSAndroid Build Coastguard Worker         {
1325*35238bceSAndroid Build Coastguard Worker             const int numToExec = de::min(maxValuesPerInvocation, numValues - curOffset);
1326*35238bceSAndroid Build Coastguard Worker 
1327*35238bceSAndroid Build Coastguard Worker             if (inputStride > 0)
1328*35238bceSAndroid Build Coastguard Worker                 gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer(),
1329*35238bceSAndroid Build Coastguard Worker                                    curOffset * inputStride, numToExec * inputStride);
1330*35238bceSAndroid Build Coastguard Worker 
1331*35238bceSAndroid Build Coastguard Worker             gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer(),
1332*35238bceSAndroid Build Coastguard Worker                                curOffset * outputStride, numToExec * outputStride);
1333*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_SHADER_STORAGE_BUFFER)");
1334*35238bceSAndroid Build Coastguard Worker 
1335*35238bceSAndroid Build Coastguard Worker             gl.dispatchCompute(numToExec, 1, 1);
1336*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()");
1337*35238bceSAndroid Build Coastguard Worker 
1338*35238bceSAndroid Build Coastguard Worker             curOffset += numToExec;
1339*35238bceSAndroid Build Coastguard Worker         }
1340*35238bceSAndroid Build Coastguard Worker     }
1341*35238bceSAndroid Build Coastguard Worker 
1342*35238bceSAndroid Build Coastguard Worker     // Read back data
1343*35238bceSAndroid Build Coastguard Worker     readOutputBuffer(outputs, numValues);
1344*35238bceSAndroid Build Coastguard Worker }
1345*35238bceSAndroid Build Coastguard Worker 
1346*35238bceSAndroid Build Coastguard Worker // Tessellation utils
1347*35238bceSAndroid Build Coastguard Worker 
generateVertexShaderForTess(glu::GLSLVersion version)1348*35238bceSAndroid Build Coastguard Worker static std::string generateVertexShaderForTess(glu::GLSLVersion version)
1349*35238bceSAndroid Build Coastguard Worker {
1350*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1351*35238bceSAndroid Build Coastguard Worker 
1352*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(version) << "\n";
1353*35238bceSAndroid Build Coastguard Worker 
1354*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n{\n"
1355*35238bceSAndroid Build Coastguard Worker         << "    gl_Position = vec4(gl_VertexID/2, gl_VertexID%2, 0.0, 1.0);\n"
1356*35238bceSAndroid Build Coastguard Worker         << "}\n";
1357*35238bceSAndroid Build Coastguard Worker 
1358*35238bceSAndroid Build Coastguard Worker     return src.str();
1359*35238bceSAndroid Build Coastguard Worker }
1360*35238bceSAndroid Build Coastguard Worker 
checkTessSupport(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec,glu::ShaderType stage)1361*35238bceSAndroid Build Coastguard Worker void checkTessSupport(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec, glu::ShaderType stage)
1362*35238bceSAndroid Build Coastguard Worker {
1363*35238bceSAndroid Build Coastguard Worker     const int numBlockRequired = 2; // highest binding is always 1 (output) i.e. count == 2
1364*35238bceSAndroid Build Coastguard Worker 
1365*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES &&
1366*35238bceSAndroid Build Coastguard Worker         !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5)))
1367*35238bceSAndroid Build Coastguard Worker         checkExtension(renderCtx, "GL_EXT_tessellation_shader");
1368*35238bceSAndroid Build Coastguard Worker 
1369*35238bceSAndroid Build Coastguard Worker     if (stage == glu::SHADERTYPE_TESSELLATION_CONTROL)
1370*35238bceSAndroid Build Coastguard Worker         checkLimit(renderCtx, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, numBlockRequired);
1371*35238bceSAndroid Build Coastguard Worker     else if (stage == glu::SHADERTYPE_TESSELLATION_EVALUATION)
1372*35238bceSAndroid Build Coastguard Worker         checkLimit(renderCtx, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, numBlockRequired);
1373*35238bceSAndroid Build Coastguard Worker     else
1374*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1375*35238bceSAndroid Build Coastguard Worker }
1376*35238bceSAndroid Build Coastguard Worker 
1377*35238bceSAndroid Build Coastguard Worker // TessControlExecutor
1378*35238bceSAndroid Build Coastguard Worker 
1379*35238bceSAndroid Build Coastguard Worker class TessControlExecutor : public BufferIoExecutor
1380*35238bceSAndroid Build Coastguard Worker {
1381*35238bceSAndroid Build Coastguard Worker public:
1382*35238bceSAndroid Build Coastguard Worker     static TessControlExecutor *create(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
1383*35238bceSAndroid Build Coastguard Worker 
1384*35238bceSAndroid Build Coastguard Worker     ~TessControlExecutor(void);
1385*35238bceSAndroid Build Coastguard Worker 
1386*35238bceSAndroid Build Coastguard Worker     void execute(int numValues, const void *const *inputs, void *const *outputs);
1387*35238bceSAndroid Build Coastguard Worker 
1388*35238bceSAndroid Build Coastguard Worker protected:
1389*35238bceSAndroid Build Coastguard Worker     static std::string generateTessControlShader(const ShaderSpec &shaderSpec);
1390*35238bceSAndroid Build Coastguard Worker 
1391*35238bceSAndroid Build Coastguard Worker private:
1392*35238bceSAndroid Build Coastguard Worker     TessControlExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
1393*35238bceSAndroid Build Coastguard Worker };
1394*35238bceSAndroid Build Coastguard Worker 
create(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)1395*35238bceSAndroid Build Coastguard Worker TessControlExecutor *TessControlExecutor::create(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
1396*35238bceSAndroid Build Coastguard Worker {
1397*35238bceSAndroid Build Coastguard Worker     checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_CONTROL);
1398*35238bceSAndroid Build Coastguard Worker 
1399*35238bceSAndroid Build Coastguard Worker     return new TessControlExecutor(renderCtx, shaderSpec);
1400*35238bceSAndroid Build Coastguard Worker }
1401*35238bceSAndroid Build Coastguard Worker 
generateTessControlShader(const ShaderSpec & shaderSpec)1402*35238bceSAndroid Build Coastguard Worker std::string TessControlExecutor::generateTessControlShader(const ShaderSpec &shaderSpec)
1403*35238bceSAndroid Build Coastguard Worker {
1404*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1405*35238bceSAndroid Build Coastguard Worker 
1406*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
1407*35238bceSAndroid Build Coastguard Worker 
1408*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
1409*35238bceSAndroid Build Coastguard Worker         src << "#extension GL_EXT_tessellation_shader : require\n";
1410*35238bceSAndroid Build Coastguard Worker 
1411*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
1412*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
1413*35238bceSAndroid Build Coastguard Worker 
1414*35238bceSAndroid Build Coastguard Worker     src << "\nlayout(vertices = 1) out;\n\n";
1415*35238bceSAndroid Build Coastguard Worker 
1416*35238bceSAndroid Build Coastguard Worker     declareBufferBlocks(src, shaderSpec);
1417*35238bceSAndroid Build Coastguard Worker 
1418*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n{\n";
1419*35238bceSAndroid Build Coastguard Worker 
1420*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < 2; ndx++)
1421*35238bceSAndroid Build Coastguard Worker         src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
1422*35238bceSAndroid Build Coastguard Worker 
1423*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < 4; ndx++)
1424*35238bceSAndroid Build Coastguard Worker         src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
1425*35238bceSAndroid Build Coastguard Worker 
1426*35238bceSAndroid Build Coastguard Worker     src << "\n"
1427*35238bceSAndroid Build Coastguard Worker         << "\thighp uint invocationId = uint(gl_PrimitiveID);\n";
1428*35238bceSAndroid Build Coastguard Worker 
1429*35238bceSAndroid Build Coastguard Worker     generateExecBufferIo(src, shaderSpec, "invocationId");
1430*35238bceSAndroid Build Coastguard Worker 
1431*35238bceSAndroid Build Coastguard Worker     src << "}\n";
1432*35238bceSAndroid Build Coastguard Worker 
1433*35238bceSAndroid Build Coastguard Worker     return src.str();
1434*35238bceSAndroid Build Coastguard Worker }
1435*35238bceSAndroid Build Coastguard Worker 
generateEmptyTessEvalShader(glu::GLSLVersion version)1436*35238bceSAndroid Build Coastguard Worker static std::string generateEmptyTessEvalShader(glu::GLSLVersion version)
1437*35238bceSAndroid Build Coastguard Worker {
1438*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1439*35238bceSAndroid Build Coastguard Worker 
1440*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(version) << "\n";
1441*35238bceSAndroid Build Coastguard Worker 
1442*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES)
1443*35238bceSAndroid Build Coastguard Worker         src << "#extension GL_EXT_tessellation_shader : require\n\n";
1444*35238bceSAndroid Build Coastguard Worker 
1445*35238bceSAndroid Build Coastguard Worker     src << "layout(triangles, ccw) in;\n";
1446*35238bceSAndroid Build Coastguard Worker 
1447*35238bceSAndroid Build Coastguard Worker     src << "\nvoid main (void)\n{\n"
1448*35238bceSAndroid Build Coastguard Worker         << "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
1449*35238bceSAndroid Build Coastguard Worker         << "}\n";
1450*35238bceSAndroid Build Coastguard Worker 
1451*35238bceSAndroid Build Coastguard Worker     return src.str();
1452*35238bceSAndroid Build Coastguard Worker }
1453*35238bceSAndroid Build Coastguard Worker 
TessControlExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)1454*35238bceSAndroid Build Coastguard Worker TessControlExecutor::TessControlExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
1455*35238bceSAndroid Build Coastguard Worker     : BufferIoExecutor(renderCtx, shaderSpec,
1456*35238bceSAndroid Build Coastguard Worker                        glu::ProgramSources()
1457*35238bceSAndroid Build Coastguard Worker                            << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
1458*35238bceSAndroid Build Coastguard Worker                            << glu::TessellationControlSource(generateTessControlShader(shaderSpec))
1459*35238bceSAndroid Build Coastguard Worker                            << glu::TessellationEvaluationSource(generateEmptyTessEvalShader(shaderSpec.version))
1460*35238bceSAndroid Build Coastguard Worker                            << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
1461*35238bceSAndroid Build Coastguard Worker {
1462*35238bceSAndroid Build Coastguard Worker }
1463*35238bceSAndroid Build Coastguard Worker 
~TessControlExecutor(void)1464*35238bceSAndroid Build Coastguard Worker TessControlExecutor::~TessControlExecutor(void)
1465*35238bceSAndroid Build Coastguard Worker {
1466*35238bceSAndroid Build Coastguard Worker }
1467*35238bceSAndroid Build Coastguard Worker 
execute(int numValues,const void * const * inputs,void * const * outputs)1468*35238bceSAndroid Build Coastguard Worker void TessControlExecutor::execute(int numValues, const void *const *inputs, void *const *outputs)
1469*35238bceSAndroid Build Coastguard Worker {
1470*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
1471*35238bceSAndroid Build Coastguard Worker 
1472*35238bceSAndroid Build Coastguard Worker     initBuffers(numValues);
1473*35238bceSAndroid Build Coastguard Worker 
1474*35238bceSAndroid Build Coastguard Worker     // Setup input buffer & copy data
1475*35238bceSAndroid Build Coastguard Worker     uploadInputBuffer(inputs, numValues);
1476*35238bceSAndroid Build Coastguard Worker 
1477*35238bceSAndroid Build Coastguard Worker     if (!m_inputs.empty())
1478*35238bceSAndroid Build Coastguard Worker         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());
1479*35238bceSAndroid Build Coastguard Worker 
1480*35238bceSAndroid Build Coastguard Worker     gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());
1481*35238bceSAndroid Build Coastguard Worker 
1482*35238bceSAndroid Build Coastguard Worker     uint32_t vertexArray;
1483*35238bceSAndroid Build Coastguard Worker     gl.genVertexArrays(1, &vertexArray);
1484*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(vertexArray);
1485*35238bceSAndroid Build Coastguard Worker 
1486*35238bceSAndroid Build Coastguard Worker     // Render patches
1487*35238bceSAndroid Build Coastguard Worker     gl.patchParameteri(GL_PATCH_VERTICES, 3);
1488*35238bceSAndroid Build Coastguard Worker     gl.drawArrays(GL_PATCHES, 0, 3 * numValues);
1489*35238bceSAndroid Build Coastguard Worker 
1490*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(0);
1491*35238bceSAndroid Build Coastguard Worker     gl.deleteVertexArrays(1, &vertexArray);
1492*35238bceSAndroid Build Coastguard Worker 
1493*35238bceSAndroid Build Coastguard Worker     // Read back data
1494*35238bceSAndroid Build Coastguard Worker     readOutputBuffer(outputs, numValues);
1495*35238bceSAndroid Build Coastguard Worker }
1496*35238bceSAndroid Build Coastguard Worker 
1497*35238bceSAndroid Build Coastguard Worker // TessEvaluationExecutor
1498*35238bceSAndroid Build Coastguard Worker 
1499*35238bceSAndroid Build Coastguard Worker class TessEvaluationExecutor : public BufferIoExecutor
1500*35238bceSAndroid Build Coastguard Worker {
1501*35238bceSAndroid Build Coastguard Worker public:
1502*35238bceSAndroid Build Coastguard Worker     static TessEvaluationExecutor *create(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
1503*35238bceSAndroid Build Coastguard Worker 
1504*35238bceSAndroid Build Coastguard Worker     ~TessEvaluationExecutor(void);
1505*35238bceSAndroid Build Coastguard Worker 
1506*35238bceSAndroid Build Coastguard Worker     void execute(int numValues, const void *const *inputs, void *const *outputs);
1507*35238bceSAndroid Build Coastguard Worker 
1508*35238bceSAndroid Build Coastguard Worker protected:
1509*35238bceSAndroid Build Coastguard Worker     static std::string generateTessEvalShader(const ShaderSpec &shaderSpec);
1510*35238bceSAndroid Build Coastguard Worker 
1511*35238bceSAndroid Build Coastguard Worker private:
1512*35238bceSAndroid Build Coastguard Worker     TessEvaluationExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec);
1513*35238bceSAndroid Build Coastguard Worker };
1514*35238bceSAndroid Build Coastguard Worker 
create(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)1515*35238bceSAndroid Build Coastguard Worker TessEvaluationExecutor *TessEvaluationExecutor::create(const glu::RenderContext &renderCtx,
1516*35238bceSAndroid Build Coastguard Worker                                                        const ShaderSpec &shaderSpec)
1517*35238bceSAndroid Build Coastguard Worker {
1518*35238bceSAndroid Build Coastguard Worker     checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_EVALUATION);
1519*35238bceSAndroid Build Coastguard Worker 
1520*35238bceSAndroid Build Coastguard Worker     return new TessEvaluationExecutor(renderCtx, shaderSpec);
1521*35238bceSAndroid Build Coastguard Worker }
1522*35238bceSAndroid Build Coastguard Worker 
generatePassthroughTessControlShader(glu::GLSLVersion version)1523*35238bceSAndroid Build Coastguard Worker static std::string generatePassthroughTessControlShader(glu::GLSLVersion version)
1524*35238bceSAndroid Build Coastguard Worker {
1525*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1526*35238bceSAndroid Build Coastguard Worker 
1527*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(version) << "\n";
1528*35238bceSAndroid Build Coastguard Worker 
1529*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES)
1530*35238bceSAndroid Build Coastguard Worker         src << "#extension GL_EXT_tessellation_shader : require\n\n";
1531*35238bceSAndroid Build Coastguard Worker 
1532*35238bceSAndroid Build Coastguard Worker     src << "layout(vertices = 1) out;\n\n";
1533*35238bceSAndroid Build Coastguard Worker 
1534*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n{\n";
1535*35238bceSAndroid Build Coastguard Worker 
1536*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < 2; ndx++)
1537*35238bceSAndroid Build Coastguard Worker         src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
1538*35238bceSAndroid Build Coastguard Worker 
1539*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < 4; ndx++)
1540*35238bceSAndroid Build Coastguard Worker         src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
1541*35238bceSAndroid Build Coastguard Worker 
1542*35238bceSAndroid Build Coastguard Worker     src << "}\n";
1543*35238bceSAndroid Build Coastguard Worker 
1544*35238bceSAndroid Build Coastguard Worker     return src.str();
1545*35238bceSAndroid Build Coastguard Worker }
1546*35238bceSAndroid Build Coastguard Worker 
generateTessEvalShader(const ShaderSpec & shaderSpec)1547*35238bceSAndroid Build Coastguard Worker std::string TessEvaluationExecutor::generateTessEvalShader(const ShaderSpec &shaderSpec)
1548*35238bceSAndroid Build Coastguard Worker {
1549*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
1550*35238bceSAndroid Build Coastguard Worker 
1551*35238bceSAndroid Build Coastguard Worker     src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
1552*35238bceSAndroid Build Coastguard Worker 
1553*35238bceSAndroid Build Coastguard Worker     if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
1554*35238bceSAndroid Build Coastguard Worker         src << "#extension GL_EXT_tessellation_shader : require\n";
1555*35238bceSAndroid Build Coastguard Worker 
1556*35238bceSAndroid Build Coastguard Worker     if (!shaderSpec.globalDeclarations.empty())
1557*35238bceSAndroid Build Coastguard Worker         src << shaderSpec.globalDeclarations << "\n";
1558*35238bceSAndroid Build Coastguard Worker 
1559*35238bceSAndroid Build Coastguard Worker     src << "\n";
1560*35238bceSAndroid Build Coastguard Worker 
1561*35238bceSAndroid Build Coastguard Worker     src << "layout(isolines, equal_spacing) in;\n\n";
1562*35238bceSAndroid Build Coastguard Worker 
1563*35238bceSAndroid Build Coastguard Worker     declareBufferBlocks(src, shaderSpec);
1564*35238bceSAndroid Build Coastguard Worker 
1565*35238bceSAndroid Build Coastguard Worker     src << "void main (void)\n{\n"
1566*35238bceSAndroid Build Coastguard Worker         << "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n"
1567*35238bceSAndroid Build Coastguard Worker         << "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n";
1568*35238bceSAndroid Build Coastguard Worker 
1569*35238bceSAndroid Build Coastguard Worker     generateExecBufferIo(src, shaderSpec, "invocationId");
1570*35238bceSAndroid Build Coastguard Worker 
1571*35238bceSAndroid Build Coastguard Worker     src << "}\n";
1572*35238bceSAndroid Build Coastguard Worker 
1573*35238bceSAndroid Build Coastguard Worker     return src.str();
1574*35238bceSAndroid Build Coastguard Worker }
1575*35238bceSAndroid Build Coastguard Worker 
TessEvaluationExecutor(const glu::RenderContext & renderCtx,const ShaderSpec & shaderSpec)1576*35238bceSAndroid Build Coastguard Worker TessEvaluationExecutor::TessEvaluationExecutor(const glu::RenderContext &renderCtx, const ShaderSpec &shaderSpec)
1577*35238bceSAndroid Build Coastguard Worker     : BufferIoExecutor(renderCtx, shaderSpec,
1578*35238bceSAndroid Build Coastguard Worker                        glu::ProgramSources()
1579*35238bceSAndroid Build Coastguard Worker                            << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
1580*35238bceSAndroid Build Coastguard Worker                            << glu::TessellationControlSource(generatePassthroughTessControlShader(shaderSpec.version))
1581*35238bceSAndroid Build Coastguard Worker                            << glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec))
1582*35238bceSAndroid Build Coastguard Worker                            << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
1583*35238bceSAndroid Build Coastguard Worker {
1584*35238bceSAndroid Build Coastguard Worker }
1585*35238bceSAndroid Build Coastguard Worker 
~TessEvaluationExecutor(void)1586*35238bceSAndroid Build Coastguard Worker TessEvaluationExecutor::~TessEvaluationExecutor(void)
1587*35238bceSAndroid Build Coastguard Worker {
1588*35238bceSAndroid Build Coastguard Worker }
1589*35238bceSAndroid Build Coastguard Worker 
execute(int numValues,const void * const * inputs,void * const * outputs)1590*35238bceSAndroid Build Coastguard Worker void TessEvaluationExecutor::execute(int numValues, const void *const *inputs, void *const *outputs)
1591*35238bceSAndroid Build Coastguard Worker {
1592*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
1593*35238bceSAndroid Build Coastguard Worker     const int alignedValues  = deAlign32(numValues, 2);
1594*35238bceSAndroid Build Coastguard Worker 
1595*35238bceSAndroid Build Coastguard Worker     // Initialize buffers with aligned value count to make room for padding
1596*35238bceSAndroid Build Coastguard Worker     initBuffers(alignedValues);
1597*35238bceSAndroid Build Coastguard Worker 
1598*35238bceSAndroid Build Coastguard Worker     // Setup input buffer & copy data
1599*35238bceSAndroid Build Coastguard Worker     uploadInputBuffer(inputs, numValues);
1600*35238bceSAndroid Build Coastguard Worker 
1601*35238bceSAndroid Build Coastguard Worker     // \todo [2014-06-26 pyry] Duplicate last value in the buffer to prevent infinite loops for example?
1602*35238bceSAndroid Build Coastguard Worker 
1603*35238bceSAndroid Build Coastguard Worker     if (!m_inputs.empty())
1604*35238bceSAndroid Build Coastguard Worker         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());
1605*35238bceSAndroid Build Coastguard Worker 
1606*35238bceSAndroid Build Coastguard Worker     gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());
1607*35238bceSAndroid Build Coastguard Worker 
1608*35238bceSAndroid Build Coastguard Worker     uint32_t vertexArray;
1609*35238bceSAndroid Build Coastguard Worker     gl.genVertexArrays(1, &vertexArray);
1610*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(vertexArray);
1611*35238bceSAndroid Build Coastguard Worker 
1612*35238bceSAndroid Build Coastguard Worker     // Render patches
1613*35238bceSAndroid Build Coastguard Worker     gl.patchParameteri(GL_PATCH_VERTICES, 2);
1614*35238bceSAndroid Build Coastguard Worker     gl.drawArrays(GL_PATCHES, 0, alignedValues);
1615*35238bceSAndroid Build Coastguard Worker 
1616*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(0);
1617*35238bceSAndroid Build Coastguard Worker     gl.deleteVertexArrays(1, &vertexArray);
1618*35238bceSAndroid Build Coastguard Worker 
1619*35238bceSAndroid Build Coastguard Worker     // Read back data
1620*35238bceSAndroid Build Coastguard Worker     readOutputBuffer(outputs, numValues);
1621*35238bceSAndroid Build Coastguard Worker }
1622*35238bceSAndroid Build Coastguard Worker 
1623*35238bceSAndroid Build Coastguard Worker // Utilities
1624*35238bceSAndroid Build Coastguard Worker 
createExecutor(const glu::RenderContext & renderCtx,glu::ShaderType shaderType,const ShaderSpec & shaderSpec)1625*35238bceSAndroid Build Coastguard Worker ShaderExecutor *createExecutor(const glu::RenderContext &renderCtx, glu::ShaderType shaderType,
1626*35238bceSAndroid Build Coastguard Worker                                const ShaderSpec &shaderSpec)
1627*35238bceSAndroid Build Coastguard Worker {
1628*35238bceSAndroid Build Coastguard Worker     switch (shaderType)
1629*35238bceSAndroid Build Coastguard Worker     {
1630*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_VERTEX:
1631*35238bceSAndroid Build Coastguard Worker         return new VertexShaderExecutor(renderCtx, shaderSpec);
1632*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_CONTROL:
1633*35238bceSAndroid Build Coastguard Worker         return TessControlExecutor::create(renderCtx, shaderSpec);
1634*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_EVALUATION:
1635*35238bceSAndroid Build Coastguard Worker         return TessEvaluationExecutor::create(renderCtx, shaderSpec);
1636*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_GEOMETRY:
1637*35238bceSAndroid Build Coastguard Worker         return GeometryShaderExecutor::create(renderCtx, shaderSpec);
1638*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_FRAGMENT:
1639*35238bceSAndroid Build Coastguard Worker         return new FragmentShaderExecutor(renderCtx, shaderSpec);
1640*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_COMPUTE:
1641*35238bceSAndroid Build Coastguard Worker         return new ComputeShaderExecutor(renderCtx, shaderSpec);
1642*35238bceSAndroid Build Coastguard Worker     default:
1643*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Unsupported shader type");
1644*35238bceSAndroid Build Coastguard Worker     }
1645*35238bceSAndroid Build Coastguard Worker }
1646*35238bceSAndroid Build Coastguard Worker 
executorSupported(glu::ShaderType shaderType)1647*35238bceSAndroid Build Coastguard Worker bool executorSupported(glu::ShaderType shaderType)
1648*35238bceSAndroid Build Coastguard Worker {
1649*35238bceSAndroid Build Coastguard Worker     switch (shaderType)
1650*35238bceSAndroid Build Coastguard Worker     {
1651*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_VERTEX:
1652*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_CONTROL:
1653*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_EVALUATION:
1654*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_GEOMETRY:
1655*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_FRAGMENT:
1656*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_COMPUTE:
1657*35238bceSAndroid Build Coastguard Worker         return true;
1658*35238bceSAndroid Build Coastguard Worker     default:
1659*35238bceSAndroid Build Coastguard Worker         return false;
1660*35238bceSAndroid Build Coastguard Worker     }
1661*35238bceSAndroid Build Coastguard Worker }
1662*35238bceSAndroid Build Coastguard Worker 
1663*35238bceSAndroid Build Coastguard Worker } // namespace ShaderExecUtil
1664*35238bceSAndroid Build Coastguard Worker } // namespace gls
1665*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1666