• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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