xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fFboTestUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief FBO test utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fFboTestUtil.hpp"
25 #include "sglrContextUtil.hpp"
26 #include "sglrGLContext.hpp"
27 #include "sglrReferenceContext.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "deStringUtil.hpp"
31 #include "deMath.h"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 
35 #include <limits>
36 
37 namespace deqp
38 {
39 namespace gles3
40 {
41 namespace Functional
42 {
43 namespace FboTestUtil
44 {
45 
46 using std::string;
47 using std::vector;
48 using tcu::IVec2;
49 using tcu::IVec3;
50 using tcu::IVec4;
51 using tcu::Vec2;
52 using tcu::Vec3;
53 using tcu::Vec4;
54 
mapDataTypeToGenericVecType(glu::DataType type)55 static rr::GenericVecType mapDataTypeToGenericVecType(glu::DataType type)
56 {
57     switch (type)
58     {
59     case glu::TYPE_FLOAT_VEC4:
60         return rr::GENERICVECTYPE_FLOAT;
61     case glu::TYPE_INT_VEC4:
62         return rr::GENERICVECTYPE_INT32;
63     case glu::TYPE_UINT_VEC4:
64         return rr::GENERICVECTYPE_UINT32;
65     default:
66         DE_ASSERT(false);
67         return rr::GENERICVECTYPE_LAST;
68     }
69 }
70 
71 template <typename T>
castVectorSaturate(const tcu::Vec4 & in)72 static tcu::Vector<T, 4> castVectorSaturate(const tcu::Vec4 &in)
73 {
74     return tcu::Vector<T, 4>(
75         ((double)in.x() + 0.5 >= (double)std::numeric_limits<T>::max()) ?
76             (std::numeric_limits<T>::max()) :
77             (((double)in.x() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) :
78                                                                                (T(in.x()))),
79         ((double)in.y() + 0.5 >= (double)std::numeric_limits<T>::max()) ?
80             (std::numeric_limits<T>::max()) :
81             (((double)in.y() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) :
82                                                                                (T(in.y()))),
83         ((double)in.z() + 0.5 >= (double)std::numeric_limits<T>::max()) ?
84             (std::numeric_limits<T>::max()) :
85             (((double)in.z() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) :
86                                                                                (T(in.z()))),
87         ((double)in.w() + 0.5 >= (double)std::numeric_limits<T>::max()) ?
88             (std::numeric_limits<T>::max()) :
89             (((double)in.w() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) :
90                                                                                (T(in.w()))));
91 }
92 
FlatColorShader(glu::DataType outputType)93 FlatColorShader::FlatColorShader(glu::DataType outputType)
94     : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
95                     << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
96                     << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
97                     << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
98                     << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
99                     << sglr::pdec::VertexSource("#version 300 es\n"
100                                                 "in highp vec4 a_position;\n"
101                                                 "void main (void)\n"
102                                                 "{\n"
103                                                 "    gl_Position = a_position;\n"
104                                                 "}\n")
105                     << sglr::pdec::FragmentSource(string("#version 300 es\n"
106                                                          "uniform highp vec4 u_color;\n"
107                                                          "layout(location = 0) out highp ") +
108                                                   glu::getDataTypeName(outputType) +
109                                                   " o_color;\n"
110                                                   "void main (void)\n"
111                                                   "{\n"
112                                                   "    o_color = " +
113                                                   glu::getDataTypeName(outputType) +
114                                                   "(u_color);\n"
115                                                   "}\n"))
116     , m_outputType(outputType)
117 {
118 }
119 
setColor(sglr::Context & context,uint32_t program,const tcu::Vec4 & color)120 void FlatColorShader::setColor(sglr::Context &context, uint32_t program, const tcu::Vec4 &color)
121 {
122     int32_t location = context.getUniformLocation(program, "u_color");
123 
124     context.useProgram(program);
125     context.uniform4fv(location, 1, color.getPtr());
126 }
127 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const128 void FlatColorShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
129                                     const int numPackets) const
130 {
131     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
132     {
133         rr::VertexPacket &packet = *packets[packetNdx];
134 
135         packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
136     }
137 }
138 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const139 void FlatColorShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
140                                      const rr::FragmentShadingContext &context) const
141 {
142     const tcu::Vec4 color(m_uniforms[0].value.f4);
143     const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
144     const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
145 
146     DE_UNREF(packets);
147 
148     if (m_outputType == glu::TYPE_FLOAT_VEC4)
149     {
150         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
151             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
152                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
153     }
154     else if (m_outputType == glu::TYPE_INT_VEC4)
155     {
156         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
157             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
158                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
159     }
160     else if (m_outputType == glu::TYPE_UINT_VEC4)
161     {
162         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
163             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
164                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
165     }
166     else
167         DE_ASSERT(false);
168 }
169 
GradientShader(glu::DataType outputType)170 GradientShader::GradientShader(glu::DataType outputType)
171     : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
172                     << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
173                     << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
174                     << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
175                     << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
176                     << sglr::pdec::Uniform("u_gradientMin", glu::TYPE_FLOAT_VEC4)
177                     << sglr::pdec::Uniform("u_gradientMax", glu::TYPE_FLOAT_VEC4)
178                     << sglr::pdec::VertexSource("#version 300 es\n"
179                                                 "in highp vec4 a_position;\n"
180                                                 "in highp vec4 a_coord;\n"
181                                                 "out highp vec4 v_coord;\n"
182                                                 "void main (void)\n"
183                                                 "{\n"
184                                                 "    gl_Position = a_position;\n"
185                                                 "    v_coord = a_coord;\n"
186                                                 "}\n")
187                     << sglr::pdec::FragmentSource(string("#version 300 es\n"
188                                                          "in highp vec4 v_coord;\n"
189                                                          "uniform highp vec4 u_gradientMin;\n"
190                                                          "uniform highp vec4 u_gradientMax;\n"
191                                                          "layout(location = 0) out highp ") +
192                                                   glu::getDataTypeName(outputType) +
193                                                   " o_color;\n"
194                                                   "void main (void)\n"
195                                                   "{\n"
196                                                   "    highp float x = v_coord.x;\n"
197                                                   "    highp float y = v_coord.y;\n"
198                                                   "    highp float f0 = (x + y) * 0.5;\n"
199                                                   "    highp float f1 = 0.5 + (x - y) * 0.5;\n"
200                                                   "    highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n"
201                                                   "    o_color = " +
202                                                   glu::getDataTypeName(outputType) +
203                                                   "(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n"
204                                                   "}\n"))
205     , m_outputType(outputType)
206 {
207 }
208 
setGradient(sglr::Context & ctx,uint32_t program,const tcu::Vec4 & gradientMin,const tcu::Vec4 & gradientMax)209 void GradientShader::setGradient(sglr::Context &ctx, uint32_t program, const tcu::Vec4 &gradientMin,
210                                  const tcu::Vec4 &gradientMax)
211 {
212     ctx.useProgram(program);
213     ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMin"), 1, gradientMin.getPtr());
214     ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMax"), 1, gradientMax.getPtr());
215 }
216 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const217 void GradientShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
218                                    const int numPackets) const
219 {
220     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
221     {
222         rr::VertexPacket &packet = *packets[packetNdx];
223 
224         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
225         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
226     }
227 }
228 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const229 void GradientShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
230                                     const rr::FragmentShadingContext &context) const
231 {
232     const tcu::Vec4 gradientMin(m_uniforms[0].value.f4);
233     const tcu::Vec4 gradientMax(m_uniforms[1].value.f4);
234 
235     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
236         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
237         {
238             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
239             const float x         = coord.x();
240             const float y         = coord.y();
241             const float f0        = (x + y) * 0.5f;
242             const float f1        = 0.5f + (x - y) * 0.5f;
243             const tcu::Vec4 fv    = Vec4(f0, f1, 1.0f - f0, 1.0f - f1);
244 
245             const tcu::Vec4 color    = gradientMin + (gradientMax - gradientMin) * fv;
246             const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
247             const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
248 
249             if (m_outputType == glu::TYPE_FLOAT_VEC4)
250                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
251             else if (m_outputType == glu::TYPE_INT_VEC4)
252                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
253             else if (m_outputType == glu::TYPE_UINT_VEC4)
254                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
255             else
256                 DE_ASSERT(false);
257         }
258 }
259 
genTexFragmentShader(const vector<glu::DataType> & samplerTypes,glu::DataType outputType)260 static string genTexFragmentShader(const vector<glu::DataType> &samplerTypes, glu::DataType outputType)
261 {
262     const char *precision = "highp";
263     std::ostringstream src;
264 
265     src << "#version 300 es\n"
266         << "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
267 
268     src << "in highp vec2 v_coord;\n";
269 
270     for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
271     {
272         src << "uniform " << precision << " " << glu::getDataTypeName(samplerTypes[samplerNdx]) << " u_sampler"
273             << samplerNdx << ";\n";
274         src << "uniform " << precision << " vec4 u_texScale" << samplerNdx << ";\n";
275         src << "uniform " << precision << " vec4 u_texBias" << samplerNdx << ";\n";
276     }
277 
278     // Output scale & bias
279     src << "uniform " << precision << " vec4 u_outScale0;\n"
280         << "uniform " << precision << " vec4 u_outBias0;\n";
281 
282     src << "\n"
283         << "void main (void)\n"
284         << "{\n"
285         << "    " << precision << " vec4 out0 = vec4(0.0);\n";
286 
287     // Texture input fetch and combine.
288     for (int inNdx = 0; inNdx < (int)samplerTypes.size(); inNdx++)
289         src << "\tout0 += vec4("
290             << "texture(u_sampler" << inNdx << ", v_coord)) * u_texScale" << inNdx << " + u_texBias" << inNdx << ";\n";
291 
292     // Write output.
293     src << "    o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
294 
295     src << "}\n";
296 
297     return src.str();
298 }
299 
genTexture2DShaderDecl(const DataTypes & samplerTypes,glu::DataType outputType)300 static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl(const DataTypes &samplerTypes,
301                                                                    glu::DataType outputType)
302 {
303     sglr::pdec::ShaderProgramDeclaration decl;
304 
305     decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
306     decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
307     decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
308     decl << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType));
309 
310     decl << sglr::pdec::VertexSource("#version 300 es\n"
311                                      "in highp vec4 a_position;\n"
312                                      "in highp vec2 a_coord;\n"
313                                      "out highp vec2 v_coord;\n"
314                                      "void main(void)\n"
315                                      "{\n"
316                                      "    gl_Position = a_position;\n"
317                                      "    v_coord = a_coord;\n"
318                                      "}\n");
319     decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
320 
321     decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
322     decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
323 
324     for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
325     {
326         decl << sglr::pdec::Uniform(std::string("u_sampler") + de::toString(ndx), samplerTypes.vec[ndx]);
327         decl << sglr::pdec::Uniform(std::string("u_texScale") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
328         decl << sglr::pdec::Uniform(std::string("u_texBias") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
329     }
330 
331     return decl;
332 }
333 
Texture2DShader(const DataTypes & samplerTypes,glu::DataType outputType,const Vec4 & outScale,const Vec4 & outBias)334 Texture2DShader::Texture2DShader(const DataTypes &samplerTypes, glu::DataType outputType, const Vec4 &outScale,
335                                  const Vec4 &outBias)
336     : sglr::ShaderProgram(genTexture2DShaderDecl(samplerTypes, outputType))
337     , m_outScale(outScale)
338     , m_outBias(outBias)
339     , m_outputType(outputType)
340 {
341     m_inputs.resize(samplerTypes.vec.size());
342 
343     // Initialize units.
344     for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
345     {
346         m_inputs[ndx].unitNdx = ndx;
347         m_inputs[ndx].scale   = Vec4(1.0f);
348         m_inputs[ndx].bias    = Vec4(0.0f);
349     }
350 }
351 
setUnit(int inputNdx,int unitNdx)352 void Texture2DShader::setUnit(int inputNdx, int unitNdx)
353 {
354     m_inputs[inputNdx].unitNdx = unitNdx;
355 }
356 
setTexScaleBias(int inputNdx,const Vec4 & scale,const Vec4 & bias)357 void Texture2DShader::setTexScaleBias(int inputNdx, const Vec4 &scale, const Vec4 &bias)
358 {
359     m_inputs[inputNdx].scale = scale;
360     m_inputs[inputNdx].bias  = bias;
361 }
362 
setOutScaleBias(const Vec4 & scale,const Vec4 & bias)363 void Texture2DShader::setOutScaleBias(const Vec4 &scale, const Vec4 &bias)
364 {
365     m_outScale = scale;
366     m_outBias  = bias;
367 }
368 
setUniforms(sglr::Context & gl,uint32_t program) const369 void Texture2DShader::setUniforms(sglr::Context &gl, uint32_t program) const
370 {
371     gl.useProgram(program);
372 
373     for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
374     {
375         string samplerName = string("u_sampler") + de::toString(texNdx);
376         string scaleName   = string("u_texScale") + de::toString(texNdx);
377         string biasName    = string("u_texBias") + de::toString(texNdx);
378 
379         gl.uniform1i(gl.getUniformLocation(program, samplerName.c_str()), m_inputs[texNdx].unitNdx);
380         gl.uniform4fv(gl.getUniformLocation(program, scaleName.c_str()), 1, m_inputs[texNdx].scale.getPtr());
381         gl.uniform4fv(gl.getUniformLocation(program, biasName.c_str()), 1, m_inputs[texNdx].bias.getPtr());
382     }
383 
384     gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
385     gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
386 }
387 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const388 void Texture2DShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
389                                     const int numPackets) const
390 {
391     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
392     {
393         rr::VertexPacket &packet = *packets[packetNdx];
394 
395         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
396         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
397     }
398 }
399 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const400 void Texture2DShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
401                                      const rr::FragmentShadingContext &context) const
402 {
403     const tcu::Vec4 outScale(m_uniforms[0].value.f4);
404     const tcu::Vec4 outBias(m_uniforms[1].value.f4);
405 
406     tcu::Vec2 texCoords[4];
407     tcu::Vec4 colors[4];
408 
409     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
410     {
411         // setup tex coords
412         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
413         {
414             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
415             texCoords[fragNdx]    = tcu::Vec2(coord.x(), coord.y());
416         }
417 
418         // clear result
419         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
420             colors[fragNdx] = tcu::Vec4(0.0f);
421 
422         // sample each texture
423         for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
424         {
425             const sglr::rc::Texture2D *tex = m_uniforms[2 + ndx * 3].sampler.tex2D;
426             const tcu::Vec4 scale(m_uniforms[2 + ndx * 3 + 1].value.f4);
427             const tcu::Vec4 bias(m_uniforms[2 + ndx * 3 + 2].value.f4);
428             tcu::Vec4 tmpColors[4];
429 
430             tex->sample4(tmpColors, texCoords);
431 
432             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
433                 colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
434         }
435 
436         // write out
437         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
438         {
439             const tcu::Vec4 color    = colors[fragNdx] * outScale + outBias;
440             const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
441             const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
442 
443             if (m_outputType == glu::TYPE_FLOAT_VEC4)
444                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
445             else if (m_outputType == glu::TYPE_INT_VEC4)
446                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
447             else if (m_outputType == glu::TYPE_UINT_VEC4)
448                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
449             else
450                 DE_ASSERT(false);
451         }
452     }
453 }
454 
TextureCubeShader(glu::DataType samplerType,glu::DataType outputType)455 TextureCubeShader::TextureCubeShader(glu::DataType samplerType, glu::DataType outputType)
456     : sglr::ShaderProgram(
457           sglr::pdec::ShaderProgramDeclaration()
458           << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
459           << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
460           << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
461           << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
462           << sglr::pdec::Uniform("u_coordMat", glu::TYPE_FLOAT_MAT3) << sglr::pdec::Uniform("u_sampler0", samplerType)
463           << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4) << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
464           << sglr::pdec::VertexSource("#version 300 es\n"
465                                       "in highp vec4 a_position;\n"
466                                       "in mediump vec2 a_coord;\n"
467                                       "uniform mat3 u_coordMat;\n"
468                                       "out mediump vec3 v_coord;\n"
469                                       "void main (void)\n"
470                                       "{\n"
471                                       "    gl_Position = a_position;\n"
472                                       "    v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
473                                       "}\n")
474           << sglr::pdec::FragmentSource(string("") +
475                                         "#version 300 es\n"
476                                         "uniform highp " +
477                                         glu::getDataTypeName(samplerType) +
478                                         " u_sampler0;\n"
479                                         "uniform highp vec4 u_scale;\n"
480                                         "uniform highp vec4 u_bias;\n"
481                                         "in mediump vec3 v_coord;\n"
482                                         "layout(location = 0) out highp " +
483                                         glu::getDataTypeName(outputType) +
484                                         " o_color;\n"
485                                         "void main (void)\n"
486                                         "{\n"
487                                         "    o_color = " +
488                                         glu::getDataTypeName(outputType) +
489                                         "(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n"
490                                         "}\n"))
491     , m_texScale(1.0f)
492     , m_texBias(0.0f)
493     , m_outputType(outputType)
494 {
495 }
496 
setFace(tcu::CubeFace face)497 void TextureCubeShader::setFace(tcu::CubeFace face)
498 {
499     static const float s_cubeTransforms[][3 * 3] = {// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
500                                                     {0.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f, 2.0f, 0.0f, -1.0f},
501                                                     // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
502                                                     {0.0f, 0.0f, 1.0f, 0.0f, -2.0f, 1.0f, -2.0f, 0.0f, 1.0f},
503                                                     // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
504                                                     {2.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f},
505                                                     // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
506                                                     {2.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, -1.0f},
507                                                     // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
508                                                     {-2.0f, 0.0f, 1.0f, 0.0f, -2.0f, 1.0f, 0.0f, 0.0f, -1.0f},
509                                                     // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
510                                                     {2.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f, 0.0f, 0.0f, 1.0f}};
511     DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
512     m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
513 }
514 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)515 void TextureCubeShader::setTexScaleBias(const Vec4 &scale, const Vec4 &bias)
516 {
517     m_texScale = scale;
518     m_texBias  = bias;
519 }
520 
setUniforms(sglr::Context & gl,uint32_t program) const521 void TextureCubeShader::setUniforms(sglr::Context &gl, uint32_t program) const
522 {
523     gl.useProgram(program);
524 
525     gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
526     gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE,
527                         m_coordMat.getColumnMajorData().getPtr());
528     gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
529     gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
530 }
531 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const532 void TextureCubeShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
533                                       const int numPackets) const
534 {
535     tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
536 
537     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
538     {
539         rr::VertexPacket &packet = *packets[packetNdx];
540         tcu::Vec2 a_coord        = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
541         tcu::Vec3 v_coord        = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
542 
543         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
544         packet.outputs[0] = tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
545     }
546 }
547 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const548 void TextureCubeShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
549                                        const rr::FragmentShadingContext &context) const
550 {
551     const tcu::Vec4 texScale(m_uniforms[2].value.f4);
552     const tcu::Vec4 texBias(m_uniforms[3].value.f4);
553 
554     tcu::Vec3 texCoords[4];
555     tcu::Vec4 colors[4];
556 
557     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
558     {
559         const sglr::rc::TextureCube *tex = m_uniforms[1].sampler.texCube;
560 
561         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
562         {
563             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
564             texCoords[fragNdx]    = tcu::Vec3(coord.x(), coord.y(), coord.z());
565         }
566 
567         tex->sample4(colors, texCoords);
568 
569         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
570         {
571             const tcu::Vec4 color    = colors[fragNdx] * texScale + texBias;
572             const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
573             const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
574 
575             if (m_outputType == glu::TYPE_FLOAT_VEC4)
576                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
577             else if (m_outputType == glu::TYPE_INT_VEC4)
578                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
579             else if (m_outputType == glu::TYPE_UINT_VEC4)
580                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
581             else
582                 DE_ASSERT(false);
583         }
584     }
585 }
586 
Texture2DArrayShader(glu::DataType samplerType,glu::DataType outputType)587 Texture2DArrayShader::Texture2DArrayShader(glu::DataType samplerType, glu::DataType outputType)
588     : sglr::ShaderProgram(
589           sglr::pdec::ShaderProgramDeclaration()
590           << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
591           << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
592           << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
593           << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
594           << sglr::pdec::Uniform("u_sampler0", samplerType) << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
595           << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4) << sglr::pdec::Uniform("u_layer", glu::TYPE_INT)
596           << sglr::pdec::VertexSource("#version 300 es\n"
597                                       "in highp vec4 a_position;\n"
598                                       "in highp vec2 a_coord;\n"
599                                       "out highp vec2 v_coord;\n"
600                                       "void main (void)\n"
601                                       "{\n"
602                                       "    gl_Position = a_position;\n"
603                                       "    v_coord = a_coord;\n"
604                                       "}\n")
605           << sglr::pdec::FragmentSource(string("") +
606                                         "#version 300 es\n"
607                                         "uniform highp " +
608                                         glu::getDataTypeName(samplerType) +
609                                         " u_sampler0;\n"
610                                         "uniform highp vec4 u_scale;\n"
611                                         "uniform highp vec4 u_bias;\n"
612                                         "uniform highp int u_layer;\n"
613                                         "in highp vec2 v_coord;\n"
614                                         "layout(location = 0) out highp " +
615                                         glu::getDataTypeName(outputType) +
616                                         " o_color;\n"
617                                         "void main (void)\n"
618                                         "{\n"
619                                         "    o_color = " +
620                                         glu::getDataTypeName(outputType) +
621                                         "(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n"
622                                         "}\n"))
623     , m_texScale(1.0f)
624     , m_texBias(0.0f)
625     , m_layer(0)
626     , m_outputType(outputType)
627 {
628 }
629 
setLayer(int layer)630 void Texture2DArrayShader::setLayer(int layer)
631 {
632     m_layer = layer;
633 }
634 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)635 void Texture2DArrayShader::setTexScaleBias(const Vec4 &scale, const Vec4 &bias)
636 {
637     m_texScale = scale;
638     m_texBias  = bias;
639 }
640 
setUniforms(sglr::Context & gl,uint32_t program) const641 void Texture2DArrayShader::setUniforms(sglr::Context &gl, uint32_t program) const
642 {
643     gl.useProgram(program);
644 
645     gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
646     gl.uniform1i(gl.getUniformLocation(program, "u_layer"), m_layer);
647     gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
648     gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
649 }
650 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const651 void Texture2DArrayShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
652                                          const int numPackets) const
653 {
654     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
655     {
656         rr::VertexPacket &packet = *packets[packetNdx];
657 
658         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
659         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
660     }
661 }
662 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const663 void Texture2DArrayShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
664                                           const rr::FragmentShadingContext &context) const
665 {
666     const tcu::Vec4 texScale(m_uniforms[1].value.f4);
667     const tcu::Vec4 texBias(m_uniforms[2].value.f4);
668     const int layer = m_uniforms[3].value.i;
669 
670     tcu::Vec3 texCoords[4];
671     tcu::Vec4 colors[4];
672 
673     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
674     {
675         const sglr::rc::Texture2DArray *tex = m_uniforms[0].sampler.tex2DArray;
676 
677         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
678         {
679             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
680             texCoords[fragNdx]    = tcu::Vec3(coord.x(), coord.y(), float(layer));
681         }
682 
683         tex->sample4(colors, texCoords);
684 
685         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
686         {
687             const tcu::Vec4 color    = colors[fragNdx] * texScale + texBias;
688             const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
689             const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
690 
691             if (m_outputType == glu::TYPE_FLOAT_VEC4)
692                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
693             else if (m_outputType == glu::TYPE_INT_VEC4)
694                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
695             else if (m_outputType == glu::TYPE_UINT_VEC4)
696                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
697             else
698                 DE_ASSERT(false);
699         }
700     }
701 }
702 
Texture3DShader(glu::DataType samplerType,glu::DataType outputType)703 Texture3DShader::Texture3DShader(glu::DataType samplerType, glu::DataType outputType)
704     : sglr::ShaderProgram(
705           sglr::pdec::ShaderProgramDeclaration()
706           << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
707           << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
708           << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
709           << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
710           << sglr::pdec::Uniform("u_sampler0", samplerType) << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
711           << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4) << sglr::pdec::Uniform("u_depth", glu::TYPE_FLOAT)
712           << sglr::pdec::VertexSource("#version 300 es\n"
713                                       "in highp vec4 a_position;\n"
714                                       "in highp vec2 a_coord;\n"
715                                       "out highp vec2 v_coord;\n"
716                                       "void main (void)\n"
717                                       "{\n"
718                                       "    gl_Position = a_position;\n"
719                                       "    v_coord = a_coord;\n"
720                                       "}\n")
721           << sglr::pdec::FragmentSource(string("") +
722                                         "#version 300 es\n"
723                                         "uniform highp " +
724                                         glu::getDataTypeName(samplerType) +
725                                         " u_sampler0;\n"
726                                         "uniform highp vec4 u_scale;\n"
727                                         "uniform highp vec4 u_bias;\n"
728                                         "uniform highp float u_depth;\n"
729                                         "in highp vec2 v_coord;\n"
730                                         "layout(location = 0) out highp " +
731                                         glu::getDataTypeName(outputType) +
732                                         " o_color;\n"
733                                         "void main (void)\n"
734                                         "{\n"
735                                         "    o_color = " +
736                                         glu::getDataTypeName(outputType) +
737                                         "(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n"
738                                         "}\n"))
739     , m_texScale(1.0f)
740     , m_texBias(0.0f)
741     , m_depth(0.0f)
742     , m_outputType(outputType)
743 {
744 }
745 
setDepth(float depth)746 void Texture3DShader::setDepth(float depth)
747 {
748     m_depth = depth;
749 }
750 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)751 void Texture3DShader::setTexScaleBias(const Vec4 &scale, const Vec4 &bias)
752 {
753     m_texScale = scale;
754     m_texBias  = bias;
755 }
756 
setUniforms(sglr::Context & gl,uint32_t program) const757 void Texture3DShader::setUniforms(sglr::Context &gl, uint32_t program) const
758 {
759     gl.useProgram(program);
760 
761     gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
762     gl.uniform1f(gl.getUniformLocation(program, "u_depth"), m_depth);
763     gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
764     gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
765 }
766 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const767 void Texture3DShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
768                                     const int numPackets) const
769 {
770     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
771     {
772         rr::VertexPacket &packet = *packets[packetNdx];
773 
774         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
775         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
776     }
777 }
778 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const779 void Texture3DShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
780                                      const rr::FragmentShadingContext &context) const
781 {
782     const tcu::Vec4 texScale(m_uniforms[1].value.f4);
783     const tcu::Vec4 texBias(m_uniforms[2].value.f4);
784     const float depth = m_uniforms[3].value.f;
785 
786     tcu::Vec3 texCoords[4];
787     tcu::Vec4 colors[4];
788 
789     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
790     {
791         const sglr::rc::Texture3D *tex = m_uniforms[0].sampler.tex3D;
792 
793         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
794         {
795             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
796             texCoords[fragNdx]    = tcu::Vec3(coord.x(), coord.y(), depth);
797         }
798 
799         tex->sample4(colors, texCoords);
800 
801         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
802         {
803             const tcu::Vec4 color    = colors[fragNdx] * texScale + texBias;
804             const tcu::IVec4 icolor  = castVectorSaturate<int32_t>(color);
805             const tcu::UVec4 uicolor = castVectorSaturate<uint32_t>(color);
806 
807             if (m_outputType == glu::TYPE_FLOAT_VEC4)
808                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
809             else if (m_outputType == glu::TYPE_INT_VEC4)
810                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
811             else if (m_outputType == glu::TYPE_UINT_VEC4)
812                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
813             else
814                 DE_ASSERT(false);
815         }
816     }
817 }
818 
DepthGradientShader(glu::DataType outputType)819 DepthGradientShader::DepthGradientShader(glu::DataType outputType)
820     : ShaderProgram(
821           sglr::pdec::ShaderProgramDeclaration()
822           << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
823           << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
824           << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
825           << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
826           << sglr::pdec::Uniform("u_maxGradient", glu::TYPE_FLOAT)
827           << sglr::pdec::Uniform("u_minGradient", glu::TYPE_FLOAT)
828           << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
829           << sglr::pdec::VertexSource("#version 300 es\n"
830                                       "in highp vec4 a_position;\n"
831                                       "in highp vec4 a_coord;\n"
832                                       "out highp vec4 v_coord;\n"
833                                       "void main (void)\n"
834                                       "{\n"
835                                       "    gl_Position = a_position;\n"
836                                       "    v_coord = a_coord;\n"
837                                       "}\n")
838           << sglr::pdec::FragmentSource(string("#version 300 es\n"
839                                                "in highp vec4 v_coord;\n"
840                                                "uniform highp float u_minGradient;\n"
841                                                "uniform highp float u_maxGradient;\n"
842                                                "uniform highp vec4 u_color;\n"
843                                                "layout(location = 0) out highp ") +
844                                         glu::getDataTypeName(outputType) +
845                                         " o_color;\n"
846                                         "void main (void)\n"
847                                         "{\n"
848                                         "    highp float x = v_coord.x;\n"
849                                         "    highp float y = v_coord.y;\n"
850                                         "    highp float f0 = (x + y) * 0.5;\n"
851                                         "    gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n"
852                                         "    o_color = " +
853                                         glu::getDataTypeName(outputType) +
854                                         "(u_color);\n"
855                                         "}\n"))
856     , m_outputType(outputType)
857     , u_minGradient(getUniformByName("u_minGradient"))
858     , u_maxGradient(getUniformByName("u_maxGradient"))
859     , u_color(getUniformByName("u_color"))
860 {
861 }
862 
setUniforms(sglr::Context & ctx,uint32_t program,const float gradientMin,const float gradientMax,const tcu::Vec4 & color)863 void DepthGradientShader::setUniforms(sglr::Context &ctx, uint32_t program, const float gradientMin,
864                                       const float gradientMax, const tcu::Vec4 &color)
865 {
866     ctx.useProgram(program);
867     ctx.uniform1fv(ctx.getUniformLocation(program, "u_minGradient"), 1, &gradientMin);
868     ctx.uniform1fv(ctx.getUniformLocation(program, "u_maxGradient"), 1, &gradientMax);
869     ctx.uniform4fv(ctx.getUniformLocation(program, "u_color"), 1, color.getPtr());
870 }
871 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const872 void DepthGradientShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
873                                         const int numPackets) const
874 {
875     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
876     {
877         rr::VertexPacket &packet = *packets[packetNdx];
878 
879         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
880         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
881     }
882 }
883 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const884 void DepthGradientShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
885                                          const rr::FragmentShadingContext &context) const
886 {
887     const float gradientMin(u_minGradient.value.f);
888     const float gradientMax(u_maxGradient.value.f);
889     const tcu::Vec4 color(u_color.value.f4);
890     const tcu::IVec4 icolor(castVectorSaturate<int32_t>(color));
891     const tcu::UVec4 uicolor(castVectorSaturate<uint32_t>(color));
892 
893     // running this shader without a depth buffer does not make any sense
894     DE_ASSERT(context.fragmentDepths);
895 
896     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
897         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
898         {
899             const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
900             const float x         = coord.x();
901             const float y         = coord.y();
902             const float f0        = (x + y) * 0.5f;
903 
904             rr::writeFragmentDepth(context, packetNdx, fragNdx, 0, gradientMin + (gradientMax - gradientMin) * f0);
905 
906             if (m_outputType == glu::TYPE_FLOAT_VEC4)
907                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
908             else if (m_outputType == glu::TYPE_INT_VEC4)
909                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
910             else if (m_outputType == glu::TYPE_UINT_VEC4)
911                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
912             else
913                 DE_ASSERT(false);
914         }
915 }
916 
clearColorBuffer(sglr::Context & ctx,const tcu::TextureFormat & format,const tcu::Vec4 & value)917 void clearColorBuffer(sglr::Context &ctx, const tcu::TextureFormat &format, const tcu::Vec4 &value)
918 {
919     const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
920 
921     switch (fmtClass)
922     {
923     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
924     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
925     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
926         ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
927         break;
928 
929     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
930         ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
931         break;
932 
933     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
934         ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
935         break;
936 
937     default:
938         DE_ASSERT(false);
939     }
940 }
941 
readPixels(sglr::Context & ctx,tcu::Surface & dst,int x,int y,int width,int height,const tcu::TextureFormat & format,const tcu::Vec4 & scale,const tcu::Vec4 & bias)942 void readPixels(sglr::Context &ctx, tcu::Surface &dst, int x, int y, int width, int height,
943                 const tcu::TextureFormat &format, const tcu::Vec4 &scale, const tcu::Vec4 &bias)
944 {
945     tcu::TextureFormat readFormat   = getFramebufferReadFormat(format);
946     glu::TransferFormat transferFmt = glu::getTransferFormat(readFormat);
947     int alignment                   = 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
948     int rowSize                     = deAlign32(readFormat.getPixelSize() * width, alignment);
949     vector<uint8_t> data(rowSize * height);
950 
951     ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
952 
953     // Convert to surface.
954     tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
955 
956     dst.setSize(width, height);
957     tcu::PixelBufferAccess dstAccess = dst.getAccess();
958 
959     for (int yo = 0; yo < height; yo++)
960         for (int xo = 0; xo < width; xo++)
961             dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
962 }
963 
getFboIncompleteReasonName(uint32_t reason)964 static const char *getFboIncompleteReasonName(uint32_t reason)
965 {
966     switch (reason)
967     {
968     case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
969         return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
970     case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
971         return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
972     case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
973         return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
974     case GL_FRAMEBUFFER_UNSUPPORTED:
975         return "GL_FRAMEBUFFER_UNSUPPORTED";
976     case GL_FRAMEBUFFER_COMPLETE:
977         return "GL_FRAMEBUFFER_COMPLETE";
978     default:
979         return "UNKNOWN";
980     }
981 }
982 
FboIncompleteException(uint32_t reason,const char * file,int line)983 FboIncompleteException::FboIncompleteException(uint32_t reason, const char *file, int line)
984     : TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
985     , m_reason(reason)
986 {
987 }
988 
getFormatName(uint32_t format)989 const char *getFormatName(uint32_t format)
990 {
991     switch (format)
992     {
993     case GL_RGB565:
994         return "rgb565";
995     case GL_RGB5_A1:
996         return "rgb5_a1";
997     case GL_RGBA4:
998         return "rgba4";
999     case GL_DEPTH_COMPONENT16:
1000         return "depth_component16";
1001     case GL_STENCIL_INDEX8:
1002         return "stencil_index8";
1003     case GL_RGBA32F:
1004         return "rgba32f";
1005     case GL_RGBA32I:
1006         return "rgba32i";
1007     case GL_RGBA32UI:
1008         return "rgba32ui";
1009     case GL_RGBA16F:
1010         return "rgba16f";
1011     case GL_RGBA16I:
1012         return "rgba16i";
1013     case GL_RGBA16UI:
1014         return "rgba16ui";
1015     case GL_RGBA8:
1016         return "rgba8";
1017     case GL_RGBA8I:
1018         return "rgba8i";
1019     case GL_RGBA8UI:
1020         return "rgba8ui";
1021     case GL_SRGB8_ALPHA8:
1022         return "srgb8_alpha8";
1023     case GL_RGB10_A2:
1024         return "rgb10_a2";
1025     case GL_RGB10_A2UI:
1026         return "rgb10_a2ui";
1027     case GL_RGBA8_SNORM:
1028         return "rgba8_snorm";
1029     case GL_RGB8:
1030         return "rgb8";
1031     case GL_R11F_G11F_B10F:
1032         return "r11f_g11f_b10f";
1033     case GL_RGB32F:
1034         return "rgb32f";
1035     case GL_RGB32I:
1036         return "rgb32i";
1037     case GL_RGB32UI:
1038         return "rgb32ui";
1039     case GL_RGB16F:
1040         return "rgb16f";
1041     case GL_RGB16I:
1042         return "rgb16i";
1043     case GL_RGB16UI:
1044         return "rgb16ui";
1045     case GL_RGB8_SNORM:
1046         return "rgb8_snorm";
1047     case GL_RGB8I:
1048         return "rgb8i";
1049     case GL_RGB8UI:
1050         return "rgb8ui";
1051     case GL_SRGB8:
1052         return "srgb8";
1053     case GL_RGB9_E5:
1054         return "rgb9_e5";
1055     case GL_RG32F:
1056         return "rg32f";
1057     case GL_RG32I:
1058         return "rg32i";
1059     case GL_RG32UI:
1060         return "rg32ui";
1061     case GL_RG16F:
1062         return "rg16f";
1063     case GL_RG16I:
1064         return "rg16i";
1065     case GL_RG16UI:
1066         return "rg16ui";
1067     case GL_RG8:
1068         return "rg8";
1069     case GL_RG8I:
1070         return "rg8i";
1071     case GL_RG8UI:
1072         return "rg8ui";
1073     case GL_RG8_SNORM:
1074         return "rg8_snorm";
1075     case GL_R32F:
1076         return "r32f";
1077     case GL_R32I:
1078         return "r32i";
1079     case GL_R32UI:
1080         return "r32ui";
1081     case GL_R16F:
1082         return "r16f";
1083     case GL_R16I:
1084         return "r16i";
1085     case GL_R16UI:
1086         return "r16ui";
1087     case GL_R8:
1088         return "r8";
1089     case GL_R8I:
1090         return "r8i";
1091     case GL_R8UI:
1092         return "r8ui";
1093     case GL_R8_SNORM:
1094         return "r8_snorm";
1095     case GL_DEPTH_COMPONENT32F:
1096         return "depth_component32f";
1097     case GL_DEPTH_COMPONENT24:
1098         return "depth_component24";
1099     case GL_DEPTH32F_STENCIL8:
1100         return "depth32f_stencil8";
1101     case GL_DEPTH24_STENCIL8:
1102         return "depth24_stencil8";
1103 
1104     default:
1105         TCU_FAIL("Unknown format");
1106     }
1107 }
1108 
getFragmentOutputType(const tcu::TextureFormat & format)1109 glu::DataType getFragmentOutputType(const tcu::TextureFormat &format)
1110 {
1111     switch (tcu::getTextureChannelClass(format.type))
1112     {
1113     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1114     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1115     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1116         return glu::TYPE_FLOAT_VEC4;
1117 
1118     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1119         return glu::TYPE_UINT_VEC4;
1120 
1121     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1122         return glu::TYPE_INT_VEC4;
1123 
1124     default:
1125         DE_FATAL("Unknown format");
1126         return glu::TYPE_LAST;
1127     }
1128 }
1129 
getFramebufferReadFormat(const tcu::TextureFormat & format)1130 tcu::TextureFormat getFramebufferReadFormat(const tcu::TextureFormat &format)
1131 {
1132     switch (tcu::getTextureChannelClass(format.type))
1133     {
1134     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1135         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1136 
1137     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1138     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1139         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1140 
1141     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1142         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1143 
1144     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1145         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1146 
1147     default:
1148         DE_FATAL("Unknown format");
1149         return tcu::TextureFormat();
1150     }
1151 }
1152 
calculateU8ConversionError(int srcBits)1153 static int calculateU8ConversionError(int srcBits)
1154 {
1155     if (srcBits > 0)
1156     {
1157         const int clampedBits = de::clamp<int>(srcBits, 0, 8);
1158         const int srcMaxValue = de::max((1 << clampedBits) - 1, 1);
1159         const int error       = int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
1160 
1161         return de::clamp<int>(error, 0, 255);
1162     }
1163     else
1164         return 1;
1165 }
1166 
getFormatThreshold(const tcu::TextureFormat & format)1167 tcu::RGBA getFormatThreshold(const tcu::TextureFormat &format)
1168 {
1169     const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
1170 
1171     return tcu::RGBA(calculateU8ConversionError(bits.x()), calculateU8ConversionError(bits.y()),
1172                      calculateU8ConversionError(bits.z()), calculateU8ConversionError(bits.w()));
1173 }
1174 
getFormatThreshold(uint32_t glFormat)1175 tcu::RGBA getFormatThreshold(uint32_t glFormat)
1176 {
1177     const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
1178 
1179     return getFormatThreshold(format);
1180 }
1181 
getToSRGB8ConversionError(int srcBits)1182 static int getToSRGB8ConversionError(int srcBits)
1183 {
1184     // \note These are pre-computed based on simulation results.
1185     static const int errors[] = {
1186         1,   // 0 bits - rounding
1187         255, // 1 bits
1188         157, // 2 bits
1189         106, // 3 bits
1190         74,  // 4 bits
1191         51,  // 5 bits
1192         34,  // 6 bits
1193         22,  // 7 bits
1194         13,  // 8 bits
1195         7,   // 9 bits
1196         4,   // 10 bits
1197         3,   // 11 bits
1198         2,   // 12 bits
1199              // 1 from this on
1200     };
1201 
1202     DE_ASSERT(srcBits >= 0);
1203     if (srcBits < DE_LENGTH_OF_ARRAY(errors))
1204         return errors[srcBits];
1205     else
1206         return 1;
1207 }
1208 
getToSRGBConversionThreshold(const tcu::TextureFormat & src,const tcu::TextureFormat & dst)1209 tcu::RGBA getToSRGBConversionThreshold(const tcu::TextureFormat &src, const tcu::TextureFormat &dst)
1210 {
1211     // Only SRGB8 and SRGB8_ALPHA8 formats are supported.
1212     DE_ASSERT(dst.type == tcu::TextureFormat::UNORM_INT8 && tcu::isSRGB(dst));
1213 
1214     const tcu::IVec4 bits  = tcu::getTextureFormatMantissaBitDepth(src);
1215     const bool dstHasAlpha = dst.order == tcu::TextureFormat::sRGBA;
1216 
1217     return tcu::RGBA(getToSRGB8ConversionError(bits.x()), getToSRGB8ConversionError(bits.y()),
1218                      getToSRGB8ConversionError(bits.z()), dstHasAlpha ? calculateU8ConversionError(bits.w()) : 0);
1219 }
1220 
1221 } // namespace FboTestUtil
1222 } // namespace Functional
1223 } // namespace gles3
1224 } // namespace deqp
1225