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 }
772