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 Special float stress tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3sSpecialFloatTests.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluStrUtil.hpp"
29 #include "gluContextInfo.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuRenderTarget.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuVectorUtil.hpp"
36 #include "deStringUtil.hpp"
37 #include "deMath.h"
38 #include "deRandom.hpp"
39
40 #include <limits>
41 #include <sstream>
42
43 using namespace glw;
44
45 namespace deqp
46 {
47 namespace gles3
48 {
49 namespace Stress
50 {
51 namespace
52 {
53
54 static const int TEST_CANVAS_SIZE = 256;
55 static const int TEST_TEXTURE_SIZE = 128;
56 static const int TEST_TEXTURE_CUBE_SIZE = 32;
57 static const deUint32 s_specialFloats[] =
58 {
59 0x00000000, // zero
60 0x80000000, // negative zero
61 0x3F800000, // one
62 0xBF800000, // negative one
63 0x00800000, // minimum positive normalized value
64 0x80800000, // maximum negative normalized value
65 0x00000001, // minimum positive denorm value
66 0x80000001, // maximum negative denorm value
67 0x7F7FFFFF, // maximum finite value.
68 0xFF7FFFFF, // minimum finite value.
69 0x7F800000, // inf
70 0xFF800000, // -inf
71 0x34000000, // epsilon
72 0xB4000000, // negative epsilon
73 0x7FC00000, // quiet_NaN
74 0xFFC00000, // negative quiet_NaN
75 0x7FC00001, // signaling_NaN
76 0xFFC00001, // negative signaling_NaN
77 0x7FEAAAAA, // quiet payloaded NaN (payload of repeated pattern of 101010...)
78 0xFFEAAAAA, // negative quiet payloaded NaN ( .. )
79 0x7FAAAAAA, // signaling payloaded NaN ( .. )
80 0xFFAAAAAA, // negative signaling payloaded NaN ( .. )
81 };
82
83 static const char* const s_colorPassthroughFragmentShaderSource = "#version 300 es\n"
84 "layout(location = 0) out mediump vec4 fragColor;\n"
85 "in mediump vec4 v_out;\n"
86 "void main ()\n"
87 "{\n"
88 " fragColor = v_out;\n"
89 "}\n";
90 static const char* const s_attrPassthroughVertexShaderSource = "#version 300 es\n"
91 "in highp vec4 a_pos;\n"
92 "in highp vec4 a_attr;\n"
93 "out highp vec4 v_attr;\n"
94 "void main ()\n"
95 "{\n"
96 " v_attr = a_attr;\n"
97 " gl_Position = a_pos;\n"
98 "}\n";
99
100 class RenderCase : public TestCase
101 {
102 public:
103 enum RenderTargetType
104 {
105 RENDERTARGETTYPE_SCREEN,
106 RENDERTARGETTYPE_FBO
107 };
108
109 RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType = RENDERTARGETTYPE_SCREEN);
110 virtual ~RenderCase (void);
111
112 virtual void init (void);
113 virtual void deinit (void);
114
115 protected:
116 bool checkResultImage (const tcu::Surface& result);
117 bool drawTestPattern (bool useTexture);
118
119 virtual std::string genVertexSource (void) const = 0;
120 virtual std::string genFragmentSource (void) const = 0;
121
122 const glu::ShaderProgram* m_program;
123 const RenderTargetType m_renderTargetType;
124 };
125
RenderCase(Context & context,const char * name,const char * desc,RenderTargetType renderTargetType)126 RenderCase::RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType)
127 : TestCase (context, name, desc)
128 , m_program (DE_NULL)
129 , m_renderTargetType (renderTargetType)
130 {
131 }
132
~RenderCase(void)133 RenderCase::~RenderCase (void)
134 {
135 deinit();
136 }
137
init(void)138 void RenderCase::init (void)
139 {
140 const int width = m_context.getRenderTarget().getWidth();
141 const int height = m_context.getRenderTarget().getHeight();
142
143 // check target size
144 if (m_renderTargetType == RENDERTARGETTYPE_SCREEN)
145 {
146 if (width < TEST_CANVAS_SIZE || height < TEST_CANVAS_SIZE)
147 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(TEST_CANVAS_SIZE) + "x" + de::toString(TEST_CANVAS_SIZE));
148 }
149 else if (m_renderTargetType == RENDERTARGETTYPE_FBO)
150 {
151 GLint maxTexSize = 0;
152 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
153
154 if (maxTexSize < TEST_CANVAS_SIZE)
155 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_CANVAS_SIZE));
156 }
157 else
158 DE_ASSERT(false);
159
160 // gen shader
161
162 m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shader." << tcu::TestLog::EndMessage;
163
164 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(genFragmentSource()));
165 m_testCtx.getLog() << *m_program;
166
167 if (!m_program->isOk())
168 throw tcu::TestError("shader compile failed");
169 }
170
deinit(void)171 void RenderCase::deinit (void)
172 {
173 if (m_program)
174 {
175 delete m_program;
176 m_program = DE_NULL;
177 }
178 }
179
checkResultImage(const tcu::Surface & result)180 bool RenderCase::checkResultImage (const tcu::Surface& result)
181 {
182 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
183 bool error = false;
184
185 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image." << tcu::TestLog::EndMessage;
186
187 for (int y = 0; y < TEST_CANVAS_SIZE; ++y)
188 for (int x = 0; x < TEST_CANVAS_SIZE; ++x)
189 {
190 const tcu::RGBA col = result.getPixel(x, y);
191
192 if (col.getGreen() == 255)
193 errorMask.setPixel(x, y, tcu::RGBA::green());
194 else
195 {
196 errorMask.setPixel(x, y, tcu::RGBA::red());
197 error = true;
198 }
199 }
200
201 if (error)
202 {
203 m_testCtx.getLog() << tcu::TestLog::Message << "Result image has missing or invalid pixels" << tcu::TestLog::EndMessage;
204 m_testCtx.getLog()
205 << tcu::TestLog::ImageSet("Results", "Result verification")
206 << tcu::TestLog::Image("Result", "Result", result)
207 << tcu::TestLog::Image("Error mask", "Error mask", errorMask)
208 << tcu::TestLog::EndImageSet;
209 }
210 else
211 {
212 m_testCtx.getLog()
213 << tcu::TestLog::ImageSet("Results", "Result verification")
214 << tcu::TestLog::Image("Result", "Result", result)
215 << tcu::TestLog::EndImageSet;
216 }
217
218 return !error;
219 }
220
drawTestPattern(bool useTexture)221 bool RenderCase::drawTestPattern (bool useTexture)
222 {
223 static const tcu::Vec4 fullscreenQuad[4] =
224 {
225 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
226 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
227 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
228 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f),
229 };
230 const char* const vertexSource = "#version 300 es\n"
231 "in highp vec4 a_pos;\n"
232 "out mediump vec4 v_position;\n"
233 "void main ()\n"
234 "{\n"
235 " v_position = a_pos;\n"
236 " gl_Position = a_pos;\n"
237 "}\n";
238 const char* const fragmentSourceNoTex = "#version 300 es\n"
239 "layout(location = 0) out mediump vec4 fragColor;\n"
240 "in mediump vec4 v_position;\n"
241 "void main ()\n"
242 "{\n"
243 " fragColor = vec4((v_position.x + 1.0) * 0.5, 1.0, 1.0, 1.0);\n"
244 "}\n";
245 const char* const fragmentSourceTex = "#version 300 es\n"
246 "layout(location = 0) out mediump vec4 fragColor;\n"
247 "uniform mediump sampler2D u_sampler;\n"
248 "in mediump vec4 v_position;\n"
249 "void main ()\n"
250 "{\n"
251 " fragColor = texture(u_sampler, v_position.xy);\n"
252 "}\n";
253 const char* const fragmentSource = (useTexture) ? (fragmentSourceTex) : (fragmentSourceNoTex);
254 const tcu::RGBA formatThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold();
255
256 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
257 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
258 bool error = false;
259
260 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a test pattern to detect " << ((useTexture) ? ("texture sampling") : ("")) << " side-effects." << tcu::TestLog::EndMessage;
261
262 // draw pattern
263 {
264 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
265 const glu::ShaderProgram patternProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource));
266 const GLint positionLoc = gl.getAttribLocation(patternProgram.getProgram(), "a_pos");
267 GLuint textureID = 0;
268
269 if (useTexture)
270 {
271 const int textureSize = 32;
272 std::vector<tcu::Vector<deUint8, 4> > buffer(textureSize*textureSize);
273
274 for (int x = 0; x < textureSize; ++x)
275 for (int y = 0; y < textureSize; ++y)
276 {
277 // sum of two axis aligned gradients. Each gradient is 127 at the edges and 0 at the center.
278 // pattern is symmetric (x and y) => no discontinuity near boundary => no need to worry of results with LINEAR filtering near boundaries
279 const deUint8 redComponent = (deUint8)de::clamp(de::abs((float)x / (float)textureSize - 0.5f) * 255.0f + de::abs((float)y / (float)textureSize - 0.5f) * 255.0f, 0.0f, 255.0f);
280
281 buffer[x * textureSize + y] = tcu::Vector<deUint8, 4>(redComponent, 255, 255, 255);
282 }
283
284 gl.genTextures(1, &textureID);
285 gl.bindTexture(GL_TEXTURE_2D, textureID);
286 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer[0].getPtr());
287 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
288 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
289 }
290
291 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
292 gl.clear(GL_COLOR_BUFFER_BIT);
293 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
294 gl.useProgram(patternProgram.getProgram());
295
296 if (useTexture)
297 gl.uniform1i(gl.getUniformLocation(patternProgram.getProgram(), "u_sampler"), 0);
298
299 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &fullscreenQuad[0]);
300
301 gl.enableVertexAttribArray(positionLoc);
302 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
303 gl.disableVertexAttribArray(positionLoc);
304
305 gl.useProgram(0);
306 gl.finish();
307 GLU_EXPECT_NO_ERROR(gl.getError(), "RenderCase::drawTestPattern");
308
309 if (textureID)
310 gl.deleteTextures(1, &textureID);
311
312 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess());
313 }
314
315 // verify pattern
316 for (int y = 0; y < TEST_CANVAS_SIZE; ++y)
317 for (int x = 0; x < TEST_CANVAS_SIZE; ++x)
318 {
319 const float texGradientPosX = deFloatFrac((float)x * 2.0f / (float)TEST_CANVAS_SIZE);
320 const float texGradientPosY = deFloatFrac((float)y * 2.0f / (float)TEST_CANVAS_SIZE);
321 const deUint8 texRedComponent = (deUint8)de::clamp(de::abs(texGradientPosX - 0.5f) * 255.0f + de::abs(texGradientPosY - 0.5f) * 255.0f, 0.0f, 255.0f);
322
323 const tcu::RGBA refColTexture = tcu::RGBA(texRedComponent, 255, 255, 255);
324 const tcu::RGBA refColGradient = tcu::RGBA((int)((float)x / (float)TEST_CANVAS_SIZE * 255.0f), 255, 255, 255);
325 const tcu::RGBA& refCol = (useTexture) ? (refColTexture) : (refColGradient);
326
327 const int colorThreshold = 10;
328 const tcu::RGBA col = resultImage.getPixel(x, y);
329 const tcu::IVec4 colorDiff = tcu::abs(col.toIVec() - refCol.toIVec());
330
331 if (colorDiff.x() > formatThreshold.getRed() + colorThreshold ||
332 colorDiff.y() > formatThreshold.getGreen() + colorThreshold ||
333 colorDiff.z() > formatThreshold.getBlue() + colorThreshold)
334 {
335 errorMask.setPixel(x, y, tcu::RGBA::red());
336 error = true;
337 }
338 else
339 errorMask.setPixel(x, y, tcu::RGBA::green());
340 }
341
342 // report error
343 if (error)
344 {
345 m_testCtx.getLog() << tcu::TestLog::Message << "Test pattern has missing/invalid pixels" << tcu::TestLog::EndMessage;
346 m_testCtx.getLog()
347 << tcu::TestLog::ImageSet("Results", "Result verification")
348 << tcu::TestLog::Image("Result", "Result", resultImage)
349 << tcu::TestLog::Image("Error mask", "Error mask", errorMask)
350 << tcu::TestLog::EndImageSet;
351 }
352 else
353 m_testCtx.getLog() << tcu::TestLog::Message << "No side-effects found." << tcu::TestLog::EndMessage;
354
355 return !error;
356 }
357
358 class FramebufferRenderCase : public RenderCase
359 {
360 public:
361 enum FrameBufferType
362 {
363 FBO_DEFAULT = 0,
364 FBO_RGBA4,
365 FBO_RGB5_A1,
366 FBO_RGB565,
367 FBO_RGBA8,
368 FBO_RGB10_A2,
369 FBO_RGBA_FLOAT16,
370 FBO_RGBA_FLOAT32,
371
372 FBO_LAST
373 };
374
375 FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType);
376 virtual ~FramebufferRenderCase (void);
377
378 virtual void init (void);
379 virtual void deinit (void);
380 IterateResult iterate (void);
381
382 virtual void testFBO (void) = DE_NULL;
383
384 protected:
385 const FrameBufferType m_fboType;
386
387 private:
388 GLuint m_texID;
389 GLuint m_fboID;
390 };
391
FramebufferRenderCase(Context & context,const char * name,const char * desc,FrameBufferType fboType)392 FramebufferRenderCase::FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType)
393 : RenderCase (context, name, desc, (fboType == FBO_DEFAULT) ? (RENDERTARGETTYPE_SCREEN) : (RENDERTARGETTYPE_FBO))
394 , m_fboType (fboType)
395 , m_texID (0)
396 , m_fboID (0)
397 {
398 DE_ASSERT(m_fboType < FBO_LAST);
399 }
400
~FramebufferRenderCase(void)401 FramebufferRenderCase::~FramebufferRenderCase (void)
402 {
403 deinit();
404 }
405
init(void)406 void FramebufferRenderCase::init (void)
407 {
408 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
409
410 // check requirements
411 if (m_fboType == FBO_RGBA_FLOAT16)
412 {
413 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_half_float") &&
414 !m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float"))
415 throw tcu::NotSupportedError("Color renderable half float texture required.");
416 }
417 else if (m_fboType == FBO_RGBA_FLOAT32)
418 {
419 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float"))
420 throw tcu::NotSupportedError("Color renderable float texture required.");
421 }
422
423 // gen shader
424 RenderCase::init();
425
426 // create render target
427 if (m_fboType == FBO_DEFAULT)
428 {
429 m_testCtx.getLog() << tcu::TestLog::Message << "Using default framebuffer." << tcu::TestLog::EndMessage;
430 }
431 else
432 {
433 GLuint internalFormat = 0;
434 GLuint format = 0;
435 GLuint type = 0;
436
437 switch (m_fboType)
438 {
439 case FBO_RGBA4: internalFormat = GL_RGBA4; format = GL_RGBA; type = GL_UNSIGNED_SHORT_4_4_4_4; break;
440 case FBO_RGB5_A1: internalFormat = GL_RGB5_A1; format = GL_RGBA; type = GL_UNSIGNED_SHORT_5_5_5_1; break;
441 case FBO_RGB565: internalFormat = GL_RGB565; format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break;
442 case FBO_RGBA8: internalFormat = GL_RGBA8; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break;
443 case FBO_RGB10_A2: internalFormat = GL_RGB10_A2; format = GL_RGBA; type = GL_UNSIGNED_INT_2_10_10_10_REV; break;
444 case FBO_RGBA_FLOAT16: internalFormat = GL_RGBA16F; format = GL_RGBA; type = GL_HALF_FLOAT; break;
445 case FBO_RGBA_FLOAT32: internalFormat = GL_RGBA32F; format = GL_RGBA; type = GL_FLOAT; break;
446
447 default:
448 DE_ASSERT(false);
449 break;
450 }
451
452 m_testCtx.getLog() << tcu::TestLog::Message
453 << "Creating fbo. Texture internalFormat = " << glu::getTextureFormatStr(internalFormat)
454 << ", format = " << glu::getTextureFormatStr(format)
455 << ", type = " << glu::getTypeStr(type)
456 << tcu::TestLog::EndMessage;
457
458 // gen texture
459 gl.genTextures(1, &m_texID);
460 gl.bindTexture(GL_TEXTURE_2D, m_texID);
461 gl.texImage2D(GL_TEXTURE_2D, 0, internalFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, 0, format, type, DE_NULL);
462 GLU_EXPECT_NO_ERROR(gl.getError(), "texture init");
463
464 // gen fbo
465 gl.genFramebuffers(1, &m_fboID);
466 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID);
467 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texID, 0);
468 GLU_EXPECT_NO_ERROR(gl.getError(), "fbo init");
469
470 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
471 throw tcu::NotSupportedError("could not create fbo for testing.");
472 }
473 }
474
deinit(void)475 void FramebufferRenderCase::deinit (void)
476 {
477 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
478
479 if (m_texID)
480 {
481 gl.deleteTextures(1, &m_texID);
482 m_texID = 0;
483 }
484
485 if (m_fboID)
486 {
487 gl.deleteFramebuffers(1, &m_fboID);
488 m_fboID = 0;
489 }
490 }
491
iterate(void)492 FramebufferRenderCase::IterateResult FramebufferRenderCase::iterate (void)
493 {
494 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
495
496 // bind fbo (or don't if we are using default)
497 if (m_fboID)
498 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID);
499
500 // do something with special floats
501 testFBO();
502
503 return STOP;
504 }
505
506 /*--------------------------------------------------------------------*//*!
507 * \brief Tests special floats as vertex attributes
508 *
509 * Tests that special floats transferred to the shader using vertex
510 * attributes do not change the results of normal floating point
511 * calculations. Special floats are put to 4-vector's x and y components and
512 * value 1.0 is put to z and w. The resulting fragment's green channel
513 * should be 1.0 everywhere.
514 *
515 * After the calculation test a test pattern is drawn to detect possible
516 * floating point operation anomalies.
517 *//*--------------------------------------------------------------------*/
518 class VertexAttributeCase : public RenderCase
519 {
520 public:
521 enum Storage
522 {
523 STORAGE_BUFFER = 0,
524 STORAGE_CLIENT,
525
526 STORAGE_LAST
527 };
528 enum ShaderType
529 {
530 TYPE_VERTEX = 0,
531 TYPE_FRAGMENT,
532
533 TYPE_LAST
534 };
535
536 VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type);
537 ~VertexAttributeCase (void);
538
539 void init (void);
540 void deinit (void);
541 IterateResult iterate (void);
542
543 private:
544 std::string genVertexSource (void) const;
545 std::string genFragmentSource (void) const;
546
547 const Storage m_storage;
548 const ShaderType m_type;
549 GLuint m_positionVboID;
550 GLuint m_attribVboID;
551 GLuint m_elementVboID;
552 };
553
VertexAttributeCase(Context & context,const char * name,const char * desc,Storage storage,ShaderType type)554 VertexAttributeCase::VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type)
555 : RenderCase (context, name, desc)
556 , m_storage (storage)
557 , m_type (type)
558 , m_positionVboID (0)
559 , m_attribVboID (0)
560 , m_elementVboID (0)
561 {
562 DE_ASSERT(storage < STORAGE_LAST);
563 DE_ASSERT(type < TYPE_LAST);
564 }
565
~VertexAttributeCase(void)566 VertexAttributeCase::~VertexAttributeCase (void)
567 {
568 deinit();
569 }
570
init(void)571 void VertexAttributeCase::init (void)
572 {
573 RenderCase::init();
574
575 // init gl resources
576 if (m_storage == STORAGE_BUFFER)
577 {
578 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
579
580 gl.genBuffers(1, &m_positionVboID);
581 gl.genBuffers(1, &m_attribVboID);
582 gl.genBuffers(1, &m_elementVboID);
583 }
584 }
585
deinit(void)586 void VertexAttributeCase::deinit (void)
587 {
588 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
589
590 RenderCase::deinit();
591
592 if (m_attribVboID)
593 {
594 gl.deleteBuffers(1, &m_attribVboID);
595 m_attribVboID = 0;
596 }
597
598 if (m_positionVboID)
599 {
600 gl.deleteBuffers(1, &m_positionVboID);
601 m_positionVboID = 0;
602 }
603
604 if (m_elementVboID)
605 {
606 gl.deleteBuffers(1, &m_elementVboID);
607 m_elementVboID = 0;
608 }
609 }
610
iterate(void)611 VertexAttributeCase::IterateResult VertexAttributeCase::iterate (void)
612 {
613 // Create a [s_specialFloats] X [s_specialFloats] grid of vertices with each vertex having 2 [s_specialFloats] values
614 // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen
615
616 std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats));
617 std::vector<tcu::UVec4> gridAttributes (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats));
618 std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6);
619 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
620
621 // vertices
622 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
623 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
624 {
625 const deUint32 one = 0x3F800000;
626 const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1]
627 const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f;
628
629 gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
630 gridAttributes[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one);
631 }
632
633 // tiles
634 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x)
635 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y)
636 {
637 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6;
638
639 indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
640 indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
641 indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
642
643 indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
644 indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
645 indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
646 }
647
648 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting a_attr for each vertex to (special, special, 1, 1)." << tcu::TestLog::EndMessage;
649
650 // Draw grid
651 {
652 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
653 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
654 const GLint attribLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr");
655
656 if (m_storage == STORAGE_BUFFER)
657 {
658 gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID);
659 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridVertices.size() * sizeof(tcu::Vec4)), &gridVertices[0], GL_STATIC_DRAW);
660 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate");
661
662 gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID);
663 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridAttributes.size() * sizeof(tcu::UVec4)), &gridAttributes[0], GL_STATIC_DRAW);
664 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate");
665
666 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementVboID);
667 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size() * sizeof(deUint16)), &indices[0], GL_STATIC_DRAW);
668 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate");
669 }
670
671 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
672 gl.clear(GL_COLOR_BUFFER_BIT);
673 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
674 gl.useProgram(m_program->getProgram());
675
676 if (m_storage == STORAGE_BUFFER)
677 {
678 gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID);
679 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
680
681 gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID);
682 gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
683
684 gl.enableVertexAttribArray(positionLoc);
685 gl.enableVertexAttribArray(attribLoc);
686 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, DE_NULL);
687 gl.disableVertexAttribArray(positionLoc);
688 gl.disableVertexAttribArray(attribLoc);
689
690 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
691 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
692 }
693 else if (m_storage == STORAGE_CLIENT)
694 {
695 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
696 gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridAttributes[0]);
697
698 gl.enableVertexAttribArray(positionLoc);
699 gl.enableVertexAttribArray(attribLoc);
700 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]);
701 gl.disableVertexAttribArray(positionLoc);
702 gl.disableVertexAttribArray(attribLoc);
703 }
704 else
705 DE_ASSERT(false);
706
707 gl.useProgram(0);
708 gl.finish();
709 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate");
710
711 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess());
712 }
713
714 // verify everywhere was drawn (all pixels have Green = 255)
715 if (!checkResultImage(resultImage))
716 {
717 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments");
718 return STOP;
719 }
720
721 // test drawing still works
722 if (!drawTestPattern(false))
723 {
724 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed");
725 return STOP;
726 }
727
728 // all ok
729 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
730 return STOP;
731 }
732
genVertexSource(void) const733 std::string VertexAttributeCase::genVertexSource (void) const
734 {
735 if (m_type == TYPE_VERTEX)
736 return
737 "#version 300 es\n"
738 "in highp vec4 a_pos;\n"
739 "in highp vec4 a_attr;\n"
740 "out mediump vec4 v_out;\n"
741 "void main ()\n"
742 "{\n"
743 " highp vec2 a1 = a_attr.xz + a_attr.yw; // add\n"
744 " highp vec2 a2 = a_attr.xz - a_attr.yw; // sub\n"
745 " highp vec2 a3 = a_attr.xz * a_attr.yw; // mul\n"
746 " highp vec2 a4 = a_attr.xz / a_attr.yw; // div\n"
747 " highp vec2 a5 = a_attr.xz + a_attr.yw * a_attr.xz; // fma\n"
748 "\n"
749 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n"
750 " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n"
751 " gl_Position = a_pos;\n"
752 "}\n";
753 else
754 return s_attrPassthroughVertexShaderSource;
755 }
756
genFragmentSource(void) const757 std::string VertexAttributeCase::genFragmentSource (void) const
758 {
759 if (m_type == TYPE_VERTEX)
760 return s_colorPassthroughFragmentShaderSource;
761 else
762 return
763 "#version 300 es\n"
764 "layout(location = 0) out mediump vec4 fragColor;\n"
765 "in highp vec4 v_attr;\n"
766 "void main ()\n"
767 "{\n"
768 " highp vec2 a1 = v_attr.xz + v_attr.yw; // add\n"
769 " highp vec2 a2 = v_attr.xz - v_attr.yw; // sub\n"
770 " highp vec2 a3 = v_attr.xz * v_attr.yw; // mul\n"
771 " highp vec2 a4 = v_attr.xz / v_attr.yw; // div\n"
772 " highp vec2 a5 = v_attr.xz + v_attr.yw * v_attr.xz; // fma\n"
773 " highp vec2 a6 = dFdx(v_attr.xz);\n"
774 "\n"
775 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y) - 6.0);\n"
776 " fragColor = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x+a6.x, 1.0);\n"
777 "}\n";
778 }
779
780 /*--------------------------------------------------------------------*//*!
781 * \brief Tests special floats as uniforms
782 *
783 * Tests that special floats transferred to the shader as uniforms do
784 * not change the results of normal floating point calculations. Special
785 * floats are put to 4-vector's x and y components and value 1.0 is put to
786 * z and w. The resulting fragment's green channel should be 1.0
787 * everywhere.
788 *
789 * After the calculation test a test pattern is drawn to detect possible
790 * floating point operation anomalies.
791 *//*--------------------------------------------------------------------*/
792 class UniformCase : public RenderCase
793 {
794 public:
795 enum ShaderType
796 {
797 TYPE_VERTEX = 0,
798 TYPE_FRAGMENT,
799 };
800
801 UniformCase (Context& context, const char* name, const char* desc, ShaderType type);
802 ~UniformCase (void);
803
804 void init (void);
805 void deinit (void);
806 IterateResult iterate (void);
807
808 private:
809 std::string genVertexSource (void) const;
810 std::string genFragmentSource (void) const;
811
812 const ShaderType m_type;
813 };
814
UniformCase(Context & context,const char * name,const char * desc,ShaderType type)815 UniformCase::UniformCase (Context& context, const char* name, const char* desc, ShaderType type)
816 : RenderCase (context, name, desc)
817 , m_type (type)
818 {
819 }
820
~UniformCase(void)821 UniformCase::~UniformCase (void)
822 {
823 deinit();
824 }
825
init(void)826 void UniformCase::init (void)
827 {
828 RenderCase::init();
829 }
830
deinit(void)831 void UniformCase::deinit (void)
832 {
833 RenderCase::deinit();
834 }
835
iterate(void)836 UniformCase::IterateResult UniformCase::iterate (void)
837 {
838 // Create a [s_specialFloats] X [s_specialFloats] grid of tile with each tile having 2 [s_specialFloats] values
839 // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen
840
841 std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1));
842 std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6);
843 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
844
845 // vertices
846 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x)
847 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y)
848 {
849 const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1]
850 const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f;
851
852 gridVertices[x * (DE_LENGTH_OF_ARRAY(s_specialFloats)+1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
853 }
854
855 // tiles
856 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
857 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
858 {
859 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats)) + y) * 6;
860
861 indices[baseNdx + 0] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0));
862 indices[baseNdx + 1] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1));
863 indices[baseNdx + 2] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0));
864
865 indices[baseNdx + 3] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0));
866 indices[baseNdx + 4] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1));
867 indices[baseNdx + 5] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1));
868 }
869
870 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting u_special for vertex each tile to (special, special, 1, 1)." << tcu::TestLog::EndMessage;
871
872 // Draw grid
873 {
874 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
875 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
876 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special");
877
878 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
879 gl.clear(GL_COLOR_BUFFER_BIT);
880 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
881 gl.useProgram(m_program->getProgram());
882
883 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
884 gl.enableVertexAttribArray(positionLoc);
885
886 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
887 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
888 {
889 const deUint32 one = 0x3F800000;
890 const tcu::UVec4 uniformValue = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one);
891 const int indexIndex = (x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y) * 6;
892
893 gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr());
894 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]);
895 }
896
897
898 gl.disableVertexAttribArray(positionLoc);
899
900 gl.useProgram(0);
901 gl.finish();
902 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformCase::iterate");
903
904 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess());
905 }
906
907 // verify everywhere was drawn (all pixels have Green = 255)
908 if (!checkResultImage(resultImage))
909 {
910 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments");
911 return STOP;
912 }
913
914 // test drawing still works
915 if (!drawTestPattern(false))
916 {
917 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed");
918 return STOP;
919 }
920
921 // all ok
922 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
923 return STOP;
924 }
925
genVertexSource(void) const926 std::string UniformCase::genVertexSource (void) const
927 {
928 if (m_type == TYPE_VERTEX)
929 return
930 "#version 300 es\n"
931 "in highp vec4 a_pos;\n"
932 "uniform highp vec4 u_special;\n"
933 "out mediump vec4 v_out;\n"
934 "void main ()\n"
935 "{\n"
936 " highp vec2 a1 = u_special.xz + u_special.yw; // add\n"
937 " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n"
938 " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n"
939 " highp vec2 a4 = u_special.xz / u_special.yw; // div\n"
940 " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n"
941 "\n"
942 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n"
943 " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n"
944 " gl_Position = a_pos;\n"
945 "}\n";
946 else
947 return
948 "#version 300 es\n"
949 "in highp vec4 a_pos;\n"
950 "void main ()\n"
951 "{\n"
952 " gl_Position = a_pos;\n"
953 "}\n";
954 }
955
genFragmentSource(void) const956 std::string UniformCase::genFragmentSource (void) const
957 {
958 if (m_type == TYPE_VERTEX)
959 return s_colorPassthroughFragmentShaderSource;
960 else
961 return
962 "#version 300 es\n"
963 "layout(location = 0) out mediump vec4 fragColor;\n"
964 "uniform highp vec4 u_special;\n"
965 "void main ()\n"
966 "{\n"
967 " highp vec2 a1 = u_special.xz + u_special.yw; // add\n"
968 " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n"
969 " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n"
970 " highp vec2 a4 = u_special.xz / u_special.yw; // div\n"
971 " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n"
972 " highp vec2 a6 = mod(u_special.xz, u_special.yw);\n"
973 " highp vec2 a7 = mix(u_special.xz, u_special.yw, a6);\n"
974 "\n"
975 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y + a7.y) - 7.0);\n"
976 " fragColor = vec4(a1.x*a3.x, green, a5.x*a4.x + a2.x*a7.x, 1.0);\n"
977 "}\n";
978 }
979
980 /*--------------------------------------------------------------------*//*!
981 * \brief Tests special floats in floating point textures
982 *
983 * Tests that sampling special floats from a floating point texture
984 * does not affect the values of other color components of the sample. Test
985 * samples a RG texture with R channel filled with special floats and G
986 * channel filled with test values.
987 *
988 * Tests that linear sampling using compare mode = COMPARE_REF_TO_TEXTURE
989 * of a floating point depth texture containing special floating point
990 * values does not produce values outside the [0, 1] range.
991 *
992 * After the calculation test a test pattern is drawn to detect possible
993 * texture sampling anomalies.
994 *//*--------------------------------------------------------------------*/
995 class TextureCase : public RenderCase
996 {
997 public:
998 enum ShaderType
999 {
1000 TYPE_VERTEX = 0,
1001 TYPE_FRAGMENT,
1002
1003 TYPE_LAST
1004 };
1005 enum TextureType
1006 {
1007 TEXTURE_FLOAT = 0,
1008 TEXTURE_DEPTH,
1009
1010 TEXTURE_LAST
1011 };
1012 enum UploadType
1013 {
1014 UPLOAD_CLIENT = 0,
1015 UPLOAD_PBO,
1016
1017 UPLOAD_LAST
1018 };
1019
1020 TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType);
1021 ~TextureCase (void);
1022
1023 void init (void);
1024 void deinit (void);
1025 IterateResult iterate (void);
1026
1027 private:
1028 std::string genVertexSource (void) const;
1029 std::string genFragmentSource (void) const;
1030
1031 const ShaderType m_type;
1032 const TextureType m_textureType;
1033 const UploadType m_uploadType;
1034 GLuint m_textureID;
1035 GLuint m_pboID;
1036 };
1037
TextureCase(Context & context,const char * name,const char * desc,ShaderType type,TextureType texType,UploadType uploadType)1038 TextureCase::TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType)
1039 : RenderCase (context, name, desc)
1040 , m_type (type)
1041 , m_textureType (texType)
1042 , m_uploadType (uploadType)
1043 , m_textureID (0)
1044 , m_pboID (0)
1045 {
1046 DE_ASSERT(type < TYPE_LAST);
1047 DE_ASSERT(texType < TEXTURE_LAST);
1048 DE_ASSERT(uploadType < UPLOAD_LAST);
1049 }
1050
~TextureCase(void)1051 TextureCase::~TextureCase (void)
1052 {
1053 deinit();
1054 }
1055
init(void)1056 void TextureCase::init (void)
1057 {
1058 // requirements
1059 {
1060 GLint maxTextureSize = 0;
1061 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1062 if (maxTextureSize < TEST_TEXTURE_SIZE)
1063 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE));
1064 }
1065
1066 RenderCase::init();
1067
1068 // gen texture
1069 {
1070 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1071 de::Random rnd (12345);
1072
1073 gl.genTextures(1, &m_textureID);
1074 gl.bindTexture(GL_TEXTURE_2D, m_textureID);
1075
1076 if (m_uploadType == UPLOAD_PBO)
1077 {
1078 gl.genBuffers(1, &m_pboID);
1079 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pboID);
1080 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init");
1081 }
1082
1083 if (m_textureType == TEXTURE_FLOAT)
1084 {
1085 std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*2);
1086 const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL);
1087
1088 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D 2-component float texture. Pixel contents are of form (special, 1)." << tcu::TestLog::EndMessage;
1089
1090 // set green channel to 1.0
1091 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x)
1092 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y)
1093 {
1094 texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 0] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1095 texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 1] = 0x3F800000; // one
1096 }
1097
1098 if (m_uploadType == UPLOAD_PBO)
1099 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW);
1100
1101 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RG32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RG, GL_FLOAT, dataPtr);
1102 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1103 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1104 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init");
1105 }
1106 else if (m_textureType == TEXTURE_DEPTH)
1107 {
1108 std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE);
1109 const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL);
1110
1111 m_testCtx.getLog() << tcu::TestLog::Message
1112 << "Creating a 2D depth texture and filling it with special floating point values.\n"
1113 << " TEXTURE_COMPARE_MODE = COMPARE_REF_TO_TEXTURE"
1114 << tcu::TestLog::EndMessage;
1115
1116 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x)
1117 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y)
1118 texData[x * TEST_TEXTURE_SIZE + y] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1119
1120 if (m_uploadType == UPLOAD_PBO)
1121 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW);
1122
1123 gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, dataPtr);
1124 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1125 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
1126 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1127 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1128 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init");
1129 }
1130 else
1131 DE_ASSERT(false);
1132
1133 if (m_uploadType == UPLOAD_PBO)
1134 {
1135 m_testCtx.getLog() << tcu::TestLog::Message << "PBO used for image upload." << tcu::TestLog::EndMessage;
1136
1137 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1138 gl.deleteBuffers(1, &m_pboID);
1139 m_pboID = 0;
1140 }
1141 }
1142 }
1143
deinit(void)1144 void TextureCase::deinit (void)
1145 {
1146 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1147
1148 RenderCase::deinit();
1149
1150 if (m_textureID)
1151 {
1152 gl.deleteTextures(1, &m_textureID);
1153 m_textureID = 0;
1154 }
1155 if (m_pboID)
1156 {
1157 gl.deleteBuffers(1, &m_pboID);
1158 m_pboID = 0;
1159 }
1160 }
1161
iterate(void)1162 TextureCase::IterateResult TextureCase::iterate (void)
1163 {
1164 // Draw a grid and texture it with a floating point texture containing special values. If all goes well, nothing special should happen
1165
1166 const int gridSize = 16;
1167 std::vector<tcu::Vec4> gridVertices (gridSize * gridSize);
1168 std::vector<tcu::Vec2> gridTexCoords (gridSize * gridSize);
1169 std::vector<deUint16> indices ((gridSize - 1) * (gridSize - 1) * 6);
1170 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1171
1172 // vertices
1173 for (int x = 0; x < gridSize; ++x)
1174 for (int y = 0; y < gridSize; ++y)
1175 {
1176 const float posX = (float)x / ((float)gridSize - 1.0f) * 2.0f - 1.0f; // map from [0, gridSize - 1] to [-1, 1]
1177 const float posY = (float)y / ((float)gridSize - 1.0f) * 2.0f - 1.0f;
1178 const float texCoordX = deFloatPow(2.0f, (float)x - (float)gridSize / 2.0f);
1179 const float texCoordY = deFloatPow(2.0f, (float)y - (float)gridSize / 2.0f);
1180
1181 gridVertices[x * gridSize + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
1182 gridTexCoords[x * gridSize + y] = tcu::Vec2(texCoordX, texCoordY);
1183 }
1184
1185 // tiles
1186 for (int x = 0; x < gridSize - 1; ++x)
1187 for (int y = 0; y < gridSize - 1; ++y)
1188 {
1189 const int baseNdx = (x * (gridSize - 1) + y) * 6;
1190
1191 indices[baseNdx + 0] = (deUint16)((x+0) * gridSize + (y+0));
1192 indices[baseNdx + 1] = (deUint16)((x+1) * gridSize + (y+1));
1193 indices[baseNdx + 2] = (deUint16)((x+1) * gridSize + (y+0));
1194
1195 indices[baseNdx + 3] = (deUint16)((x+0) * gridSize + (y+0));
1196 indices[baseNdx + 4] = (deUint16)((x+1) * gridSize + (y+1));
1197 indices[baseNdx + 5] = (deUint16)((x+0) * gridSize + (y+1));
1198 }
1199
1200 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader." << tcu::TestLog::EndMessage;
1201
1202 // Draw grid
1203 {
1204 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1205 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
1206 const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr");
1207 const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler");
1208
1209 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1210 gl.clear(GL_COLOR_BUFFER_BIT);
1211 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1212 gl.useProgram(m_program->getProgram());
1213
1214 gl.uniform1i(samplerLoc, 0);
1215 gl.bindTexture(GL_TEXTURE_2D, m_textureID);
1216
1217 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
1218 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]);
1219
1220 gl.enableVertexAttribArray(positionLoc);
1221 gl.enableVertexAttribArray(texCoordLoc);
1222 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]);
1223 gl.disableVertexAttribArray(positionLoc);
1224 gl.disableVertexAttribArray(texCoordLoc);
1225
1226 gl.useProgram(0);
1227 gl.finish();
1228 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::iterate");
1229
1230 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess());
1231 }
1232
1233 // verify everywhere was drawn (all pixels have Green = 255)
1234 if (!checkResultImage(resultImage))
1235 {
1236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments");
1237 return STOP;
1238 }
1239
1240 // test drawing and textures still works
1241 if (!drawTestPattern(true))
1242 {
1243 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed");
1244 return STOP;
1245 }
1246
1247 // all ok
1248 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1249 return STOP;
1250 }
1251
genVertexSource(void) const1252 std::string TextureCase::genVertexSource (void) const
1253 {
1254 // vertex shader is passthrough, fragment does the calculations
1255 if (m_type == TYPE_FRAGMENT)
1256 return s_attrPassthroughVertexShaderSource;
1257
1258 // vertex shader does the calculations
1259 std::ostringstream buf;
1260 buf << "#version 300 es\n"
1261 "in highp vec4 a_pos;\n"
1262 "in highp vec2 a_attr;\n"
1263 "out mediump vec4 v_out;\n";
1264
1265 if (m_textureType == TEXTURE_FLOAT)
1266 buf << "uniform highp sampler2D u_sampler;\n";
1267 else if (m_textureType == TEXTURE_DEPTH)
1268 buf << "uniform highp sampler2DShadow u_sampler;\n";
1269 else
1270 DE_ASSERT(DE_FALSE);
1271
1272 buf << "void main ()\n"
1273 "{\n";
1274
1275 if (m_textureType == TEXTURE_FLOAT)
1276 buf << " v_out = vec4(textureLod(u_sampler, a_attr, 0.0).rg, 1.0, 1.0);\n";
1277 else if (m_textureType == TEXTURE_DEPTH)
1278 buf << " highp float a1 = textureLod(u_sampler, vec3(a_attr, 0.0), 0.0);\n"
1279 " v_out = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n";
1280 else
1281 DE_ASSERT(DE_FALSE);
1282
1283 buf << " gl_Position = a_pos;\n"
1284 "}\n";
1285 return buf.str();
1286 }
1287
genFragmentSource(void) const1288 std::string TextureCase::genFragmentSource (void) const
1289 {
1290 // fragment shader is passthrough
1291 if (m_type == TYPE_VERTEX)
1292 return s_colorPassthroughFragmentShaderSource;
1293
1294 // fragment shader does the calculations
1295 std::ostringstream buf;
1296 buf << "#version 300 es\n"
1297 "layout(location = 0) out mediump vec4 fragColor;\n";
1298
1299 if (m_textureType == TEXTURE_FLOAT)
1300 buf << "uniform highp sampler2D u_sampler;\n";
1301 else if (m_textureType == TEXTURE_DEPTH)
1302 buf << "uniform highp sampler2DShadow u_sampler;\n";
1303 else
1304 DE_ASSERT(DE_FALSE);
1305
1306 buf << "in highp vec4 v_attr;\n"
1307 "void main ()\n"
1308 "{\n";
1309
1310 if (m_textureType == TEXTURE_FLOAT)
1311 buf << " highp vec2 a1 = texture(u_sampler, v_attr.xy).rg;\n"
1312 " fragColor = vec4(a1.x, a1.y, 1.0, 1.0);\n";
1313 else if (m_textureType == TEXTURE_DEPTH)
1314 buf << " highp float a1 = texture(u_sampler, vec3(v_attr.xy, 0.0));\n"
1315 " fragColor = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n";
1316 else
1317 DE_ASSERT(DE_FALSE);
1318
1319 buf << "}\n";
1320 return buf.str();
1321 }
1322
1323 /*--------------------------------------------------------------------*//*!
1324 * \brief Tests special floats as texture samping arguments
1325 *
1326 * Tests that special floats given as texture coordinates or LOD levels
1327 * to sampling functions do not return invalid values (values not in the
1328 * texture). Every texel's green component is 1.0.
1329 *
1330 * After the calculation test a test pattern is drawn to detect possible
1331 * texture sampling anomalies.
1332 *//*--------------------------------------------------------------------*/
1333 class TextureSamplerCase : public RenderCase
1334 {
1335 public:
1336 enum ShaderType
1337 {
1338 TYPE_VERTEX = 0,
1339 TYPE_FRAGMENT,
1340
1341 TYPE_LAST
1342 };
1343 enum TestType
1344 {
1345 TEST_TEX_COORD = 0,
1346 TEST_LOD,
1347 TEST_GRAD,
1348 TEST_TEX_COORD_CUBE,
1349
1350 TEST_LAST
1351 };
1352
1353 TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType);
1354 ~TextureSamplerCase (void);
1355
1356 void init (void);
1357 void deinit (void);
1358 IterateResult iterate (void);
1359
1360 private:
1361 std::string genVertexSource (void) const;
1362 std::string genFragmentSource (void) const;
1363
1364 const ShaderType m_type;
1365 const TestType m_testType;
1366 GLuint m_textureID;
1367 };
1368
TextureSamplerCase(Context & context,const char * name,const char * desc,ShaderType type,TestType testType)1369 TextureSamplerCase::TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType)
1370 : RenderCase (context, name, desc)
1371 , m_type (type)
1372 , m_testType (testType)
1373 , m_textureID (0)
1374 {
1375 DE_ASSERT(type < TYPE_LAST);
1376 DE_ASSERT(testType < TEST_LAST);
1377 }
1378
~TextureSamplerCase(void)1379 TextureSamplerCase::~TextureSamplerCase (void)
1380 {
1381 deinit();
1382 }
1383
init(void)1384 void TextureSamplerCase::init (void)
1385 {
1386 // requirements
1387 {
1388 GLint maxTextureSize = 0;
1389 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1390 if (maxTextureSize < TEST_TEXTURE_SIZE)
1391 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE));
1392 }
1393
1394 RenderCase::init();
1395
1396 // gen texture
1397 {
1398 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1399 std::vector<deUint8> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*4);
1400 de::Random rnd (12345);
1401
1402 gl.genTextures(1, &m_textureID);
1403
1404 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x)
1405 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y)
1406 {
1407 // RGBA8, green and alpha channel are always 255 for verification
1408 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 0] = rnd.getUint32() & 0xFF;
1409 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 1] = 0xFF;
1410 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 2] = rnd.getUint32() & 0xFF;
1411 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 3] = 0xFF;
1412 }
1413
1414 if (m_testType == TEST_TEX_COORD)
1415 {
1416 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D texture with a test pattern." << tcu::TestLog::EndMessage;
1417
1418 gl.bindTexture(GL_TEXTURE_2D, m_textureID);
1419 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]);
1420 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1421 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1422 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init");
1423 }
1424 else if (m_testType == TEST_LOD || m_testType == TEST_GRAD)
1425 {
1426 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a mipmapped 2D texture with a test pattern." << tcu::TestLog::EndMessage;
1427
1428 gl.bindTexture(GL_TEXTURE_2D, m_textureID);
1429
1430 for (int level = 0; (TEST_TEXTURE_SIZE >> level); ++level)
1431 gl.texImage2D(GL_TEXTURE_2D, level, GL_RGBA8, TEST_TEXTURE_SIZE >> level, TEST_TEXTURE_SIZE >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]);
1432
1433 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1434 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1435 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init");
1436 }
1437 else if (m_testType == TEST_TEX_COORD_CUBE)
1438 {
1439 DE_STATIC_ASSERT(TEST_TEXTURE_CUBE_SIZE <= TEST_TEXTURE_SIZE);
1440
1441 static const GLenum faces[] =
1442 {
1443 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1444 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
1445 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
1446 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
1447 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
1448 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1449 };
1450
1451 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a cube map with a test pattern." << tcu::TestLog::EndMessage;
1452
1453 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID);
1454
1455 for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); ++faceNdx)
1456 gl.texImage2D(faces[faceNdx], 0, GL_RGBA8, TEST_TEXTURE_CUBE_SIZE, TEST_TEXTURE_CUBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]);
1457
1458 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1459 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1460 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init");
1461 }
1462 else
1463 DE_ASSERT(DE_FALSE);
1464 }
1465 }
1466
deinit(void)1467 void TextureSamplerCase::deinit (void)
1468 {
1469 RenderCase::deinit();
1470
1471 if (m_textureID)
1472 {
1473 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1474
1475 gl.deleteTextures(1, &m_textureID);
1476 m_textureID = 0;
1477 }
1478 }
1479
iterate(void)1480 TextureSamplerCase::IterateResult TextureSamplerCase::iterate (void)
1481 {
1482 // Draw a grid and texture it with a texture and sample it using special special values. The result samples should all have the green channel at 255 as per the test image.
1483
1484 std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats));
1485 std::vector<tcu::UVec2> gridTexCoords (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats));
1486 std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6);
1487 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1488
1489 // vertices
1490 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
1491 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
1492 {
1493 const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1]
1494 const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f;
1495
1496 gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
1497 gridTexCoords[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec2(s_specialFloats[x], s_specialFloats[y]);
1498 }
1499
1500 // tiles
1501 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x)
1502 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y)
1503 {
1504 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6;
1505
1506 indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
1507 indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
1508 indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
1509
1510 indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0));
1511 indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
1512 indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1));
1513 }
1514
1515 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader. Sampling from the texture using special floating point values." << tcu::TestLog::EndMessage;
1516
1517 // Draw grid
1518 {
1519 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1520 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
1521 const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr");
1522 const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler");
1523
1524 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1525 gl.clear(GL_COLOR_BUFFER_BIT);
1526 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1527 gl.useProgram(m_program->getProgram());
1528
1529 gl.uniform1i(samplerLoc, 0);
1530 if (m_testType != TEST_TEX_COORD_CUBE)
1531 gl.bindTexture(GL_TEXTURE_2D, m_textureID);
1532 else
1533 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID);
1534
1535 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
1536 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]);
1537
1538 gl.enableVertexAttribArray(positionLoc);
1539 gl.enableVertexAttribArray(texCoordLoc);
1540 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]);
1541 gl.disableVertexAttribArray(positionLoc);
1542 gl.disableVertexAttribArray(texCoordLoc);
1543
1544 gl.useProgram(0);
1545 gl.finish();
1546 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::iterate");
1547
1548 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess());
1549 }
1550
1551 // verify everywhere was drawn and samples were from the texture (all pixels have Green = 255)
1552 if (!checkResultImage(resultImage))
1553 {
1554 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments");
1555 return STOP;
1556 }
1557
1558 // test drawing and textures still works
1559 if (!drawTestPattern(true))
1560 {
1561 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed");
1562 return STOP;
1563 }
1564
1565 // all ok
1566 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1567 return STOP;
1568 }
1569
genVertexSource(void) const1570 std::string TextureSamplerCase::genVertexSource (void) const
1571 {
1572 // vertex shader is passthrough, fragment does the calculations
1573 if (m_type == TYPE_FRAGMENT)
1574 return s_attrPassthroughVertexShaderSource;
1575
1576 // vertex shader does the calculations
1577 std::ostringstream buf;
1578 buf << "#version 300 es\n"
1579 "in highp vec4 a_pos;\n"
1580 "in highp vec2 a_attr;\n";
1581
1582 if (m_testType != TEST_TEX_COORD_CUBE)
1583 buf << "uniform highp sampler2D u_sampler;\n";
1584 else
1585 buf << "uniform highp samplerCube u_sampler;\n";
1586
1587 buf << "out mediump vec4 v_out;\n"
1588 "void main ()\n"
1589 "{\n";
1590
1591 if (m_testType == TEST_TEX_COORD)
1592 buf << " v_out = textureLod(u_sampler, a_attr, 0.0);\n";
1593 else if (m_testType == TEST_LOD)
1594 buf << " v_out = textureLod(u_sampler, a_attr, a_attr.x);\n";
1595 else if (m_testType == TEST_GRAD)
1596 buf << " v_out = textureGrad(u_sampler, a_attr, a_attr, a_attr.yx);\n";
1597 else if (m_testType == TEST_TEX_COORD_CUBE)
1598 buf << " v_out = textureLod(u_sampler, vec3(a_attr, a_attr.x + a_attr.y), 0.0);\n";
1599 else
1600 DE_ASSERT(DE_FALSE);
1601
1602 buf << "\n"
1603 " gl_Position = a_pos;\n"
1604 "}\n";
1605
1606 return buf.str();
1607 }
1608
genFragmentSource(void) const1609 std::string TextureSamplerCase::genFragmentSource (void) const
1610 {
1611 // fragment shader is passthrough
1612 if (m_type == TYPE_VERTEX)
1613 return s_colorPassthroughFragmentShaderSource;
1614
1615 // fragment shader does the calculations
1616 std::ostringstream buf;
1617 buf << "#version 300 es\n"
1618 "layout(location = 0) out mediump vec4 fragColor;\n";
1619
1620 if (m_testType != TEST_TEX_COORD_CUBE)
1621 buf << "uniform highp sampler2D u_sampler;\n";
1622 else
1623 buf << "uniform highp samplerCube u_sampler;\n";
1624
1625 buf << "in highp vec4 v_attr;\n"
1626 "void main ()\n"
1627 "{\n";
1628
1629 if (m_testType == TEST_TEX_COORD)
1630 buf << " fragColor = texture(u_sampler, v_attr.xy);\n";
1631 else if (m_testType == TEST_LOD)
1632 buf << " fragColor = texture(u_sampler, v_attr.xy, v_attr.x);\n";
1633 else if (m_testType == TEST_GRAD)
1634 buf << " fragColor = textureGrad(u_sampler, v_attr.xy, v_attr.xy, v_attr.yx);\n";
1635 else if (m_testType == TEST_TEX_COORD_CUBE)
1636 buf << " fragColor = texture(u_sampler, vec3(v_attr.xy,v_attr.x + v_attr.y));\n";
1637 else
1638 DE_ASSERT(DE_FALSE);
1639
1640 buf << "}\n";
1641
1642 return buf.str();
1643 }
1644
1645 /*--------------------------------------------------------------------*//*!
1646 * \brief Tests special floats as fragment shader outputs
1647 *
1648 * Tests that outputting special floats from a fragment shader does not change
1649 * the normal floating point values of outputted from a fragment shader. Special
1650 * floats are outputted in the green component, normal floating point values
1651 * in the red and blue component. Potential changes are tested by rendering
1652 * test pattern two times with different floating point values. The resulting
1653 * images' red and blue channels should be equal.
1654 *//*--------------------------------------------------------------------*/
1655 class OutputCase : public FramebufferRenderCase
1656 {
1657 public:
1658 OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type);
1659 ~OutputCase (void);
1660
1661 void testFBO (void);
1662
1663 private:
1664 std::string genVertexSource (void) const;
1665 std::string genFragmentSource (void) const;
1666 };
1667
OutputCase(Context & context,const char * name,const char * desc,FramebufferRenderCase::FrameBufferType type)1668 OutputCase::OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type)
1669 : FramebufferRenderCase (context, name, desc, type)
1670 {
1671 }
1672
~OutputCase(void)1673 OutputCase::~OutputCase (void)
1674 {
1675 deinit();
1676 }
1677
testFBO(void)1678 void OutputCase::testFBO (void)
1679 {
1680 // Create a 1 X [s_specialFloats] grid of tiles (stripes).
1681 std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * 2);
1682 std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * 6);
1683 tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8));
1684 tcu::TextureLevel specialImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1685 tcu::TextureLevel normalImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1686
1687 // vertices
1688 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y)
1689 {
1690 const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1]
1691
1692 gridVertices[y * 2 + 0] = tcu::Vec4(-1.0, posY, 0.0f, 1.0f);
1693 gridVertices[y * 2 + 1] = tcu::Vec4( 1.0, posY, 0.0f, 1.0f);
1694 }
1695
1696 // tiles
1697 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
1698 {
1699 const int baseNdx = y * 6;
1700
1701 indices[baseNdx + 0] = (deUint16)((y + 0) * 2);
1702 indices[baseNdx + 1] = (deUint16)((y + 1) * 2);
1703 indices[baseNdx + 2] = (deUint16)((y + 1) * 2 + 1);
1704
1705 indices[baseNdx + 3] = (deUint16)((y + 0) * 2);
1706 indices[baseNdx + 4] = (deUint16)((y + 1) * 2 + 1);
1707 indices[baseNdx + 5] = (deUint16)((y + 0) * 2 + 1);
1708 }
1709
1710 // Draw grids
1711 {
1712 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1713 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
1714 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special");
1715
1716 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1717 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1718 gl.useProgram(m_program->getProgram());
1719 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw");
1720
1721 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
1722 gl.enableVertexAttribArray(positionLoc);
1723
1724 // draw 2 passes. Special and normal.
1725 for (int passNdx = 0; passNdx < 2; ++passNdx)
1726 {
1727 const bool specialPass = (passNdx == 0);
1728
1729 m_testCtx.getLog() << tcu::TestLog::Message << "Pass " << passNdx << ": Drawing stripes with the shader. Setting u_special for each stripe to (" << ((specialPass) ? ("special") : ("1.0")) << ")." << tcu::TestLog::EndMessage;
1730
1731 // draw stripes
1732 gl.clear(GL_COLOR_BUFFER_BIT);
1733 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y)
1734 {
1735 const deUint32 one = 0x3F800000;
1736 const deUint32 special = s_specialFloats[y];
1737 const deUint32 uniformValue = (specialPass) ? (special) : (one);
1738 const int indexIndex = y * 6;
1739
1740 gl.uniform1fv(specialLoc, 1, (const float*)&uniformValue);
1741 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]);
1742 }
1743
1744 gl.finish();
1745 glu::readPixels(m_context.getRenderContext(), 0, 0, ((specialPass) ? (specialImage) : (normalImage)).getAccess());
1746 }
1747
1748 gl.disableVertexAttribArray(positionLoc);
1749 gl.useProgram(0);
1750 GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate");
1751 }
1752
1753 // Check results
1754 {
1755 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1756 const tcu::RGBA badPixelColor = tcu::RGBA::red();
1757 const tcu::RGBA okPixelColor = tcu::RGBA::green();
1758 int badPixels = 0;
1759
1760 m_testCtx.getLog() << tcu::TestLog::Message << "Checking passes have identical red and blue channels and the green channel is correct in the constant pass." << tcu::TestLog::EndMessage;
1761
1762 for (int y = 0; y < specialImage.getHeight(); ++y)
1763 for (int x = 0; x < specialImage.getWidth(); ++x)
1764 {
1765 const float greenThreshold = 0.1f;
1766 const tcu::Vec4 cNormal = normalImage.getAccess().getPixel(x, y);
1767 const tcu::Vec4 cSpecial = specialImage.getAccess().getPixel(x, y);
1768
1769 if (cNormal.x() != cSpecial.x() || cNormal.z() != cSpecial.z() || cNormal.y() < 1.0f - greenThreshold)
1770 {
1771 ++badPixels;
1772 errorMask.setPixel(x, y, badPixelColor);
1773 }
1774 else
1775 errorMask.setPixel(x, y, okPixelColor);
1776 }
1777
1778 m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage;
1779
1780 if (badPixels)
1781 {
1782 m_testCtx.getLog()
1783 << tcu::TestLog::ImageSet("Results", "Result verification")
1784 << tcu::TestLog::Image("Image with special green channel", "Image with special green channel", specialImage)
1785 << tcu::TestLog::Image("Image with constant green channel", "Image with constant green channel", normalImage)
1786 << tcu::TestLog::Image("Error Mask", "Error Mask", errorMask)
1787 << tcu::TestLog::EndImageSet;
1788
1789 // all ok?
1790 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1791 }
1792 else
1793 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1794 }
1795 }
1796
genVertexSource(void) const1797 std::string OutputCase::genVertexSource (void) const
1798 {
1799 return
1800 "#version 300 es\n"
1801 "in highp vec4 a_pos;\n"
1802 "out highp vec2 v_pos;\n"
1803 "void main ()\n"
1804 "{\n"
1805 " gl_Position = a_pos;\n"
1806 " v_pos = a_pos.xy;\n"
1807 "}\n";
1808 }
1809
genFragmentSource(void) const1810 std::string OutputCase::genFragmentSource (void) const
1811 {
1812 return
1813 "#version 300 es\n"
1814 "layout(location = 0) out highp vec4 fragColor;\n"
1815 "uniform highp float u_special;\n"
1816 "in highp vec2 v_pos;\n"
1817 "void main ()\n"
1818 "{\n"
1819 " fragColor = vec4((v_pos.x + 1.0) * 0.5, u_special, (v_pos.y + 1.0) * 0.5, 1.0);\n"
1820 "}\n";
1821 }
1822
1823 /*--------------------------------------------------------------------*//*!
1824 * \brief Tests special floats in blending
1825 *
1826 * Tests special floats as alpha and color components with various blending
1827 * modes. Test draws a test pattern and then does various blend operations
1828 * with special float values. After the blending test another test pattern
1829 * is drawn to detect possible blending anomalies. Test patterns should be
1830 * identical.
1831 *//*--------------------------------------------------------------------*/
1832 class BlendingCase : public FramebufferRenderCase
1833 {
1834 public:
1835 BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type);
1836 ~BlendingCase (void);
1837
1838 void testFBO (void);
1839
1840 private:
1841 void drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex);
1842
1843 std::string genVertexSource (void) const;
1844 std::string genFragmentSource (void) const;
1845 };
1846
BlendingCase(Context & context,const char * name,const char * desc,FramebufferRenderCase::FrameBufferType type)1847 BlendingCase::BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type)
1848 : FramebufferRenderCase (context, name, desc, type)
1849 {
1850 }
1851
~BlendingCase(void)1852 BlendingCase::~BlendingCase (void)
1853 {
1854 deinit();
1855 }
1856
testFBO(void)1857 void BlendingCase::testFBO (void)
1858 {
1859 static const GLenum equations[] =
1860 {
1861 GL_FUNC_ADD,
1862 GL_FUNC_SUBTRACT,
1863 GL_FUNC_REVERSE_SUBTRACT,
1864 GL_MIN,
1865 GL_MAX
1866 };
1867 static const GLenum functions[] =
1868 {
1869 GL_ZERO,
1870 GL_ONE,
1871 GL_SRC_COLOR,
1872 GL_ONE_MINUS_SRC_COLOR,
1873 GL_SRC_ALPHA,
1874 GL_ONE_MINUS_SRC_ALPHA,
1875 };
1876
1877 // Create a [BlendFuncs] X [s_specialFloats] grid of tiles. ( BlendFuncs = equations x functions )
1878
1879 const int numBlendFuncs = DE_LENGTH_OF_ARRAY(equations) * DE_LENGTH_OF_ARRAY(functions);
1880 std::vector<tcu::Vec4> gridVertices ((numBlendFuncs + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1));
1881 std::vector<deUint16> indices (numBlendFuncs * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6);
1882 tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8));
1883 tcu::TextureLevel beforeImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1884 tcu::TextureLevel afterImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1885
1886 // vertices
1887 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x)
1888 for (int y = 0; y < numBlendFuncs + 1; ++y)
1889 {
1890 const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats)] to [-1, 1]
1891 const float posY = (float)y / (float)numBlendFuncs * 2.0f - 1.0f;
1892
1893 gridVertices[x * (numBlendFuncs + 1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
1894 }
1895
1896 // tiles
1897 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
1898 for (int y = 0; y < numBlendFuncs; ++y)
1899 {
1900 const int baseNdx = (x * numBlendFuncs + y) * 6;
1901
1902 indices[baseNdx + 0] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0));
1903 indices[baseNdx + 1] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1));
1904 indices[baseNdx + 2] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+0));
1905
1906 indices[baseNdx + 3] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0));
1907 indices[baseNdx + 4] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1));
1908 indices[baseNdx + 5] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+1));
1909 }
1910
1911 // Draw tiles
1912 {
1913 const int numPasses = 5;
1914 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1915 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos");
1916 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special");
1917
1918 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1919 gl.clear(GL_COLOR_BUFFER_BIT);
1920 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1921 gl.useProgram(m_program->getProgram());
1922 gl.enable(GL_BLEND);
1923 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw");
1924
1925 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]);
1926 gl.enableVertexAttribArray(positionLoc);
1927
1928 // draw "before" image
1929 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing pre-draw pattern." << tcu::TestLog::EndMessage;
1930 drawTestImage(beforeImage.getAccess(), specialLoc, (int)gridVertices.size() - 1);
1931 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw pattern");
1932
1933 // draw multiple passes with special floats
1934 gl.clear(GL_COLOR_BUFFER_BIT);
1935 for (int passNdx = 0; passNdx < numPasses; ++passNdx)
1936 {
1937 de::Random rnd(123 + 567 * passNdx);
1938
1939 m_testCtx.getLog()
1940 << tcu::TestLog::Message
1941 << "Pass " << passNdx << ": Drawing tiles with the shader.\n"
1942 << "\tVarying u_special for each tile.\n"
1943 << "\tVarying blend function and blend equation for each tile.\n"
1944 << tcu::TestLog::EndMessage;
1945
1946 // draw tiles
1947 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x)
1948 for (int y = 0; y < numBlendFuncs; ++y)
1949 {
1950 const GLenum blendEquation = equations[y % DE_LENGTH_OF_ARRAY(equations)];
1951 const GLenum blendFunction = functions[y / DE_LENGTH_OF_ARRAY(equations)];
1952 const GLenum blendFunctionDst = rnd.choose<GLenum>(DE_ARRAY_BEGIN(functions), DE_ARRAY_END(functions));
1953 const int indexIndex = (x * numBlendFuncs + y) * 6;
1954
1955 // "rnd.get"s are run in a deterministic order
1956 const deUint32 componentR = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1957 const deUint32 componentG = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1958 const deUint32 componentB = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1959 const deUint32 componentA = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats));
1960 const tcu::UVec4 uniformValue = tcu::UVec4(componentR, componentG, componentB, componentA);
1961
1962 gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr());
1963 gl.blendEquation(blendEquation);
1964 gl.blendFunc(blendFunction, blendFunctionDst);
1965 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]);
1966 }
1967 }
1968 GLU_EXPECT_NO_ERROR(gl.getError(), "special passes");
1969
1970 // draw "after" image
1971 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing post-draw pattern." << tcu::TestLog::EndMessage;
1972 drawTestImage(afterImage.getAccess(), specialLoc, (int)gridVertices.size() - 1);
1973 GLU_EXPECT_NO_ERROR(gl.getError(), "post-draw pattern");
1974
1975 gl.disableVertexAttribArray(positionLoc);
1976 gl.useProgram(0);
1977 GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate");
1978 }
1979
1980 // Check results
1981 {
1982 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1983 const tcu::RGBA badPixelColor = tcu::RGBA::red();
1984 const tcu::RGBA okPixelColor = tcu::RGBA::green();
1985 int badPixels = 0;
1986
1987 m_testCtx.getLog() << tcu::TestLog::Message << "Checking patterns are identical." << tcu::TestLog::EndMessage;
1988
1989 for (int y = 0; y < beforeImage.getHeight(); ++y)
1990 for (int x = 0; x < beforeImage.getWidth(); ++x)
1991 {
1992 const tcu::Vec4 cBefore = beforeImage.getAccess().getPixel(x, y);
1993 const tcu::Vec4 cAfter = afterImage.getAccess().getPixel(x, y);
1994
1995 if (cBefore != cAfter)
1996 {
1997 ++badPixels;
1998 errorMask.setPixel(x, y, badPixelColor);
1999 }
2000 else
2001 errorMask.setPixel(x, y, okPixelColor);
2002 }
2003
2004 m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage;
2005
2006 if (badPixels)
2007 {
2008 m_testCtx.getLog()
2009 << tcu::TestLog::ImageSet("Results", "Result verification")
2010 << tcu::TestLog::Image("Pattern drawn before special float blending", "Pattern drawn before special float blending", beforeImage)
2011 << tcu::TestLog::Image("Pattern drawn after special float blending", "Pattern drawn after special float blending", afterImage)
2012 << tcu::TestLog::EndImageSet;
2013
2014 // all ok?
2015 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
2016 }
2017 else
2018 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2019 }
2020 }
2021
drawTestImage(tcu::PixelBufferAccess dst,GLuint uColorLoc,int maxVertexIndex)2022 void BlendingCase::drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex)
2023 {
2024 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2025 de::Random rnd (123);
2026
2027 gl.clear(GL_COLOR_BUFFER_BIT);
2028 gl.blendEquation(GL_FUNC_ADD);
2029 gl.blendFunc(GL_ONE, GL_ONE);
2030
2031 for (int tri = 0; tri < 20; ++tri)
2032 {
2033 tcu::Vec4 color;
2034 color.x() = rnd.getFloat();
2035 color.y() = rnd.getFloat();
2036 color.z() = rnd.getFloat();
2037 color.w() = rnd.getFloat();
2038 gl.uniform4fv(uColorLoc, 1, color.getPtr());
2039
2040 deUint16 indices[3];
2041 indices[0] = (deUint16)rnd.getInt(0, maxVertexIndex);
2042 indices[1] = (deUint16)rnd.getInt(0, maxVertexIndex);
2043 indices[2] = (deUint16)rnd.getInt(0, maxVertexIndex);
2044
2045 gl.drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
2046 }
2047
2048 gl.finish();
2049 glu::readPixels(m_context.getRenderContext(), 0, 0, dst);
2050 }
2051
genVertexSource(void) const2052 std::string BlendingCase::genVertexSource (void) const
2053 {
2054 return
2055 "#version 300 es\n"
2056 "in highp vec4 a_pos;\n"
2057 "void main ()\n"
2058 "{\n"
2059 " gl_Position = a_pos;\n"
2060 "}\n";
2061 }
2062
genFragmentSource(void) const2063 std::string BlendingCase::genFragmentSource (void) const
2064 {
2065 return
2066 "#version 300 es\n"
2067 "layout(location = 0) out highp vec4 fragColor;\n"
2068 "uniform highp vec4 u_special;\n"
2069 "void main ()\n"
2070 "{\n"
2071 " fragColor = u_special;\n"
2072 "}\n";
2073 }
2074
2075 } //anonymous
2076
SpecialFloatTests(Context & context)2077 SpecialFloatTests::SpecialFloatTests (Context& context)
2078 : TestCaseGroup(context, "special_float", "Special float tests")
2079 {
2080 }
2081
~SpecialFloatTests(void)2082 SpecialFloatTests::~SpecialFloatTests (void)
2083 {
2084 }
2085
init(void)2086 void SpecialFloatTests::init (void)
2087 {
2088 tcu::TestCaseGroup* const vertexGroup = new tcu::TestCaseGroup(m_testCtx, "vertex", "Run vertex shader with special float values");
2089 tcu::TestCaseGroup* const fragmentGroup = new tcu::TestCaseGroup(m_testCtx, "fragment", "Run fragment shader with special float values");
2090 tcu::TestCaseGroup* const framebufferGroup = new tcu::TestCaseGroup(m_testCtx, "framebuffer", "Test framebuffers containing special float values");
2091
2092 // .vertex
2093 {
2094 vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_VERTEX));
2095 vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_VERTEX));
2096 vertexGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_VERTEX));
2097 vertexGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT));
2098 vertexGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO));
2099 vertexGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT));
2100 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD));
2101 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD_CUBE));
2102 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_LOD));
2103 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_GRAD));
2104
2105 addChild(vertexGroup);
2106 }
2107
2108 // .fragment
2109 {
2110 fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_FRAGMENT));
2111 fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_FRAGMENT));
2112 fragmentGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_FRAGMENT));
2113 fragmentGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT));
2114 fragmentGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO));
2115 fragmentGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT));
2116 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD));
2117 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD_CUBE));
2118 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_LOD));
2119 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_GRAD));
2120
2121 addChild(fragmentGroup);
2122 }
2123
2124 // .framebuffer
2125 {
2126 framebufferGroup->addChild(new OutputCase (m_context, "write_default", "write special floating point values to default framebuffer", FramebufferRenderCase::FBO_DEFAULT));
2127 framebufferGroup->addChild(new OutputCase (m_context, "write_rgba4", "write special floating point values to RGBA4 framebuffer", FramebufferRenderCase::FBO_RGBA4));
2128 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb5_a1", "write special floating point values to RGB5_A1 framebuffer", FramebufferRenderCase::FBO_RGB5_A1));
2129 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb565", "write special floating point values to RGB565 framebuffer", FramebufferRenderCase::FBO_RGB565));
2130 framebufferGroup->addChild(new OutputCase (m_context, "write_rgba8", "write special floating point values to RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8));
2131 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb10_a2", "write special floating point values to RGB10_A2 framebuffer", FramebufferRenderCase::FBO_RGB10_A2));
2132 framebufferGroup->addChild(new OutputCase (m_context, "write_float16", "write special floating point values to float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16));
2133 framebufferGroup->addChild(new OutputCase (m_context, "write_float32", "write special floating point values to float32 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT32));
2134
2135 framebufferGroup->addChild(new BlendingCase (m_context, "blend_default", "blend special floating point values in a default framebuffer", FramebufferRenderCase::FBO_DEFAULT));
2136 framebufferGroup->addChild(new BlendingCase (m_context, "blend_rgba8", "blend special floating point values in a RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8));
2137 framebufferGroup->addChild(new BlendingCase (m_context, "blend_float16", "blend special floating point values in a float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16));
2138
2139 addChild(framebufferGroup);
2140 }
2141 }
2142
2143 } // Stress
2144 } // gles3
2145 } // deqp
2146