Lower correlation threshold in flush-finish tests again am: 6455e6f987 am: 84373d7748...
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fShaderFramebufferFetchTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2017 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 EXT Shader Framebuffer Fetch Tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fShaderFramebufferFetchTests.hpp"
25 #include "es31fFboTestUtil.hpp"
26
27 #include "tcuTestLog.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuVectorUtil.hpp"
32
33 #include "gluShaderProgram.hpp"
34 #include "gluPixelTransfer.hpp"
35 #include "gluTextureUtil.hpp"
36 #include "gluContextInfo.hpp"
37 #include "gluObjectWrapper.hpp"
38
39 #include "glwFunctions.hpp"
40 #include "glwEnums.hpp"
41
42 #include "deStringUtil.hpp"
43
44 #include <vector>
45
46 namespace deqp
47 {
48 namespace gles31
49 {
50 namespace Functional
51 {
52 namespace
53 {
54
55 using std::vector;
56 using std::string;
57 using tcu::TestLog;
58
59 using namespace glw;
60 using namespace FboTestUtil;
61
62 static void checkExtensionSupport (Context& context, const char* extName)
63 {
64         if (!context.getContextInfo().isExtensionSupported(extName))
65                 throw tcu::NotSupportedError(string(extName) + " not supported");
66 }
67
68 static void checkFramebufferFetchSupport (Context& context)
69 {
70         checkExtensionSupport(context, "GL_EXT_shader_framebuffer_fetch");
71 }
72
73 static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext)
74 {
75         const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
76         switch (format)
77         {
78                 // Color-renderable formats
79                 case GL_RGBA32I:
80                 case GL_RGBA32UI:
81                 case GL_RGBA16I:
82                 case GL_RGBA16UI:
83                 case GL_RGBA8:
84                 case GL_RGBA8I:
85                 case GL_RGBA8UI:
86                 case GL_SRGB8_ALPHA8:
87                 case GL_RGB10_A2:
88                 case GL_RGB10_A2UI:
89                 case GL_RGBA4:
90                 case GL_RGB5_A1:
91                 case GL_RGB8:
92                 case GL_RGB565:
93                 case GL_RG32I:
94                 case GL_RG32UI:
95                 case GL_RG16I:
96                 case GL_RG16UI:
97                 case GL_RG8:
98                 case GL_RG8I:
99                 case GL_RG8UI:
100                 case GL_R32I:
101                 case GL_R32UI:
102                 case GL_R16I:
103                 case GL_R16UI:
104                 case GL_R8:
105                 case GL_R8I:
106                 case GL_R8UI:
107                         return true;
108
109                 // Float format
110                 case GL_RGBA32F:
111                 case GL_RGB32F:
112                 case GL_R11F_G11F_B10F:
113                 case GL_RG32F:
114                 case GL_R32F:
115                         return isES32;
116
117                 default:
118                         return false;
119         }
120 }
121
122 tcu::TextureFormat getReadPixelFormat (const tcu::TextureFormat& format)
123 {
124         switch (tcu::getTextureChannelClass(format.type))
125         {
126                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
127                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
128
129                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
130                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
131
132                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
133                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
134                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
135
136                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
137                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
138
139                 default:
140                         DE_ASSERT(false);
141                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
142         }
143 }
144
145 tcu::Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
146 {
147         DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
148         DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
149
150         DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
151         DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
152
153         DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
154         DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
155
156         const tcu::IVec4        srcBits         = tcu::getTextureFormatBitDepth(sourceFormat);
157         const tcu::IVec4        readBits        = tcu::getTextureFormatBitDepth(readPixelsFormat);
158
159         return tcu::Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
160 }
161
162 tcu::UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
163 {
164         const tcu::IVec4        srcMantissaBits         = tcu::getTextureFormatMantissaBitDepth(sourceFormat);
165         const tcu::IVec4        readMantissaBits        = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
166         tcu::IVec4                      ULPDiff(0);
167
168         for (int i = 0; i < 4; i++)
169                 if (readMantissaBits[i] >= srcMantissaBits[i])
170                         ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
171
172         return tcu::UVec4(4) * (tcu::UVec4(1) << (ULPDiff.cast<deUint32>()));
173 }
174
175 static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts)
176 {
177         for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
178         {
179                 const std::string& extension = *iter;
180
181                 if (context.getContextInfo().isExtensionSupported(extension.c_str()))
182                         return true;
183         }
184
185         return false;
186 }
187
188 static std::string getColorOutputType(tcu::TextureFormat format)
189 {
190         switch (tcu::getTextureChannelClass(format.type))
191         {
192                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:         return "uvec4";
193                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:           return "ivec4";
194                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
195                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
196                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:           return "vec4";
197                 default:
198                         DE_FATAL("Unsupported TEXTURECHANNELCLASS");
199                         return "";
200         }
201 }
202
203 static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext)
204 {
205         const bool                                      isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
206         std::vector<std::string>        out;
207
208         DE_ASSERT(!isRequiredFormat(format, renderContext));
209
210         switch (format)
211         {
212                 case GL_RGB16F:
213                         out.push_back("GL_EXT_color_buffer_half_float");
214                         break;
215
216                 case GL_RGBA16F:
217                 case GL_RG16F:
218                 case GL_R16F:
219                         out.push_back("GL_EXT_color_buffer_half_float");
220
221                 case GL_RGBA32F:
222                 case GL_RGB32F:
223                 case GL_R11F_G11F_B10F:
224                 case GL_RG32F:
225                 case GL_R32F:
226                         if (!isES32)
227                                 out.push_back("GL_EXT_color_buffer_float");
228                         break;
229
230                 default:
231                         break;
232         }
233
234         return out;
235 }
236
237 void checkFormatSupport (Context& context, deUint32 sizedFormat)
238 {
239         const bool                                              isCoreFormat    = isRequiredFormat(sizedFormat, context.getRenderContext());
240         const std::vector<std::string>  requiredExts    = (!isCoreFormat) ? getEnablingExtensions(sizedFormat, context.getRenderContext()) : std::vector<std::string>();
241
242         // Check that we don't try to use invalid formats.
243         DE_ASSERT(isCoreFormat || !requiredExts.empty());
244
245         if (!requiredExts.empty() && !isAnyExtensionSupported(context, requiredExts))
246                 throw tcu::NotSupportedError("Format not supported");
247 }
248
249 tcu::Vec4 scaleColorValue (tcu::TextureFormat format, const tcu::Vec4& color)
250 {
251         const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(format);
252         const tcu::Vec4                                 cScale                  = fmtInfo.valueMax-fmtInfo.valueMin;
253         const tcu::Vec4                                 cBias                   = fmtInfo.valueMin;
254
255         return tcu::RGBA(color).toVec() * cScale + cBias;
256 }
257
258 // Base class for framebuffer fetch test cases
259
260 class FramebufferFetchTestCase : public TestCase
261 {
262 public:
263                                                                         FramebufferFetchTestCase                (Context& context, const char* name, const char* desc, deUint32 format);
264                                                                         ~FramebufferFetchTestCase               (void);
265
266         void                                                    init                                                    (void);
267         void                                                    deinit                                                  (void);
268
269 protected:
270         string                                                  genPassThroughVertSource                (void);
271         virtual glu::ProgramSources             genShaderSources                                (void);
272
273         void                                                    genFramebufferWithTexture               (const tcu::Vec4& color);
274         void                                                    genAttachementTexture                   (const tcu::Vec4& color);
275         void                                                    genUniformColor                                 (const tcu::Vec4& color);
276
277         void                                                    render                                                  (void);
278         void                                                    verifyRenderbuffer                              (TestLog& log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel& result);
279
280         const glw::Functions&                   m_gl;
281         const deUint32                                  m_format;
282
283         glu::ShaderProgram*                             m_program;
284         GLuint                                                  m_framebuffer;
285         GLuint                                                  m_texColorBuffer;
286
287         tcu::TextureFormat                              m_texFmt;
288         glu::TransferFormat                             m_transferFmt;
289         bool                                                    m_isFilterable;
290
291         enum
292         {
293                 VIEWPORT_WIDTH  = 64,
294                 VIEWPORT_HEIGHT = 64,
295         };
296 };
297
298 FramebufferFetchTestCase::FramebufferFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
299         : TestCase (context, name, desc)
300         , m_gl                                  (m_context.getRenderContext().getFunctions())
301         , m_format                              (format)
302         , m_program                             (DE_NULL)
303         , m_framebuffer                 (0)
304         , m_texColorBuffer              (0)
305         , m_texFmt                              (glu::mapGLInternalFormat(m_format))
306         , m_transferFmt                 (glu::getTransferFormat(m_texFmt))
307         , m_isFilterable                (glu::isGLInternalColorFormatFilterable(m_format))
308 {
309 }
310
311 FramebufferFetchTestCase::~FramebufferFetchTestCase (void)
312 {
313         FramebufferFetchTestCase::deinit();
314 }
315
316 void FramebufferFetchTestCase::init (void)
317 {
318         checkFramebufferFetchSupport (m_context);
319         checkFormatSupport(m_context, m_format);
320
321         DE_ASSERT(!m_program);
322         m_program = new glu::ShaderProgram(m_context.getRenderContext(), genShaderSources());
323
324         m_testCtx.getLog() << *m_program;
325
326         if (!m_program->isOk())
327         {
328                 delete m_program;
329                 m_program = DE_NULL;
330                 TCU_FAIL("Failed to compile shader program");
331         }
332
333         m_gl.useProgram(m_program->getProgram());
334 }
335
336 void FramebufferFetchTestCase::deinit (void)
337 {
338         delete m_program;
339         m_program = DE_NULL;
340
341         if (m_framebuffer)
342         {
343                 m_gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
344                 m_gl.deleteFramebuffers(1, &m_framebuffer);
345                 m_framebuffer = 0;
346         }
347
348         if (m_texColorBuffer)
349         {
350                 m_gl.deleteTextures(1, &m_texColorBuffer);
351                 m_texColorBuffer = 0;
352         }
353 }
354
355 string FramebufferFetchTestCase::genPassThroughVertSource (void)
356 {
357         std::ostringstream vertShaderSource;
358
359         vertShaderSource        << "#version 310 es\n"
360                                                 << "in highp vec4 a_position;\n"
361                                                 << "\n"
362                                                 << "void main (void)\n"
363                                                 << "{\n"
364                                                 << "    gl_Position = a_position;\n"
365                                                 << "}\n";
366
367         return vertShaderSource.str();
368 }
369
370 glu::ProgramSources FramebufferFetchTestCase::genShaderSources (void)
371 {
372         const string            vecType = getColorOutputType(m_texFmt);
373         std::ostringstream      fragShaderSource;
374
375         fragShaderSource        << "#version 310 es\n"
376                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
377                                                 << "layout(location = 0) inout highp " << vecType << " o_color;\n"
378                                                 << "uniform highp " << vecType << " u_color;\n"
379                                                 << "\n"
380                                                 << "void main (void)\n"
381                                                 << "{\n"
382                                                 << "    o_color += u_color;\n"
383                                                 << "}\n";
384
385         return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
386 }
387
388 void FramebufferFetchTestCase::genFramebufferWithTexture (const tcu::Vec4& color)
389 {
390         m_gl.genFramebuffers(1, &m_framebuffer);
391         m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
392
393         genAttachementTexture(color);
394         GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachementTexture()");
395
396         m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
397         TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
398 }
399
400 void FramebufferFetchTestCase::genAttachementTexture (const tcu::Vec4& color)
401 {
402         tcu::TextureLevel                       data                                    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
403         tcu::TextureChannelClass        textureChannelClass =   tcu::getTextureChannelClass(m_texFmt.type);
404
405         m_gl.genTextures(1, &m_texColorBuffer);
406         m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
407
408         m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
409         m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
410         m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_R,              GL_CLAMP_TO_EDGE);
411         m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MIN_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
412         m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MAG_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
413
414         if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
415                 tcu::clear(data.getAccess(), color.asUint());
416         else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
417                 tcu::clear(data.getAccess(), color.asInt());
418         else
419                 tcu::clear(data.getAccess(), color);
420
421         m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
422         m_gl.bindTexture(GL_TEXTURE_2D, 0);
423 }
424
425 void FramebufferFetchTestCase::verifyRenderbuffer (TestLog&     log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel&     result)
426 {
427         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
428
429         switch (tcu::getTextureChannelClass(format.type))
430         {
431                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
432                 {
433                         const string            name            = "Renderbuffer";
434                         const string            desc            = "Compare renderbuffer (floating_point)";
435                         const tcu::UVec4        threshold       = getFloatULPThreshold(format, result.getFormat());
436
437                         if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
438                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
439
440                         break;
441                 }
442
443                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
444                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
445                 {
446                         const string            name            = "Renderbuffer";
447                         const string            desc            = "Compare renderbuffer (integer)";
448                         const tcu::UVec4        threshold       (1, 1, 1, 1);
449
450                         if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
451                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
452
453                         break;
454                 }
455
456                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
457                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
458                 {
459                         const string            name            = "Renderbuffer";
460                         const string            desc            = "Compare renderbuffer (fixed point)";
461                         const tcu::Vec4         threshold       = getFixedPointFormatThreshold(format, result.getFormat());
462
463                         if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
464                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
465
466                         break;
467                 }
468
469                 default:
470                 {
471                         DE_ASSERT(DE_FALSE);
472                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
473                 }
474         }
475 }
476
477 void FramebufferFetchTestCase::genUniformColor (const tcu::Vec4& color)
478 {
479         const GLuint colorLocation      = m_gl.getUniformLocation(m_program->getProgram(), "u_color");
480
481         switch (tcu::getTextureChannelClass(m_texFmt.type))
482         {
483                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
484                 {
485                         m_gl.uniform4uiv(colorLocation, 1, color.asUint().getPtr());
486                         break;
487                 }
488
489                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
490                 {
491                         m_gl.uniform4iv(colorLocation, 1, color.asInt().getPtr());
492                         break;
493                 }
494                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
495                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
496                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
497                 {
498                         m_gl.uniform4fv(colorLocation, 1, color.asFloat().getPtr());
499                         break;
500                 }
501                 default:
502                         DE_ASSERT(DE_FALSE);
503         }
504
505         GLU_EXPECT_NO_ERROR(m_gl.getError(), "genUniformColor()");
506 }
507
508 void FramebufferFetchTestCase::render (void)
509 {
510         const GLfloat coords[] =
511         {
512                 -1.0f, -1.0f,
513                 +1.0f, -1.0f,
514                 +1.0f, +1.0f,
515                 -1.0f, +1.0f,
516         };
517
518         const GLushort indices[] =
519         {
520                 0, 1, 2, 2, 3, 0,
521         };
522
523         const GLuint    coordLocation   = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
524
525         m_gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
526
527         glu::Buffer coordinatesBuffer(m_context.getRenderContext());
528         glu::Buffer elementsBuffer(m_context.getRenderContext());
529
530         m_gl.bindBuffer(GL_ARRAY_BUFFER, *coordinatesBuffer);
531         m_gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW);
532         m_gl.enableVertexAttribArray(coordLocation);
533         m_gl.vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
534
535         m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementsBuffer);
536         m_gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW);
537
538         m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
539         GLU_EXPECT_NO_ERROR(m_gl.getError(), "render()");
540 }
541
542 // Test description:
543 // - Attach texture containing solid color to framebuffer.
544 // - Draw full quad covering the entire viewport.
545 // - Sum framebuffer read color with passed in uniform color.
546 // - Compare resulting surface with reference.
547
548 class TextureFormatTestCase : public FramebufferFetchTestCase
549 {
550 public:
551                                                 TextureFormatTestCase           (Context& context, const char* name, const char* desc, deUint32 format);
552                                                 ~TextureFormatTestCase          (void) {};
553
554         IterateResult           iterate                                         (void);
555
556 private:
557         tcu::TextureLevel       genReferenceTexture                     (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
558 };
559
560 TextureFormatTestCase::TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format)
561         : FramebufferFetchTestCase(context, name, desc, format)
562 {
563 }
564
565 tcu::TextureLevel TextureFormatTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
566 {
567         tcu::TextureLevel                       reference                       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
568         tcu::TextureChannelClass        textureChannelClass = tcu::getTextureChannelClass(m_texFmt.type);
569
570         if (textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
571         {
572                 tcu::clear(reference.getAccess(), fbColor.asUint() + uniformColor.asUint());
573         }
574         else if (textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
575         {
576                 tcu::clear(reference.getAccess(), fbColor.asInt() + uniformColor.asInt());
577         }
578         else
579         {
580                 if (tcu::isSRGB(m_texFmt))
581                 {
582                         const tcu::Vec4 fragmentColor = tcu::sRGBToLinear(fbColor) + uniformColor;
583                         tcu::clear(reference.getAccess(), tcu::linearToSRGB(fragmentColor));
584                 }
585                 else
586                 {
587                         tcu::clear(reference.getAccess(), fbColor + uniformColor);
588                 }
589         }
590
591         return reference;
592 }
593
594 TextureFormatTestCase::IterateResult TextureFormatTestCase::iterate (void)
595 {
596         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
597         const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
598
599         tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
600         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
601
602         genFramebufferWithTexture(fbColor);
603         genUniformColor(uniformColor);
604         render();
605
606         glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
607         verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
608
609         return STOP;
610 }
611
612 // Test description:
613 // - Attach multiple textures containing solid colors to framebuffer.
614 // - Draw full quad covering the entire viewport.
615 // - For each render target sum framebuffer read color with passed in uniform color.
616 // - Compare resulting surfaces with references.
617
618 class MultipleRenderTargetsTestCase : public FramebufferFetchTestCase
619 {
620 public:
621                                                 MultipleRenderTargetsTestCase           (Context& context, const char* name, const char* desc, deUint32 format);
622                                                 ~MultipleRenderTargetsTestCase          (void);
623
624         IterateResult           iterate                                                         (void);
625         void                            deinit                                                          (void);
626
627 private:
628         void                            genFramebufferWithTextures                      (const vector<tcu::Vec4>& colors);
629         void                            genAttachmentTextures                           (const vector<tcu::Vec4>& colors);
630         tcu::TextureLevel       genReferenceTexture                                     (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
631         glu::ProgramSources genShaderSources                                    (void);
632
633         enum
634         {
635                 MAX_COLOR_BUFFERS = 4
636         };
637
638         GLuint                          m_texColorBuffers                                       [MAX_COLOR_BUFFERS];
639         GLenum                          m_colorBuffers                                          [MAX_COLOR_BUFFERS];
640 };
641
642 MultipleRenderTargetsTestCase::MultipleRenderTargetsTestCase (Context& context, const char* name, const char* desc, deUint32 format)
643         : FramebufferFetchTestCase(context, name, desc, format)
644         , m_texColorBuffers ()
645 {
646         m_colorBuffers[0] = GL_COLOR_ATTACHMENT0;
647         m_colorBuffers[1] = GL_COLOR_ATTACHMENT1;
648         m_colorBuffers[2] = GL_COLOR_ATTACHMENT2;
649         m_colorBuffers[3] = GL_COLOR_ATTACHMENT3;
650 }
651
652 MultipleRenderTargetsTestCase::~MultipleRenderTargetsTestCase (void)
653 {
654         MultipleRenderTargetsTestCase::deinit();
655 }
656
657 void MultipleRenderTargetsTestCase::deinit (void)
658 {
659         // Clean up texture data
660         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
661         {
662                 if (m_texColorBuffers[i])
663                         m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texColorBuffers[i]);
664         }
665
666         FramebufferFetchTestCase::deinit();
667 }
668
669 void MultipleRenderTargetsTestCase::genFramebufferWithTextures (const vector<tcu::Vec4>& colors)
670 {
671         m_gl.genFramebuffers(1, &m_framebuffer);
672         m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
673
674         genAttachmentTextures(colors);
675
676         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
677                 m_gl.framebufferTexture2D(GL_FRAMEBUFFER, m_colorBuffers[i], GL_TEXTURE_2D, m_texColorBuffers[i], 0);
678
679         TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
680
681         m_gl.drawBuffers((glw::GLsizei)MAX_COLOR_BUFFERS, &m_colorBuffers[0]);
682         GLU_EXPECT_NO_ERROR(m_gl.getError(), "genFramebufferWithTextures()");
683 }
684
685 void MultipleRenderTargetsTestCase::genAttachmentTextures (const vector<tcu::Vec4>& colors)
686 {
687         tcu::TextureLevel       data    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
688
689         m_gl.genTextures(MAX_COLOR_BUFFERS, m_texColorBuffers);
690
691         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
692         {
693                 m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffers[i]);
694
695                 m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
696                 m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
697                 m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_R,              GL_CLAMP_TO_EDGE);
698                 m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MIN_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
699                 m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MAG_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
700
701                 clear(data.getAccess(), colors[i]);
702                 m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
703         }
704
705         m_gl.bindTexture(GL_TEXTURE_2D, 0);
706         GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachmentTextures()");
707 }
708
709 tcu::TextureLevel MultipleRenderTargetsTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
710 {
711         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
712         tcu::clear(reference.getAccess(), fbColor + uniformColor);
713
714         return reference;
715 }
716
717 glu::ProgramSources MultipleRenderTargetsTestCase::genShaderSources (void)
718 {
719         const string            vecType = getColorOutputType(m_texFmt);
720         std::ostringstream      fragShaderSource;
721
722         fragShaderSource        << "#version 310 es\n"
723                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
724                                                 << "layout(location = 0) inout highp " << vecType << " o_color0;\n"
725                                                 << "layout(location = 1) inout highp " << vecType << " o_color1;\n"
726                                                 << "layout(location = 2) inout highp " << vecType << " o_color2;\n"
727                                                 << "layout(location = 3) inout highp " << vecType << " o_color3;\n"
728                                                 << "uniform highp " << vecType << " u_color;\n"
729                                                 << "\n"
730                                                 << "void main (void)\n"
731                                                 << "{\n"
732                                                 << "    o_color0 += u_color;\n"
733                                                 << "    o_color1 += u_color;\n"
734                                                 << "    o_color2 += u_color;\n"
735                                                 << "    o_color3 += u_color;\n"
736                                                 << "}\n";
737
738         return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
739 }
740
741 MultipleRenderTargetsTestCase::IterateResult MultipleRenderTargetsTestCase::iterate (void)
742 {
743         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
744         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
745
746         vector<tcu::Vec4> colors;
747         colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.9f, 0.0f, 0.0f, 1.0f)));
748         colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.0f, 1.0f)));
749         colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.9f, 1.0f)));
750         colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.9f, 1.0f)));
751
752         genFramebufferWithTextures(colors);
753         genUniformColor(uniformColor);
754         render();
755
756         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_colorBuffers); ++i)
757         {
758                 tcu::TextureLevel       reference               = genReferenceTexture(colors[i], uniformColor);
759
760                 m_gl.readBuffer(m_colorBuffers[i]);
761                 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
762                 verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
763         }
764
765         return STOP;
766 }
767
768 // Test description:
769 // - Same as TextureFormatTestCase except uses built-in fragment output of ES 2.0
770
771 class LastFragDataTestCase : public FramebufferFetchTestCase
772 {
773 public:
774                                                 LastFragDataTestCase                    (Context& context, const char* name, const char* desc, deUint32 format);
775                                                 ~LastFragDataTestCase                   (void) {};
776
777         IterateResult           iterate                                                 (void);
778
779 private:
780         glu::ProgramSources genShaderSources                            (void);
781         tcu::TextureLevel       genReferenceTexture                             (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
782 };
783
784 LastFragDataTestCase::LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format)
785         : FramebufferFetchTestCase(context, name, desc, format)
786 {
787 }
788
789 glu::ProgramSources LastFragDataTestCase::genShaderSources (void)
790 {
791         const string            vecType = getColorOutputType(m_texFmt);
792         std::ostringstream      vertShaderSource;
793         std::ostringstream      fragShaderSource;
794
795         vertShaderSource        << "#version 100\n"
796                                                 << "attribute vec4 a_position;\n"
797                                                 << "\n"
798                                                 << "void main (void)\n"
799                                                 << "{\n"
800                                                 << "    gl_Position = a_position;\n"
801                                                 << "}\n";
802
803         fragShaderSource        << "#version 100\n"
804                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
805                                                 << "uniform highp " << vecType << " u_color;\n"
806                                                 << "\n"
807                                                 << "void main (void)\n"
808                                                 << "{\n"
809                                                 << "    gl_FragColor = u_color + gl_LastFragData[0];\n"
810                                                 << "}\n";
811
812         return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
813 }
814
815 tcu::TextureLevel LastFragDataTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
816 {
817         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
818         tcu::clear(reference.getAccess(), fbColor + uniformColor);
819
820         return reference;
821 }
822
823 LastFragDataTestCase::IterateResult LastFragDataTestCase::iterate (void)
824 {
825         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
826         const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
827
828         tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
829         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
830
831         genFramebufferWithTexture(fbColor);
832         genUniformColor(uniformColor);
833         render();
834
835         glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
836         verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
837
838         return STOP;
839 }
840
841 // Test description:
842 // - Attach texture containing solid color to framebuffer.
843 // - Create one 2D texture for sampler with a grid pattern
844 // - Draw full screen quad covering the entire viewport.
845 // - Sum color values taken from framebuffer texture and sampled texture
846 // - Compare resulting surface with reference.
847
848 class TexelFetchTestCase : public FramebufferFetchTestCase
849 {
850 public:
851                                                 TexelFetchTestCase              (Context& context, const char* name, const char* desc, deUint32 format);
852                                                 ~TexelFetchTestCase             (void) {}
853
854         IterateResult           iterate                                 (void);
855
856 private:
857         glu::ProgramSources genShaderSources            (void);
858         tcu::TextureLevel       genReferenceTexture             (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor);
859         void                            genSamplerTexture               (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd);
860
861         GLuint                          m_samplerTexture;
862 };
863
864 TexelFetchTestCase::TexelFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
865         : FramebufferFetchTestCase(context, name, desc, format)
866         , m_samplerTexture(0)
867 {
868 }
869
870 void TexelFetchTestCase::genSamplerTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd)
871 {
872         tcu::TextureLevel       data    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
873
874         m_gl.activeTexture(GL_TEXTURE1);
875
876         m_gl.genTextures(1, &m_samplerTexture);
877         m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
878         m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
879         m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
880
881         tcu::fillWithGrid(data.getAccess(), 8, colorEven, colorOdd);
882
883         m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
884         m_gl.bindTexture(GL_TEXTURE_2D, 0);
885
886         const GLuint samplerLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_sampler");
887         m_gl.uniform1i(samplerLocation, 1);
888
889         GLU_EXPECT_NO_ERROR(m_gl.getError(), "genSamplerTexture()");
890 }
891
892 glu::ProgramSources TexelFetchTestCase::genShaderSources (void)
893 {
894         const string            vecType = getColorOutputType(m_texFmt);
895         std::ostringstream      fragShaderSource;
896
897         fragShaderSource        << "#version 310 es\n"
898                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
899                                                 << "layout(location = 0) inout highp " << vecType << " o_color;\n"
900                                                 << "\n"
901                                                 << "uniform sampler2D u_sampler;\n"
902                                                 << "void main (void)\n"
903                                                 << "{\n"
904                                                 << "    o_color += texelFetch(u_sampler, ivec2(gl_FragCoord), 0);\n"
905                                                 << "}\n";
906
907         return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
908 }
909
910 tcu::TextureLevel TexelFetchTestCase::genReferenceTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor)
911 {
912         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
913         tcu::fillWithGrid(reference.getAccess(), 8, colorEven + fbColor, colorOdd + fbColor);
914
915         return reference;
916 }
917
918 TexelFetchTestCase::IterateResult TexelFetchTestCase::iterate (void)
919 {
920         const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));
921         const tcu::Vec4         colorEven               = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f));
922         const tcu::Vec4         colorOdd                = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));
923
924         genSamplerTexture(colorEven, colorOdd);
925         tcu::TextureLevel       reference               = genReferenceTexture(colorEven, colorOdd, fbColor);
926         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
927
928         genFramebufferWithTexture(fbColor);
929         render();
930
931         glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
932         verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
933
934         // cleanup
935         m_gl.deleteTextures(1, &m_samplerTexture);
936
937         return STOP;
938 }
939
940 // Test description:
941 // - Attach texture containing solid color to framebuffer.
942 // - Draw full screen quad covering the entire viewport.
943 // - Multiple assignments are made to the output color for fragments on the right vertical half of the screen.
944 // - A single assignment is made to the output color for fragments on the left vertical centre of the screen.
945 // - Values are calculated using the sum of the passed in uniform color and the previous framebuffer color.
946 // - Compare resulting surface with reference.
947
948 class MultipleAssignmentTestCase : public FramebufferFetchTestCase
949 {
950 public:
951                                                 MultipleAssignmentTestCase              (Context& context, const char* name, const char* desc, deUint32 format);
952                                                 ~MultipleAssignmentTestCase             (void) {}
953
954         IterateResult           iterate                                                 (void);
955
956 private:
957         glu::ProgramSources genShaderSources                            (void);
958         tcu::TextureLevel       genReferenceTexture                             (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
959 };
960
961 MultipleAssignmentTestCase::MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format)
962         : FramebufferFetchTestCase(context, name, desc, format)
963 {
964 }
965
966 glu::ProgramSources MultipleAssignmentTestCase::genShaderSources (void)
967 {
968         const string            vecType = getColorOutputType(m_texFmt);
969         std::ostringstream      vertShaderSource;
970         std::ostringstream      fragShaderSource;
971
972         vertShaderSource        << "#version 310 es\n"
973                                                 << "in highp vec4 a_position;\n"
974                                                 << "out highp vec4 v_position;\n"
975                                                 << "\n"
976                                                 << "void main (void)\n"
977                                                 << "{\n"
978                                                 << "    gl_Position = a_position;\n"
979                                                 << "    v_position  = gl_Position;\n"
980                                                 << "}\n";
981
982         fragShaderSource        << "#version 310 es\n"
983                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
984                                                 << "in highp vec4 v_position;\n"
985                                                 << "layout(location = 0) inout highp " << vecType << " o_color;\n"
986                                                 << "uniform highp " << vecType << " u_color;\n"
987                                                 << "\n"
988                                                 << "void main (void)\n"
989                                                 << "{\n"
990                                                 << "    if (v_position.x > 0.0f)\n"
991                                                 << "            o_color += u_color;\n"
992                                                 << "\n"
993                                                 << "    o_color += u_color;\n"
994                                                 << "}\n";
995
996         return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
997 }
998
999 tcu::TextureLevel MultipleAssignmentTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
1000 {
1001         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
1002
1003         int     width   = reference.getAccess().getWidth();
1004         int     height  = reference.getAccess().getHeight();
1005         int     left    = width /2;
1006         int     top             = height/2;
1007
1008         tcu::Vec4 compositeColor(uniformColor * 2.0f);
1009
1010         tcu::clear(getSubregion(reference.getAccess(), left,            0,              0, width-left,  top,            1),     fbColor + compositeColor);
1011         tcu::clear(getSubregion(reference.getAccess(), 0,                       top,    0, left,                height-top,     1), fbColor + uniformColor);
1012         tcu::clear(getSubregion(reference.getAccess(), left,            top,    0, width-left,  height-top, 1), fbColor + compositeColor);
1013         tcu::clear(getSubregion(reference.getAccess(), 0,                       0,              0, left,                top,            1),     fbColor + uniformColor);
1014
1015         return reference;
1016 }
1017
1018 MultipleAssignmentTestCase::IterateResult MultipleAssignmentTestCase::iterate (void)
1019 {
1020         const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
1021         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.25f, 0.0f, 0.0f, 1.0f));
1022
1023         tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
1024         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
1025
1026         genFramebufferWithTexture(fbColor);
1027         genUniformColor(uniformColor);
1028         render();
1029
1030         glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
1031         verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
1032
1033         return STOP;
1034 }
1035
1036 // Test description:
1037 // - Attach texture containing grid pattern to framebuffer.
1038 // - Using framebuffer reads discard odd squares in the grid.
1039 // - The even squares framebuffer color is added to the passed in uniform color.
1040
1041 class FragmentDiscardTestCase : public FramebufferFetchTestCase
1042 {
1043 public:
1044                                                 FragmentDiscardTestCase         (Context& context, const char* name, const char* desc, deUint32 format);
1045                                                 ~FragmentDiscardTestCase        (void) {}
1046
1047         IterateResult           iterate                                         (void);
1048
1049 private:
1050         glu::ProgramSources genShaderSources                    (void);
1051         void                            genFramebufferWithGrid          (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
1052         tcu::TextureLevel       genReferenceTexture                     (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
1053 };
1054
1055 FragmentDiscardTestCase::FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1056         : FramebufferFetchTestCase(context, name, desc, format)
1057 {
1058 }
1059
1060 glu::ProgramSources FragmentDiscardTestCase::genShaderSources (void)
1061 {
1062         const string            vecType = getColorOutputType(m_texFmt);
1063         std::ostringstream      fragShaderSource;
1064
1065         fragShaderSource        << "#version 310 es\n"
1066                                                 << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
1067                                                 << "layout(location = 0) inout highp " << vecType << " o_color;\n"
1068                                                 << "uniform highp " << vecType << " u_color;\n"
1069                                                 << "\n"
1070                                                 << "void main (void)\n"
1071                                                 << "{\n"
1072                                                 << "    const highp float threshold = 0.0005f;\n"
1073                                                 << "    bool valuesEqual = all(lessThan(abs(o_color - u_color), vec4(threshold)));\n\n"
1074                                                 << "    if (valuesEqual)\n"
1075                                                 << "            o_color += u_color;\n"
1076                                                 << "    else\n"
1077                                                 << "            discard;\n"
1078                                                 << "}\n";
1079
1080         return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
1081 }
1082
1083 void FragmentDiscardTestCase::genFramebufferWithGrid (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
1084 {
1085         tcu::TextureLevel data  (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
1086
1087         m_gl.genFramebuffers(1, &m_framebuffer);
1088         m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
1089
1090         m_gl.genTextures(1, &m_texColorBuffer);
1091         m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
1092
1093         tcu::fillWithGrid(data.getAccess(), 8, fbColorEven, fbColorOdd);
1094
1095         m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
1096         m_gl.bindTexture(GL_TEXTURE_2D, 0);
1097
1098         m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
1099         TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
1100 }
1101
1102 tcu::TextureLevel FragmentDiscardTestCase::genReferenceTexture (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
1103 {
1104         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
1105         tcu::fillWithGrid(reference.getAccess(), 8, fbColorEven + fbColorEven, fbColorOdd);
1106
1107         return reference;
1108 }
1109
1110 FragmentDiscardTestCase::IterateResult FragmentDiscardTestCase::iterate (void)
1111 {
1112         const tcu::Vec4         fbColorEven             = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f));
1113         const tcu::Vec4         fbColorOdd              = scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
1114
1115         tcu::TextureLevel       reference               = genReferenceTexture(fbColorEven, fbColorOdd);
1116         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
1117         genFramebufferWithGrid(fbColorEven, fbColorOdd);
1118
1119         genUniformColor(fbColorEven);
1120         render();
1121
1122         glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
1123         verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
1124
1125         return STOP;
1126 }
1127
1128 // Test description:
1129 // - Create 2D texture array containing three mipmaps.
1130 // - Each mipmap level is assigned a different color.
1131 // - Attach single mipmap level to framebuffer and draw full screen quad.
1132 // - Sum framebuffer read color with passed in uniform color.
1133 // - Compare resulting surface with reference.
1134 // - Repeat for subsequent mipmap levels.
1135
1136 class TextureLevelTestCase : public FramebufferFetchTestCase
1137 {
1138 public:
1139                                                 TextureLevelTestCase                    (Context& context, const char* name, const char* desc, deUint32 format);
1140                                                 ~TextureLevelTestCase                   (void) {}
1141
1142         IterateResult           iterate                                                 (void);
1143
1144 private:
1145         void                            create2DTextureArrayMipMaps             (const vector<tcu::Vec4>& colors);
1146         tcu::TextureLevel       genReferenceTexture                             (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
1147         void                            genReferenceMipmap                              (const tcu::Vec4& color, tcu::TextureLevel& reference);
1148 };
1149
1150 TextureLevelTestCase::TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1151         : FramebufferFetchTestCase(context, name, desc, format)
1152 {
1153 }
1154
1155 void TextureLevelTestCase::create2DTextureArrayMipMaps (const vector<tcu::Vec4>& colors)
1156 {
1157         int                                             numLevels       = (int)colors.size();
1158         tcu::TextureLevel               levelData       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));
1159
1160         m_gl.genTextures(1, &m_texColorBuffer);
1161         m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);
1162
1163         m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, 0, m_transferFmt.format, m_transferFmt.dataType, DE_NULL);
1164         m_gl.generateMipmap(GL_TEXTURE_2D_ARRAY);
1165
1166         for (int level = 0; level < numLevels; level++)
1167         {
1168                 int             levelW          = de::max(1, VIEWPORT_WIDTH             >> level);
1169                 int             levelH          = de::max(1, VIEWPORT_HEIGHT    >> level);
1170
1171                 levelData.setSize(levelW, levelH, 1);
1172
1173                 clear(levelData.getAccess(), colors[level]);
1174                 m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, level, m_format, levelW, levelH, 1, 0, m_transferFmt.format, m_transferFmt.dataType, levelData.getAccess().getDataPtr());
1175         }
1176
1177         m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
1178         GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayMipMaps()");
1179 }
1180
1181 tcu::TextureLevel TextureLevelTestCase::genReferenceTexture (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
1182 {
1183         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level, 1);
1184
1185         genReferenceMipmap(colors[level] + uniformColor, reference);
1186
1187         return reference;
1188 }
1189
1190 void TextureLevelTestCase::genReferenceMipmap (const tcu::Vec4& color, tcu::TextureLevel& reference)
1191 {
1192         const int       width   = reference.getAccess().getWidth();
1193         const int       height  = reference.getAccess().getHeight();
1194         const int       left    = width  / 2;
1195         const int       top             = height / 2;
1196
1197         clear(getSubregion(reference.getAccess(), left,         0,              0, width-left,  top,            1),     color);
1198         clear(getSubregion(reference.getAccess(), 0,            top,    0, left,                height-top,     1), color);
1199         clear(getSubregion(reference.getAccess(), left,         top,    0, width-left,  height-top, 1), color);
1200         clear(getSubregion(reference.getAccess(), 0,            0,              0, left,                top,            1),     color);
1201 }
1202
1203 TextureLevelTestCase::IterateResult TextureLevelTestCase::iterate (void)
1204 {
1205         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f));
1206         vector<tcu::Vec4>       levelColors;
1207
1208         levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
1209         levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
1210         levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
1211
1212         m_gl.genFramebuffers(1, &m_framebuffer);
1213         m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
1214
1215         create2DTextureArrayMipMaps(levelColors);
1216
1217         // attach successive mipmap layers to framebuffer and render
1218         for (int level = 0; level < (int)levelColors.size(); ++level)
1219         {
1220                 std::ostringstream name, desc;
1221                 name << "Level "                << level;
1222                 desc << "Mipmap level " << level;
1223
1224                 const tcu::ScopedLogSection     section                 (m_testCtx.getLog(), name.str(), desc.str());
1225                 tcu::TextureLevel                       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH >> level, VIEWPORT_HEIGHT >> level);
1226                 tcu::TextureLevel                       reference               = genReferenceTexture(level, levelColors, uniformColor);
1227
1228                 m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, level, 0);
1229
1230                 genUniformColor(uniformColor);
1231                 render();
1232
1233                 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
1234                 verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
1235
1236                 if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
1237                         return STOP;
1238         }
1239
1240         return STOP;
1241 }
1242
1243 class TextureLayerTestCase : public FramebufferFetchTestCase
1244 {
1245 public:
1246                                                 TextureLayerTestCase            (Context& context, const char* name, const char* desc, deUint32 format);
1247                                                 ~TextureLayerTestCase           (void) {}
1248
1249         IterateResult           iterate                                         (void);
1250
1251 private:
1252         void                            create2DTextureArrayLayers      (const vector<tcu::Vec4>&  colors);
1253         tcu::TextureLevel       genReferenceTexture                     (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
1254 };
1255
1256 TextureLayerTestCase::TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1257         : FramebufferFetchTestCase(context, name, desc, format)
1258 {
1259 }
1260
1261 void TextureLayerTestCase::create2DTextureArrayLayers (const vector<tcu::Vec4>& colors)
1262 {
1263         int                                             numLayers       = (int)colors.size();
1264         tcu::TextureLevel               layerData       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));
1265
1266         m_gl.genTextures(1, &m_texColorBuffer);
1267         m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);
1268         m_gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);
1269         m_gl.bindImageTexture(0, m_texColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, m_format);
1270
1271         layerData.setSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);
1272
1273         for (int layer = 0; layer < numLayers; layer++)
1274         {
1275                 clear(layerData.getAccess(), colors[layer]);
1276                 m_gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, m_transferFmt.format, m_transferFmt.dataType, layerData.getAccess().getDataPtr());
1277         }
1278
1279         m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
1280         GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayLayers()");
1281 }
1282
1283 tcu::TextureLevel TextureLayerTestCase::genReferenceTexture (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
1284 {
1285         tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
1286         clear(reference.getAccess(), colors[layer] + uniformColor);
1287
1288         return reference;
1289 }
1290
1291 // Test description
1292 // - Create 2D texture array containing three layers.
1293 // - Each layer is assigned a different color.
1294 // - Attach single layer to framebuffer and draw full screen quad.
1295 // - Sum framebuffer read color with passed in uniform color.
1296 // - Compare resulting surface with reference.
1297 // - Repeat for subsequent texture layers.
1298
1299 TextureLayerTestCase::IterateResult TextureLayerTestCase::iterate (void)
1300 {
1301         const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
1302         tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
1303         vector<tcu::Vec4>       layerColors;
1304
1305         layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
1306         layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
1307         layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
1308
1309         m_gl.genFramebuffers(1, &m_framebuffer);
1310         m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
1311
1312         create2DTextureArrayLayers(layerColors);
1313
1314         for (int layer = 0; layer < (int)layerColors.size(); ++layer)
1315         {
1316                 std::ostringstream name, desc;
1317                 name << "Layer " << layer;
1318                 desc << "Layer " << layer;
1319
1320                 const tcu::ScopedLogSection section             (m_testCtx.getLog(), name.str(), desc.str());
1321                 tcu::TextureLevel                       reference       = genReferenceTexture(layer, layerColors, uniformColor);
1322
1323                 m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, 0, layer);
1324
1325                 genUniformColor(uniformColor);
1326                 render();
1327
1328                 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
1329                 verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
1330
1331                 if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
1332                         return STOP;
1333         }
1334
1335         return STOP;
1336 }
1337
1338 } // Anonymous
1339
1340 ShaderFramebufferFetchTests::ShaderFramebufferFetchTests (Context& context)
1341         : TestCaseGroup (context, "framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch tests")
1342 {
1343 }
1344
1345 ShaderFramebufferFetchTests::~ShaderFramebufferFetchTests (void)
1346 {
1347 }
1348
1349 void ShaderFramebufferFetchTests::init (void)
1350 {
1351         tcu::TestCaseGroup* const basicTestGroup                                = new tcu::TestCaseGroup(m_testCtx, "basic",                            "Basic framebuffer shader fetch tests");
1352         tcu::TestCaseGroup* const framebufferFormatTestGroup    = new tcu::TestCaseGroup(m_testCtx, "framebuffer_format",       "Texture render target formats tests");
1353
1354         // basic
1355         {
1356                 basicTestGroup->addChild(new TexelFetchTestCase                         (m_context,             "texel_fetch",                                  "Framebuffer fetches in conjunction with shader texel fetches",                 GL_RGBA8));
1357                 basicTestGroup->addChild(new LastFragDataTestCase                       (m_context,             "last_frag_data",                               "Framebuffer fetches with built-in fragment output of ES 2.0",                  GL_RGBA8));
1358                 basicTestGroup->addChild(new FragmentDiscardTestCase            (m_context,             "fragment_discard",                             "Framebuffer fetches in combination with fragment discards",                    GL_RGBA8));
1359                 basicTestGroup->addChild(new MultipleAssignmentTestCase         (m_context,             "multiple_assignment",                  "Multiple assignments to fragment color inout",                                                 GL_RGBA8));
1360                 basicTestGroup->addChild(new MultipleRenderTargetsTestCase      (m_context,             "multiple_render_targets",              "Framebuffer fetches used in combination with multiple render targets", GL_RGBA8));
1361                 basicTestGroup->addChild(new TextureLevelTestCase                       (m_context,             "framebuffer_texture_level",    "Framebuffer fetches with individual texture render target mipmaps",    GL_RGBA8));
1362                 basicTestGroup->addChild(new TextureLayerTestCase                       (m_context,             "framebuffer_texture_layer",    "Framebuffer fetches with individual texture render target layers",             GL_RGBA8));
1363         }
1364
1365         // framebuffer formats
1366         {
1367                 static const deUint32 colorFormats[] =
1368                 {
1369                         // RGBA formats
1370                         GL_RGBA32I,
1371                         GL_RGBA32UI,
1372                         GL_RGBA16I,
1373                         GL_RGBA16UI,
1374                         GL_RGBA8,
1375                         GL_RGBA8I,
1376                         GL_RGBA8UI,
1377                         GL_SRGB8_ALPHA8,
1378                         GL_RGB10_A2,
1379                         GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1,
1380
1381                         // RGB formats
1382                         GL_RGB8,
1383                         GL_RGB565,
1384
1385                         // RG formats
1386                         GL_RG32I,
1387                         GL_RG32UI,
1388                         GL_RG16I,
1389                         GL_RG16UI,
1390                         GL_RG8,
1391                         GL_RG8I,
1392                         GL_RG8UI,
1393
1394                         // R formats
1395                         GL_R32I,
1396                         GL_R32UI,
1397                         GL_R16I,
1398                         GL_R16UI,
1399                         GL_R8,
1400                         GL_R8I,
1401                         GL_R8UI,
1402
1403                         // GL_EXT_color_buffer_float
1404                         GL_RGBA32F,
1405                         GL_RGBA16F,
1406                         GL_R11F_G11F_B10F,
1407                         GL_RG32F,
1408                         GL_RG16F,
1409                         GL_R32F,
1410                         GL_R16F,
1411
1412                         // GL_EXT_color_buffer_half_float
1413                         GL_RGB16F
1414                 };
1415
1416                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1417                         framebufferFormatTestGroup->addChild(new TextureFormatTestCase(m_context, getFormatName(colorFormats[ndx]), "Framebuffer fetches from texture attachments with varying formats", colorFormats[ndx]));
1418         }
1419
1420         addChild(basicTestGroup);
1421         addChild(framebufferFormatTestGroup);
1422 }
1423
1424 } // Functional
1425 } // gles31
1426 } // deqp