xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cShaderImageSizeTests.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 "gl4cShaderImageSizeTests.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 gl4cts
34 {
35 using namespace glw;
36 
37 namespace
38 {
39 typedef tcu::Vec3 vec3;
40 typedef tcu::Vec4 vec4;
41 typedef tcu::IVec4 ivec4;
42 typedef tcu::UVec4 uvec4;
43 
44 class ShaderImageSizeBase : public deqp::SubcaseBase
45 {
Title()46     virtual std::string Title()
47     {
48         return "";
49     }
50 
Purpose()51     virtual std::string Purpose()
52     {
53         return "";
54     }
55 
Method()56     virtual std::string Method()
57     {
58         return "";
59     }
60 
PassCriteria()61     virtual std::string PassCriteria()
62     {
63         return "";
64     }
65 
66 public:
SupportedInVS(int requiredVS)67     bool SupportedInVS(int requiredVS)
68     {
69         GLint imagesVS;
70         glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
71         if (imagesVS >= requiredVS)
72             return true;
73         else
74         {
75             std::ostringstream reason;
76             reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
77                    << std::endl;
78             OutputNotSupported(reason.str());
79             return false;
80         }
81     }
82 
SupportedInTCS(int requiredTCS)83     bool SupportedInTCS(int requiredTCS)
84     {
85         GLint imagesTCS;
86         glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
87         if (imagesTCS >= requiredTCS)
88             return true;
89         else
90         {
91             std::ostringstream reason;
92             reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
93                    << std::endl;
94             OutputNotSupported(reason.str());
95             return false;
96         }
97     }
98 
SupportedInTES(int requiredTES)99     bool SupportedInTES(int requiredTES)
100     {
101         GLint imagesTES;
102         glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
103         if (imagesTES >= requiredTES)
104             return true;
105         else
106         {
107             std::ostringstream reason;
108             reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
109                    << std::endl;
110             OutputNotSupported(reason.str());
111             return false;
112         }
113     }
114 
SupportedInGS(int requiredGS)115     bool SupportedInGS(int requiredGS)
116     {
117         GLint imagesGS;
118         glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
119         if (imagesGS >= requiredGS)
120             return true;
121         else
122         {
123             std::ostringstream reason;
124             reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
125                    << std::endl;
126             OutputNotSupported(reason.str());
127             return false;
128         }
129     }
130 
SupportedInStage(int stage,int required)131     bool SupportedInStage(int stage, int required)
132     {
133         switch (stage)
134         {
135         case 0:
136             return SupportedInVS(required);
137         case 1:
138             return SupportedInTCS(required);
139         case 2:
140             return SupportedInTES(required);
141         case 3:
142             return SupportedInGS(required);
143         default:
144             return true;
145         }
146     }
147 
SupportedSamples(int required)148     bool SupportedSamples(int required)
149     {
150         int i;
151         glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
152         if (i >= required)
153             return true;
154         else
155         {
156             std::ostringstream reason;
157             reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
158             OutputNotSupported(reason.str());
159             return false;
160         }
161     }
162 
getWindowWidth()163     int getWindowWidth()
164     {
165         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
166         return renderTarget.getWidth();
167     }
168 
getWindowHeight()169     int getWindowHeight()
170     {
171         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
172         return renderTarget.getHeight();
173     }
174 
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)175     inline bool ColorEqual(const vec4 &c0, const vec4 &c1, const vec4 &epsilon)
176     {
177         if (fabs(c0[0] - c1[0]) > epsilon[0])
178             return false;
179         if (fabs(c0[1] - c1[1]) > epsilon[1])
180             return false;
181         if (fabs(c0[2] - c1[2]) > epsilon[2])
182             return false;
183         if (fabs(c0[3] - c1[3]) > epsilon[3])
184             return false;
185         return true;
186     }
187 
188     template <class T>
ToString(T v)189     std::string ToString(T v)
190     {
191         std::ostringstream s;
192         s << "[";
193         for (int i = 0; i < 4; ++i)
194             s << v[i] << (i == 3 ? "" : ",");
195         s << "]";
196         return s.str();
197     }
198 
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)199     bool ValidateReadBuffer(int x, int y, int w, int h, const vec4 &expected)
200     {
201         bool status                           = true;
202         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
203         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
204         vec4 g_color_eps                      = vec4(
205             1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
206             1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
207 
208         std::vector<vec4> fb(w * h);
209         glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
210 
211         for (int yy = 0; yy < h; ++yy)
212         {
213             for (int xx = 0; xx < w; ++xx)
214             {
215                 const int idx = yy * w + xx;
216                 if (!ColorEqual(fb[idx], expected, g_color_eps))
217                 {
218                     m_context.getTestContext().getLog()
219                         << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
220                         << tcu::TestLog::EndMessage;
221                     status = false;
222                     return status;
223                 }
224             }
225         }
226         return status;
227     }
228 
CheckProgram(GLuint program)229     bool CheckProgram(GLuint program)
230     {
231         if (program == 0)
232             return true;
233         GLint status;
234         glGetProgramiv(program, GL_LINK_STATUS, &status);
235 
236         if (status == GL_FALSE)
237         {
238             GLint attached_shaders;
239             glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
240 
241             if (attached_shaders > 0)
242             {
243                 std::vector<GLuint> shaders(attached_shaders);
244                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
245 
246                 for (GLint i = 0; i < attached_shaders; ++i)
247                 {
248                     GLenum type;
249                     glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
250                     switch (type)
251                     {
252                     case GL_VERTEX_SHADER:
253                         m_context.getTestContext().getLog()
254                             << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
255                         break;
256                     case GL_TESS_CONTROL_SHADER:
257                         m_context.getTestContext().getLog()
258                             << tcu::TestLog::Message << "*** Tessellation Control Shader ***"
259                             << tcu::TestLog::EndMessage;
260                         break;
261                     case GL_TESS_EVALUATION_SHADER:
262                         m_context.getTestContext().getLog()
263                             << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
264                             << tcu::TestLog::EndMessage;
265                         break;
266                     case GL_GEOMETRY_SHADER:
267                         m_context.getTestContext().getLog()
268                             << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
269                         break;
270                     case GL_FRAGMENT_SHADER:
271                         m_context.getTestContext().getLog()
272                             << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
273                         break;
274                     case GL_COMPUTE_SHADER:
275                         m_context.getTestContext().getLog()
276                             << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
277                         break;
278                     default:
279                         m_context.getTestContext().getLog()
280                             << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
281                         break;
282                     }
283                     GLint length;
284                     glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
285                     if (length > 0)
286                     {
287                         std::vector<GLchar> source(length);
288                         glGetShaderSource(shaders[i], length, NULL, &source[0]);
289                         m_context.getTestContext().getLog()
290                             << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
291                     }
292                     glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
293                     if (length > 0)
294                     {
295                         std::vector<GLchar> log(length);
296                         glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
297                         m_context.getTestContext().getLog()
298                             << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
299                     }
300                 }
301             }
302             GLint length;
303             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
304             if (length > 0)
305             {
306                 std::vector<GLchar> log(length);
307                 glGetProgramInfoLog(program, length, NULL, &log[0]);
308                 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
309             }
310         }
311         return status == GL_TRUE ? true : false;
312     }
313 };
314 
315 template <typename T>
316 std::string ImageTypePrefix();
317 
318 template <>
ImageTypePrefix()319 std::string ImageTypePrefix<vec4>()
320 {
321     return "";
322 }
323 
324 template <>
ImageTypePrefix()325 std::string ImageTypePrefix<ivec4>()
326 {
327     return "i";
328 }
329 
330 template <>
ImageTypePrefix()331 std::string ImageTypePrefix<uvec4>()
332 {
333     return "u";
334 }
335 
336 template <typename T>
337 std::string ImageFormatPostfix();
338 
339 template <>
ImageFormatPostfix()340 std::string ImageFormatPostfix<vec4>()
341 {
342     return "f";
343 }
344 
345 template <>
ImageFormatPostfix()346 std::string ImageFormatPostfix<ivec4>()
347 {
348     return "i";
349 }
350 
351 template <>
ImageFormatPostfix()352 std::string ImageFormatPostfix<uvec4>()
353 {
354     return "ui";
355 }
356 
357 template <typename T>
358 GLenum TexInternalFormat();
359 
360 template <>
TexInternalFormat()361 GLenum TexInternalFormat<vec4>()
362 {
363     return GL_RGBA32F;
364 }
365 
366 template <>
TexInternalFormat()367 GLenum TexInternalFormat<ivec4>()
368 {
369     return GL_RGBA32I;
370 }
371 
372 template <>
TexInternalFormat()373 GLenum TexInternalFormat<uvec4>()
374 {
375     return GL_RGBA32UI;
376 }
377 
378 template <typename T>
379 GLenum TexType();
380 
381 template <>
TexType()382 GLenum TexType<vec4>()
383 {
384     return GL_FLOAT;
385 }
386 
387 template <>
TexType()388 GLenum TexType<ivec4>()
389 {
390     return GL_INT;
391 }
392 
393 template <>
TexType()394 GLenum TexType<uvec4>()
395 {
396     return GL_UNSIGNED_INT;
397 }
398 
399 template <typename T>
400 GLenum TexFormat();
401 
402 template <>
TexFormat()403 GLenum TexFormat<vec4>()
404 {
405     return GL_RGBA;
406 }
407 
408 template <>
TexFormat()409 GLenum TexFormat<ivec4>()
410 {
411     return GL_RGBA_INTEGER;
412 }
413 
414 template <>
TexFormat()415 GLenum TexFormat<uvec4>()
416 {
417     return GL_RGBA_INTEGER;
418 }
419 //=============================================================================
420 // ImageSizeMachine
421 //-----------------------------------------------------------------------------
422 class ImageSizeMachine : public deqp::GLWrapper
423 {
424     GLuint m_pipeline;
425     GLuint m_program[3];
426     GLuint m_vertex_array;
427     GLuint m_texture;
428 
429     template <typename T>
GenShader(int stage,bool ms_and_1d,bool subroutine)430     std::string GenShader(int stage, bool ms_and_1d, bool subroutine)
431     {
432         std::ostringstream os;
433         os << "#version 430 core";
434         if (stage == 4)
435         { // CS
436             os << NL "#extension GL_ARB_compute_shader : require";
437         }
438         os << NL "layout(binding = 0, rgba32i) writeonly uniform iimage2D g_result;";
439         if (ms_and_1d == false)
440         {
441             os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
442                << "image2D g_image_2d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform "
443                << ImageTypePrefix<T>() << "image3D g_image_3d;" NL "layout(binding = 3, rgba32"
444                << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
445                << "image2D g_image_cube;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform "
446                << ImageTypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "layout(binding = 5, rgba32"
447                << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
448                << "image2DRect g_image_rect;" NL "layout(binding = 6, rgba32" << ImageFormatPostfix<T>() << ") uniform "
449                << ImageTypePrefix<T>() << "image2DArray g_image_2d_array;" NL "layout(binding = 7, rgba32"
450                << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() << "imageBuffer g_image_buffer;";
451         }
452         else
453         {
454             os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
455                << "image1D g_image_1d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform "
456                << ImageTypePrefix<T>() << "image1DArray g_image_1d_array;" NL "layout(binding = 3, rgba32"
457                << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
458                << "image2DMS g_image_2dms;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform "
459                << ImageTypePrefix<T>() << "image2DMSArray g_image_2dms_array;";
460         }
461         if (subroutine)
462         {
463             os << NL "subroutine void FuncType(int coord);" NL "subroutine uniform FuncType g_func;";
464         }
465         if (stage == 0)
466         { // VS
467             os << NL "void main() {" NL "  int coord = gl_VertexID;";
468         }
469         else if (stage == 1)
470         { // TCS
471             os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
472                      "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
473                      "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL "  int coord = gl_PrimitiveID;";
474         }
475         else if (stage == 2)
476         { // TES
477             os << NL "layout(quads, point_mode) in;" NL "void main() {" NL "  int coord = gl_PrimitiveID;";
478         }
479         else if (stage == 3)
480         { // GS
481             os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
482                      "  int coord = gl_PrimitiveIDIn;";
483         }
484         else if (stage == 4)
485         { // CS
486             os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL "  int coord = int(gl_GlobalInvocationID.x);";
487         }
488         else if (stage == 5)
489         { // FS
490             os << NL "void main() {" NL "  int coord = gl_PrimitiveID;";
491         }
492         if (subroutine)
493         {
494             os << NL "  g_func(coord);" NL "}" NL "subroutine(FuncType) void Func0(int coord) {";
495         }
496         if (ms_and_1d == false)
497         {
498             os << NL "  imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_2d), 0, 0));" NL
499                      "  imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_3d), 0));" NL
500                      "  imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_cube), 0, 0));" NL
501                      "  imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_cube_array), 0));" NL
502                      "  imageStore(g_result, ivec2(coord, 4), ivec4(imageSize(g_image_rect), 0, 0));" NL
503                      "  imageStore(g_result, ivec2(coord, 5), ivec4(imageSize(g_image_2d_array), 0));" NL
504                      "  imageStore(g_result, ivec2(coord, 6), ivec4(imageSize(g_image_buffer), 0, 0, 0));" NL "}";
505         }
506         else
507         {
508             os << NL "  imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_1d), 0, 0, 0));" NL
509                      "  imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_1d_array), 0, 0));" NL
510                      "  imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_2dms), 0, 0));" NL
511                      "  imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_2dms_array), 0));" NL
512                      "  imageStore(g_result, ivec2(coord, 4), ivec4(0));" NL
513                      "  imageStore(g_result, ivec2(coord, 5), ivec4(0));" NL
514                      "  imageStore(g_result, ivec2(coord, 6), ivec4(0));" NL "}";
515         }
516         return os.str();
517     }
518 
CheckProgram(GLuint program)519     bool CheckProgram(GLuint program)
520     {
521         if (program == 0)
522             return true;
523         GLint status;
524         glGetProgramiv(program, GL_LINK_STATUS, &status);
525 
526         if (status == GL_FALSE)
527         {
528             GLint attached_shaders;
529             glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
530 
531             if (attached_shaders > 0)
532             {
533                 std::vector<GLuint> shaders(attached_shaders);
534                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
535 
536                 for (GLint i = 0; i < attached_shaders; ++i)
537                 {
538                     GLenum type;
539                     glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
540                     switch (type)
541                     {
542                     case GL_VERTEX_SHADER:
543                         m_context.getTestContext().getLog()
544                             << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
545                         break;
546                     case GL_TESS_CONTROL_SHADER:
547                         m_context.getTestContext().getLog()
548                             << tcu::TestLog::Message << "*** Tessellation Control Shader ***"
549                             << tcu::TestLog::EndMessage;
550                         break;
551                     case GL_TESS_EVALUATION_SHADER:
552                         m_context.getTestContext().getLog()
553                             << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
554                             << tcu::TestLog::EndMessage;
555                         break;
556                     case GL_GEOMETRY_SHADER:
557                         m_context.getTestContext().getLog()
558                             << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
559                         break;
560                     case GL_FRAGMENT_SHADER:
561                         m_context.getTestContext().getLog()
562                             << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
563                         break;
564                     case GL_COMPUTE_SHADER:
565                         m_context.getTestContext().getLog()
566                             << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
567                         break;
568                     default:
569                         m_context.getTestContext().getLog()
570                             << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
571                         break;
572                     }
573                     GLint length;
574                     glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
575                     if (length > 0)
576                     {
577                         std::vector<GLchar> source(length);
578                         glGetShaderSource(shaders[i], length, NULL, &source[0]);
579                         m_context.getTestContext().getLog()
580                             << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
581                     }
582                     glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
583                     if (length > 0)
584                     {
585                         std::vector<GLchar> log(length);
586                         glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
587                         m_context.getTestContext().getLog()
588                             << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
589                     }
590                 }
591             }
592             GLint length;
593             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
594             if (length > 0)
595             {
596                 std::vector<GLchar> log(length);
597                 glGetProgramInfoLog(program, length, NULL, &log[0]);
598                 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
599             }
600         }
601         return status == GL_TRUE ? true : false;
602     }
603 
604 public:
ImageSizeMachine()605     ImageSizeMachine()
606     {
607         glGenProgramPipelines(1, &m_pipeline);
608         memset(m_program, 0, sizeof(m_program));
609         glGenVertexArrays(1, &m_vertex_array);
610         glGenTextures(1, &m_texture);
611     }
612 
~ImageSizeMachine()613     ~ImageSizeMachine()
614     {
615         glDeleteProgramPipelines(1, &m_pipeline);
616         for (int i = 0; i < 3; ++i)
617             glDeleteProgram(m_program[i]);
618         glDeleteVertexArrays(1, &m_vertex_array);
619         glDeleteTextures(1, &m_texture);
620     }
621 
622     template <typename T>
Run(int stage,bool ms_and_1d,ivec4 expected_result[7],bool subroutine=false)623     long Run(int stage, bool ms_and_1d, ivec4 expected_result[7], bool subroutine = false)
624     {
625         if (stage == 0)
626         { // VS
627             std::string vs            = GenShader<T>(stage, ms_and_1d, subroutine);
628             const char *const glsl_vs = vs.c_str();
629             m_program[0]              = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
630             glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
631         }
632         else if (stage == 1)
633         { // TCS
634             const char *const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
635                                         "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
636             const char *const glsl_tes = "#version 430 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
637             std::string tcs            = GenShader<T>(stage, ms_and_1d, subroutine);
638             const char *const glsl_tcs = tcs.c_str();
639             m_program[0]               = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
640             m_program[1]               = glCreateShaderProgramv(GL_TESS_CONTROL_SHADER, 1, &glsl_tcs);
641             m_program[2]               = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes);
642             glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
643             glUseProgramStages(m_pipeline, GL_TESS_CONTROL_SHADER_BIT, m_program[1]);
644             glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[2]);
645         }
646         else if (stage == 2)
647         { // TES
648             const char *const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
649                                         "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
650             std::string tes            = GenShader<T>(stage, ms_and_1d, subroutine);
651             const char *const glsl_tes = tes.c_str();
652             m_program[0]               = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
653             m_program[1]               = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes);
654             glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
655             glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[1]);
656         }
657         else if (stage == 3)
658         { // GS
659             const char *const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
660                                         "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
661             std::string gs            = GenShader<T>(stage, ms_and_1d, subroutine);
662             const char *const glsl_gs = gs.c_str();
663             m_program[0]              = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
664             m_program[1]              = glCreateShaderProgramv(GL_GEOMETRY_SHADER, 1, &glsl_gs);
665             glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
666             glUseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, m_program[1]);
667         }
668         else if (stage == 4)
669         { // CS
670             std::string cs            = GenShader<T>(stage, ms_and_1d, subroutine);
671             const char *const glsl_cs = cs.c_str();
672             m_program[0]              = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
673             glUseProgramStages(m_pipeline, GL_COMPUTE_SHADER_BIT, m_program[0]);
674         }
675         else if (stage == 5)
676         { // FS
677             const char *const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
678                                         "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
679             std::string fs            = GenShader<T>(stage, ms_and_1d, subroutine);
680             const char *const glsl_fs = fs.c_str();
681             m_program[0]              = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
682             m_program[1]              = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
683             glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
684             glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
685         }
686         for (int i = 0; i < 3; ++i)
687         {
688             if (!CheckProgram(m_program[i]))
689                 return ERROR;
690         }
691 
692         glBindTexture(GL_TEXTURE_2D, m_texture);
693         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
694         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
695         {
696             ivec4 data[7];
697             for (int i = 0; i < 7; ++i)
698                 data[i] = ivec4(100000);
699             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 7, 0, GL_RGBA_INTEGER, GL_INT, &data[0]);
700         }
701         glBindTexture(GL_TEXTURE_2D, 0);
702 
703         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
704         glBindProgramPipeline(m_pipeline);
705         glBindVertexArray(m_vertex_array);
706         if (stage != 5)
707         {
708             glEnable(GL_RASTERIZER_DISCARD);
709         }
710         if (stage == 1 || stage == 2)
711         { // TCS or TES
712             glPatchParameteri(GL_PATCH_VERTICES, 1);
713             glDrawArrays(GL_PATCHES, 0, 1);
714             glPatchParameteri(GL_PATCH_VERTICES, 3);
715         }
716         else if (stage == 4)
717         { // CS
718             glDispatchCompute(1, 1, 1);
719         }
720         else
721         {
722             glDrawArrays(GL_POINTS, 0, 1);
723         }
724         glDisable(GL_RASTERIZER_DISCARD);
725 
726         glBindTexture(GL_TEXTURE_2D, m_texture);
727         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
728         {
729             ivec4 data[7];
730             glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_INT, &data[0]);
731             for (int i = 0; i < 7; ++i)
732             {
733                 if (data[i] != expected_result[i])
734                 {
735                     m_context.getTestContext().getLog()
736                         << tcu::TestLog::Message << "Returned value is: (" << data[i][0] << " " << data[i][1] << " "
737                         << data[i][2] << " " << data[i][3] << "). Expected value is: (" << expected_result[i][0] << " "
738                         << expected_result[i][1] << " " << expected_result[i][2] << " " << expected_result[i][3]
739                         << "). Image unit is: " << (i + 1) << tcu::TestLog::EndMessage;
740                     return ERROR;
741                 }
742             }
743         }
744         return NO_ERROR;
745     }
746 };
747 //=============================================================================
748 // 1.1.x.y BasicNonMS
749 //-----------------------------------------------------------------------------
750 
751 template <typename T, int STAGE>
752 class BasicNonMS : public ShaderImageSizeBase
753 {
754     GLuint m_texture[7];
755     GLuint m_buffer;
756 
Setup()757     virtual long Setup()
758     {
759         glGenTextures(7, m_texture);
760         glGenBuffers(1, &m_buffer);
761         return NO_ERROR;
762     }
763 
Run()764     virtual long Run()
765     {
766         if (!SupportedInStage(STAGE, 8))
767             return NOT_SUPPORTED;
768 
769         const GLenum target[7] = {
770             GL_TEXTURE_2D,        GL_TEXTURE_3D,       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY,
771             GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BUFFER};
772         for (int i = 0; i < 7; ++i)
773         {
774             glBindTexture(target[i], m_texture[i]);
775             if (target[i] != GL_TEXTURE_BUFFER)
776             {
777                 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
778                 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
779             }
780 
781             if (i == 0)
782             {
783                 glTexStorage2D(target[i], 10, TexInternalFormat<T>(), 512, 128);
784                 glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
785             }
786             else if (i == 1)
787             {
788                 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 8, 8, 4);
789                 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
790             }
791             else if (i == 2)
792             {
793                 glTexStorage2D(target[i], 4, TexInternalFormat<T>(), 16, 16);
794                 glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
795             }
796             else if (i == 3)
797             {
798                 glTexStorage3D(target[i], 2, TexInternalFormat<T>(), 4, 4, 12);
799                 glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
800             }
801             else if (i == 4)
802             {
803                 glTexStorage2D(target[i], 1, TexInternalFormat<T>(), 16, 8);
804                 glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
805             }
806             else if (i == 5)
807             {
808                 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 127, 39, 12);
809                 glBindImageTexture(6, m_texture[i], 2, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
810             }
811             else if (i == 6)
812             {
813                 std::vector<GLubyte> data(256);
814                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
815                 glBufferData(GL_TEXTURE_BUFFER, 256, &data[0], GL_STATIC_DRAW);
816                 glTexBuffer(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer);
817                 glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
818             }
819         }
820         ImageSizeMachine machine;
821         ivec4 res[7] = {ivec4(256, 64, 0, 0), ivec4(8, 8, 4, 0),   ivec4(16, 16, 0, 0), ivec4(2, 2, 2, 0),
822                         ivec4(16, 8, 0, 0),   ivec4(31, 9, 12, 0), ivec4(16, 0, 0, 0)};
823         return machine.Run<T>(STAGE, false, res);
824     }
825 
Cleanup()826     virtual long Cleanup()
827     {
828         glDeleteTextures(7, m_texture);
829         glDeleteBuffers(1, &m_buffer);
830         return NO_ERROR;
831     }
832 };
833 //=============================================================================
834 // 1.2.x.y BasicMS
835 //-----------------------------------------------------------------------------
836 
837 template <typename T, int STAGE>
838 class BasicMS : public ShaderImageSizeBase
839 {
840     GLuint m_texture[4];
841 
Setup()842     virtual long Setup()
843     {
844         glGenTextures(4, m_texture);
845         return NO_ERROR;
846     }
847 
Run()848     virtual long Run()
849     {
850         if (!SupportedInStage(STAGE, 5))
851             return NOT_SUPPORTED;
852         if (!SupportedSamples(4))
853             return NOT_SUPPORTED;
854 
855         const GLenum target[4] = {GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE,
856                                   GL_TEXTURE_2D_MULTISAMPLE_ARRAY};
857         for (int i = 0; i < 4; ++i)
858         {
859             glBindTexture(target[i], m_texture[i]);
860             if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY)
861             {
862                 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
863                 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
864             }
865 
866             if (i == 0)
867             {
868                 glTexStorage1D(target[i], 10, TexInternalFormat<T>(), 512);
869                 glBindImageTexture(1, m_texture[i], 6, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
870             }
871             else if (i == 1)
872             {
873                 glTexStorage2D(target[i], 3, TexInternalFormat<T>(), 15, 7);
874                 glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
875             }
876             else if (i == 2)
877             {
878                 glTexImage2DMultisample(target[i], 4, TexInternalFormat<T>(), 17, 19, GL_FALSE);
879                 glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
880             }
881             else if (i == 3)
882             {
883                 glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE);
884                 glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
885             }
886         }
887         ImageSizeMachine machine;
888         ivec4 res[7] = {ivec4(8, 0, 0, 0), ivec4(7, 7, 0, 0), ivec4(17, 19, 0, 0), ivec4(64, 32, 5, 0), ivec4(0),
889                         ivec4(0),          ivec4(0)};
890         return machine.Run<T>(STAGE, true, res);
891     }
892 
Cleanup()893     virtual long Cleanup()
894     {
895         glDeleteTextures(4, m_texture);
896         return NO_ERROR;
897     }
898 };
899 //=============================================================================
900 // 2.1 AdvancedChangeSize
901 //-----------------------------------------------------------------------------
902 class AdvancedChangeSize : public ShaderImageSizeBase
903 {
904     GLuint m_pipeline;
905     GLuint m_program[2];
906     GLuint m_vertex_array;
907     GLuint m_texture[2];
908 
Setup()909     virtual long Setup()
910     {
911         glGenProgramPipelines(1, &m_pipeline);
912         memset(m_program, 0, sizeof(m_program));
913         glGenVertexArrays(1, &m_vertex_array);
914         glGenTextures(2, m_texture);
915         return NO_ERROR;
916     }
917 
Run()918     virtual long Run()
919     {
920         const char *const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
921                                     "const vec2 g_position[3] = { vec2(-1, -1), vec2(3, -1), vec2(-1, 3) };" NL
922                                     "void main() { gl_Position = vec4(g_position[gl_VertexID], 0, 1); }";
923         const char *const glsl_fs =
924             "#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL
925             "layout(binding = 0, rgba8) uniform image2D g_image[2];" NL "uniform ivec2 g_expected_size[2];" NL
926             "uniform int g_0 = 0, g_1 = 1;" NL "void main() {" NL "  vec4 c = vec4(0, 1, 0, 1);" NL
927             "  if (imageSize(g_image[g_0]).xy != g_expected_size[g_0]) c = vec4(1, 0, 0, 1);" NL
928             "  if (imageSize(g_image[g_1]).yx != g_expected_size[g_1]) c = vec4(1, 0, 0, 1);" NL "  g_color = c;" NL
929             "}";
930         m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
931         m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
932         for (int i = 0; i < 2; ++i)
933             if (!CheckProgram(m_program[i]))
934                 return ERROR;
935 
936         glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
937         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
938 
939         glBindVertexArray(m_vertex_array);
940         glBindProgramPipeline(m_pipeline);
941 
942         int size[2] = {32, 128};
943         for (int i = 0; i < 2; ++i)
944         {
945             glBindTexture(GL_TEXTURE_2D, m_texture[i]);
946             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
947             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
948             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[i], size[i], 0, GL_RGBA, GL_FLOAT, NULL);
949             glBindImageTexture(i, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
950         }
951 
952         for (int i = 0; i < 3; ++i)
953         {
954             glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[0]"), size[0],
955                                size[0]);
956             glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[1]"), size[1],
957                                size[1]);
958             glClear(GL_COLOR_BUFFER_BIT);
959             glDrawArrays(GL_TRIANGLES, 0, 3);
960 
961             {
962                 bool status = true;
963                 std::vector<vec3> fb(getWindowWidth() * getWindowHeight());
964                 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGB, GL_FLOAT, &fb[0][0]);
965                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
966                     status = false;
967                 if (!status)
968                     return ERROR;
969             }
970 
971             size[0] /= 2;
972             size[1] /= 2;
973 
974             glBindTexture(GL_TEXTURE_2D, m_texture[0]);
975             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[0], size[0], 0, GL_RGBA, GL_FLOAT, NULL);
976             glBindTexture(GL_TEXTURE_2D, m_texture[1]);
977             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[1], size[1], 0, GL_RGBA, GL_FLOAT, NULL);
978         }
979         return NO_ERROR;
980     }
981 
Cleanup()982     virtual long Cleanup()
983     {
984         glDeleteProgramPipelines(1, &m_pipeline);
985         for (int i = 0; i < 2; ++i)
986             glDeleteProgram(m_program[i]);
987         glDeleteVertexArrays(1, &m_vertex_array);
988         glDeleteTextures(2, m_texture);
989         return NO_ERROR;
990     }
991 };
992 //=============================================================================
993 // 2.2.x.y AdvancedNonMS
994 //-----------------------------------------------------------------------------
995 
996 template <typename T, int STAGE>
997 class AdvancedNonMS : public ShaderImageSizeBase
998 {
999     GLuint m_texture[7];
1000     GLuint m_buffer;
1001 
Setup()1002     virtual long Setup()
1003     {
1004         glGenTextures(7, m_texture);
1005         glGenBuffers(1, &m_buffer);
1006         return NO_ERROR;
1007     }
1008 
Run()1009     virtual long Run()
1010     {
1011         if (!SupportedInStage(STAGE, 8))
1012             return NOT_SUPPORTED;
1013 
1014         const GLenum target[7] = {GL_TEXTURE_2D_ARRAY,       GL_TEXTURE_3D,        GL_TEXTURE_CUBE_MAP_ARRAY,
1015                                   GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY,
1016                                   GL_TEXTURE_BUFFER};
1017         for (int i = 0; i < 7; ++i)
1018         {
1019             glBindTexture(target[i], m_texture[i]);
1020             if (target[i] != GL_TEXTURE_BUFFER)
1021             {
1022                 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1023                 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1024             }
1025 
1026             if (i == 0)
1027             {
1028                 glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1029                 glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1030                 glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 3, GL_READ_ONLY, TexInternalFormat<T>());
1031             }
1032             else if (i == 1)
1033             {
1034                 glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 2, 0, TexFormat<T>(), TexType<T>(), NULL);
1035                 glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1036                 glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1037                 glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1038             }
1039             else if (i == 2)
1040             {
1041                 glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 12, 0, TexFormat<T>(), TexType<T>(), NULL);
1042                 glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 12, 0, TexFormat<T>(), TexType<T>(), NULL);
1043                 glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>());
1044             }
1045             else if (i == 3)
1046             {
1047                 glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1048                 glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1049                 glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1050                 glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1051             }
1052             else if (i == 4)
1053             {
1054                 glTexImage2D(target[i], 0, TexInternalFormat<T>(), 123, 11, 0, TexFormat<T>(), TexType<T>(), NULL);
1055                 glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
1056             }
1057             else if (i == 5)
1058             {
1059                 glTexImage3D(target[i], 0, TexInternalFormat<T>(), 13, 7, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1060                 glTexImage3D(target[i], 1, TexInternalFormat<T>(), 6, 3, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1061                 glTexImage3D(target[i], 2, TexInternalFormat<T>(), 3, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1062                 glTexImage3D(target[i], 3, TexInternalFormat<T>(), 1, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1063                 glBindImageTexture(6, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1064             }
1065             else if (i == 6)
1066             {
1067                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
1068                 glBufferData(GL_TEXTURE_BUFFER, 1024, NULL, GL_STATIC_DRAW);
1069                 glTexBufferRange(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer, 256, 512);
1070                 glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, TexInternalFormat<T>());
1071             }
1072         }
1073         ImageSizeMachine machine;
1074         ivec4 res[7] = {ivec4(1, 1, 0, 0),    ivec4(2, 2, 1, 0), ivec4(2, 2, 0, 0), ivec4(2, 2, 3, 0),
1075                         ivec4(123, 11, 0, 0), ivec4(6, 3, 4, 0), ivec4(32, 0, 0, 0)};
1076         return machine.Run<T>(STAGE, false, res, true);
1077     }
1078 
Cleanup()1079     virtual long Cleanup()
1080     {
1081         glDeleteTextures(7, m_texture);
1082         glDeleteBuffers(1, &m_buffer);
1083         return NO_ERROR;
1084     }
1085 };
1086 //=============================================================================
1087 // 2.3.x.y AdvancedMS
1088 //-----------------------------------------------------------------------------
1089 template <typename T, int STAGE>
1090 class AdvancedMS : public ShaderImageSizeBase
1091 {
1092     GLuint m_texture[4];
1093 
Setup()1094     virtual long Setup()
1095     {
1096         glGenTextures(4, m_texture);
1097         return NO_ERROR;
1098     }
1099 
Run()1100     virtual long Run()
1101     {
1102         if (!SupportedInStage(STAGE, 5))
1103             return NOT_SUPPORTED;
1104         if (!SupportedSamples(4))
1105             return NOT_SUPPORTED;
1106 
1107         const GLenum target[4] = {GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
1108                                   GL_TEXTURE_2D_MULTISAMPLE_ARRAY};
1109         for (int i = 0; i < 4; ++i)
1110         {
1111             glBindTexture(target[i], m_texture[i]);
1112             if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY)
1113             {
1114                 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1115                 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1116             }
1117 
1118             if (i == 0)
1119             {
1120                 glTexImage1D(target[i], 0, TexInternalFormat<T>(), 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1121                 glTexImage1D(target[i], 1, TexInternalFormat<T>(), 3, 0, TexFormat<T>(), TexType<T>(), NULL);
1122                 glTexImage1D(target[i], 2, TexInternalFormat<T>(), 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1123                 glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1124             }
1125             else if (i == 1)
1126             {
1127                 glTexImage2D(target[i], 0, TexInternalFormat<T>(), 7, 15, 0, TexFormat<T>(), TexType<T>(), NULL);
1128                 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1129             }
1130             else if (i == 2)
1131             {
1132                 glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 7, 9, 3, GL_FALSE);
1133                 glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>());
1134             }
1135             else if (i == 3)
1136             {
1137                 glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE);
1138                 glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1139             }
1140         }
1141         ImageSizeMachine machine;
1142         ivec4 res[7] = {ivec4(3, 0, 0, 0), ivec4(7, 15, 0, 0), ivec4(7, 9, 0, 0), ivec4(64, 32, 5, 0),
1143                         ivec4(0),          ivec4(0),           ivec4(0)};
1144         return machine.Run<T>(STAGE, true, res, true);
1145     }
1146 
Cleanup()1147     virtual long Cleanup()
1148     {
1149         glDeleteTextures(4, m_texture);
1150         return NO_ERROR;
1151     }
1152 };
1153 //=============================================================================
1154 // 4.1 NegativeCompileTime
1155 //-----------------------------------------------------------------------------
1156 class NegativeCompileTime : public ShaderImageSizeBase
1157 {
Run()1158     virtual long Run()
1159     {
1160         // '#extension GL_ARB_shader_image_size : require' is missing
1161         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 g_color;" NL
1162                      "layout(binding = 0, rg16f) uniform image2D g_image;" NL "uniform ivec2 g_expected_size;" NL
1163                      "void main() {" NL "  if (imageSize(g_image) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL
1164                      "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
1165             return ERROR;
1166         // imageSize(sampler)
1167         if (!Compile("#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL
1168                      "layout(binding = 0) uniform sampler2D g_sampler;" NL "uniform ivec2 g_expected_size;" NL
1169                      "void main() {" NL "  if (imageSize(g_sampler) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL
1170                      "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
1171             return ERROR;
1172         return NO_ERROR;
1173     }
1174 
Compile(const std::string & source)1175     bool Compile(const std::string &source)
1176     {
1177         const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
1178 
1179         const char *const src = source.c_str();
1180         glShaderSource(sh, 1, &src, NULL);
1181         glCompileShader(sh);
1182 
1183         GLchar log[1024];
1184         glGetShaderInfoLog(sh, sizeof(log), NULL, log);
1185         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
1186                                             << log << tcu::TestLog::EndMessage;
1187 
1188         GLint status;
1189         glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
1190         glDeleteShader(sh);
1191 
1192         if (status == GL_TRUE)
1193         {
1194             m_context.getTestContext().getLog()
1195                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
1196             return false;
1197         }
1198         return true;
1199     }
1200 };
1201 
1202 } // anonymous namespace
1203 
ShaderImageSizeTests(deqp::Context & context)1204 ShaderImageSizeTests::ShaderImageSizeTests(deqp::Context &context) : TestCaseGroup(context, "shader_image_size", "")
1205 {
1206 }
1207 
~ShaderImageSizeTests(void)1208 ShaderImageSizeTests::~ShaderImageSizeTests(void)
1209 {
1210 }
1211 
init()1212 void ShaderImageSizeTests::init()
1213 {
1214     using namespace deqp;
1215     addChild(new TestSubcase(m_context, "basic-nonMS-vs-float", TestSubcase::Create<BasicNonMS<vec4, 0>>));
1216     addChild(new TestSubcase(m_context, "basic-nonMS-vs-int", TestSubcase::Create<BasicNonMS<ivec4, 0>>));
1217     addChild(new TestSubcase(m_context, "basic-nonMS-vs-uint", TestSubcase::Create<BasicNonMS<uvec4, 0>>));
1218     addChild(new TestSubcase(m_context, "basic-nonMS-tcs-float", TestSubcase::Create<BasicNonMS<vec4, 1>>));
1219     addChild(new TestSubcase(m_context, "basic-nonMS-tcs-int", TestSubcase::Create<BasicNonMS<ivec4, 1>>));
1220     addChild(new TestSubcase(m_context, "basic-nonMS-tcs-uint", TestSubcase::Create<BasicNonMS<uvec4, 1>>));
1221     addChild(new TestSubcase(m_context, "basic-nonMS-tes-float", TestSubcase::Create<BasicNonMS<vec4, 2>>));
1222     addChild(new TestSubcase(m_context, "basic-nonMS-tes-int", TestSubcase::Create<BasicNonMS<ivec4, 2>>));
1223     addChild(new TestSubcase(m_context, "basic-nonMS-tes-uint", TestSubcase::Create<BasicNonMS<uvec4, 2>>));
1224     addChild(new TestSubcase(m_context, "basic-nonMS-gs-float", TestSubcase::Create<BasicNonMS<vec4, 3>>));
1225     addChild(new TestSubcase(m_context, "basic-nonMS-gs-int", TestSubcase::Create<BasicNonMS<ivec4, 3>>));
1226     addChild(new TestSubcase(m_context, "basic-nonMS-gs-uint", TestSubcase::Create<BasicNonMS<uvec4, 3>>));
1227     addChild(new TestSubcase(m_context, "basic-nonMS-fs-float", TestSubcase::Create<BasicNonMS<vec4, 5>>));
1228     addChild(new TestSubcase(m_context, "basic-nonMS-fs-int", TestSubcase::Create<BasicNonMS<ivec4, 5>>));
1229     addChild(new TestSubcase(m_context, "basic-nonMS-fs-uint", TestSubcase::Create<BasicNonMS<uvec4, 5>>));
1230     addChild(new TestSubcase(m_context, "basic-nonMS-cs-float", TestSubcase::Create<BasicNonMS<vec4, 4>>));
1231     addChild(new TestSubcase(m_context, "basic-nonMS-cs-int", TestSubcase::Create<BasicNonMS<ivec4, 4>>));
1232     addChild(new TestSubcase(m_context, "basic-nonMS-cs-uint", TestSubcase::Create<BasicNonMS<uvec4, 4>>));
1233     addChild(new TestSubcase(m_context, "basic-ms-vs-float", TestSubcase::Create<BasicMS<vec4, 0>>));
1234     addChild(new TestSubcase(m_context, "basic-ms-vs-int", TestSubcase::Create<BasicMS<ivec4, 0>>));
1235     addChild(new TestSubcase(m_context, "basic-ms-vs-uint", TestSubcase::Create<BasicMS<uvec4, 0>>));
1236     addChild(new TestSubcase(m_context, "basic-ms-tcs-float", TestSubcase::Create<BasicMS<vec4, 1>>));
1237     addChild(new TestSubcase(m_context, "basic-ms-tcs-int", TestSubcase::Create<BasicMS<ivec4, 1>>));
1238     addChild(new TestSubcase(m_context, "basic-ms-tcs-uint", TestSubcase::Create<BasicMS<uvec4, 1>>));
1239     addChild(new TestSubcase(m_context, "basic-ms-tes-float", TestSubcase::Create<BasicMS<vec4, 2>>));
1240     addChild(new TestSubcase(m_context, "basic-ms-tes-int", TestSubcase::Create<BasicMS<ivec4, 2>>));
1241     addChild(new TestSubcase(m_context, "basic-ms-tes-uint", TestSubcase::Create<BasicMS<uvec4, 2>>));
1242     addChild(new TestSubcase(m_context, "basic-ms-gs-float", TestSubcase::Create<BasicMS<vec4, 3>>));
1243     addChild(new TestSubcase(m_context, "basic-ms-gs-int", TestSubcase::Create<BasicMS<ivec4, 3>>));
1244     addChild(new TestSubcase(m_context, "basic-ms-gs-uint", TestSubcase::Create<BasicMS<uvec4, 3>>));
1245     addChild(new TestSubcase(m_context, "basic-ms-fs-float", TestSubcase::Create<BasicMS<vec4, 5>>));
1246     addChild(new TestSubcase(m_context, "basic-ms-fs-int", TestSubcase::Create<BasicMS<ivec4, 5>>));
1247     addChild(new TestSubcase(m_context, "basic-ms-fs-uint", TestSubcase::Create<BasicMS<uvec4, 5>>));
1248     addChild(new TestSubcase(m_context, "basic-ms-cs-float", TestSubcase::Create<BasicMS<vec4, 4>>));
1249     addChild(new TestSubcase(m_context, "basic-ms-cs-int", TestSubcase::Create<BasicMS<ivec4, 4>>));
1250     addChild(new TestSubcase(m_context, "basic-ms-cs-uint", TestSubcase::Create<BasicMS<uvec4, 4>>));
1251     addChild(new TestSubcase(m_context, "advanced-changeSize", TestSubcase::Create<AdvancedChangeSize>));
1252     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-float", TestSubcase::Create<AdvancedNonMS<vec4, 0>>));
1253     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 0>>));
1254     addChild(new TestSubcase(m_context, "advanced-nonMS-vs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 0>>));
1255     addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-float", TestSubcase::Create<AdvancedNonMS<vec4, 1>>));
1256     addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 1>>));
1257     addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 1>>));
1258     addChild(new TestSubcase(m_context, "advanced-nonMS-tes-float", TestSubcase::Create<AdvancedNonMS<vec4, 2>>));
1259     addChild(new TestSubcase(m_context, "advanced-nonMS-tes-int", TestSubcase::Create<AdvancedNonMS<ivec4, 2>>));
1260     addChild(new TestSubcase(m_context, "advanced-nonMS-tes-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 2>>));
1261     addChild(new TestSubcase(m_context, "advanced-nonMS-gs-float", TestSubcase::Create<AdvancedNonMS<vec4, 3>>));
1262     addChild(new TestSubcase(m_context, "advanced-nonMS-gs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 3>>));
1263     addChild(new TestSubcase(m_context, "advanced-nonMS-gs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 3>>));
1264     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-float", TestSubcase::Create<AdvancedNonMS<vec4, 5>>));
1265     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 5>>));
1266     addChild(new TestSubcase(m_context, "advanced-nonMS-fs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 5>>));
1267     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-float", TestSubcase::Create<AdvancedNonMS<vec4, 4>>));
1268     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 4>>));
1269     addChild(new TestSubcase(m_context, "advanced-nonMS-cs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 4>>));
1270     addChild(new TestSubcase(m_context, "advanced-ms-vs-float", TestSubcase::Create<AdvancedMS<vec4, 0>>));
1271     addChild(new TestSubcase(m_context, "advanced-ms-vs-int", TestSubcase::Create<AdvancedMS<ivec4, 0>>));
1272     addChild(new TestSubcase(m_context, "advanced-ms-vs-uint", TestSubcase::Create<AdvancedMS<uvec4, 0>>));
1273     addChild(new TestSubcase(m_context, "advanced-ms-tcs-float", TestSubcase::Create<AdvancedMS<vec4, 1>>));
1274     addChild(new TestSubcase(m_context, "advanced-ms-tcs-int", TestSubcase::Create<AdvancedMS<ivec4, 1>>));
1275     addChild(new TestSubcase(m_context, "advanced-ms-tcs-uint", TestSubcase::Create<AdvancedMS<uvec4, 1>>));
1276     addChild(new TestSubcase(m_context, "advanced-ms-tes-float", TestSubcase::Create<AdvancedMS<vec4, 2>>));
1277     addChild(new TestSubcase(m_context, "advanced-ms-tes-int", TestSubcase::Create<AdvancedMS<ivec4, 2>>));
1278     addChild(new TestSubcase(m_context, "advanced-ms-tes-uint", TestSubcase::Create<AdvancedMS<uvec4, 2>>));
1279     addChild(new TestSubcase(m_context, "advanced-ms-gs-float", TestSubcase::Create<AdvancedMS<vec4, 3>>));
1280     addChild(new TestSubcase(m_context, "advanced-ms-gs-int", TestSubcase::Create<AdvancedMS<ivec4, 3>>));
1281     addChild(new TestSubcase(m_context, "advanced-ms-gs-uint", TestSubcase::Create<AdvancedMS<uvec4, 3>>));
1282     addChild(new TestSubcase(m_context, "advanced-ms-fs-float", TestSubcase::Create<AdvancedMS<vec4, 5>>));
1283     addChild(new TestSubcase(m_context, "advanced-ms-fs-int", TestSubcase::Create<AdvancedMS<ivec4, 5>>));
1284     addChild(new TestSubcase(m_context, "advanced-ms-fs-uint", TestSubcase::Create<AdvancedMS<uvec4, 5>>));
1285     addChild(new TestSubcase(m_context, "advanced-ms-cs-float", TestSubcase::Create<AdvancedMS<vec4, 4>>));
1286     addChild(new TestSubcase(m_context, "advanced-ms-cs-int", TestSubcase::Create<AdvancedMS<ivec4, 4>>));
1287     addChild(new TestSubcase(m_context, "advanced-ms-cs-uint", TestSubcase::Create<AdvancedMS<uvec4, 4>>));
1288     addChild(new TestSubcase(m_context, "negative-compileTime", TestSubcase::Create<NegativeCompileTime>));
1289 }
1290 
1291 } // namespace gl4cts
1292