xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2015 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 Program Pipeline State Query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fProgramPipelineStateQueryTests.hpp"
25 #include "es31fInfoLogQueryShared.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluCallLogWrapper.hpp"
29 #include "gluObjectWrapper.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "glwFunctions.hpp"
32 #include "glwEnums.hpp"
33 
34 namespace deqp
35 {
36 namespace gles31
37 {
38 namespace Functional
39 {
40 namespace
41 {
42 
43 using namespace gls::StateQueryUtil;
44 
getVerifierSuffix(QueryType type)45 static const char *getVerifierSuffix(QueryType type)
46 {
47     switch (type)
48     {
49     case QUERY_PIPELINE_INTEGER:
50         return "get_program_pipelineiv";
51     default:
52         DE_ASSERT(false);
53         return DE_NULL;
54     }
55 }
56 
57 static const char *const s_vertexSource =
58     "#version 310 es\n"
59     "out highp vec4 v_color;\n"
60     "void main()\n"
61     "{\n"
62     "    gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
63     "    v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
64     "}\n";
65 static const char *const s_fragmentSource = "#version 310 es\n"
66                                             "in highp vec4 v_color;\n"
67                                             "layout(location=0) out highp vec4 o_color;\n"
68                                             "void main()\n"
69                                             "{\n"
70                                             "    o_color = v_color;\n"
71                                             "}\n";
72 static const char *const s_computeSource  = "#version 310 es\n"
73                                             "layout (local_size_x = 1, local_size_y = 1) in;\n"
74                                             "layout(binding = 0) buffer Output\n"
75                                             "{\n"
76                                             "    highp float val;\n"
77                                             "} sb_out;\n"
78                                             "\n"
79                                             "void main (void)\n"
80                                             "{\n"
81                                             "    sb_out.val = 1.0;\n"
82                                             "}\n";
83 
84 class ActiveProgramCase : public TestCase
85 {
86 public:
87     ActiveProgramCase(Context &context, QueryType verifier, const char *name, const char *desc);
88     IterateResult iterate(void);
89 
90 private:
91     const QueryType m_verifier;
92 };
93 
ActiveProgramCase(Context & context,QueryType verifier,const char * name,const char * desc)94 ActiveProgramCase::ActiveProgramCase(Context &context, QueryType verifier, const char *name, const char *desc)
95     : TestCase(context, name, desc)
96     , m_verifier(verifier)
97 {
98 }
99 
iterate(void)100 ActiveProgramCase::IterateResult ActiveProgramCase::iterate(void)
101 {
102     const glu::ShaderProgram vtxProgram(m_context.getRenderContext(), glu::ProgramSources()
103                                                                           << glu::ProgramSeparable(true)
104                                                                           << glu::VertexSource(s_vertexSource));
105     const glu::ShaderProgram frgProgram(m_context.getRenderContext(), glu::ProgramSources()
106                                                                           << glu::ProgramSeparable(true)
107                                                                           << glu::FragmentSource(s_fragmentSource));
108     const glu::ProgramPipeline pipeline(m_context.getRenderContext());
109     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
110     tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
111 
112     {
113         const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
114         m_testCtx.getLog() << vtxProgram;
115     }
116 
117     {
118         const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
119         m_testCtx.getLog() << frgProgram;
120     }
121 
122     if (!vtxProgram.isOk() || !frgProgram.isOk())
123         throw tcu::TestError("failed to build program");
124 
125     gl.enableLogging(true);
126     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
127 
128     gl.glBindProgramPipeline(pipeline.getPipeline());
129     gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
130     gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
131     GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
132     gl.glBindProgramPipeline(0);
133     GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
134 
135     {
136         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
137         verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, 0, m_verifier);
138     }
139 
140     {
141         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set");
142 
143         gl.glActiveShaderProgram(pipeline.getPipeline(), frgProgram.getProgram());
144         GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
145         verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, (int)frgProgram.getProgram(),
146                                    m_verifier);
147     }
148 
149     result.setTestContextResult(m_testCtx);
150     return STOP;
151 }
152 
153 class PipelineProgramCase : public TestCase
154 {
155 public:
156     PipelineProgramCase(Context &context, QueryType verifier, const char *name, const char *desc, glw::GLenum stage);
157     IterateResult iterate(void);
158 
159 private:
160     const QueryType m_verifier;
161     const glw::GLenum m_targetStage;
162 };
163 
PipelineProgramCase(Context & context,QueryType verifier,const char * name,const char * desc,glw::GLenum stage)164 PipelineProgramCase::PipelineProgramCase(Context &context, QueryType verifier, const char *name, const char *desc,
165                                          glw::GLenum stage)
166     : TestCase(context, name, desc)
167     , m_verifier(verifier)
168     , m_targetStage(stage)
169 {
170 }
171 
iterate(void)172 PipelineProgramCase::IterateResult PipelineProgramCase::iterate(void)
173 {
174     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
175     tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
176     const int stageBit = (m_targetStage == GL_VERTEX_SHADER)   ? (GL_VERTEX_SHADER_BIT) :
177                          (m_targetStage == GL_FRAGMENT_SHADER) ? (GL_FRAGMENT_SHADER_BIT) :
178                                                                  (GL_COMPUTE_SHADER_BIT);
179     glu::ProgramSources sources;
180 
181     if (m_targetStage == GL_VERTEX_SHADER)
182         sources << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource);
183     else if (m_targetStage == GL_FRAGMENT_SHADER)
184         sources << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource);
185     else if (m_targetStage == GL_COMPUTE_SHADER)
186         sources << glu::ProgramSeparable(true) << glu::ComputeSource(s_computeSource);
187     else
188         DE_ASSERT(false);
189 
190     gl.enableLogging(true);
191 
192     {
193         glu::ShaderProgram program(m_context.getRenderContext(), sources);
194 
195         {
196             const tcu::ScopedLogSection section(m_testCtx.getLog(), "program", "Program");
197             m_testCtx.getLog() << program;
198         }
199 
200         if (!program.isOk())
201             throw tcu::TestError("failed to build program");
202 
203         {
204             const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
205             glu::ProgramPipeline pipeline(m_context.getRenderContext());
206 
207             gl.glBindProgramPipeline(pipeline.getPipeline());
208             GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline");
209 
210             verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, 0, m_verifier);
211         }
212 
213         {
214             const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set");
215             glu::ProgramPipeline pipeline(m_context.getRenderContext());
216 
217             gl.glBindProgramPipeline(pipeline.getPipeline());
218             gl.glUseProgramStages(pipeline.getPipeline(), stageBit, program.getProgram());
219             GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline");
220 
221             verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, program.getProgram(),
222                                        m_verifier);
223         }
224     }
225 
226     result.setTestContextResult(m_testCtx);
227     return STOP;
228 }
229 
230 class ValidateStatusCase : public TestCase
231 {
232 public:
233     ValidateStatusCase(Context &context, QueryType verifier, const char *name, const char *desc);
234     IterateResult iterate(void);
235 
236 private:
237     const QueryType m_verifier;
238 };
239 
ValidateStatusCase(Context & context,QueryType verifier,const char * name,const char * desc)240 ValidateStatusCase::ValidateStatusCase(Context &context, QueryType verifier, const char *name, const char *desc)
241     : TestCase(context, name, desc)
242     , m_verifier(verifier)
243 {
244 }
245 
iterate(void)246 ValidateStatusCase::IterateResult ValidateStatusCase::iterate(void)
247 {
248     glu::ShaderProgram vtxProgram(m_context.getRenderContext(), glu::ProgramSources()
249                                                                     << glu::ProgramSeparable(true)
250                                                                     << glu::VertexSource(s_vertexSource));
251     glu::ShaderProgram frgProgram(m_context.getRenderContext(), glu::ProgramSources()
252                                                                     << glu::ProgramSeparable(true)
253                                                                     << glu::FragmentSource(s_fragmentSource));
254     glu::ProgramPipeline pipeline(m_context.getRenderContext());
255     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
256     tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
257 
258     {
259         const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
260         m_testCtx.getLog() << vtxProgram;
261     }
262 
263     {
264         const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
265         m_testCtx.getLog() << frgProgram;
266     }
267 
268     if (!vtxProgram.isOk() || !frgProgram.isOk())
269         throw tcu::TestError("failed to build program");
270 
271     gl.enableLogging(true);
272 
273     gl.glBindProgramPipeline(pipeline.getPipeline());
274     gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
275     gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
276     GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
277     gl.glBindProgramPipeline(0);
278     GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
279 
280     {
281         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
282         verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, 0, m_verifier);
283     }
284 
285     {
286         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Validate");
287 
288         gl.glValidateProgramPipeline(pipeline.getPipeline());
289         GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
290         verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, GL_TRUE, m_verifier);
291     }
292 
293     result.setTestContextResult(m_testCtx);
294     return STOP;
295 }
296 
297 class InfoLogCase : public TestCase
298 {
299 public:
300     InfoLogCase(Context &context, const char *name, const char *desc);
301     IterateResult iterate(void);
302 };
303 
InfoLogCase(Context & context,const char * name,const char * desc)304 InfoLogCase::InfoLogCase(Context &context, const char *name, const char *desc) : TestCase(context, name, desc)
305 {
306 }
307 
iterate(void)308 InfoLogCase::IterateResult InfoLogCase::iterate(void)
309 {
310     using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
311 
312     static const char *const s_incompatibleFragmentSource = "#version 310 es\n"
313                                                             "in mediump vec2 v_colorB;\n"
314                                                             "in mediump vec2 v_colorC;\n"
315                                                             "layout(location=0) out highp vec4 o_color;\n"
316                                                             "void main()\n"
317                                                             "{\n"
318                                                             "    o_color = v_colorB.xxyy + v_colorC.yyxy;\n"
319                                                             "}\n";
320 
321     glu::ShaderProgram vtxProgram(m_context.getRenderContext(), glu::ProgramSources()
322                                                                     << glu::ProgramSeparable(true)
323                                                                     << glu::VertexSource(s_vertexSource));
324     glu::ShaderProgram frgProgram(m_context.getRenderContext(),
325                                   glu::ProgramSources() << glu::ProgramSeparable(true)
326                                                         << glu::FragmentSource(s_incompatibleFragmentSource));
327     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
328     tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
329 
330     {
331         const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
332         m_testCtx.getLog() << vtxProgram;
333     }
334 
335     {
336         const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
337         m_testCtx.getLog() << frgProgram;
338     }
339 
340     if (!vtxProgram.isOk() || !frgProgram.isOk())
341         throw tcu::TestError("failed to build program");
342 
343     gl.enableLogging(true);
344 
345     {
346         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
347         glu::ProgramPipeline pipeline(m_context.getRenderContext());
348         std::string buf(3, 'X');
349         int written = -1;
350 
351         verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_INFO_LOG_LENGTH, 0, QUERY_PIPELINE_INTEGER);
352 
353         gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 2, &written, &buf[0]);
354         GLU_EXPECT_NO_ERROR(gl.glGetError(), "query log");
355 
356         if (written == -1)
357             result.fail("'length' was not written to");
358         else if (written != 0)
359             result.fail("'length' was not 0");
360         else if (buf[0] != '\0')
361             result.fail("log was not 0-sized null-terminated string");
362         else if (buf[1] != 'X' || buf[2] != 'X')
363             result.fail("buffer after returned length modified");
364     }
365 
366     {
367         const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "ValidationFail", "Failed validation");
368         glu::ProgramPipeline pipeline(m_context.getRenderContext());
369         StateQueryMemoryWriteGuard<glw::GLint> logLen;
370 
371         gl.glBindProgramPipeline(pipeline.getPipeline());
372         gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
373         gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
374         GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
375 
376         gl.glBindProgramPipeline(0);
377         GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
378         gl.glValidateProgramPipeline(pipeline.getPipeline());
379         GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
380 
381         gl.glGetProgramPipelineiv(pipeline.getPipeline(), GL_INFO_LOG_LENGTH, &logLen);
382         GLU_EXPECT_NO_ERROR(gl.glGetError(), "get INFO_LOG_LENGTH");
383 
384         if (logLen.verifyValidity(result))
385             verifyInfoLogQuery(result, gl, logLen, pipeline.getPipeline(),
386                                &glu::CallLogWrapper::glGetProgramPipelineInfoLog, "glGetProgramPipelineInfoLog");
387     }
388 
389     result.setTestContextResult(m_testCtx);
390     return STOP;
391 }
392 
393 } // namespace
394 
ProgramPipelineStateQueryTests(Context & context)395 ProgramPipelineStateQueryTests::ProgramPipelineStateQueryTests(Context &context)
396     : TestCaseGroup(context, "program_pipeline", "Program Pipeline State Query tests")
397 {
398 }
399 
~ProgramPipelineStateQueryTests(void)400 ProgramPipelineStateQueryTests::~ProgramPipelineStateQueryTests(void)
401 {
402 }
403 
init(void)404 void ProgramPipelineStateQueryTests::init(void)
405 {
406     static const QueryType verifiers[] = {
407         QUERY_PIPELINE_INTEGER,
408     };
409 
410 #define FOR_EACH_VERIFIER(X)                                                                  \
411     do                                                                                        \
412     {                                                                                         \
413         for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx) \
414         {                                                                                     \
415             const char *verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);           \
416             const QueryType verifier   = verifiers[verifierNdx];                              \
417             this->addChild(X);                                                                \
418         }                                                                                     \
419     } while (0)
420 
421     FOR_EACH_VERIFIER(new ActiveProgramCase(
422         m_context, verifier, (std::string("active_program_") + verifierSuffix).c_str(), "Test ACTIVE_PROGRAM"));
423     FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier,
424                                               (std::string("vertex_shader_") + verifierSuffix).c_str(),
425                                               "Test VERTEX_SHADER", GL_VERTEX_SHADER));
426     FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier,
427                                               (std::string("fragment_shader_") + verifierSuffix).c_str(),
428                                               "Test FRAGMENT_SHADER", GL_FRAGMENT_SHADER));
429     FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier,
430                                               (std::string("compute_shader_") + verifierSuffix).c_str(),
431                                               "Test COMPUTE_SHADER", GL_COMPUTE_SHADER));
432     FOR_EACH_VERIFIER(new ValidateStatusCase(
433         m_context, verifier, (std::string("validate_status_") + verifierSuffix).c_str(), "Test VALIDATE_STATUS"));
434 
435 #undef FOR_EACH_VERIFIER
436 
437     this->addChild(new InfoLogCase(m_context, "info_log", "Test info log"));
438 }
439 
440 } // namespace Functional
441 } // namespace gles31
442 } // namespace deqp
443