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
checkExtensionSupport(Context & context,const char * extName)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
checkFramebufferFetchSupport(Context & context)68 static void checkFramebufferFetchSupport (Context& context)
69 {
70 checkExtensionSupport(context, "GL_EXT_shader_framebuffer_fetch");
71 }
72
isRequiredFormat(deUint32 format,glu::RenderContext & renderContext)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
getReadPixelFormat(const tcu::TextureFormat & format)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
getFixedPointFormatThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)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
getFloatULPThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)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
isAnyExtensionSupported(Context & context,const std::vector<std::string> & requiredExts)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
getColorOutputType(tcu::TextureFormat format)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
getEnablingExtensions(deUint32 format,glu::RenderContext & renderContext)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
checkFormatSupport(Context & context,deUint32 sizedFormat)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
scaleColorValue(tcu::TextureFormat format,const tcu::Vec4 & color)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
FramebufferFetchTestCase(Context & context,const char * name,const char * desc,deUint32 format)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
~FramebufferFetchTestCase(void)311 FramebufferFetchTestCase::~FramebufferFetchTestCase (void)
312 {
313 FramebufferFetchTestCase::deinit();
314 }
315
init(void)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
deinit(void)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
genPassThroughVertSource(void)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
genShaderSources(void)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
genFramebufferWithTexture(const tcu::Vec4 & color)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
genAttachementTexture(const tcu::Vec4 & color)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
verifyRenderbuffer(TestLog & log,const tcu::TextureFormat & format,const tcu::TextureLevel & reference,const tcu::TextureLevel & result)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
genUniformColor(const tcu::Vec4 & color)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
render(void)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);
~TextureFormatTestCase(void)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
TextureFormatTestCase(Context & context,const char * name,const char * desc,deUint32 format)560 TextureFormatTestCase::TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format)
561 : FramebufferFetchTestCase(context, name, desc, format)
562 {
563 }
564
genReferenceTexture(const tcu::Vec4 & fbColor,const tcu::Vec4 & uniformColor)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
iterate(void)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
MultipleRenderTargetsTestCase(Context & context,const char * name,const char * desc,deUint32 format)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
~MultipleRenderTargetsTestCase(void)652 MultipleRenderTargetsTestCase::~MultipleRenderTargetsTestCase (void)
653 {
654 MultipleRenderTargetsTestCase::deinit();
655 }
656
deinit(void)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
genFramebufferWithTextures(const vector<tcu::Vec4> & colors)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
genAttachmentTextures(const vector<tcu::Vec4> & colors)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
genReferenceTexture(const tcu::Vec4 & fbColor,const tcu::Vec4 & uniformColor)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
genShaderSources(void)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
iterate(void)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);
~LastFragDataTestCase(void)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
LastFragDataTestCase(Context & context,const char * name,const char * desc,deUint32 format)784 LastFragDataTestCase::LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format)
785 : FramebufferFetchTestCase(context, name, desc, format)
786 {
787 }
788
genShaderSources(void)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
genReferenceTexture(const tcu::Vec4 & fbColor,const tcu::Vec4 & uniformColor)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
iterate(void)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);
~TexelFetchTestCase(void)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
TexelFetchTestCase(Context & context,const char * name,const char * desc,deUint32 format)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
genSamplerTexture(const tcu::Vec4 & colorEven,const tcu::Vec4 & colorOdd)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
genShaderSources(void)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
genReferenceTexture(const tcu::Vec4 & colorEven,const tcu::Vec4 & colorOdd,const tcu::Vec4 & fbColor)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
iterate(void)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);
~MultipleAssignmentTestCase(void)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
MultipleAssignmentTestCase(Context & context,const char * name,const char * desc,deUint32 format)961 MultipleAssignmentTestCase::MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format)
962 : FramebufferFetchTestCase(context, name, desc, format)
963 {
964 }
965
genShaderSources(void)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
genReferenceTexture(const tcu::Vec4 & fbColor,const tcu::Vec4 & uniformColor)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
iterate(void)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);
~FragmentDiscardTestCase(void)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
FragmentDiscardTestCase(Context & context,const char * name,const char * desc,deUint32 format)1055 FragmentDiscardTestCase::FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1056 : FramebufferFetchTestCase(context, name, desc, format)
1057 {
1058 }
1059
genShaderSources(void)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
genFramebufferWithGrid(const tcu::Vec4 & fbColorEven,const tcu::Vec4 & fbColorOdd)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
genReferenceTexture(const tcu::Vec4 & fbColorEven,const tcu::Vec4 & fbColorOdd)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
iterate(void)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);
~TextureLevelTestCase(void)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
TextureLevelTestCase(Context & context,const char * name,const char * desc,deUint32 format)1150 TextureLevelTestCase::TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1151 : FramebufferFetchTestCase(context, name, desc, format)
1152 {
1153 }
1154
create2DTextureArrayMipMaps(const vector<tcu::Vec4> & colors)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
genReferenceTexture(int level,const vector<tcu::Vec4> & colors,const tcu::Vec4 & uniformColor)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
genReferenceMipmap(const tcu::Vec4 & color,tcu::TextureLevel & reference)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
iterate(void)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);
~TextureLayerTestCase(void)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
TextureLayerTestCase(Context & context,const char * name,const char * desc,deUint32 format)1256 TextureLayerTestCase::TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format)
1257 : FramebufferFetchTestCase(context, name, desc, format)
1258 {
1259 }
1260
create2DTextureArrayLayers(const vector<tcu::Vec4> & colors)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
genReferenceTexture(int layer,const vector<tcu::Vec4> & colors,const tcu::Vec4 & uniformColor)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
iterate(void)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
ShaderFramebufferFetchTests(Context & context)1340 ShaderFramebufferFetchTests::ShaderFramebufferFetchTests (Context& context)
1341 : TestCaseGroup (context, "framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch tests")
1342 {
1343 }
1344
~ShaderFramebufferFetchTests(void)1345 ShaderFramebufferFetchTests::~ShaderFramebufferFetchTests (void)
1346 {
1347 }
1348
init(void)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
1427