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