Fix gl_FragData usage in draw_buffers test
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fShaderFragDataTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief GLSL ES 1.0 gl_FragData[] tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fShaderFragDataTests.hpp"
25
26 #include "glsShaderLibrary.hpp"
27
28 #include "gluRenderContext.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluDrawUtil.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluObjectWrapper.hpp"
33
34 #include "tcuRenderTarget.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuSurface.hpp"
38
39 #include "glwFunctions.hpp"
40 #include "glwEnums.hpp"
41
42 namespace deqp
43 {
44 namespace gles3
45 {
46 namespace Functional
47 {
48
49 using std::string;
50 using tcu::TestLog;
51
52 namespace
53 {
54
55 enum IndexExprType
56 {
57         INDEX_EXPR_STATIC       = 0,
58         INDEX_EXPR_UNIFORM,
59         INDEX_EXPR_DYNAMIC,
60
61         INDEX_EXPR_TYPE_LAST
62 };
63
64 static bool compareSingleColor (tcu::TestLog& log, const tcu::Surface& surface, tcu::RGBA expectedColor, tcu::RGBA threshold)
65 {
66         const int       maxPrints                       = 10;
67         int                     numFailedPixels         = 0;
68
69         log << TestLog::Message << "Expecting " << expectedColor << " with threshold " << threshold << TestLog::EndMessage;
70
71         for (int y = 0; y < surface.getHeight(); y++)
72         {
73                 for (int x = 0; x < surface.getWidth(); x++)
74                 {
75                         const tcu::RGBA         resultColor             = surface.getPixel(x, y);
76                         const bool                      isOk                    = compareThreshold(resultColor, expectedColor, threshold);
77
78                         if (!isOk)
79                         {
80                                 if (numFailedPixels < maxPrints)
81                                         log << TestLog::Message << "ERROR: Got " << resultColor << " at (" << x << ", " << y << ")!" << TestLog::EndMessage;
82                                 else if (numFailedPixels == maxPrints)
83                                         log << TestLog::Message << "..." << TestLog::EndMessage;
84
85                                 numFailedPixels += 1;
86                         }
87                 }
88         }
89
90         if (numFailedPixels > 0)
91         {
92                 log << TestLog::Message << "Found " << numFailedPixels << " invalid pixels, comparison FAILED!" << TestLog::EndMessage;
93                 log << TestLog::Image("ResultImage", "Result Image", surface);
94                 return false;
95         }
96         else
97         {
98                 log << TestLog::Message << "Image comparison passed." << TestLog::EndMessage;
99                 return true;
100         }
101 }
102
103 class FragDataIndexingCase : public TestCase
104 {
105 public:
106         FragDataIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType)
107                 : TestCase                      (context, name, description)
108                 , m_indexExprType       (indexExprType)
109         {
110         }
111
112         static glu::ProgramSources genSources (const IndexExprType indexExprType)
113         {
114                 const char* const       fragIndexExpr   = indexExprType == INDEX_EXPR_STATIC    ? "0"                           :
115                                                                                           indexExprType == INDEX_EXPR_UNIFORM   ? "u_index"                     :
116                                                                                           indexExprType == INDEX_EXPR_DYNAMIC   ? "int(v_index)"        : DE_NULL;
117                 glu::ProgramSources     sources;
118
119                 DE_ASSERT(fragIndexExpr);
120
121                 sources << glu::VertexSource(
122                         "attribute highp vec4 a_position;\n"
123                         "attribute highp float a_index;\n"
124                         "attribute highp vec4 a_color;\n"
125                         "varying mediump float v_index;\n"
126                         "varying mediump vec4 v_color;\n"
127                         "void main (void)\n"
128                         "{\n"
129                         "       gl_Position = a_position;\n"
130                         "       v_color = a_color;\n"
131                         "       v_index = a_index;\n"
132                         "}\n");
133
134                 sources << glu::FragmentSource(string(
135                         "varying mediump vec4 v_color;\n"
136                         "varying mediump float v_index;\n"
137                         "uniform mediump int u_index;\n"
138                         "void main (void)\n"
139                         "{\n"
140                         "       gl_FragData[") + fragIndexExpr + "] = v_color;\n"
141                         "}\n");
142
143                 return sources;
144         }
145
146         IterateResult iterate (void)
147         {
148                 const glu::RenderContext&               renderCtx               = m_context.getRenderContext();
149                 const glw::Functions&                   gl                              = renderCtx.getFunctions();
150                 const glu::ShaderProgram                program                 (renderCtx, genSources(m_indexExprType));
151                 const int                                               viewportW               = de::min(renderCtx.getRenderTarget().getWidth(), 128);
152                 const int                                               viewportH               = de::min(renderCtx.getRenderTarget().getHeight(), 128);
153
154                 const float positions[] =
155                 {
156                         -1.0f, -1.0f,
157                         +1.0f, -1.0f,
158                         -1.0f, +1.0f,
159                         +1.0f, +1.0f
160                 };
161                 const float colors[] =
162                 {
163                         0.0f, 1.0f, 0.0f, 1.0f,
164                         0.0f, 1.0f, 0.0f, 1.0f,
165                         0.0f, 1.0f, 0.0f, 1.0f,
166                         0.0f, 1.0f, 0.0f, 1.0f
167                 };
168                 const float             indexValues[]   = { 0.0f, 0.0f, 0.0f, 0.0f };
169                 const deUint8   indices[]               = { 0, 1, 2, 2, 1, 3 };
170
171                 const glu::VertexArrayBinding vertexArrays[] =
172                 {
173                         glu::va::Float("a_position",    2, 4, 0, &positions[0]),
174                         glu::va::Float("a_color",               4, 4, 0, &colors[0]),
175                         glu::va::Float("a_index",               1, 4, 0, &indexValues[0])
176                 };
177
178                 m_testCtx.getLog() << program;
179
180                 if (!program.isOk())
181                 {
182                         if (m_indexExprType == INDEX_EXPR_STATIC)
183                                 TCU_FAIL("Compile failed");
184                         else
185                                 throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported");
186                 }
187
188                 gl.clearColor   (1.0f, 0.0f, 0.0f, 1.0f);
189                 gl.clear                (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
190
191                 gl.viewport             (0, 0, viewportW, viewportH);
192                 gl.useProgram   (program.getProgram());
193                 gl.uniform1i    (gl.getUniformLocation(program.getProgram(), "u_index"), 0);
194
195                 glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
196                                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
197                 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
198
199                 {
200                         tcu::Surface            result          (viewportW, viewportH);
201                         const tcu::RGBA         threshold       = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
202                         bool                            isOk;
203
204                         glu::readPixels(renderCtx, 0, 0, result.getAccess());
205                         GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");
206
207                         isOk = compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold);
208
209                         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
210                                                                         isOk ? "Pass"                           : "Image comparison failed");
211                 }
212
213                 return STOP;
214         }
215
216 private:
217         const IndexExprType m_indexExprType;
218 };
219
220 class FragDataDrawBuffersCase : public TestCase
221 {
222 public:
223         FragDataDrawBuffersCase (Context& context)
224                 : TestCase(context, "draw_buffers", "gl_FragData[] and glDrawBuffers() interaction")
225         {
226         }
227
228         IterateResult iterate (void)
229         {
230                 const glu::RenderContext&               renderCtx               = m_context.getRenderContext();
231                 const glu::ShaderProgram                program                 (renderCtx, glu::ProgramSources()
232                                                                                                                         << glu::VertexSource(
233                                                                                                                                 "attribute highp vec4 a_position;\n"
234                                                                                                                                 "attribute highp vec4 a_color;\n"
235                                                                                                                                 "varying mediump vec4 v_color;\n"
236                                                                                                                                 "void main (void)\n"
237                                                                                                                                 "{\n"
238                                                                                                                                 "       gl_Position = a_position;\n"
239                                                                                                                                 "       v_color = a_color;\n"
240                                                                                                                                 "}\n")
241                                                                                                                         << glu::FragmentSource(
242                                                                                                                                 "varying mediump vec4 v_color;\n"
243                                                                                                                                 "uniform mediump int u_index;\n"
244                                                                                                                                 "void main (void)\n"
245                                                                                                                                 "{\n"
246                                                                                                                                 "       gl_FragData[u_index] = v_color;\n"
247                                                                                                                                 "}\n"));
248                 const glw::Functions&                   gl                              = renderCtx.getFunctions();
249                 const int                                               width                   = 128;
250                 const int                                               height                  = 128;
251                 const int                                               indexLoc                = program.isOk() ? gl.getUniformLocation(program.getProgram(), "u_index") : -1;
252                 const glu::Framebuffer                  fbo                             (renderCtx);
253                 const glu::Renderbuffer                 colorBuf0               (renderCtx);
254                 const glu::Renderbuffer                 colorBuf1               (renderCtx);
255
256                 const float positions[] =
257                 {
258                         -1.0f, -1.0f,
259                         +1.0f, -1.0f,
260                         -1.0f, +1.0f,
261                         +1.0f, +1.0f
262                 };
263                 const float colors[] =
264                 {
265                         0.0f, 1.0f, 0.0f, 1.0f,
266                         0.0f, 1.0f, 0.0f, 1.0f,
267                         0.0f, 1.0f, 0.0f, 1.0f,
268                         0.0f, 1.0f, 0.0f, 1.0f
269                 };
270                 const deUint8   indices[]               = { 0, 1, 2, 2, 1, 3 };
271
272                 const glu::VertexArrayBinding vertexArrays[] =
273                 {
274                         glu::va::Float("a_position",    2, 4, 0, &positions[0]),
275                         glu::va::Float("a_color",               4, 4, 0, &colors[0])
276                 };
277
278                 m_testCtx.getLog() << program;
279
280                 if (!program.isOk())
281                         throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported");
282
283                 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
284                 for (int ndx = 0; ndx < 2; ndx++)
285                 {
286                         const deUint32  rbo     = ndx == 0 ? *colorBuf0 : *colorBuf1;
287
288                         gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
289                         gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
290                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+ndx, GL_RENDERBUFFER, rbo);
291                 }
292                 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
293
294                 {
295                         const deUint32 drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
296                         gl.drawBuffers(DE_LENGTH_OF_ARRAY(drawBuffers), &drawBuffers[0]);
297                 }
298
299                 gl.viewport             (0, 0, width, height);
300                 gl.useProgram   (program.getProgram());
301
302                 GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
303
304                 bool                    allOk           = true;
305                 const tcu::RGBA threshold       = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
306
307                 for (int ndx = 0; ndx < 2; ndx++)
308                 {
309                         gl.clearBufferfv(GL_COLOR, 0, tcu::RGBA::red().toVec().getPtr());
310                         gl.clearBufferfv(GL_COLOR, 1, tcu::RGBA::red().toVec().getPtr());
311
312                         m_testCtx.getLog() << TestLog::Message << "Drawing to attachments " << ndx << TestLog::EndMessage;
313
314                         gl.uniform1i(indexLoc, ndx);
315                         glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
316                                           glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
317
318                         GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
319
320                         {
321                                 tcu::Surface result(width, height);
322
323                                 m_testCtx.getLog() << TestLog::Message << "Verifying attachment " << ndx << "..." << TestLog::EndMessage;
324
325                                 gl.readBuffer(GL_COLOR_ATTACHMENT0+ndx);
326                                 glu::readPixels(renderCtx, 0, 0, result.getAccess());
327                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");
328
329                                 if (!compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold))
330                                         allOk = false;
331                         }
332                 }
333
334                 m_testCtx.setTestResult(allOk ? QP_TEST_RESULT_PASS     : QP_TEST_RESULT_FAIL,
335                                                                 allOk ? "Pass"                          : "Image comparison failed");
336
337                 return STOP;
338         }
339 };
340
341 } // anonymous
342
343 ShaderFragDataTests::ShaderFragDataTests (Context& context)
344         : TestCaseGroup(context, "fragdata", "gl_FragData[] Tests")
345 {
346 }
347
348 ShaderFragDataTests::~ShaderFragDataTests (void)
349 {
350 }
351
352 void ShaderFragDataTests::init (void)
353 {
354         addChild(new FragDataIndexingCase               (m_context, "valid_static_index",       "Valid gl_FragData[] assignment using static index",    INDEX_EXPR_STATIC));
355         addChild(new FragDataIndexingCase               (m_context, "valid_uniform_index",      "Valid gl_FragData[] assignment using uniform index",   INDEX_EXPR_UNIFORM));
356         addChild(new FragDataIndexingCase               (m_context, "valid_dynamic_index",      "Valid gl_FragData[] assignment using dynamic index",   INDEX_EXPR_DYNAMIC));
357         addChild(new FragDataDrawBuffersCase    (m_context));
358
359         // Negative cases.
360         {
361                 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
362                 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/fragdata.test");
363
364                 for (std::vector<tcu::TestNode*>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++)
365                         addChild(*i);
366         }
367 }
368
369 } // Functional
370 } // gles3
371 } // deqp