xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gles31/es31cShaderImageSizeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "es31cShaderImageSizeTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include <assert.h>
31 #include <cstdarg>
32 
33 namespace glcts
34 {
35 using namespace glw;
36 
37 namespace
38 {
39 typedef tcu::Vec2 vec2;
40 typedef tcu::Vec3 vec3;
41 typedef tcu::Vec4 vec4;
42 typedef tcu::IVec4 ivec4;
43 typedef tcu::UVec4 uvec4;
44 
45 const char *const kGLSLVer =
46     "#version 310 es\n" NL "precision highp float;" NL "precision highp int;" NL "precision highp image2D;" NL
47     "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL
48     "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL
49     "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL
50     "precision highp uimageCube;" NL "precision highp uimage2DArray;";
51 
52 class ShaderImageSizeBase : public glcts::SubcaseBase
53 {
54 public:
Title()55     virtual std::string Title()
56     {
57         return NL "";
58     }
Purpose()59     virtual std::string Purpose()
60     {
61         return NL "";
62     }
Method()63     virtual std::string Method()
64     {
65         return NL "";
66     }
PassCriteria()67     virtual std::string PassCriteria()
68     {
69         return NL "";
70     }
IsVSFSAvailable(int requiredVS,int requiredFS)71     bool IsVSFSAvailable(int requiredVS, int requiredFS)
72     {
73         GLint imagesVS, imagesFS;
74         glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
75         glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS);
76         if (imagesVS >= requiredVS && imagesFS >= requiredFS)
77             return true;
78         else
79         {
80             std::ostringstream reason;
81             reason << "Required " << requiredVS << " VS storage blocks but only " << imagesVS << " available."
82                    << std::endl
83                    << "Required " << requiredFS << " FS storage blocks but only " << imagesFS << " available."
84                    << std::endl;
85             OutputNotSupported(reason.str());
86             return false;
87         }
88     }
89 };
90 
91 template <typename T>
92 std::string ImageTypePrefix();
93 
94 template <>
ImageTypePrefix()95 std::string ImageTypePrefix<vec4>()
96 {
97     return "";
98 }
99 
100 template <>
ImageTypePrefix()101 std::string ImageTypePrefix<ivec4>()
102 {
103     return "i";
104 }
105 
106 template <>
ImageTypePrefix()107 std::string ImageTypePrefix<uvec4>()
108 {
109     return "u";
110 }
111 
112 template <typename T>
113 std::string ImageFormatPostfix();
114 
115 template <>
ImageFormatPostfix()116 std::string ImageFormatPostfix<vec4>()
117 {
118     return "f";
119 }
120 
121 template <>
ImageFormatPostfix()122 std::string ImageFormatPostfix<ivec4>()
123 {
124     return "i";
125 }
126 
127 template <>
ImageFormatPostfix()128 std::string ImageFormatPostfix<uvec4>()
129 {
130     return "ui";
131 }
132 
133 template <typename T>
134 GLenum TexInternalFormat();
135 
136 template <>
TexInternalFormat()137 GLenum TexInternalFormat<vec4>()
138 {
139     return GL_RGBA32F;
140 }
141 
142 template <>
TexInternalFormat()143 GLenum TexInternalFormat<ivec4>()
144 {
145     return GL_RGBA32I;
146 }
147 
148 template <>
TexInternalFormat()149 GLenum TexInternalFormat<uvec4>()
150 {
151     return GL_RGBA32UI;
152 }
153 
154 template <typename T>
155 GLenum TexType();
156 
157 template <typename T>
158 GLenum TexFormat();
159 
160 //=============================================================================
161 // ImageSizeMachine
162 //-----------------------------------------------------------------------------
163 class ImageSizeMachine : public glcts::GLWrapper
164 {
165     GLuint m_pipeline;
166     GLuint m_program[3];
167     GLuint m_vertex_array;
168     GLuint m_buffer;
169     bool pipeline;
170     GLuint m_xfb_id;
171 
CheckProgram(GLuint program)172     bool CheckProgram(GLuint program)
173     {
174         if (program == 0)
175             return true;
176         GLint status;
177         glGetProgramiv(program, GL_LINK_STATUS, &status);
178 
179         if (status == GL_FALSE)
180         {
181             GLint attached_shaders;
182             glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
183 
184             if (attached_shaders > 0)
185             {
186                 std::vector<GLuint> shaders(attached_shaders);
187                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
188 
189                 for (GLint i = 0; i < attached_shaders; ++i)
190                 {
191                     GLenum type;
192                     glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
193                     switch (type)
194                     {
195                     case GL_VERTEX_SHADER:
196                         m_context.getTestContext().getLog()
197                             << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
198                         break;
199                     case GL_FRAGMENT_SHADER:
200                         m_context.getTestContext().getLog()
201                             << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
202                         break;
203                     case GL_COMPUTE_SHADER:
204                         m_context.getTestContext().getLog()
205                             << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
206                         break;
207                     default:
208                         m_context.getTestContext().getLog()
209                             << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
210                         break;
211                     }
212 
213                     GLint length;
214                     glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
215                     if (length > 0)
216                     {
217                         std::vector<GLchar> source(length);
218                         glGetShaderSource(shaders[i], length, NULL, &source[0]);
219                         m_context.getTestContext().getLog()
220                             << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
221                     }
222                     glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
223                     if (length > 0)
224                     {
225                         std::vector<GLchar> log(length);
226                         glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
227                         m_context.getTestContext().getLog()
228                             << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
229                     }
230                 }
231             }
232             GLint length;
233             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
234             if (length > 0)
235             {
236                 std::vector<GLchar> log(length);
237                 glGetProgramInfoLog(program, length, NULL, &log[0]);
238                 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
239             }
240         }
241         return status == GL_TRUE ? true : false;
242     }
243 
CompileShader(GLuint shader)244     bool CompileShader(GLuint shader)
245     {
246         glCompileShader(shader);
247 
248         GLint status;
249         glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
250         if (status == GL_FALSE)
251         {
252             GLsizei length;
253             GLchar log[1024];
254             glGetShaderInfoLog(shader, sizeof(log), &length, log);
255             if (length > 1)
256             {
257                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
258                                                     << log << tcu::TestLog::EndMessage;
259             }
260             return false;
261         }
262         return true;
263     }
264 
LinkProgram(GLuint program)265     bool LinkProgram(GLuint program)
266     {
267         glLinkProgram(program);
268 
269         GLint status;
270         glGetProgramiv(program, GL_LINK_STATUS, &status);
271         if (status == GL_FALSE)
272         {
273             GLsizei length;
274             GLchar log[1024];
275             glGetProgramInfoLog(program, sizeof(log), &length, log);
276             if (length > 1)
277             {
278                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
279                                                     << log << tcu::TestLog::EndMessage;
280             }
281             return false;
282         }
283         return true;
284     }
285 
CreateComputeProgram(const std::string & cs)286     GLuint CreateComputeProgram(const std::string &cs)
287     {
288         const GLuint p = glCreateProgram();
289 
290         if (!cs.empty())
291         {
292             const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
293             glAttachShader(p, sh);
294             glDeleteShader(sh);
295             const char *const src[2] = {kGLSLVer, cs.c_str()};
296             glShaderSource(sh, 2, src, NULL);
297             if (!CompileShader(sh))
298             {
299                 m_context.getTestContext().getLog()
300                     << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
301                 return p;
302             }
303         }
304         if (!LinkProgram(p))
305         {
306             if (!cs.empty())
307                 m_context.getTestContext().getLog()
308                     << tcu::TestLog::Message << kGLSLVer << cs << tcu::TestLog::EndMessage;
309             return p;
310         }
311 
312         return p;
313     }
314 
BuildProgram(const char * src_vs,const char * src_fs,bool use_xfb,bool * result=NULL)315     GLuint BuildProgram(const char *src_vs, const char *src_fs, bool use_xfb, bool *result = NULL)
316     {
317         const GLuint p = glCreateProgram();
318 
319         if (src_vs)
320         {
321             GLuint sh = glCreateShader(GL_VERTEX_SHADER);
322             glAttachShader(p, sh);
323             glDeleteShader(sh);
324             const char *const src[2] = {kGLSLVer, src_vs};
325             glShaderSource(sh, 2, src, NULL);
326             if (!CompileShader(sh))
327             {
328                 m_context.getTestContext().getLog()
329                     << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
330                 if (result)
331                     *result = false;
332                 return p;
333             }
334         }
335         if (src_fs)
336         {
337             GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
338             glAttachShader(p, sh);
339             glDeleteShader(sh);
340             const char *const src[2] = {kGLSLVer, src_fs};
341             glShaderSource(sh, 2, src, NULL);
342             if (!CompileShader(sh))
343             {
344                 m_context.getTestContext().getLog()
345                     << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
346                 if (result)
347                     *result = false;
348                 return p;
349             }
350         }
351         if (use_xfb)
352             SetupTransformFeedback(p);
353         if (!LinkProgram(p))
354         {
355             if (src_vs)
356                 m_context.getTestContext().getLog()
357                     << tcu::TestLog::Message << kGLSLVer << src_vs << tcu::TestLog::EndMessage;
358             if (src_fs)
359                 m_context.getTestContext().getLog()
360                     << tcu::TestLog::Message << kGLSLVer << src_fs << tcu::TestLog::EndMessage;
361             if (result)
362                 *result = false;
363             return p;
364         }
365 
366         return p;
367     }
368 
SetupTransformFeedback(GLuint program)369     void SetupTransformFeedback(GLuint program)
370     {
371         const char *const varying_name = "count";
372         glTransformFeedbackVaryings(program, 1, &varying_name, GL_INTERLEAVED_ATTRIBS);
373     }
374 
Equal(const ivec4 & result,const ivec4 & expected)375     inline bool Equal(const ivec4 &result, const ivec4 &expected)
376     {
377         if (expected[0] != result[0])
378             return false;
379         if (expected[1] != result[1])
380             return false;
381         if (expected[2] != result[2])
382             return false;
383         if (expected[3] != result[3])
384             return false;
385         return true;
386     }
387 
388     template <typename T>
GenShader(int stage)389     std::string GenShader(int stage)
390     {
391         std::ostringstream os;
392         os << NL "#define KSIZE 4";
393         if (stage == 0)
394         { // VS uses transform feedback
395             os << NL "flat out ivec4 count[KSIZE];";
396         }
397         else
398         { // CS + FS use SSBO
399             os << NL "layout(std430) buffer OutputBuffer {" NL "  ivec4 count[KSIZE];" NL "};";
400         }
401         os << NL "layout(binding = 0, rgba32" << ImageFormatPostfix<T>() << ") readonly writeonly uniform highp "
402            << ImageTypePrefix<T>() << "image2D g_image_2d;" NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>()
403            << ") readonly writeonly uniform highp " << ImageTypePrefix<T>()
404            << "image3D g_image_3d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>()
405            << ") readonly writeonly uniform highp " << ImageTypePrefix<T>()
406            << "imageCube g_image_cube;" NL "layout(binding = 3, rgba32" << ImageFormatPostfix<T>()
407            << ") readonly writeonly uniform highp " << ImageTypePrefix<T>() << "image2DArray g_image_2d_array;";
408         if (stage == 0)
409         { // VS
410             os << NL "void main() {" NL "  int coord = gl_VertexID;" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0;" NL
411                      "#endif";
412         }
413         else if (stage == 4)
414         { // CS
415             os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL "  int coord = int(gl_GlobalInvocationID.x);";
416         }
417         else if (stage == 5)
418         { // FS
419             os << NL "uniform int fakePrimitiveID;" NL "void main() {" NL "  int coord = fakePrimitiveID;";
420         }
421         os << NL "  count[coord + 0] = ivec4(imageSize(g_image_2d), 0, 0);" NL
422                  "  count[coord + 1] = ivec4(imageSize(g_image_3d), 0);" NL
423                  "  count[coord + 2] = ivec4(imageSize(g_image_cube), 0, 0);" NL
424                  "  count[coord + 3] = ivec4(imageSize(g_image_2d_array), 0);" NL "}";
425         return os.str();
426     }
427 
428 public:
ImageSizeMachine()429     ImageSizeMachine() : pipeline(false)
430     {
431         if (pipeline)
432             glGenProgramPipelines(1, &m_pipeline);
433         memset(m_program, 0, sizeof(m_program));
434         glGenVertexArrays(1, &m_vertex_array);
435         glGenBuffers(1, &m_buffer);
436         glGenTransformFeedbacks(1, &m_xfb_id);
437     }
438 
~ImageSizeMachine()439     ~ImageSizeMachine()
440     {
441         if (pipeline)
442         {
443             glDeleteProgramPipelines(1, &m_pipeline);
444             for (int i = 0; i < 3; ++i)
445                 glDeleteProgram(m_program[i]);
446         }
447         else
448         {
449             glDeleteProgram(m_program[0]);
450         }
451         glDeleteVertexArrays(1, &m_vertex_array);
452         glDeleteBuffers(1, &m_buffer);
453         glDeleteTransformFeedbacks(1, &m_xfb_id);
454     }
455 
456     template <typename T>
Run(int stage,ivec4 expected_result[4])457     long Run(int stage, ivec4 expected_result[4])
458     {
459         const int kSize = 4;
460         if (stage == 0)
461         { // VS
462             glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
463             const char *const glsl_fs = NL "void main() {" NL "  discard;" NL "}";
464             std::string vs            = GenShader<T>(stage);
465             const char *const glsl_vs = vs.c_str();
466             if (pipeline)
467             {
468                 m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
469                 m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
470                 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
471                 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
472             }
473             else
474             {
475                 m_program[0] = BuildProgram(glsl_vs, glsl_fs, true);
476             }
477         }
478         else if (stage == 4)
479         { // CS
480             std::string cs            = GenShader<T>(stage);
481             const char *const glsl_cs = cs.c_str();
482             if (pipeline)
483             {
484                 m_program[0] = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
485                 glUseProgramStages(m_pipeline, GL_COMPUTE_SHADER_BIT, m_program[0]);
486             }
487             else
488             {
489                 m_program[0] = CreateComputeProgram(glsl_cs);
490             }
491         }
492         else if (stage == 5)
493         { // FS
494             const char *const glsl_vs =
495                 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL
496                    "#ifdef GL_ES" NL "  gl_PointSize = 1.0;" NL "#endif" NL "}";
497             std::string fs            = GenShader<T>(stage);
498             const char *const glsl_fs = fs.c_str();
499             if (pipeline)
500             {
501                 m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
502                 m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
503                 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
504                 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
505             }
506             else
507             {
508                 m_program[0] = BuildProgram(glsl_vs, glsl_fs, false);
509             }
510         }
511         if (!CheckProgram(m_program[0]))
512             return ERROR;
513         if (pipeline)
514             if (!CheckProgram(m_program[1]))
515                 return ERROR;
516 
517         ivec4 data[kSize];
518         for (int i = 0; i < kSize; ++i)
519             data[i] = ivec4(100000);
520 
521         GLenum output_buffer_type = (stage == 0) ? GL_TRANSFORM_FEEDBACK_BUFFER : GL_SHADER_STORAGE_BUFFER;
522 
523         glBindBufferBase(output_buffer_type, 0, m_buffer);
524         glBufferData(output_buffer_type, kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
525 
526         if (pipeline)
527             glBindProgramPipeline(m_pipeline);
528         else
529             glUseProgram(m_program[0]);
530         glBindVertexArray(m_vertex_array);
531 
532         if (stage == 0)
533             glBeginTransformFeedback(GL_POINTS);
534 
535         if (stage == 4)
536             glDispatchCompute(1, 1, 1);
537         else
538             glDrawArrays(GL_POINTS, 0, 1);
539 
540         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
541 
542         if (stage == 0)
543             glEndTransformFeedback();
544 
545         ivec4 *map_data = (ivec4 *)glMapBufferRange(output_buffer_type, 0, kSize * 4 * 4, GL_MAP_READ_BIT);
546         for (int i = 0; i < kSize; ++i)
547         {
548             if (!Equal(map_data[i], expected_result[i]))
549             {
550                 m_context.getTestContext().getLog()
551                     << tcu::TestLog::Message << "Returned value is: (" << map_data[i][0] << " " << map_data[i][1] << " "
552                     << map_data[i][2] << " " << map_data[i][3] << "). Expected value is: (" << expected_result[i][0]
553                     << " " << expected_result[i][1] << " " << expected_result[i][2] << " " << expected_result[i][3]
554                     << "). Image unit is: " << i << tcu::TestLog::EndMessage;
555                 return ERROR;
556             }
557         }
558         glUnmapBuffer(output_buffer_type);
559 
560         if (stage == 0)
561             glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
562 
563         return NO_ERROR;
564     }
565 };
566 
567 //=============================================================================
568 // 1.1.x.y BasicNonMS
569 //-----------------------------------------------------------------------------
570 template <typename T, int STAGE>
571 class BasicNonMS : public ShaderImageSizeBase
572 {
573     GLuint m_texture[4];
574 
Setup()575     virtual long Setup()
576     {
577         glGenTextures(4, m_texture);
578         return NO_ERROR;
579     }
Run()580     virtual long Run()
581     {
582         if (STAGE == 0 && !IsVSFSAvailable(4, 0))
583             return NOT_SUPPORTED;
584         if (STAGE == 5 && !IsVSFSAvailable(0, 4))
585             return NOT_SUPPORTED;
586 
587         const GLenum target[4] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY};
588         for (int i = 0; i < 4; ++i)
589         {
590             glBindTexture(target[i], m_texture[i]);
591             glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
592             glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
593 
594             if (i == 0)
595             {
596                 glTexStorage2D(target[i], 10, TexInternalFormat<T>(), 512, 128);
597                 glBindImageTexture(0, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
598             }
599             else if (i == 1)
600             {
601                 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 8, 8, 4);
602                 glBindImageTexture(1, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
603             }
604             else if (i == 2)
605             {
606                 glTexStorage2D(target[i], 4, TexInternalFormat<T>(), 16, 16);
607                 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_WRITE, TexInternalFormat<T>());
608             }
609             else if (i == 3)
610             {
611                 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 127, 39, 12);
612                 glBindImageTexture(3, m_texture[i], 2, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
613             }
614         }
615         ImageSizeMachine machine;
616         ivec4 res[4] = {ivec4(256, 64, 0, 0), ivec4(8, 8, 4, 0), ivec4(16, 16, 0, 0), ivec4(31, 9, 12, 0)};
617         return machine.Run<T>(STAGE, res);
618     }
Cleanup()619     virtual long Cleanup()
620     {
621         glDeleteTextures(4, m_texture);
622         return NO_ERROR;
623     }
624 };
625 //=============================================================================
626 // 2.2.x.y AdvancedNonMS
627 //-----------------------------------------------------------------------------
628 template <typename T, int STAGE>
629 class AdvancedNonMS : public ShaderImageSizeBase
630 {
631     GLuint m_texture[4];
632 
Setup()633     virtual long Setup()
634     {
635         glGenTextures(4, m_texture);
636         return NO_ERROR;
637     }
Run()638     virtual long Run()
639     {
640         if (STAGE == 0 && !IsVSFSAvailable(4, 0))
641             return NOT_SUPPORTED;
642         if (STAGE == 5 && !IsVSFSAvailable(0, 4))
643             return NOT_SUPPORTED;
644 
645         const GLenum target[4] = {GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY};
646         for (int i = 0; i < 4; ++i)
647         {
648             glBindTexture(target[i], m_texture[i]);
649             glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
650             glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
651 
652             if (i == 0)
653             {
654                 glTexStorage3D(target[i], 2, TexInternalFormat<T>(), 2, 2, 7);
655                 glBindImageTexture(0, m_texture[i], 1, GL_FALSE, 3, GL_READ_ONLY, TexInternalFormat<T>());
656             }
657             else if (i == 1)
658             {
659                 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 4, 4, 2);
660                 glBindImageTexture(1, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
661             }
662             else if (i == 2)
663             {
664                 glTexStorage2D(target[i], 2, TexInternalFormat<T>(), 2, 2);
665                 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_WRITE, TexInternalFormat<T>());
666             }
667             else if (i == 3)
668             {
669                 glTexStorage3D(target[i], 4, TexInternalFormat<T>(), 13, 7, 4);
670                 glBindImageTexture(3, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
671             }
672         }
673         ImageSizeMachine machine;
674         ivec4 res[4] = {ivec4(1, 1, 0, 0), ivec4(2, 2, 1, 0), ivec4(2, 2, 0, 0), ivec4(6, 3, 4, 0)};
675         return machine.Run<T>(STAGE, res);
676     }
Cleanup()677     virtual long Cleanup()
678     {
679         glDeleteTextures(4, m_texture);
680         return NO_ERROR;
681     }
682 };
683 //=============================================================================
684 // 4.1 NegativeCompileTime
685 //-----------------------------------------------------------------------------
686 class NegativeCompileTime : public ShaderImageSizeBase
687 {
Run()688     virtual long Run()
689     {
690         if (!Compile( // imagesize return type check
691                 "#version 310 es" NL "precision highp float;" NL "precision highp int;" NL
692                 "layout(local_size_x = 1) in;" NL "layout(r32f) uniform image2D g_image;" NL
693                 "layout(std430) buffer OutputBuffer { vec4 g_color; };" NL "void main() {" NL
694                 "  if (imageSize(g_image) == ivec3(5)) g_color = vec4(0, 1, 0, 1);" NL
695                 "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
696         {
697             return ERROR;
698         }
699         if (!Compile( // imageSize(samplertype)
700                 "#version 310 es" NL "precision highp float;" NL "precision highp int;" NL
701                 "layout(local_size_x = 1) in;" NL "layout(r32f) uniform sampler2D g_image;" NL
702                 "layout(std430) buffer OutputBuffer { vec4 g_color; };" NL "void main() {" NL
703                 "  if (imageSize(g_image) == ivec2(5)) g_color = vec4(0, 1, 0, 1);" NL
704                 "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
705         {
706             return ERROR;
707         }
708         return NO_ERROR;
709     }
710 
Compile(const std::string & source)711     bool Compile(const std::string &source)
712     {
713         const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
714 
715         const char *const src = source.c_str();
716         glShaderSource(sh, 1, &src, NULL);
717         glCompileShader(sh);
718 
719         GLchar log[1024];
720         glGetShaderInfoLog(sh, sizeof(log), NULL, log);
721         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
722                                             << log << tcu::TestLog::EndMessage;
723 
724         GLint status;
725         glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
726         glDeleteShader(sh);
727 
728         if (status == GL_TRUE)
729         {
730             m_context.getTestContext().getLog()
731                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
732             return false;
733         }
734         return true;
735     }
736 };
737 
738 } // anonymous namespace
739 
ShaderImageSizeTests(glcts::Context & context)740 ShaderImageSizeTests::ShaderImageSizeTests(glcts::Context &context) : TestCaseGroup(context, "shader_image_size", "")
741 {
742 }
743 
~ShaderImageSizeTests(void)744 ShaderImageSizeTests::~ShaderImageSizeTests(void)
745 {
746 }
747 
init()748 void ShaderImageSizeTests::init()
749 {
750     using namespace glcts;
751     addChild(new TestSubcase(m_context, "basic-nonMS-vs-float", TestSubcase::Create<BasicNonMS<vec4, 0>>));
752     addChild(new TestSubcase(m_context, "basic-nonMS-vs-int", TestSubcase::Create<BasicNonMS<ivec4, 0>>));
753     addChild(new TestSubcase(m_context, "basic-nonMS-vs-uint", TestSubcase::Create<BasicNonMS<uvec4, 0>>));
754     addChild(new TestSubcase(m_context, "basic-nonMS-fs-float", TestSubcase::Create<BasicNonMS<vec4, 5>>));
755     addChild(new TestSubcase(m_context, "basic-nonMS-fs-int", TestSubcase::Create<BasicNonMS<ivec4, 5>>));
756     addChild(new TestSubcase(m_context, "basic-nonMS-fs-uint", TestSubcase::Create<BasicNonMS<uvec4, 5>>));
757     addChild(new TestSubcase(m_context, "basic-nonMS-cs-float", TestSubcase::Create<BasicNonMS<vec4, 4>>));
758     addChild(new TestSubcase(m_context, "basic-nonMS-cs-int", TestSubcase::Create<BasicNonMS<ivec4, 4>>));
759     addChild(new TestSubcase(m_context, "basic-nonMS-cs-uint", TestSubcase::Create<BasicNonMS<uvec4, 4>>));
760     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-float", TestSubcase::Create<AdvancedNonMS<vec4, 0>>));
761     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 0>>));
762     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 0>>));
763     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-float", TestSubcase::Create<AdvancedNonMS<vec4, 5>>));
764     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 5>>));
765     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 5>>));
766     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-float", TestSubcase::Create<AdvancedNonMS<vec4, 4>>));
767     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 4>>));
768     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 4>>));
769     addChild(new TestSubcase(m_context, "negative-compileTime", TestSubcase::Create<NegativeCompileTime>));
770 }
771 } // namespace glcts
772