xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fShaderFragDataTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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 gl_FragData[] tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fShaderFragDataTests.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 gles2
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 
compareSingleColor(tcu::TestLog & log,const tcu::Surface & surface,tcu::RGBA expectedColor,tcu::RGBA threshold)64 static bool compareSingleColor(tcu::TestLog &log, const tcu::Surface &surface, tcu::RGBA expectedColor,
65                                tcu::RGBA threshold)
66 {
67     const int maxPrints = 10;
68     int numFailedPixels = 0;
69 
70     log << TestLog::Message << "Expecting " << expectedColor << " with threshold " << threshold << TestLog::EndMessage;
71 
72     for (int y = 0; y < surface.getHeight(); y++)
73     {
74         for (int x = 0; x < surface.getWidth(); x++)
75         {
76             const tcu::RGBA resultColor = surface.getPixel(x, y);
77             const bool isOk             = compareThreshold(resultColor, expectedColor, threshold);
78 
79             if (!isOk)
80             {
81                 if (numFailedPixels < maxPrints)
82                     log << TestLog::Message << "ERROR: Got " << resultColor << " at (" << x << ", " << y << ")!"
83                         << TestLog::EndMessage;
84                 else if (numFailedPixels == maxPrints)
85                     log << TestLog::Message << "..." << TestLog::EndMessage;
86 
87                 numFailedPixels += 1;
88             }
89         }
90     }
91 
92     if (numFailedPixels > 0)
93     {
94         log << TestLog::Message << "Found " << numFailedPixels << " invalid pixels, comparison FAILED!"
95             << TestLog::EndMessage;
96         log << TestLog::Image("ResultImage", "Result Image", surface);
97         return false;
98     }
99     else
100     {
101         log << TestLog::Message << "Image comparison passed." << TestLog::EndMessage;
102         return true;
103     }
104 }
105 
106 class FragDataIndexingCase : public TestCase
107 {
108 public:
FragDataIndexingCase(Context & context,const char * name,const char * description,IndexExprType indexExprType)109     FragDataIndexingCase(Context &context, const char *name, const char *description, IndexExprType indexExprType)
110         : TestCase(context, name, description)
111         , m_indexExprType(indexExprType)
112     {
113     }
114 
genSources(const IndexExprType indexExprType)115     static glu::ProgramSources genSources(const IndexExprType indexExprType)
116     {
117         const char *const fragIndexExpr = indexExprType == INDEX_EXPR_STATIC  ? "0" :
118                                           indexExprType == INDEX_EXPR_UNIFORM ? "u_index" :
119                                           indexExprType == INDEX_EXPR_DYNAMIC ? "int(v_index)" :
120                                                                                 DE_NULL;
121         glu::ProgramSources sources;
122 
123         DE_ASSERT(fragIndexExpr);
124 
125         sources << glu::VertexSource("attribute highp vec4 a_position;\n"
126                                      "attribute highp float a_index;\n"
127                                      "attribute highp vec4 a_color;\n"
128                                      "varying mediump float v_index;\n"
129                                      "varying mediump vec4 v_color;\n"
130                                      "void main (void)\n"
131                                      "{\n"
132                                      "    gl_Position = a_position;\n"
133                                      "    v_color = a_color;\n"
134                                      "    v_index = a_index;\n"
135                                      "}\n");
136 
137         sources << glu::FragmentSource(string("varying mediump vec4 v_color;\n"
138                                               "varying mediump float v_index;\n"
139                                               "uniform mediump int u_index;\n"
140                                               "void main (void)\n"
141                                               "{\n"
142                                               "    gl_FragData[") +
143                                        fragIndexExpr +
144                                        "] = v_color;\n"
145                                        "}\n");
146 
147         return sources;
148     }
149 
iterate(void)150     IterateResult iterate(void)
151     {
152         const glu::RenderContext &renderCtx = m_context.getRenderContext();
153         const glw::Functions &gl            = renderCtx.getFunctions();
154         const glu::ShaderProgram program(renderCtx, genSources(m_indexExprType));
155         const int viewportW = de::min(renderCtx.getRenderTarget().getWidth(), 128);
156         const int viewportH = de::min(renderCtx.getRenderTarget().getHeight(), 128);
157 
158         const float positions[]   = {-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f};
159         const float colors[]      = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
160                                      0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
161         const float indexValues[] = {0.0f, 0.0f, 0.0f, 0.0f};
162         const uint8_t indices[]   = {0, 1, 2, 2, 1, 3};
163 
164         const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 2, 4, 0, &positions[0]),
165                                                         glu::va::Float("a_color", 4, 4, 0, &colors[0]),
166                                                         glu::va::Float("a_index", 1, 4, 0, &indexValues[0])};
167 
168         m_testCtx.getLog() << program;
169 
170         if (!program.isOk())
171         {
172             if (m_indexExprType == INDEX_EXPR_STATIC)
173                 TCU_FAIL("Compile failed");
174             else
175                 throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported");
176         }
177 
178         gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
179         gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
180 
181         gl.viewport(0, 0, viewportW, viewportH);
182         gl.useProgram(program.getProgram());
183         gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_index"), 0);
184 
185         glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
186                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
187         GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
188 
189         {
190             tcu::Surface result(viewportW, viewportH);
191             const tcu::RGBA threshold =
192                 renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1, 1, 1, 1);
193             bool isOk;
194 
195             glu::readPixels(renderCtx, 0, 0, result.getAccess());
196             GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");
197 
198             isOk = compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold);
199 
200             m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
201                                     isOk ? "Pass" : "Image comparison failed");
202         }
203 
204         return STOP;
205     }
206 
207 private:
208     const IndexExprType m_indexExprType;
209 };
210 
211 } // namespace
212 
ShaderFragDataTests(Context & context)213 ShaderFragDataTests::ShaderFragDataTests(Context &context) : TestCaseGroup(context, "fragdata", "gl_FragData[] Tests")
214 {
215 }
216 
~ShaderFragDataTests(void)217 ShaderFragDataTests::~ShaderFragDataTests(void)
218 {
219 }
220 
init(void)221 void ShaderFragDataTests::init(void)
222 {
223     addChild(new FragDataIndexingCase(m_context, "valid_static_index",
224                                       "Valid gl_FragData[] assignment using static index", INDEX_EXPR_STATIC));
225     addChild(new FragDataIndexingCase(m_context, "valid_uniform_index",
226                                       "Valid gl_FragData[] assignment using uniform index", INDEX_EXPR_UNIFORM));
227     addChild(new FragDataIndexingCase(m_context, "valid_dynamic_index",
228                                       "Valid gl_FragData[] assignment using dynamic index", INDEX_EXPR_DYNAMIC));
229 
230     // Negative cases.
231     {
232         gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
233         std::vector<tcu::TestNode *> negativeCases = library.loadShaderFile("shaders/fragdata.test");
234 
235         for (std::vector<tcu::TestNode *>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++)
236             addChild(*i);
237     }
238 }
239 
240 } // namespace Functional
241 } // namespace gles2
242 } // namespace deqp
243