xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fInternalFormatQueryTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 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 Internal format query tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fInternalFormatQueryTests.hpp"
25 #include "tcuTestLog.hpp"
26 #include "gluRenderContext.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "glwFunctions.hpp"
30 #include "glwEnums.hpp"
31 
32 namespace deqp
33 {
34 namespace gles31
35 {
36 namespace Functional
37 {
38 namespace
39 {
40 
41 class FormatSamplesCase : public TestCase
42 {
43 public:
44     enum FormatType
45     {
46         FORMAT_COLOR,
47         FORMAT_INT,
48         FORMAT_DEPTH_STENCIL
49     };
50 
51     FormatSamplesCase(Context &ctx, const char *name, const char *desc, glw::GLenum texTarget,
52                       glw::GLenum internalFormat, FormatType type);
53 
54 private:
55     void init(void);
56     IterateResult iterate(void);
57 
58     const glw::GLenum m_target;
59     const glw::GLenum m_internalFormat;
60     const FormatType m_type;
61 };
62 
FormatSamplesCase(Context & ctx,const char * name,const char * desc,glw::GLenum target,glw::GLenum internalFormat,FormatType type)63 FormatSamplesCase::FormatSamplesCase(Context &ctx, const char *name, const char *desc, glw::GLenum target,
64                                      glw::GLenum internalFormat, FormatType type)
65     : TestCase(ctx, name, desc)
66     , m_target(target)
67     , m_internalFormat(internalFormat)
68     , m_type(type)
69 {
70     DE_ASSERT(m_target == GL_TEXTURE_2D_MULTISAMPLE || m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
71               m_target == GL_RENDERBUFFER);
72 }
73 
init(void)74 void FormatSamplesCase::init(void)
75 {
76     const bool isTextureTarget =
77         (m_target == GL_TEXTURE_2D_MULTISAMPLE) || (m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
78     auto ctxType            = m_context.getRenderContext().getType();
79     const bool isES32orGL45 = glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
80                               glu::contextSupports(ctxType, glu::ApiType::core(4, 5));
81 
82     if (!isES32orGL45 && m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY &&
83         !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
84         TCU_THROW(NotSupportedError, "Test requires OES_texture_storage_multisample_2d_array extension or a context "
85                                      "version equal or higher than 3.2");
86 
87     // stencil8 textures are not supported without GL_OES_texture_stencil8 extension
88     if (!isES32orGL45 && isTextureTarget && m_internalFormat == GL_STENCIL_INDEX8 &&
89         !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_stencil8"))
90         TCU_THROW(NotSupportedError,
91                   "Test requires GL_OES_texture_stencil8 extension or a context version equal or higher than 3.2");
92 }
93 
iterate(void)94 FormatSamplesCase::IterateResult FormatSamplesCase::iterate(void)
95 {
96     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
97     bool isFloatFormat         = false;
98     bool error                 = false;
99     glw::GLint maxSamples      = 0;
100     glw::GLint numSampleCounts = 0;
101     auto ctxType               = m_context.getRenderContext().getType();
102     const bool isES32orGL45    = glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
103                               glu::contextSupports(ctxType, glu::ApiType::core(4, 5));
104 
105     if (!isES32orGL45)
106     {
107         if (m_internalFormat == GL_RGBA16F || m_internalFormat == GL_R32F || m_internalFormat == GL_RG32F ||
108             m_internalFormat == GL_RGBA32F || m_internalFormat == GL_R16F || m_internalFormat == GL_RG16F ||
109             m_internalFormat == GL_R11F_G11F_B10F)
110         {
111             TCU_THROW(NotSupportedError, "The internal format is not supported in a context lower than 3.2");
112         }
113     }
114     else if (m_internalFormat == GL_RGBA16F || m_internalFormat == GL_R32F || m_internalFormat == GL_RG32F ||
115              m_internalFormat == GL_RGBA32F)
116     {
117         isFloatFormat = true;
118     }
119 
120     // Lowest limit
121     {
122         const glw::GLenum samplesEnum = (m_type == FORMAT_COLOR) ? (GL_MAX_COLOR_TEXTURE_SAMPLES) :
123                                         (m_type == FORMAT_INT)   ? (GL_MAX_INTEGER_SAMPLES) :
124                                                                    (GL_MAX_DEPTH_TEXTURE_SAMPLES);
125         m_testCtx.getLog() << tcu::TestLog::Message << "Format must support sample count of "
126                            << glu::getGettableStateStr(samplesEnum) << tcu::TestLog::EndMessage;
127 
128         gl.getIntegerv(samplesEnum, &maxSamples);
129         GLU_EXPECT_NO_ERROR(gl.getError(), "get MAX_*_SAMPLES");
130 
131         m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(samplesEnum) << " = " << maxSamples
132                            << tcu::TestLog::EndMessage;
133 
134         if (maxSamples < 1)
135         {
136             m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: minimum value of "
137                                << glu::getGettableStateStr(samplesEnum) << " is 1" << tcu::TestLog::EndMessage;
138             error = true;
139         }
140     }
141 
142     // Number of sample counts
143     {
144         gl.getInternalformativ(m_target, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
145         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
146 
147         m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_SAMPLE_COUNTS = " << numSampleCounts
148                            << tcu::TestLog::EndMessage;
149 
150         if (!isFloatFormat)
151         {
152             if (numSampleCounts < 1)
153             {
154                 m_testCtx.getLog()
155                     << tcu::TestLog::Message
156                     << "ERROR: Format MUST support some multisample configuration, got GL_NUM_SAMPLE_COUNTS = "
157                     << numSampleCounts << tcu::TestLog::EndMessage;
158                 error = true;
159             }
160         }
161     }
162 
163     // Sample counts
164     {
165         tcu::MessageBuilder samplesMsg(&m_testCtx.getLog());
166         std::vector<glw::GLint> samples(numSampleCounts > 0 ? numSampleCounts : 1);
167 
168         if (numSampleCounts > 0 || isFloatFormat)
169         {
170             gl.getInternalformativ(m_target, m_internalFormat, GL_SAMPLES, numSampleCounts, &samples[0]);
171             GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
172         }
173         else
174             TCU_FAIL("glGetInternalFormativ() reported 0 supported sample counts");
175 
176         // make a pretty log
177 
178         samplesMsg << "GL_SAMPLES = [";
179         for (size_t ndx = 0; ndx < samples.size(); ++ndx)
180         {
181             if (ndx)
182                 samplesMsg << ", ";
183             samplesMsg << samples[ndx];
184         }
185         samplesMsg << "]" << tcu::TestLog::EndMessage;
186 
187         // Samples are in order
188         for (size_t ndx = 1; ndx < samples.size(); ++ndx)
189         {
190             if (samples[ndx - 1] <= samples[ndx])
191             {
192                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Samples must be ordered descending."
193                                    << tcu::TestLog::EndMessage;
194                 error = true;
195                 break;
196             }
197         }
198 
199         // samples are positive
200         for (size_t ndx = 1; ndx < samples.size(); ++ndx)
201         {
202             if (samples[ndx - 1] <= 0)
203             {
204                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Only positive SAMPLES allowed."
205                                    << tcu::TestLog::EndMessage;
206                 error = true;
207                 break;
208             }
209         }
210 
211         // maxSamples must be supported
212         if (!isFloatFormat)
213         {
214             if (samples[0] < maxSamples)
215             {
216                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: MAX_*_SAMPLES must be supported."
217                                    << tcu::TestLog::EndMessage;
218                 error = true;
219             }
220         }
221     }
222 
223     // Result
224     if (!error)
225         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
226     else
227         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value");
228 
229     return STOP;
230 }
231 
232 class NumSampleCountsBufferCase : public TestCase
233 {
234 public:
235     NumSampleCountsBufferCase(Context &ctx, const char *name, const char *desc);
236 
237 private:
238     IterateResult iterate(void);
239 };
240 
NumSampleCountsBufferCase(Context & ctx,const char * name,const char * desc)241 NumSampleCountsBufferCase::NumSampleCountsBufferCase(Context &ctx, const char *name, const char *desc)
242     : TestCase(ctx, name, desc)
243 {
244 }
245 
iterate(void)246 NumSampleCountsBufferCase::IterateResult NumSampleCountsBufferCase::iterate(void)
247 {
248     const glw::GLint defaultValue = -123; // queries always return positive values
249     const glw::Functions &gl      = m_context.getRenderContext().getFunctions();
250     bool error                    = false;
251 
252     // Query to larger buffer
253     {
254         glw::GLint buffer[2] = {defaultValue, defaultValue};
255 
256         m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_NUM_SAMPLE_COUNTS to larger-than-needed buffer."
257                            << tcu::TestLog::EndMessage;
258         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 2, buffer);
259         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
260 
261         if (buffer[1] != defaultValue)
262         {
263             m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: trailing values were modified."
264                                << tcu::TestLog::EndMessage;
265             error = true;
266         }
267     }
268 
269     // Query to empty buffer
270     {
271         glw::GLint buffer[1] = {defaultValue};
272 
273         m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_NUM_SAMPLE_COUNTS to zero-sized buffer."
274                            << tcu::TestLog::EndMessage;
275         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 0, buffer);
276         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
277 
278         if (buffer[0] != defaultValue)
279         {
280             m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds."
281                                << tcu::TestLog::EndMessage;
282             error = true;
283         }
284     }
285 
286     // Result
287     if (!error)
288         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
289     else
290         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected buffer modification");
291 
292     return STOP;
293 }
294 
295 class SamplesBufferCase : public TestCase
296 {
297 public:
298     SamplesBufferCase(Context &ctx, const char *name, const char *desc);
299 
300 private:
301     IterateResult iterate(void);
302 };
303 
SamplesBufferCase(Context & ctx,const char * name,const char * desc)304 SamplesBufferCase::SamplesBufferCase(Context &ctx, const char *name, const char *desc) : TestCase(ctx, name, desc)
305 {
306 }
307 
iterate(void)308 SamplesBufferCase::IterateResult SamplesBufferCase::iterate(void)
309 {
310     const glw::GLint defaultValue = -123; // queries always return positive values
311     const glw::Functions &gl      = m_context.getRenderContext().getFunctions();
312     bool error                    = false;
313 
314     glw::GLint numSampleCounts = 0;
315 
316     // Number of sample counts
317     {
318         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
319         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
320 
321         m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_SAMPLE_COUNTS = " << numSampleCounts
322                            << tcu::TestLog::EndMessage;
323     }
324 
325     if (numSampleCounts < 1)
326     {
327         m_testCtx.getLog() << tcu::TestLog::Message
328                            << "ERROR: Format MUST support some multisample configuration, got GL_NUM_SAMPLE_COUNTS = "
329                            << numSampleCounts << tcu::TestLog::EndMessage;
330         error = true;
331     }
332     else
333     {
334         // Query to larger buffer
335         {
336             std::vector<glw::GLint> buffer(numSampleCounts + 1, defaultValue);
337 
338             m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to larger-than-needed buffer."
339                                << tcu::TestLog::EndMessage;
340             gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, (glw::GLsizei)buffer.size(),
341                                    &buffer[0]);
342             GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
343 
344             if (buffer.back() != defaultValue)
345             {
346                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: trailing value was modified."
347                                    << tcu::TestLog::EndMessage;
348                 error = true;
349             }
350         }
351 
352         // Query to smaller buffer
353         if (numSampleCounts > 2)
354         {
355             glw::GLint buffer[3] = {defaultValue, defaultValue, defaultValue};
356 
357             m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to buffer with bufSize=2."
358                                << tcu::TestLog::EndMessage;
359             gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 2, buffer);
360             GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
361 
362             if (buffer[2] != defaultValue)
363             {
364                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds."
365                                    << tcu::TestLog::EndMessage;
366                 error = true;
367             }
368         }
369 
370         // Query to empty buffer
371         {
372             glw::GLint buffer[1] = {defaultValue};
373 
374             m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to zero-sized buffer."
375                                << tcu::TestLog::EndMessage;
376             gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 0, buffer);
377             GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
378 
379             if (buffer[0] != defaultValue)
380             {
381                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds."
382                                    << tcu::TestLog::EndMessage;
383                 error = true;
384             }
385         }
386     }
387 
388     // Result
389     if (!error)
390         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
391     else
392         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected buffer modification");
393 
394     return STOP;
395 }
396 
397 } // namespace
398 
InternalFormatQueryTests(Context & context)399 InternalFormatQueryTests::InternalFormatQueryTests(Context &context)
400     : TestCaseGroup(context, "internal_format", "Internal format queries")
401 {
402 }
403 
~InternalFormatQueryTests(void)404 InternalFormatQueryTests::~InternalFormatQueryTests(void)
405 {
406 }
407 
init(void)408 void InternalFormatQueryTests::init(void)
409 {
410     static const struct InternalFormat
411     {
412         const char *name;
413         glw::GLenum format;
414         FormatSamplesCase::FormatType type;
415     } internalFormats[] = {
416         // color renderable
417         {"r8", GL_R8, FormatSamplesCase::FORMAT_COLOR},
418         {"rg8", GL_RG8, FormatSamplesCase::FORMAT_COLOR},
419         {"rgb8", GL_RGB8, FormatSamplesCase::FORMAT_COLOR},
420         {"rgb565", GL_RGB565, FormatSamplesCase::FORMAT_COLOR},
421         {"rgba4", GL_RGBA4, FormatSamplesCase::FORMAT_COLOR},
422         {"rgb5_a1", GL_RGB5_A1, FormatSamplesCase::FORMAT_COLOR},
423         {"rgba8", GL_RGBA8, FormatSamplesCase::FORMAT_COLOR},
424         {"rgb10_a2", GL_RGB10_A2, FormatSamplesCase::FORMAT_COLOR},
425         {"rgb10_a2ui", GL_RGB10_A2UI, FormatSamplesCase::FORMAT_INT},
426         {"srgb8_alpha8", GL_SRGB8_ALPHA8, FormatSamplesCase::FORMAT_COLOR},
427         {"r8i", GL_R8I, FormatSamplesCase::FORMAT_INT},
428         {"r8ui", GL_R8UI, FormatSamplesCase::FORMAT_INT},
429         {"r16i", GL_R16I, FormatSamplesCase::FORMAT_INT},
430         {"r16ui", GL_R16UI, FormatSamplesCase::FORMAT_INT},
431         {"r32i", GL_R32I, FormatSamplesCase::FORMAT_INT},
432         {"r32ui", GL_R32UI, FormatSamplesCase::FORMAT_INT},
433         {"rg8i", GL_RG8I, FormatSamplesCase::FORMAT_INT},
434         {"rg8ui", GL_RG8UI, FormatSamplesCase::FORMAT_INT},
435         {"rg16i", GL_RG16I, FormatSamplesCase::FORMAT_INT},
436         {"rg16ui", GL_RG16UI, FormatSamplesCase::FORMAT_INT},
437         {"rg32i", GL_RG32I, FormatSamplesCase::FORMAT_INT},
438         {"rg32ui", GL_RG32UI, FormatSamplesCase::FORMAT_INT},
439         {"rgba8i", GL_RGBA8I, FormatSamplesCase::FORMAT_INT},
440         {"rgba8ui", GL_RGBA8UI, FormatSamplesCase::FORMAT_INT},
441         {"rgba16i", GL_RGBA16I, FormatSamplesCase::FORMAT_INT},
442         {"rgba16ui", GL_RGBA16UI, FormatSamplesCase::FORMAT_INT},
443         {"rgba32i", GL_RGBA32I, FormatSamplesCase::FORMAT_INT},
444         {"rgba32ui", GL_RGBA32UI, FormatSamplesCase::FORMAT_INT},
445 
446         // float formats
447         {"r16f", GL_R16F, FormatSamplesCase::FORMAT_COLOR},
448         {"rg16f", GL_RG16F, FormatSamplesCase::FORMAT_COLOR},
449         {"rgba16f", GL_RGBA16F, FormatSamplesCase::FORMAT_COLOR},
450         {"r32f", GL_R32F, FormatSamplesCase::FORMAT_INT},
451         {"rg32f", GL_RG32F, FormatSamplesCase::FORMAT_INT},
452         {"rgba32f", GL_RGBA32F, FormatSamplesCase::FORMAT_INT},
453         {"r11f_g11f_b10f", GL_R11F_G11F_B10F, FormatSamplesCase::FORMAT_COLOR},
454 
455         // depth renderable
456         {"depth_component16", GL_DEPTH_COMPONENT16, FormatSamplesCase::FORMAT_DEPTH_STENCIL},
457         {"depth_component24", GL_DEPTH_COMPONENT24, FormatSamplesCase::FORMAT_DEPTH_STENCIL},
458         {"depth_component32f", GL_DEPTH_COMPONENT32F, FormatSamplesCase::FORMAT_DEPTH_STENCIL},
459         {"depth24_stencil8", GL_DEPTH24_STENCIL8, FormatSamplesCase::FORMAT_DEPTH_STENCIL},
460         {"depth32f_stencil8", GL_DEPTH32F_STENCIL8, FormatSamplesCase::FORMAT_DEPTH_STENCIL},
461 
462         // stencil renderable
463         {"stencil_index8", GL_STENCIL_INDEX8, FormatSamplesCase::FORMAT_DEPTH_STENCIL}
464         // DEPTH24_STENCIL8,  duplicate
465         // DEPTH32F_STENCIL8  duplicate
466     };
467 
468     static const struct
469     {
470         const char *name;
471         uint32_t target;
472     } textureTargets[] = {
473         {"renderbuffer", GL_RENDERBUFFER},
474         {"texture_2d_multisample", GL_TEXTURE_2D_MULTISAMPLE},
475         {"texture_2d_multisample_array", GL_TEXTURE_2D_MULTISAMPLE_ARRAY},
476     };
477 
478     for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(textureTargets); ++groupNdx)
479     {
480         tcu::TestCaseGroup *const group =
481             new tcu::TestCaseGroup(m_testCtx, textureTargets[groupNdx].name,
482                                    glu::getInternalFormatTargetName(textureTargets[groupNdx].target));
483         const glw::GLenum texTarget = textureTargets[groupNdx].target;
484 
485         addChild(group);
486 
487         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(internalFormats); ++caseNdx)
488         {
489             const std::string name = std::string(internalFormats[caseNdx].name) + "_samples";
490             const std::string desc = std::string("Verify GL_SAMPLES of ") + internalFormats[caseNdx].name;
491 
492             group->addChild(new FormatSamplesCase(m_context, name.c_str(), desc.c_str(), texTarget,
493                                                   internalFormats[caseNdx].format, internalFormats[caseNdx].type));
494         }
495     }
496 
497     // Check buffer sizes are honored
498     {
499         tcu::TestCaseGroup *const group =
500             new tcu::TestCaseGroup(m_testCtx, "partial_query", "Query data to too short a buffer");
501 
502         addChild(group);
503 
504         group->addChild(new NumSampleCountsBufferCase(m_context, "num_sample_counts",
505                                                       "Query GL_NUM_SAMPLE_COUNTS to too short a buffer"));
506         group->addChild(new SamplesBufferCase(m_context, "samples", "Query GL_SAMPLES to too short a buffer"));
507     }
508 }
509 
510 } // namespace Functional
511 } // namespace gles31
512 } // namespace deqp
513