• 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 "gl4cShaderImageLoadStoreTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuPlatform.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include <assert.h>
33 #include <climits>
34 #include <cmath>
35 #include <cstdarg>
36 #include <deque>
37 #include <iomanip>
38 #include <map>
39 #include <sstream>
40 #include <tcuFloat.hpp>
41 
42 namespace gl4cts
43 {
44 using namespace glw;
45 
46 namespace
47 {
48 typedef tcu::Vec2  vec2;
49 typedef tcu::Vec4  vec4;
50 typedef tcu::IVec4 ivec4;
51 typedef tcu::UVec4 uvec4;
52 typedef tcu::Mat4  mat4;
53 
54 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
55 {
Title()56 	virtual std::string Title()
57 	{
58 		return "";
59 	}
60 
Purpose()61 	virtual std::string Purpose()
62 	{
63 		return "";
64 	}
65 
Method()66 	virtual std::string Method()
67 	{
68 		return "";
69 	}
70 
PassCriteria()71 	virtual std::string PassCriteria()
72 	{
73 		return "";
74 	}
75 
76 public:
SupportedInVS(int requiredVS)77 	bool SupportedInVS(int requiredVS)
78 	{
79 		GLint imagesVS;
80 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
81 		if (imagesVS >= requiredVS)
82 			return true;
83 		else
84 		{
85 			std::ostringstream reason;
86 			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
87 				   << std::endl;
88 			OutputNotSupported(reason.str());
89 			return false;
90 		}
91 	}
92 
SupportedInTCS(int requiredTCS)93 	bool SupportedInTCS(int requiredTCS)
94 	{
95 		GLint imagesTCS;
96 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
97 		if (imagesTCS >= requiredTCS)
98 			return true;
99 		else
100 		{
101 			std::ostringstream reason;
102 			reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
103 				   << std::endl;
104 			OutputNotSupported(reason.str());
105 			return false;
106 		}
107 	}
108 
SupportedInTES(int requiredTES)109 	bool SupportedInTES(int requiredTES)
110 	{
111 		GLint imagesTES;
112 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
113 		if (imagesTES >= requiredTES)
114 			return true;
115 		else
116 		{
117 			std::ostringstream reason;
118 			reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
119 				   << std::endl;
120 			OutputNotSupported(reason.str());
121 			return false;
122 		}
123 	}
124 
SupportedInGS(int requiredGS)125 	bool SupportedInGS(int requiredGS)
126 	{
127 		GLint imagesGS;
128 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
129 		if (imagesGS >= requiredGS)
130 			return true;
131 		else
132 		{
133 			std::ostringstream reason;
134 			reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
135 				   << std::endl;
136 			OutputNotSupported(reason.str());
137 			return false;
138 		}
139 	}
140 
SupportedInGeomStages(int required)141 	bool SupportedInGeomStages(int required)
142 	{
143 		return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
144 			   SupportedInGS(required);
145 	}
146 
SupportedInStage(int stage,int required)147 	bool SupportedInStage(int stage, int required)
148 	{
149 		switch (stage)
150 		{
151 		case 0:
152 			return SupportedInVS(required);
153 		case 1:
154 			return SupportedInTCS(required);
155 		case 2:
156 			return SupportedInTES(required);
157 		case 3:
158 			return SupportedInGS(required);
159 		default:
160 			return true;
161 		}
162 	}
163 
SupportedSamples(int required)164 	bool SupportedSamples(int required)
165 	{
166 		int i;
167 		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
168 		if (i >= required)
169 			return true;
170 		else
171 		{
172 			std::ostringstream reason;
173 			reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
174 			OutputNotSupported(reason.str());
175 			return false;
176 		}
177 	}
178 
getWindowWidth()179 	int getWindowWidth()
180 	{
181 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
182 		return renderTarget.getWidth();
183 	}
184 
getWindowHeight()185 	int getWindowHeight()
186 	{
187 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
188 		return renderTarget.getHeight();
189 	}
190 
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)191 	void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
192 	{
193 		vk::PlatformMemoryLimits memoryLimits;
194 		m_context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
195 		GLsizeiptr sysSpace		  = memoryLimits.totalSystemMemory;
196 		GLsizeiptr devSpace		  = memoryLimits.totalDeviceLocalMemory;
197 		int		   devInSysLayers = 0;
198 
199 		if (devSpace == 0)
200 		{
201 			devInSysLayers = devLayers;
202 			devLayers	  = 0;
203 		}
204 
205 		// Check if available memory is enough
206 		GLsizeiptr pixelsPerLayer = width * height;
207 		GLsizeiptr sysRequired	= pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
208 		GLsizeiptr devRequired	= pixelsPerLayer * devBPP * devLayers;
209 		if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
210 		{
211 			return;
212 		}
213 
214 		// Scales the width and height such that the overall texture fits into
215 		// the available space for both system and device.
216 		GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
217 		if (devSpace != 0)
218 		{
219 			GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
220 			scale			  = de::min(devScale, scale);
221 		}
222 		int newWidth  = int(width * scale);
223 		int newHeight = int(height * scale);
224 
225 		m_context.getTestContext().getLog()
226 			<< tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
227 			<< " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
228 
229 		width  = newWidth;
230 		height = newHeight;
231 	}
232 
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)233 	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
234 	{
235 		if (fabs(c0[0] - c1[0]) > epsilon[0])
236 			return false;
237 		if (fabs(c0[1] - c1[1]) > epsilon[1])
238 			return false;
239 		if (fabs(c0[2] - c1[2]) > epsilon[2])
240 			return false;
241 		if (fabs(c0[3] - c1[3]) > epsilon[3])
242 			return false;
243 		return true;
244 	}
245 
IsEqual(vec4 a,vec4 b)246 	bool IsEqual(vec4 a, vec4 b)
247 	{
248 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
249 	}
250 
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)251 	bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
252 	{
253 		if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
254 		{
255 			return ColorEqual(v0, v1, vec4(0.0001f));
256 		}
257 		else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
258 		{
259 			return ColorEqual(v0, v1, vec4(0.01f));
260 		}
261 		return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
262 	}
263 
Equal(const ivec4 & a,const ivec4 & b,GLenum)264 	bool Equal(const ivec4& a, const ivec4& b, GLenum)
265 	{
266 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
267 	}
268 
Equal(const uvec4 & a,const uvec4 & b,GLenum)269 	bool Equal(const uvec4& a, const uvec4& b, GLenum)
270 	{
271 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
272 	}
273 
274 	template <class T>
ToString(T v)275 	std::string ToString(T v)
276 	{
277 		std::ostringstream s;
278 		s << "[";
279 		for (int i = 0; i < 4; ++i)
280 			s << v[i] << (i == 3 ? "" : ",");
281 		s << "]";
282 		return s.str();
283 	}
284 
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)285 	bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
286 	{
287 		bool					 status		  = true;
288 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
289 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
290 		vec4					 g_color_eps  = vec4(
291 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
292 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
293 
294 		std::vector<vec4> fb(w * h);
295 		glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
296 
297 		for (int yy = 0; yy < h; ++yy)
298 		{
299 			for (int xx = 0; xx < w; ++xx)
300 			{
301 				const int idx = yy * w + xx;
302 				if (!ColorEqual(fb[idx], expected, g_color_eps))
303 				{
304 					m_context.getTestContext().getLog()
305 						<< tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
306 						<< tcu::TestLog::EndMessage;
307 					status = false;
308 					return status;
309 				}
310 			}
311 		}
312 		return status;
313 	}
314 
CompileShader(GLuint shader)315 	bool CompileShader(GLuint shader)
316 	{
317 		glCompileShader(shader);
318 
319 		GLint status;
320 		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
321 		if (status == GL_FALSE)
322 		{
323 			GLsizei length;
324 			GLchar  log[1024];
325 			glGetShaderInfoLog(shader, sizeof(log), &length, log);
326 			if (length > 1)
327 			{
328 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
329 													<< log << tcu::TestLog::EndMessage;
330 			}
331 			return false;
332 		}
333 		return true;
334 	}
335 
LinkProgram(GLuint program)336 	bool LinkProgram(GLuint program)
337 	{
338 		glLinkProgram(program);
339 
340 		GLint status;
341 		glGetProgramiv(program, GL_LINK_STATUS, &status);
342 		if (status == GL_FALSE)
343 		{
344 			GLsizei length;
345 			GLchar  log[1024];
346 			glGetProgramInfoLog(program, sizeof(log), &length, log);
347 			if (length > 1)
348 			{
349 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
350 													<< log << tcu::TestLog::EndMessage;
351 			}
352 			return false;
353 		}
354 		return true;
355 	}
356 
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)357 	GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
358 						const char* src_fs, bool* result = NULL)
359 	{
360 		const GLuint p = glCreateProgram();
361 
362 		if (src_vs)
363 		{
364 			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
365 			glAttachShader(p, sh);
366 			glDeleteShader(sh);
367 			glShaderSource(sh, 1, &src_vs, NULL);
368 			if (!CompileShader(sh))
369 			{
370 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
371 				if (result)
372 					*result = false;
373 				return p;
374 			}
375 		}
376 		if (src_tcs)
377 		{
378 			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
379 			glAttachShader(p, sh);
380 			glDeleteShader(sh);
381 			glShaderSource(sh, 1, &src_tcs, NULL);
382 			if (!CompileShader(sh))
383 			{
384 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
385 				if (result)
386 					*result = false;
387 				return p;
388 			}
389 		}
390 		if (src_tes)
391 		{
392 			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
393 			glAttachShader(p, sh);
394 			glDeleteShader(sh);
395 			glShaderSource(sh, 1, &src_tes, NULL);
396 			if (!CompileShader(sh))
397 			{
398 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
399 				if (result)
400 					*result = false;
401 				return p;
402 			}
403 		}
404 		if (src_gs)
405 		{
406 			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
407 			glAttachShader(p, sh);
408 			glDeleteShader(sh);
409 			glShaderSource(sh, 1, &src_gs, NULL);
410 			if (!CompileShader(sh))
411 			{
412 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
413 				if (result)
414 					*result = false;
415 				return p;
416 			}
417 		}
418 		if (src_fs)
419 		{
420 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
421 			glAttachShader(p, sh);
422 			glDeleteShader(sh);
423 			glShaderSource(sh, 1, &src_fs, NULL);
424 			if (!CompileShader(sh))
425 			{
426 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
427 				if (result)
428 					*result = false;
429 				return p;
430 			}
431 		}
432 		if (!LinkProgram(p))
433 		{
434 			if (src_vs)
435 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
436 			if (src_tcs)
437 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
438 			if (src_tes)
439 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
440 			if (src_gs)
441 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
442 			if (src_fs)
443 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
444 			if (result)
445 				*result = false;
446 			return p;
447 		}
448 
449 		return p;
450 	}
451 
BuildShaderProgram(GLenum type,const char * src)452 	GLuint BuildShaderProgram(GLenum type, const char* src)
453 	{
454 		const GLuint p = glCreateShaderProgramv(type, 1, &src);
455 
456 		GLint status;
457 		glGetProgramiv(p, GL_LINK_STATUS, &status);
458 		if (status == GL_FALSE)
459 		{
460 			GLchar log[1024];
461 			glGetProgramInfoLog(p, sizeof(log), NULL, log);
462 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
463 												<< log << "\n"
464 												<< src << tcu::TestLog::EndMessage;
465 		}
466 
467 		return p;
468 	}
469 
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)470 	void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
471 	{
472 		assert(vao && vbo);
473 
474 		// interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
475 		const float v[] = {
476 			-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,  1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
477 			0.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f,
478 			1.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f,  0.0f,
479 		};
480 		glGenBuffers(1, vbo);
481 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
482 		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
483 		glBindBuffer(GL_ARRAY_BUFFER, 0);
484 
485 		if (ebo)
486 		{
487 			std::vector<GLushort> index_data(4);
488 			for (int i = 0; i < 4; ++i)
489 			{
490 				index_data[i] = static_cast<GLushort>(i);
491 			}
492 			glGenBuffers(1, ebo);
493 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
494 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
495 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
496 		}
497 
498 		glGenVertexArrays(1, vao);
499 		glBindVertexArray(*vao);
500 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
501 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
502 		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
503 		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
504 		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
505 		glBindBuffer(GL_ARRAY_BUFFER, 0);
506 		glEnableVertexAttribArray(0);
507 		glEnableVertexAttribArray(1);
508 		glEnableVertexAttribArray(2);
509 		glEnableVertexAttribArray(3);
510 		if (ebo)
511 		{
512 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
513 		}
514 		glBindVertexArray(0);
515 	}
516 
FormatEnumToString(GLenum e)517 	std::string FormatEnumToString(GLenum e)
518 	{
519 		switch (e)
520 		{
521 		case GL_RGBA32F:
522 			return "rgba32f";
523 		case GL_RGBA16F:
524 			return "rgba16f";
525 		case GL_RG32F:
526 			return "rg32f";
527 		case GL_RG16F:
528 			return "rg16f";
529 		case GL_R11F_G11F_B10F:
530 			return "r11f_g11f_b10f";
531 		case GL_R32F:
532 			return "r32f";
533 		case GL_R16F:
534 			return "r16f";
535 
536 		case GL_RGBA32UI:
537 			return "rgba32ui";
538 		case GL_RGBA16UI:
539 			return "rgba16ui";
540 		case GL_RGB10_A2UI:
541 			return "rgb10_a2ui";
542 		case GL_RGBA8UI:
543 			return "rgba8ui";
544 		case GL_RG32UI:
545 			return "rg32ui";
546 		case GL_RG16UI:
547 			return "rg16ui";
548 		case GL_RG8UI:
549 			return "rg8ui";
550 		case GL_R32UI:
551 			return "r32ui";
552 		case GL_R16UI:
553 			return "r16ui";
554 		case GL_R8UI:
555 			return "r8ui";
556 
557 		case GL_RGBA32I:
558 			return "rgba32i";
559 		case GL_RGBA16I:
560 			return "rgba16i";
561 		case GL_RGBA8I:
562 			return "rgba8i";
563 		case GL_RG32I:
564 			return "rg32i";
565 		case GL_RG16I:
566 			return "rg16i";
567 		case GL_RG8I:
568 			return "rg8i";
569 		case GL_R32I:
570 			return "r32i";
571 		case GL_R16I:
572 			return "r16i";
573 		case GL_R8I:
574 			return "r8i";
575 
576 		case GL_RGBA16:
577 			return "rgba16";
578 		case GL_RGB10_A2:
579 			return "rgb10_a2";
580 		case GL_RGBA8:
581 			return "rgba8";
582 		case GL_RG16:
583 			return "rg16";
584 		case GL_RG8:
585 			return "rg8";
586 		case GL_R16:
587 			return "r16";
588 		case GL_R8:
589 			return "r8";
590 
591 		case GL_RGBA16_SNORM:
592 			return "rgba16_snorm";
593 		case GL_RGBA8_SNORM:
594 			return "rgba8_snorm";
595 		case GL_RG16_SNORM:
596 			return "rg16_snorm";
597 		case GL_RG8_SNORM:
598 			return "rg8_snorm";
599 		case GL_R16_SNORM:
600 			return "r16_snorm";
601 		case GL_R8_SNORM:
602 			return "r8_snorm";
603 		}
604 
605 		assert(0);
606 		return "";
607 	}
608 
StageName(int stage)609 	const char* StageName(int stage)
610 	{
611 		switch (stage)
612 		{
613 		case 0:
614 			return "Vertex Shader";
615 		case 1:
616 			return "Tessellation Control Shader";
617 		case 2:
618 			return "Tessellation Evaluation Shader";
619 		case 3:
620 			return "Geometry Shader";
621 		case 4:
622 			return "Compute Shader";
623 		}
624 		assert(0);
625 		return NULL;
626 	}
627 
628 	template <typename T>
629 	GLenum Format();
630 
631 	template <typename T>
632 	GLenum Type();
633 
634 	template <typename T>
635 	std::string TypePrefix();
636 
637 	template <typename T>
638 	GLenum ImageType(GLenum target);
639 
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)640 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
641 	{
642 		glClearBufferfv(buffer, drawbuffer, &color[0]);
643 	}
644 
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)645 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
646 	{
647 		glClearBufferiv(buffer, drawbuffer, &color[0]);
648 	}
649 
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)650 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
651 	{
652 		glClearBufferuiv(buffer, drawbuffer, &color[0]);
653 	}
654 
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)655 	bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
656 					  GLint size, GLenum type)
657 	{
658 		std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
659 		assert(iter != name_index_map.end());
660 
661 		GLchar  name_gl[32];
662 		GLsizei length_gl;
663 		GLint   size_gl;
664 		GLenum  type_gl;
665 
666 		glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
667 
668 		if (std::string(name_gl) != name)
669 		{
670 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
671 												<< " should be " << name << tcu::TestLog::EndMessage;
672 			return false;
673 		}
674 		if (length_gl != static_cast<GLsizei>(name.length()))
675 		{
676 			m_context.getTestContext().getLog()
677 				<< tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
678 				<< ")" << tcu::TestLog::EndMessage;
679 			return false;
680 		}
681 		if (size_gl != size)
682 		{
683 			m_context.getTestContext().getLog()
684 				<< tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
685 				<< ")" << tcu::TestLog::EndMessage;
686 			return false;
687 		}
688 		if (type_gl != type)
689 		{
690 			m_context.getTestContext().getLog()
691 				<< tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
692 				<< ")" << tcu::TestLog::EndMessage;
693 			return false;
694 		}
695 
696 		return true;
697 	}
698 
CheckMax(GLenum pname,GLint min_value)699 	bool CheckMax(GLenum pname, GLint min_value)
700 	{
701 		GLboolean b;
702 		GLint	 i;
703 		GLfloat   f;
704 		GLdouble  d;
705 		GLint64   i64;
706 
707 		glGetIntegerv(pname, &i);
708 		if (i < min_value)
709 			return false;
710 
711 		glGetBooleanv(pname, &b);
712 		if (b != (i ? GL_TRUE : GL_FALSE))
713 			return false;
714 
715 		glGetFloatv(pname, &f);
716 		if (static_cast<GLint>(f) < min_value)
717 			return false;
718 
719 		glGetDoublev(pname, &d);
720 		if (static_cast<GLint>(d) < min_value)
721 			return false;
722 
723 		glGetInteger64v(pname, &i64);
724 		if (static_cast<GLint>(i64) < min_value)
725 			return false;
726 
727 		return true;
728 	}
729 
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)730 	bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
731 					  GLenum format)
732 	{
733 		GLint	 i;
734 		GLboolean b;
735 
736 		glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
737 		if (static_cast<GLuint>(i) != texture)
738 		{
739 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
740 												<< " should be " << texture << tcu::TestLog::EndMessage;
741 			return false;
742 		}
743 		glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
744 		if (b != (i ? GL_TRUE : GL_FALSE))
745 		{
746 			m_context.getTestContext().getLog()
747 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
748 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
749 			return false;
750 		}
751 
752 		glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
753 		if (i != level)
754 		{
755 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
756 												<< " should be " << level << tcu::TestLog::EndMessage;
757 			return false;
758 		}
759 		glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
760 		if (b != (i ? GL_TRUE : GL_FALSE))
761 		{
762 			m_context.getTestContext().getLog()
763 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
764 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
765 			return false;
766 		}
767 
768 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
769 		if (i != layered)
770 		{
771 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
772 												<< " should be " << layered << tcu::TestLog::EndMessage;
773 			return false;
774 		}
775 		glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
776 		if (b != (i ? GL_TRUE : GL_FALSE))
777 		{
778 			m_context.getTestContext().getLog()
779 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
780 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
781 			return false;
782 		}
783 
784 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
785 		if (i != layer)
786 		{
787 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
788 												<< " should be " << layer << tcu::TestLog::EndMessage;
789 			return false;
790 		}
791 		glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
792 		if (b != (i ? GL_TRUE : GL_FALSE))
793 		{
794 			m_context.getTestContext().getLog()
795 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
796 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
797 			return false;
798 		}
799 
800 		glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
801 		if (static_cast<GLenum>(i) != access)
802 		{
803 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
804 												<< " should be " << access << tcu::TestLog::EndMessage;
805 			return false;
806 		}
807 		glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
808 		if (b != (i ? GL_TRUE : GL_FALSE))
809 		{
810 			m_context.getTestContext().getLog()
811 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
812 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
813 			return false;
814 		}
815 
816 		glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
817 		if (static_cast<GLenum>(i) != format)
818 		{
819 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
820 												<< " should be " << format << tcu::TestLog::EndMessage;
821 			return false;
822 		}
823 		glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
824 		if (b != (i ? GL_TRUE : GL_FALSE))
825 		{
826 			m_context.getTestContext().getLog()
827 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
828 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
829 			return false;
830 		}
831 
832 		return true;
833 	}
EnumToString(GLenum e)834 	const char* EnumToString(GLenum e)
835 	{
836 		switch (e)
837 		{
838 		case GL_TEXTURE_1D:
839 			return "GL_TEXTURE_1D";
840 		case GL_TEXTURE_2D:
841 			return "GL_TEXTURE_2D";
842 		case GL_TEXTURE_3D:
843 			return "GL_TEXTURE_3D";
844 		case GL_TEXTURE_RECTANGLE:
845 			return "GL_TEXTURE_RECTANGLE";
846 		case GL_TEXTURE_CUBE_MAP:
847 			return "GL_TEXTURE_CUBE_MAP";
848 		case GL_TEXTURE_1D_ARRAY:
849 			return "GL_TEXTURE_1D_ARRAY";
850 		case GL_TEXTURE_2D_ARRAY:
851 			return "GL_TEXTURE_2D_ARRAY";
852 		case GL_TEXTURE_CUBE_MAP_ARRAY:
853 			return "GL_TEXTURE_CUBE_MAP_ARRAY";
854 
855 		default:
856 			assert(0);
857 			break;
858 		}
859 		return NULL;
860 	}
861 };
862 
863 template <>
Format()864 GLenum ShaderImageLoadStoreBase::Format<vec4>()
865 {
866 	return GL_RGBA;
867 }
868 
869 template <>
Format()870 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
871 {
872 	return GL_RGBA_INTEGER;
873 }
874 
875 template <>
Format()876 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
877 {
878 	return GL_RGBA_INTEGER;
879 }
880 
881 template <>
Format()882 GLenum ShaderImageLoadStoreBase::Format<GLint>()
883 {
884 	return GL_RED_INTEGER;
885 }
886 
887 template <>
Format()888 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
889 {
890 	return GL_RED_INTEGER;
891 }
892 
893 template <>
Type()894 GLenum ShaderImageLoadStoreBase::Type<vec4>()
895 {
896 	return GL_FLOAT;
897 }
898 
899 template <>
Type()900 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
901 {
902 	return GL_INT;
903 }
904 
905 template <>
Type()906 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
907 {
908 	return GL_UNSIGNED_INT;
909 }
910 
911 template <>
Type()912 GLenum ShaderImageLoadStoreBase::Type<GLint>()
913 {
914 	return GL_INT;
915 }
916 
917 template <>
Type()918 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
919 {
920 	return GL_UNSIGNED_INT;
921 }
922 
923 template <>
TypePrefix()924 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
925 {
926 	return "";
927 }
928 
929 template <>
TypePrefix()930 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
931 {
932 	return "i";
933 }
934 
935 template <>
TypePrefix()936 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
937 {
938 	return "u";
939 }
940 
941 template <>
TypePrefix()942 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
943 {
944 	return "i";
945 }
946 
947 template <>
TypePrefix()948 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
949 {
950 	return "u";
951 }
952 
953 template <>
ImageType(GLenum target)954 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
955 {
956 	switch (target)
957 	{
958 	case GL_TEXTURE_1D:
959 		return GL_IMAGE_1D;
960 	case GL_TEXTURE_2D:
961 		return GL_IMAGE_2D;
962 	case GL_TEXTURE_3D:
963 		return GL_IMAGE_3D;
964 	case GL_TEXTURE_RECTANGLE:
965 		return GL_IMAGE_2D_RECT;
966 	case GL_TEXTURE_CUBE_MAP:
967 		return GL_IMAGE_CUBE;
968 	case GL_TEXTURE_BUFFER:
969 		return GL_IMAGE_BUFFER;
970 	case GL_TEXTURE_1D_ARRAY:
971 		return GL_IMAGE_1D_ARRAY;
972 	case GL_TEXTURE_2D_ARRAY:
973 		return GL_IMAGE_2D_ARRAY;
974 	case GL_TEXTURE_CUBE_MAP_ARRAY:
975 		return GL_IMAGE_CUBE_MAP_ARRAY;
976 	case GL_TEXTURE_2D_MULTISAMPLE:
977 		return GL_IMAGE_2D_MULTISAMPLE;
978 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
979 		return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
980 	}
981 	assert(0);
982 	return 0;
983 }
984 
985 template <>
ImageType(GLenum target)986 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
987 {
988 	switch (target)
989 	{
990 	case GL_TEXTURE_1D:
991 		return GL_INT_IMAGE_1D;
992 	case GL_TEXTURE_2D:
993 		return GL_INT_IMAGE_2D;
994 	case GL_TEXTURE_3D:
995 		return GL_INT_IMAGE_3D;
996 	case GL_TEXTURE_RECTANGLE:
997 		return GL_INT_IMAGE_2D_RECT;
998 	case GL_TEXTURE_CUBE_MAP:
999 		return GL_INT_IMAGE_CUBE;
1000 	case GL_TEXTURE_BUFFER:
1001 		return GL_INT_IMAGE_BUFFER;
1002 	case GL_TEXTURE_1D_ARRAY:
1003 		return GL_INT_IMAGE_1D_ARRAY;
1004 	case GL_TEXTURE_2D_ARRAY:
1005 		return GL_INT_IMAGE_2D_ARRAY;
1006 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1007 		return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1008 	case GL_TEXTURE_2D_MULTISAMPLE:
1009 		return GL_INT_IMAGE_2D_MULTISAMPLE;
1010 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1011 		return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1012 	}
1013 	assert(0);
1014 	return 0;
1015 }
1016 
1017 template <>
ImageType(GLenum target)1018 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1019 {
1020 	switch (target)
1021 	{
1022 	case GL_TEXTURE_1D:
1023 		return GL_UNSIGNED_INT_IMAGE_1D;
1024 	case GL_TEXTURE_2D:
1025 		return GL_UNSIGNED_INT_IMAGE_2D;
1026 	case GL_TEXTURE_3D:
1027 		return GL_UNSIGNED_INT_IMAGE_3D;
1028 	case GL_TEXTURE_RECTANGLE:
1029 		return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1030 	case GL_TEXTURE_CUBE_MAP:
1031 		return GL_UNSIGNED_INT_IMAGE_CUBE;
1032 	case GL_TEXTURE_BUFFER:
1033 		return GL_UNSIGNED_INT_IMAGE_BUFFER;
1034 	case GL_TEXTURE_1D_ARRAY:
1035 		return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1036 	case GL_TEXTURE_2D_ARRAY:
1037 		return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1038 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1039 		return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1040 	case GL_TEXTURE_2D_MULTISAMPLE:
1041 		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1042 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1043 		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1044 	}
1045 	assert(0);
1046 	return 0;
1047 }
1048 
1049 //-----------------------------------------------------------------------------
1050 // 1.1.1 BasicAPIGet
1051 //-----------------------------------------------------------------------------
1052 class BasicAPIGet : public ShaderImageLoadStoreBase
1053 {
Run()1054 	virtual long Run()
1055 	{
1056 		if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1057 		{
1058 			m_context.getTestContext().getLog()
1059 				<< tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1060 			return ERROR;
1061 		}
1062 		if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1063 		{
1064 			m_context.getTestContext().getLog()
1065 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1066 				<< tcu::TestLog::EndMessage;
1067 			return ERROR;
1068 		}
1069 		if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1070 		{
1071 			m_context.getTestContext().getLog()
1072 				<< tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1073 			return ERROR;
1074 		}
1075 		if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1076 		{
1077 			m_context.getTestContext().getLog()
1078 				<< tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1079 				<< tcu::TestLog::EndMessage;
1080 			return ERROR;
1081 		}
1082 		if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1083 		{
1084 			m_context.getTestContext().getLog()
1085 				<< tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1086 				<< tcu::TestLog::EndMessage;
1087 			return ERROR;
1088 		}
1089 		if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1090 		{
1091 			m_context.getTestContext().getLog()
1092 				<< tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1093 				<< tcu::TestLog::EndMessage;
1094 			return ERROR;
1095 		}
1096 		if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1097 		{
1098 			m_context.getTestContext().getLog()
1099 				<< tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1100 				<< tcu::TestLog::EndMessage;
1101 			return ERROR;
1102 		}
1103 		if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1104 		{
1105 			m_context.getTestContext().getLog()
1106 				<< tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1107 				<< tcu::TestLog::EndMessage;
1108 			return ERROR;
1109 		}
1110 		if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1111 		{
1112 			m_context.getTestContext().getLog()
1113 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1114 				<< tcu::TestLog::EndMessage;
1115 			return ERROR;
1116 		}
1117 		return NO_ERROR;
1118 	}
1119 };
1120 //-----------------------------------------------------------------------------
1121 // 1.1.2 BasicAPIBind
1122 //-----------------------------------------------------------------------------
1123 class BasicAPIBind : public ShaderImageLoadStoreBase
1124 {
1125 	GLuint m_texture;
1126 
Setup()1127 	virtual long Setup()
1128 	{
1129 		m_texture = 0;
1130 		return NO_ERROR;
1131 	}
1132 
Run()1133 	virtual long Run()
1134 	{
1135 		for (GLuint index = 0; index < 8; ++index)
1136 		{
1137 			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1138 			{
1139 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1140 													<< " has invalid default state." << tcu::TestLog::EndMessage;
1141 				return ERROR;
1142 			}
1143 		}
1144 
1145 		glGenTextures(1, &m_texture);
1146 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1147 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1148 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1149 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1152 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1153 
1154 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1155 		if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1156 			return ERROR;
1157 
1158 		glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1159 		if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1160 			return ERROR;
1161 
1162 		glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1163 		if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1164 			return ERROR;
1165 
1166 		glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1167 		if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1168 			return ERROR;
1169 
1170 		glDeleteTextures(1, &m_texture);
1171 		m_texture = 0;
1172 
1173 		for (GLuint index = 0; index < 8; ++index)
1174 		{
1175 			GLint name;
1176 			glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1177 			if (name != 0)
1178 			{
1179 				m_context.getTestContext().getLog()
1180 					<< tcu::TestLog::Message << "Binding point " << index
1181 					<< " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1182 				return ERROR;
1183 			}
1184 		}
1185 
1186 		return NO_ERROR;
1187 	}
1188 
Cleanup()1189 	virtual long Cleanup()
1190 	{
1191 		glDeleteTextures(1, &m_texture);
1192 		return NO_ERROR;
1193 	}
1194 };
1195 //-----------------------------------------------------------------------------
1196 // 1.1.3 BasicAPIBarrier
1197 //-----------------------------------------------------------------------------
1198 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1199 {
Run()1200 	virtual long Run()
1201 	{
1202 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1203 		glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1204 		glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1205 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1206 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1207 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1208 		glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1209 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1210 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1211 		glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1212 		glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1213 		glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1214 
1215 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1216 						GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1217 						GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1218 						GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1219 
1220 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
1221 
1222 		return NO_ERROR;
1223 	}
1224 };
1225 //-----------------------------------------------------------------------------
1226 // 1.1.4 BasicAPITexParam
1227 //-----------------------------------------------------------------------------
1228 class BasicAPITexParam : public ShaderImageLoadStoreBase
1229 {
1230 	GLuint m_texture;
1231 
Setup()1232 	virtual long Setup()
1233 	{
1234 		m_texture = 0;
1235 		return NO_ERROR;
1236 	}
1237 
Run()1238 	virtual long Run()
1239 	{
1240 		glGenTextures(1, &m_texture);
1241 		glBindTexture(GL_TEXTURE_2D, m_texture);
1242 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1243 
1244 		GLint   i;
1245 		GLfloat f;
1246 		GLuint  ui;
1247 
1248 		glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1249 		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1250 		{
1251 			m_context.getTestContext().getLog()
1252 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1253 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1254 				<< tcu::TestLog::EndMessage;
1255 			return ERROR;
1256 		}
1257 		glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1258 		if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1259 		{
1260 			m_context.getTestContext().getLog()
1261 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1262 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1263 				<< tcu::TestLog::EndMessage;
1264 			return ERROR;
1265 		}
1266 		glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1267 		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1268 		{
1269 			m_context.getTestContext().getLog()
1270 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1271 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1272 				<< tcu::TestLog::EndMessage;
1273 			return ERROR;
1274 		}
1275 		glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1276 		if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1277 		{
1278 			m_context.getTestContext().getLog()
1279 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1280 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1281 				<< tcu::TestLog::EndMessage;
1282 			return ERROR;
1283 		}
1284 
1285 		return NO_ERROR;
1286 	}
1287 
Cleanup()1288 	virtual long Cleanup()
1289 	{
1290 		glDeleteTextures(1, &m_texture);
1291 		return NO_ERROR;
1292 	}
1293 };
1294 //-----------------------------------------------------------------------------
1295 // 1.2.1 BasicAllFormatsStore
1296 //-----------------------------------------------------------------------------
1297 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1298 {
1299 	GLuint m_vao;
1300 	GLuint m_vbo;
1301 
Setup()1302 	virtual long Setup()
1303 	{
1304 		m_vao = 0;
1305 		m_vbo = 0;
1306 		return NO_ERROR;
1307 	}
1308 
Run()1309 	virtual long Run()
1310 	{
1311 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1312 
1313 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1314 			return ERROR;
1315 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1316 			return ERROR;
1317 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1318 			return ERROR;
1319 
1320 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1321 			return ERROR;
1322 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1323 			return ERROR;
1324 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1325 			return ERROR;
1326 
1327 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1328 			return ERROR;
1329 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1330 			return ERROR;
1331 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1332 			return ERROR;
1333 
1334 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1335 			return ERROR;
1336 
1337 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1338 			return ERROR;
1339 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1340 			return ERROR;
1341 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1342 			return ERROR;
1343 
1344 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1345 			return ERROR;
1346 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1347 			return ERROR;
1348 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1349 			return ERROR;
1350 
1351 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1352 			return ERROR;
1353 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354 			return ERROR;
1355 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1356 			return ERROR;
1357 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1358 			return ERROR;
1359 
1360 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1361 			return ERROR;
1362 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1363 			return ERROR;
1364 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1365 			return ERROR;
1366 
1367 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1368 			return ERROR;
1369 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1370 			return ERROR;
1371 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1372 			return ERROR;
1373 
1374 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1375 			return ERROR;
1376 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1377 			return ERROR;
1378 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1379 			return ERROR;
1380 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1381 			return ERROR;
1382 
1383 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1384 			return ERROR;
1385 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1386 			return ERROR;
1387 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1388 			return ERROR;
1389 
1390 		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1391 			return ERROR;
1392 		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1393 			return ERROR;
1394 		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1395 			return ERROR;
1396 
1397 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1398 			return ERROR;
1399 		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1400 			return ERROR;
1401 		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1402 			return ERROR;
1403 
1404 		return NO_ERROR;
1405 	}
1406 
1407 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1408 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1409 	{
1410 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1411 							 "  gl_Position = i_position;" NL "}";
1412 		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1413 		const int	  kSize   = 16;
1414 		std::vector<T> data(kSize * kSize);
1415 		GLuint		   texture;
1416 		glGenTextures(1, &texture);
1417 
1418 		for (GLuint unit = 0; unit < 8; ++unit)
1419 		{
1420 			glBindTexture(GL_TEXTURE_2D, texture);
1421 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1422 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1423 			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1424 			glBindTexture(GL_TEXTURE_2D, 0);
1425 
1426 			glViewport(0, 0, kSize, kSize);
1427 			glUseProgram(program);
1428 			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1429 			glBindVertexArray(m_vao);
1430 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1431 
1432 			glBindTexture(GL_TEXTURE_2D, texture);
1433 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1434 			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1435 
1436 			for (int i = 0; i < kSize * kSize; ++i)
1437 			{
1438 				if (!Equal(data[i], expected_value, internalformat))
1439 				{
1440 					glDeleteTextures(1, &texture);
1441 					glUseProgram(0);
1442 					glDeleteProgram(program);
1443 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1444 														<< ". Value should be: " << ToString(expected_value)
1445 														<< ". Format is: " << FormatEnumToString(internalformat)
1446 														<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1447 					return false;
1448 				}
1449 			}
1450 
1451 			if (unit < 7)
1452 			{
1453 				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1454 			}
1455 		}
1456 
1457 		glDeleteTextures(1, &texture);
1458 		glUseProgram(0);
1459 		glDeleteProgram(program);
1460 
1461 		return true;
1462 	}
1463 
Cleanup()1464 	virtual long Cleanup()
1465 	{
1466 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1467 		glDeleteVertexArrays(1, &m_vao);
1468 		glDeleteBuffers(1, &m_vbo);
1469 		return NO_ERROR;
1470 	}
1471 
1472 	template <typename T>
GenFS(GLenum internalformat,const T & value)1473 	std::string GenFS(GLenum internalformat, const T& value)
1474 	{
1475 		std::ostringstream os;
1476 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1477 		   << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1478 								 "  imageStore(g_image, coord, "
1479 		   << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1480 		return os.str();
1481 	}
1482 };
1483 //-----------------------------------------------------------------------------
1484 // 1.2.2 BasicAllFormatsLoad
1485 //-----------------------------------------------------------------------------
1486 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1487 {
1488 	GLuint m_vao;
1489 	GLuint m_vbo;
1490 
Setup()1491 	virtual long Setup()
1492 	{
1493 		m_vao = 0;
1494 		m_vbo = 0;
1495 		return NO_ERROR;
1496 	}
1497 
Run()1498 	virtual long Run()
1499 	{
1500 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1501 
1502 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1503 			return ERROR;
1504 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1505 			return ERROR;
1506 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1507 			return ERROR;
1508 
1509 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1510 			return ERROR;
1511 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1512 			return ERROR;
1513 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1514 			return ERROR;
1515 
1516 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1517 			return ERROR;
1518 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1519 			return ERROR;
1520 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1521 			return ERROR;
1522 
1523 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1524 			return ERROR;
1525 
1526 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1527 			return ERROR;
1528 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1529 			return ERROR;
1530 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1531 			return ERROR;
1532 
1533 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1534 			return ERROR;
1535 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1536 			return ERROR;
1537 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1538 			return ERROR;
1539 
1540 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1541 			return ERROR;
1542 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1543 			return ERROR;
1544 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1545 			return ERROR;
1546 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1547 			return ERROR;
1548 
1549 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1550 			return ERROR;
1551 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1552 			return ERROR;
1553 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1554 			return ERROR;
1555 
1556 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1557 			return ERROR;
1558 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1559 			return ERROR;
1560 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1561 			return ERROR;
1562 
1563 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1564 			return ERROR;
1565 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1566 			return ERROR;
1567 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1568 			return ERROR;
1569 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1570 			return ERROR;
1571 
1572 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1573 			return ERROR;
1574 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1575 			return ERROR;
1576 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1577 			return ERROR;
1578 
1579 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1580 			return ERROR;
1581 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1582 			return ERROR;
1583 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1584 			return ERROR;
1585 
1586 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1587 			return ERROR;
1588 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1589 			return ERROR;
1590 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1591 			return ERROR;
1592 
1593 		return NO_ERROR;
1594 	}
1595 
1596 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1597 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
1598 	{
1599 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1600 							 "  gl_Position = i_position;" NL "}";
1601 		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1602 		const int	  kSize   = 16;
1603 		std::vector<T> data(kSize * kSize, value);
1604 		GLuint		   texture;
1605 		glGenTextures(1, &texture);
1606 
1607 		for (GLuint unit = 0; unit < 8; ++unit)
1608 		{
1609 			glBindTexture(GL_TEXTURE_2D, texture);
1610 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1611 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1612 			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1613 			glBindTexture(GL_TEXTURE_2D, 0);
1614 
1615 			glViewport(0, 0, kSize, kSize);
1616 			glClear(GL_COLOR_BUFFER_BIT);
1617 			glUseProgram(program);
1618 			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1619 			glBindVertexArray(m_vao);
1620 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1621 
1622 			if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1623 			{
1624 				glDeleteTextures(1, &texture);
1625 				glUseProgram(0);
1626 				glDeleteProgram(program);
1627 				m_context.getTestContext().getLog()
1628 					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1629 					<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1630 				return false;
1631 			}
1632 
1633 			if (unit < 7)
1634 			{
1635 				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1636 			}
1637 		}
1638 
1639 		glDeleteTextures(1, &texture);
1640 		glUseProgram(0);
1641 		glDeleteProgram(program);
1642 
1643 		return true;
1644 	}
1645 
Cleanup()1646 	virtual long Cleanup()
1647 	{
1648 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1649 		glDeleteVertexArrays(1, &m_vao);
1650 		glDeleteBuffers(1, &m_vbo);
1651 		return NO_ERROR;
1652 	}
1653 
1654 	template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1655 	std::string GenFS(GLenum internalformat, const T& expected_value)
1656 	{
1657 		std::ostringstream os;
1658 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1659 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1660 		   << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1661 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1662 		   << expected_value
1663 		   << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1664 		return os.str();
1665 	}
1666 };
1667 //-----------------------------------------------------------------------------
1668 // 1.2.3 BasicAllFormatsStoreGeometryStages
1669 //-----------------------------------------------------------------------------
1670 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1671 {
1672 	GLuint m_vao;
1673 
Setup()1674 	virtual long Setup()
1675 	{
1676 		glGenVertexArrays(1, &m_vao);
1677 		return NO_ERROR;
1678 	}
1679 
Run()1680 	virtual long Run()
1681 	{
1682 		if (!SupportedInGeomStages(1))
1683 			return NOT_SUPPORTED;
1684 		glEnable(GL_RASTERIZER_DISCARD);
1685 
1686 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1687 			return ERROR;
1688 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1689 			return ERROR;
1690 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1691 			return ERROR;
1692 
1693 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1694 			return ERROR;
1695 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1696 			return ERROR;
1697 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1698 			return ERROR;
1699 
1700 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1701 			return ERROR;
1702 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1703 			return ERROR;
1704 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1705 			return ERROR;
1706 
1707 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1708 			return ERROR;
1709 
1710 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1711 			return ERROR;
1712 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1713 			return ERROR;
1714 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1715 			return ERROR;
1716 
1717 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1718 			return ERROR;
1719 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1720 			return ERROR;
1721 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1722 			return ERROR;
1723 
1724 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1725 			return ERROR;
1726 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1727 			return ERROR;
1728 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1729 			return ERROR;
1730 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1731 			return ERROR;
1732 
1733 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1734 			return ERROR;
1735 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1736 			return ERROR;
1737 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1738 			return ERROR;
1739 
1740 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1741 			return ERROR;
1742 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1743 			return ERROR;
1744 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1745 			return ERROR;
1746 
1747 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1748 			return ERROR;
1749 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1750 			return ERROR;
1751 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1752 			return ERROR;
1753 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1754 			return ERROR;
1755 
1756 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1757 			return ERROR;
1758 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1759 			return ERROR;
1760 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1761 			return ERROR;
1762 
1763 		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1764 			return ERROR;
1765 		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1766 			return ERROR;
1767 		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1768 			return ERROR;
1769 
1770 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1771 			return ERROR;
1772 		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1773 			return ERROR;
1774 		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1775 			return ERROR;
1776 
1777 		return NO_ERROR;
1778 	}
1779 
1780 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1781 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1782 	{
1783 		const GLuint program =
1784 			BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1785 						 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1786 		const int	  kSize = 1;
1787 		std::vector<T> data(kSize * kSize);
1788 		GLuint		   texture[4];
1789 		glGenTextures(4, texture);
1790 
1791 		for (int i = 0; i < 4; ++i)
1792 		{
1793 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1794 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1795 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1796 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1797 		}
1798 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1799 
1800 		glUseProgram(program);
1801 		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1802 		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1803 		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1804 		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1805 		for (GLuint i = 0; i < 4; ++i)
1806 		{
1807 			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1808 		}
1809 		glBindVertexArray(m_vao);
1810 		glPatchParameteri(GL_PATCH_VERTICES, 1);
1811 		glDrawArrays(GL_PATCHES, 0, 1);
1812 		glPatchParameteri(GL_PATCH_VERTICES, 3);
1813 
1814 		for (int i = 0; i < 4; ++i)
1815 		{
1816 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1817 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1818 			glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1819 
1820 			if (!Equal(data[0], expected_value, internalformat))
1821 			{
1822 				glDeleteTextures(4, texture);
1823 				glUseProgram(0);
1824 				glDeleteProgram(program);
1825 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1826 													<< ". Value should be: " << ToString(expected_value)
1827 													<< ". Format is: " << FormatEnumToString(internalformat)
1828 													<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1829 				return false;
1830 			}
1831 		}
1832 		glDeleteTextures(4, texture);
1833 		glUseProgram(0);
1834 		glDeleteProgram(program);
1835 		return true;
1836 	}
1837 
Cleanup()1838 	virtual long Cleanup()
1839 	{
1840 		glDisable(GL_RASTERIZER_DISCARD);
1841 		glDeleteVertexArrays(1, &m_vao);
1842 		return NO_ERROR;
1843 	}
1844 
1845 	template <typename T>
GenVS(GLenum internalformat,const T & value)1846 	std::string GenVS(GLenum internalformat, const T& value)
1847 	{
1848 		std::ostringstream os;
1849 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1850 		   << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1851 								 "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  imageStore(g_image0, coord, "
1852 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1853 		return os.str();
1854 	}
1855 
1856 	template <typename T>
GenTCS(GLenum internalformat,const T & value)1857 	std::string GenTCS(GLenum internalformat, const T& value)
1858 	{
1859 		std::ostringstream os;
1860 		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1861 		   << ") writeonly uniform " << TypePrefix<T>()
1862 		   << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1863 			  "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1864 			  "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1865 			  "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1866 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1867 		return os.str();
1868 	}
1869 
1870 	template <typename T>
GenTES(GLenum internalformat,const T & value)1871 	std::string GenTES(GLenum internalformat, const T& value)
1872 	{
1873 		std::ostringstream os;
1874 		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1875 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1876 		   << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1877 			  "  imageStore(g_image2, coord, "
1878 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1879 		return os.str();
1880 	}
1881 
1882 	template <typename T>
GenGS(GLenum internalformat,const T & value)1883 	std::string GenGS(GLenum internalformat, const T& value)
1884 	{
1885 		std::ostringstream os;
1886 		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1887 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1888 		   << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1889 			  "  imageStore(g_image3, coord, "
1890 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1891 		return os.str();
1892 	}
1893 };
1894 //-----------------------------------------------------------------------------
1895 // 1.2.4 BasicAllFormatsLoadGeometryStages
1896 //-----------------------------------------------------------------------------
1897 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1898 {
1899 	GLuint m_vao;
1900 
Setup()1901 	virtual long Setup()
1902 	{
1903 		glGenVertexArrays(1, &m_vao);
1904 		return NO_ERROR;
1905 	}
1906 
Run()1907 	virtual long Run()
1908 	{
1909 		if (!SupportedInGeomStages(2))
1910 			return NOT_SUPPORTED;
1911 		glEnable(GL_RASTERIZER_DISCARD);
1912 
1913 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1914 			return ERROR;
1915 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1916 			return ERROR;
1917 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1918 			return ERROR;
1919 
1920 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1921 			return ERROR;
1922 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1923 			return ERROR;
1924 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1925 			return ERROR;
1926 
1927 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1928 			return ERROR;
1929 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1930 			return ERROR;
1931 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1932 			return ERROR;
1933 
1934 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1935 			return ERROR;
1936 
1937 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1938 			return ERROR;
1939 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1940 			return ERROR;
1941 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1942 			return ERROR;
1943 
1944 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1945 			return ERROR;
1946 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1947 			return ERROR;
1948 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1949 			return ERROR;
1950 
1951 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1952 			return ERROR;
1953 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1954 			return ERROR;
1955 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1956 			return ERROR;
1957 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1958 			return ERROR;
1959 
1960 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1961 			return ERROR;
1962 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1963 			return ERROR;
1964 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1965 			return ERROR;
1966 
1967 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1968 			return ERROR;
1969 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1970 			return ERROR;
1971 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1972 			return ERROR;
1973 
1974 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1975 			return ERROR;
1976 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1977 			return ERROR;
1978 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1979 			return ERROR;
1980 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1981 			return ERROR;
1982 
1983 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1984 			return ERROR;
1985 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1986 			return ERROR;
1987 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1988 			return ERROR;
1989 
1990 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1991 			return ERROR;
1992 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1993 			return ERROR;
1994 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1995 			return ERROR;
1996 
1997 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1998 			return ERROR;
1999 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2000 			return ERROR;
2001 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2002 			return ERROR;
2003 
2004 		return NO_ERROR;
2005 	}
2006 
2007 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2008 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2009 	{
2010 		const GLuint program = BuildProgram(
2011 			GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2012 			GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2013 		const int	  kSize = 1;
2014 		std::vector<T> data(kSize * kSize, value);
2015 		GLuint		   texture[8];
2016 		glGenTextures(8, texture);
2017 
2018 		for (int i = 0; i < 4; ++i)
2019 		{
2020 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2021 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2022 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2023 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2024 		}
2025 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2026 		vec4 zero(0);
2027 		for (int i = 4; i < 8; ++i)
2028 		{
2029 			glBindTexture(GL_TEXTURE_2D, texture[i]);
2030 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2031 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2032 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2033 		}
2034 		glBindTexture(GL_TEXTURE_2D, 0);
2035 
2036 		glUseProgram(program);
2037 		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2038 		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2039 		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2040 		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2041 		glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2042 		glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2043 		glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2044 		glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2045 
2046 		for (GLuint i = 0; i < 4; ++i)
2047 		{
2048 			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2049 		}
2050 		for (GLuint i = 4; i < 8; ++i)
2051 		{
2052 			glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2053 		}
2054 		glBindVertexArray(m_vao);
2055 		glPatchParameteri(GL_PATCH_VERTICES, 1);
2056 		glDrawArrays(GL_PATCHES, 0, 1);
2057 		glPatchParameteri(GL_PATCH_VERTICES, 3);
2058 
2059 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2060 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
2061 		vec4					 g_color_eps  = vec4(
2062 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2063 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2064 
2065 		for (int i = 0; i < 4; ++i)
2066 		{
2067 			glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2068 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2069 			vec4 result;
2070 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2071 			if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2072 			{
2073 				glDeleteTextures(8, texture);
2074 				glUseProgram(0);
2075 				glDeleteProgram(program);
2076 				m_context.getTestContext().getLog()
2077 					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2078 					<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2079 				return false;
2080 			}
2081 		}
2082 		glDeleteTextures(8, texture);
2083 		glUseProgram(0);
2084 		glDeleteProgram(program);
2085 		return true;
2086 	}
2087 
Cleanup()2088 	virtual long Cleanup()
2089 	{
2090 		glDisable(GL_RASTERIZER_DISCARD);
2091 		glDeleteVertexArrays(1, &m_vao);
2092 		return NO_ERROR;
2093 	}
2094 
2095 	template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2096 	std::string GenVS(GLenum internalformat, const T& expected_value)
2097 	{
2098 		std::ostringstream os;
2099 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2100 		   << TypePrefix<T>()
2101 		   << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2102 			  "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2103 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2104 		   << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2105 								"  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2106 		return os.str();
2107 	}
2108 
2109 	template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2110 	std::string GenTCS(GLenum internalformat, const T& expected_value)
2111 	{
2112 		std::ostringstream os;
2113 		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2114 		   << ") readonly uniform " << TypePrefix<T>()
2115 		   << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2116 			  "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2117 			  "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2118 			  "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2119 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2120 		   << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2121 								"  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2122 		return os.str();
2123 	}
2124 
2125 	template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2126 	std::string GenTES(GLenum internalformat, const T& expected_value)
2127 	{
2128 		std::ostringstream os;
2129 		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2130 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2131 		   << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2132 			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2133 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2134 		   << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2135 								"  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2136 		return os.str();
2137 	}
2138 
2139 	template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2140 	std::string GenGS(GLenum internalformat, const T& expected_value)
2141 	{
2142 		std::ostringstream os;
2143 		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2144 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2145 		   << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2146 			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2147 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2148 		   << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2149 								"  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2150 		return os.str();
2151 	}
2152 };
2153 //-----------------------------------------------------------------------------
2154 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2155 //-----------------------------------------------------------------------------
2156 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2157 {
Run()2158 	virtual long Run()
2159 	{
2160 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2161 		{
2162 			m_context.getTestContext().getLog()
2163 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2164 				<< tcu::TestLog::EndMessage;
2165 			return NOT_SUPPORTED;
2166 		}
2167 
2168 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2169 			return ERROR;
2170 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2171 			return ERROR;
2172 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2173 			return ERROR;
2174 
2175 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2176 			return ERROR;
2177 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2178 			return ERROR;
2179 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2180 			return ERROR;
2181 
2182 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2183 			return ERROR;
2184 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2185 			return ERROR;
2186 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2187 			return ERROR;
2188 
2189 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2190 			return ERROR;
2191 
2192 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2193 			return ERROR;
2194 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2195 			return ERROR;
2196 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2197 			return ERROR;
2198 
2199 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2200 			return ERROR;
2201 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2202 			return ERROR;
2203 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2204 			return ERROR;
2205 
2206 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2207 			return ERROR;
2208 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2209 			return ERROR;
2210 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2211 			return ERROR;
2212 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2213 			return ERROR;
2214 
2215 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2216 			return ERROR;
2217 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2218 			return ERROR;
2219 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2220 			return ERROR;
2221 
2222 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2223 			return ERROR;
2224 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2225 			return ERROR;
2226 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2227 			return ERROR;
2228 
2229 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2230 			return ERROR;
2231 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2232 			return ERROR;
2233 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2234 			return ERROR;
2235 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2236 			return ERROR;
2237 
2238 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2239 			return ERROR;
2240 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2241 			return ERROR;
2242 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2243 			return ERROR;
2244 
2245 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2246 			return ERROR;
2247 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2248 			return ERROR;
2249 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2250 			return ERROR;
2251 
2252 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2253 			return ERROR;
2254 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2255 			return ERROR;
2256 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2257 			return ERROR;
2258 
2259 		return NO_ERROR;
2260 	}
2261 
2262 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2263 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2264 	{
2265 		GLuint			  program;
2266 		std::string		  source = GenCS<T>(internalformat);
2267 		const char* const src	= source.c_str();
2268 		GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
2269 		glShaderSource(sh, 1, &src, NULL);
2270 		glCompileShader(sh);
2271 		program = glCreateProgram();
2272 		glAttachShader(program, sh);
2273 		glLinkProgram(program);
2274 		glDeleteShader(sh);
2275 
2276 		const int	  kSize = 1;
2277 		std::vector<T> data(kSize * kSize, value);
2278 		GLuint		   texture[2];
2279 		glGenTextures(2, texture);
2280 
2281 		glBindTexture(GL_TEXTURE_2D, texture[0]);
2282 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2283 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2284 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2285 		glBindTexture(GL_TEXTURE_2D, texture[1]);
2286 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2287 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2288 		vec4 zero(0);
2289 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2290 
2291 		glBindTexture(GL_TEXTURE_2D, 0);
2292 
2293 		glUseProgram(program);
2294 		glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2295 		glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2296 
2297 		glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2298 		glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2299 
2300 		glDispatchCompute(1, 1, 1);
2301 
2302 		for (int i = 0; i < 2; ++i)
2303 		{
2304 			glBindTexture(GL_TEXTURE_2D, texture[i]);
2305 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2306 			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2307 
2308 			if (!Equal(data[0], expected_value, internalformat))
2309 			{
2310 				glDeleteTextures(4, texture);
2311 				glUseProgram(0);
2312 				glDeleteProgram(program);
2313 				m_context.getTestContext().getLog()
2314 					<< tcu::TestLog::Message << "Value is: " << ToString(data[0])
2315 					<< ". Value should be: " << ToString(expected_value)
2316 					<< ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2317 				return false;
2318 			}
2319 		}
2320 		glDeleteTextures(2, texture);
2321 		glUseProgram(0);
2322 		glDeleteProgram(program);
2323 		return true;
2324 	}
2325 
2326 	template <typename T>
GenCS(GLenum internalformat)2327 	std::string GenCS(GLenum internalformat)
2328 	{
2329 		std::ostringstream os;
2330 		os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2331 			  "layout("
2332 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2333 		   << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2334 		   << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2335 								 "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2336 		   << TypePrefix<T>()
2337 		   << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2338 		return os.str();
2339 	}
2340 };
2341 //-----------------------------------------------------------------------------
2342 // 1.3.1 BasicAllTargetsStore
2343 //-----------------------------------------------------------------------------
2344 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2345 {
2346 	GLuint m_vao;
2347 	GLuint m_vbo;
2348 
Setup()2349 	virtual long Setup()
2350 	{
2351 		m_vao = 0;
2352 		m_vbo = 0;
2353 		return NO_ERROR;
2354 	}
2355 
Run()2356 	virtual long Run()
2357 	{
2358 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2359 
2360 		if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2361 			return ERROR;
2362 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2363 			return ERROR;
2364 		if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2365 			return ERROR;
2366 
2367 		if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2368 			return ERROR;
2369 		if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2370 			return ERROR;
2371 		if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2372 			return ERROR;
2373 
2374 		if (SupportedSamples(4))
2375 		{
2376 			if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2377 				return ERROR;
2378 
2379 			GLint isamples;
2380 			glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2381 			if (isamples >= 4)
2382 			{
2383 				if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2384 					return ERROR;
2385 				if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2386 					return ERROR;
2387 			}
2388 		}
2389 		return NO_ERROR;
2390 	}
2391 
Cleanup()2392 	virtual long Cleanup()
2393 	{
2394 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2395 		glDeleteVertexArrays(1, &m_vao);
2396 		glDeleteBuffers(1, &m_vbo);
2397 		return NO_ERROR;
2398 	}
2399 
2400 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2401 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2402 	{
2403 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2404 							 "  gl_Position = i_position;" NL "}";
2405 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2406 		GLuint		 textures[8];
2407 		GLuint		 buffer;
2408 		glGenTextures(8, textures);
2409 		glGenBuffers(1, &buffer);
2410 
2411 		const int	  kSize = 16;
2412 		std::vector<T> data(kSize * kSize * 2);
2413 
2414 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2415 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2417 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2418 		glBindTexture(GL_TEXTURE_1D, 0);
2419 
2420 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2421 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2424 		glBindTexture(GL_TEXTURE_2D, 0);
2425 
2426 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2427 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2428 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2429 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2430 		glBindTexture(GL_TEXTURE_3D, 0);
2431 
2432 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2433 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2434 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2435 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2436 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2437 
2438 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2439 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2440 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2441 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2442 					 &data[0]);
2443 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2444 					 &data[0]);
2445 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2446 					 &data[0]);
2447 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2448 					 &data[0]);
2449 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2450 					 &data[0]);
2451 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2452 					 &data[0]);
2453 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2454 
2455 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2456 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2457 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2458 		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2459 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2460 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2461 
2462 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2463 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2464 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2465 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2466 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2467 
2468 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2469 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2470 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2471 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2472 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2473 
2474 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2476 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2477 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2478 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2479 		glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2480 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2482 
2483 		glUseProgram(program);
2484 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2485 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2486 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2487 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2488 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2489 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2490 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2491 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2492 
2493 		glBindVertexArray(m_vao);
2494 		glViewport(0, 0, kSize, kSize);
2495 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2496 
2497 		bool status = true;
2498 
2499 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2500 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2501 		glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2502 		glBindTexture(GL_TEXTURE_1D, 0);
2503 		for (int i = 0; i < kSize; ++i)
2504 		{
2505 			if (!tcu::allEqual(data[i], expected_value))
2506 			{
2507 				status = false;
2508 				m_context.getTestContext().getLog()
2509 					<< tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2510 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2511 				break;
2512 			}
2513 		}
2514 		std::fill(data.begin(), data.end(), T(0));
2515 
2516 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2517 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2518 		glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2519 		glBindTexture(GL_TEXTURE_2D, 0);
2520 		for (int i = 0; i < kSize * kSize; ++i)
2521 		{
2522 			if (!tcu::allEqual(data[i], expected_value))
2523 			{
2524 				status = false;
2525 				m_context.getTestContext().getLog()
2526 					<< tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2527 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2528 				break;
2529 			}
2530 		}
2531 
2532 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2533 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2534 		glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2535 		glBindTexture(GL_TEXTURE_3D, 0);
2536 		for (int i = 0; i < kSize * kSize * 2; ++i)
2537 		{
2538 			if (!tcu::allEqual(data[i], expected_value))
2539 			{
2540 				status = false;
2541 				m_context.getTestContext().getLog()
2542 					<< tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2543 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2544 				break;
2545 			}
2546 		}
2547 
2548 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2549 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2550 		glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2551 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2552 		for (int i = 0; i < kSize * kSize; ++i)
2553 		{
2554 			if (!tcu::allEqual(data[i], expected_value))
2555 			{
2556 				status = false;
2557 				m_context.getTestContext().getLog()
2558 					<< tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2559 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2560 				break;
2561 			}
2562 		}
2563 
2564 		{
2565 			glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2566 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2567 			for (int face = 0; face < 6; ++face)
2568 			{
2569 				glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2570 				for (int i = 0; i < kSize * kSize; ++i)
2571 				{
2572 					if (!tcu::allEqual(data[i], expected_value))
2573 					{
2574 						status = false;
2575 						m_context.getTestContext().getLog()
2576 							<< tcu::TestLog::Message
2577 							<< "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2578 							<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2579 						break;
2580 					}
2581 				}
2582 			}
2583 			glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2584 		}
2585 
2586 		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2587 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2588 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2589 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2590 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2591 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2592 		for (int i = 0; i < kSize; ++i)
2593 		{
2594 			if (!tcu::allEqual(data[i], expected_value))
2595 			{
2596 				status = false;
2597 				m_context.getTestContext().getLog()
2598 					<< tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2599 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2600 				break;
2601 			}
2602 		}
2603 
2604 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2605 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2606 		glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2607 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2608 		for (int i = 0; i < kSize * 2; ++i)
2609 		{
2610 			if (!tcu::allEqual(data[i], expected_value))
2611 			{
2612 				status = false;
2613 				m_context.getTestContext().getLog()
2614 					<< tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2615 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2616 				break;
2617 			}
2618 		}
2619 
2620 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2621 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2622 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2623 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2624 		for (int i = 0; i < kSize * kSize * 2; ++i)
2625 		{
2626 			if (!tcu::allEqual(data[i], expected_value))
2627 			{
2628 				status = false;
2629 				m_context.getTestContext().getLog()
2630 					<< tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2631 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2632 				break;
2633 			}
2634 		}
2635 
2636 		glUseProgram(0);
2637 		glDeleteProgram(program);
2638 		glDeleteTextures(8, textures);
2639 		glDeleteBuffers(1, &buffer);
2640 
2641 		return status;
2642 	}
2643 
2644 	template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2645 	bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2646 	{
2647 
2648 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2649 							 "  gl_Position = i_position;" NL "}";
2650 		const GLuint program	 = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2651 		const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2652 		GLuint		 textures[2];
2653 		glGenTextures(2, textures);
2654 
2655 		const int kSize = 16;
2656 
2657 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2658 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2659 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2660 
2661 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2662 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2663 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2664 
2665 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2666 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2667 
2668 		glClear(GL_COLOR_BUFFER_BIT);
2669 		glUseProgram(program);
2670 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2671 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2672 
2673 		glBindVertexArray(m_vao);
2674 		glViewport(0, 0, kSize, kSize);
2675 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2676 
2677 		bool status = true;
2678 
2679 		glActiveTexture(GL_TEXTURE0);
2680 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2681 		glActiveTexture(GL_TEXTURE1);
2682 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2683 
2684 		glUseProgram(val_program);
2685 		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2686 		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2687 
2688 		glBindVertexArray(m_vao);
2689 		glViewport(0, 0, kSize, kSize);
2690 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2691 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2692 
2693 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2694 		{
2695 			status = false;
2696 			m_context.getTestContext().getLog()
2697 				<< tcu::TestLog::Message
2698 				<< "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2699 				<< tcu::TestLog::EndMessage;
2700 		}
2701 
2702 		glActiveTexture(GL_TEXTURE0);
2703 		glDeleteTextures(2, textures);
2704 		glUseProgram(0);
2705 		glDeleteProgram(program);
2706 		glDeleteProgram(val_program);
2707 
2708 		return status;
2709 	}
2710 
2711 	template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2712 	bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2713 	{
2714 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2715 							 "  gl_Position = i_position;" NL "}";
2716 		const GLuint program =
2717 			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2718 		GLuint textures[1];
2719 		glGenTextures(1, textures);
2720 
2721 		const int kSize = 16;
2722 
2723 		std::vector<T> data(kSize * kSize * 12);
2724 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2725 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2726 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2727 					 &data[0]);
2728 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2729 
2730 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2731 
2732 		glUseProgram(program);
2733 		glBindVertexArray(m_vao);
2734 		glViewport(0, 0, kSize, kSize);
2735 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2736 
2737 		bool status = true;
2738 
2739 		std::fill(data.begin(), data.end(), T(0));
2740 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2741 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2742 		glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2743 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2744 		for (int i = 0; i < kSize * kSize * 12; ++i)
2745 		{
2746 			if (!tcu::allEqual(data[i], expected_value))
2747 			{
2748 				status = false;
2749 				m_context.getTestContext().getLog()
2750 					<< tcu::TestLog::Message
2751 					<< "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2752 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2753 				break;
2754 			}
2755 		}
2756 
2757 		glDeleteTextures(1, textures);
2758 		glUseProgram(0);
2759 		glDeleteProgram(program);
2760 
2761 		return status;
2762 	}
2763 
2764 	template <typename T>
GenFS(GLenum internalformat,const T & write_value)2765 	std::string GenFS(GLenum internalformat, const T& write_value)
2766 	{
2767 		std::ostringstream os;
2768 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2769 		   << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2770 		   << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2771 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2772 		   << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2773 		   << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2774 		   << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2775 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2776 		   << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2777 		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2778 		   << ") writeonly uniform " << TypePrefix<T>()
2779 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2780 			  "  imageStore(g_image_1d, coord.x, "
2781 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2782 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2783 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2784 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2785 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2786 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2787 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2788 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2789 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2790 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2791 		   << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2792 		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2793 		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2794 		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795 		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796 		   << write_value << ");" NL "  discard;" NL "}";
2797 		return os.str();
2798 	}
2799 
2800 	template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2801 	std::string GenFSMS(GLenum internalformat, const T& write_value)
2802 	{
2803 		std::ostringstream os;
2804 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2805 		   << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2806 		   << ") writeonly uniform " << TypePrefix<T>()
2807 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2808 			  "  imageStore(g_image_2dms, coord, 0, "
2809 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2810 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2811 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2812 		   << TypePrefix<T>() << "vec4" << write_value
2813 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2814 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2815 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2816 		   << TypePrefix<T>() << "vec4" << write_value
2817 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2818 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2819 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2820 		   << TypePrefix<T>() << "vec4" << write_value
2821 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2822 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2823 		   << "vec4" << write_value << ");" NL "  discard;" NL "}";
2824 		return os.str();
2825 	}
2826 
2827 	template <typename T>
GenFSMSVal(const T & expected_value)2828 	std::string GenFSMSVal(const T& expected_value)
2829 	{
2830 		std::ostringstream os;
2831 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2832 		   << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2833 		   << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2834 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2835 		   << TypePrefix<T>() << "vec4" << expected_value
2836 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2837 		   << TypePrefix<T>() << "vec4" << expected_value
2838 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2839 		   << TypePrefix<T>() << "vec4" << expected_value
2840 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2841 		   << TypePrefix<T>() << "vec4" << expected_value
2842 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2843 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2844 		   << TypePrefix<T>() << "vec4" << expected_value
2845 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2846 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2847 		   << TypePrefix<T>() << "vec4" << expected_value
2848 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2849 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2850 		   << TypePrefix<T>() << "vec4" << expected_value
2851 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2852 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2853 		   << TypePrefix<T>() << "vec4" << expected_value
2854 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2856 		   << TypePrefix<T>() << "vec4" << expected_value
2857 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2858 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2859 		   << TypePrefix<T>() << "vec4" << expected_value
2860 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2861 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2862 		   << TypePrefix<T>() << "vec4" << expected_value
2863 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2864 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2865 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2866 		return os.str();
2867 	}
2868 
2869 	template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2870 	std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2871 	{
2872 		std::ostringstream os;
2873 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2874 		   << TypePrefix<T>()
2875 		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2876 			  "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2877 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2878 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2879 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2880 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2881 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2882 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2883 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2884 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2885 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2886 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2887 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2888 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2889 		return os.str();
2890 	}
2891 };
2892 //-----------------------------------------------------------------------------
2893 // 1.3.2.1 BasicAllTargetsLoadNonMS
2894 //-----------------------------------------------------------------------------
2895 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2896 {
2897 	GLuint m_vao;
2898 	GLuint m_vbo;
2899 
Setup()2900 	virtual long Setup()
2901 	{
2902 		m_vao = 0;
2903 		m_vbo = 0;
2904 		return NO_ERROR;
2905 	}
2906 
Run()2907 	virtual long Run()
2908 	{
2909 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2910 
2911 		if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2912 			return ERROR;
2913 		if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2914 			return ERROR;
2915 		if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2916 			return ERROR;
2917 
2918 		if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2919 			return ERROR;
2920 		if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2921 			return ERROR;
2922 		if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2923 			return ERROR;
2924 
2925 		return NO_ERROR;
2926 	}
2927 
Cleanup()2928 	virtual long Cleanup()
2929 	{
2930 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2931 		glDeleteVertexArrays(1, &m_vao);
2932 		glDeleteBuffers(1, &m_vbo);
2933 		return NO_ERROR;
2934 	}
2935 
2936 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2937 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2938 	{
2939 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2940 							 "  gl_Position = i_position;" NL "}";
2941 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2942 		GLuint		 textures[7];
2943 		GLuint		 buffer;
2944 		glGenTextures(7, textures);
2945 		glGenBuffers(1, &buffer);
2946 
2947 		const int	  kSize = 16;
2948 		std::vector<T> data(kSize * kSize * 2, value);
2949 
2950 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2951 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2952 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2953 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2954 		glBindTexture(GL_TEXTURE_1D, 0);
2955 
2956 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2957 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2958 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2959 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2960 		glBindTexture(GL_TEXTURE_2D, 0);
2961 
2962 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2963 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2964 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2965 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2966 		glBindTexture(GL_TEXTURE_3D, 0);
2967 
2968 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2969 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2972 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2973 
2974 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2975 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2976 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2977 		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2978 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2979 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2980 
2981 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2982 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2983 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2984 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2985 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2986 
2987 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2988 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2989 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2990 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2991 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2992 
2993 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2995 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2996 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997 		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2998 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3000 
3001 		glClear(GL_COLOR_BUFFER_BIT);
3002 
3003 		glUseProgram(program);
3004 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3005 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3006 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3007 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3008 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3009 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3010 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3011 
3012 		glBindVertexArray(m_vao);
3013 		glViewport(0, 0, kSize, kSize);
3014 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3015 
3016 		bool status = true;
3017 
3018 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3019 		{
3020 			status = false;
3021 		}
3022 
3023 		std::map<std::string, GLuint> name_index_map;
3024 		GLint uniforms;
3025 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3026 		if (uniforms != 7)
3027 		{
3028 			status = false;
3029 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3030 												<< " should be 7." << tcu::TestLog::EndMessage;
3031 		}
3032 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3033 		{
3034 			GLchar name[32];
3035 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3036 			name_index_map.insert(std::make_pair(std::string(name), index));
3037 		}
3038 
3039 		if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3040 			status = false;
3041 		if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3042 			status = false;
3043 		if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3044 			status = false;
3045 		if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3046 			status = false;
3047 		if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3048 			status = false;
3049 		if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3050 			status = false;
3051 		if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3052 			status = false;
3053 
3054 		glUseProgram(0);
3055 		glDeleteProgram(program);
3056 		glDeleteTextures(7, textures);
3057 		glDeleteBuffers(1, &buffer);
3058 
3059 		return status;
3060 	}
3061 
3062 	template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3063 	bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3064 	{
3065 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3066 							 "  gl_Position = i_position;" NL "}";
3067 		const GLuint program =
3068 			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3069 		GLuint textures[2];
3070 		glGenTextures(2, textures);
3071 
3072 		const int	  kSize = 16;
3073 		std::vector<T> data(kSize * kSize * 12, value);
3074 
3075 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3076 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3077 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3079 					 &data[0]);
3080 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3081 					 &data[0]);
3082 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3083 					 &data[0]);
3084 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3085 					 &data[0]);
3086 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3087 					 &data[0]);
3088 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3089 					 &data[0]);
3090 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3091 
3092 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3093 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3094 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3095 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3096 					 &data[0]);
3097 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3098 
3099 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100 		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3101 
3102 		glClear(GL_COLOR_BUFFER_BIT);
3103 
3104 		glUseProgram(program);
3105 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3106 		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3107 
3108 		glBindVertexArray(m_vao);
3109 		glViewport(0, 0, kSize, kSize);
3110 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3111 
3112 		bool status = true;
3113 
3114 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3115 		{
3116 			status = false;
3117 		}
3118 
3119 		std::map<std::string, GLuint> name_index_map;
3120 		GLint uniforms;
3121 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3122 		if (uniforms != 2)
3123 		{
3124 			status = false;
3125 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3126 												<< " should be 2." << tcu::TestLog::EndMessage;
3127 		}
3128 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3129 		{
3130 			GLchar name[32];
3131 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3132 			name_index_map.insert(std::make_pair(std::string(name), index));
3133 		}
3134 
3135 		if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3136 			status = false;
3137 		if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3138 			status = false;
3139 
3140 		glUseProgram(0);
3141 		glDeleteProgram(program);
3142 		glDeleteTextures(2, textures);
3143 
3144 		return status;
3145 	}
3146 
3147 	template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3148 	std::string GenFS(GLenum internalformat, const T& expected_value)
3149 	{
3150 		std::ostringstream os;
3151 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3152 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3153 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3154 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3155 		   << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3156 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3157 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3158 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3159 		   << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3160 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3161 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3162 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3163 		   << TypePrefix<T>()
3164 		   << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3165 		   << expected_value
3166 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3167 		   << TypePrefix<T>() << "vec4" << expected_value
3168 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3169 			  "  if (v != "
3170 		   << TypePrefix<T>() << "vec4" << expected_value
3171 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3172 			  "  if (v != "
3173 		   << TypePrefix<T>() << "vec4" << expected_value
3174 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3175 		   << TypePrefix<T>() << "vec4" << expected_value
3176 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3177 		   << TypePrefix<T>() << "vec4" << expected_value
3178 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3179 			  "  if (v != "
3180 		   << TypePrefix<T>() << "vec4" << expected_value
3181 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3182 			  "  if (v != "
3183 		   << TypePrefix<T>() << "vec4" << expected_value
3184 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3185 			  "  if (v != "
3186 		   << TypePrefix<T>() << "vec4" << expected_value
3187 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3188 			  "  if (v != "
3189 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3190 		return os.str();
3191 	}
3192 
3193 	template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3194 	std::string GenFSCube(GLenum internalformat, const T& expected_value)
3195 	{
3196 		std::ostringstream os;
3197 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3198 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3199 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3200 		   << TypePrefix<T>()
3201 		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3202 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3203 		   << TypePrefix<T>()
3204 		   << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3205 		   << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3206 										  "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  if (v != "
3207 		   << TypePrefix<T>() << "vec4" << expected_value
3208 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3209 			  "  if (v != "
3210 		   << TypePrefix<T>() << "vec4" << expected_value
3211 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3212 			  "  if (v != "
3213 		   << TypePrefix<T>() << "vec4" << expected_value
3214 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3215 			  "  if (v != "
3216 		   << TypePrefix<T>() << "vec4" << expected_value
3217 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3218 			  "  if (v != "
3219 		   << TypePrefix<T>() << "vec4" << expected_value
3220 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3221 			  "  if (v != "
3222 		   << TypePrefix<T>() << "vec4" << expected_value
3223 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3224 			  "  if (v != "
3225 		   << TypePrefix<T>() << "vec4" << expected_value
3226 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3227 			  "  if (v != "
3228 		   << TypePrefix<T>() << "vec4" << expected_value
3229 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3230 			  "  if (v != "
3231 		   << TypePrefix<T>() << "vec4" << expected_value
3232 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3233 			  "  if (v != "
3234 		   << TypePrefix<T>() << "vec4" << expected_value
3235 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3236 			  "  if (v != "
3237 		   << TypePrefix<T>() << "vec4" << expected_value
3238 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3239 			  "  if (v != "
3240 		   << TypePrefix<T>() << "vec4" << expected_value
3241 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3242 			  "  if (v != "
3243 		   << TypePrefix<T>() << "vec4" << expected_value
3244 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3245 			  "  if (v != "
3246 		   << TypePrefix<T>() << "vec4" << expected_value
3247 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3248 			  "  if (v != "
3249 		   << TypePrefix<T>() << "vec4" << expected_value
3250 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3251 			  "  if (v != "
3252 		   << TypePrefix<T>() << "vec4" << expected_value
3253 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3254 			  "  if (v != "
3255 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3256 		return os.str();
3257 	}
3258 };
3259 //-----------------------------------------------------------------------------
3260 // 1.3.2.2 BasicAllTargetsLoadMS
3261 //-----------------------------------------------------------------------------
3262 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3263 {
3264 	GLuint m_vao;
3265 	GLuint m_vbo;
3266 
Setup()3267 	virtual long Setup()
3268 	{
3269 		m_vao = 0;
3270 		m_vbo = 0;
3271 		return NO_ERROR;
3272 	}
3273 
Run()3274 	virtual long Run()
3275 	{
3276 		if (!SupportedSamples(4))
3277 			return NOT_SUPPORTED;
3278 
3279 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3280 
3281 		if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3282 			return ERROR;
3283 
3284 		GLint isamples;
3285 		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3286 		if (isamples >= 4)
3287 		{
3288 			if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3289 				return ERROR;
3290 			if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3291 				return ERROR;
3292 		}
3293 
3294 		return NO_ERROR;
3295 	}
3296 
Cleanup()3297 	virtual long Cleanup()
3298 	{
3299 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3300 		glDeleteVertexArrays(1, &m_vao);
3301 		glDeleteBuffers(1, &m_vbo);
3302 		return NO_ERROR;
3303 	}
3304 
3305 	template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3306 	bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3307 	{
3308 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3309 							 "  gl_Position = i_position;" NL "}";
3310 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3311 		GLuint		 textures[2];
3312 		glGenTextures(2, textures);
3313 
3314 		const int kSize = 16;
3315 
3316 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3317 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3318 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3319 
3320 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3321 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3322 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3323 
3324 		GLuint fbo;
3325 		glGenFramebuffers(1, &fbo);
3326 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3327 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3328 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3329 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3330 		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3331 		glDrawBuffers(3, draw_buffers);
3332 		ClearBuffer(GL_COLOR, 0, value);
3333 		ClearBuffer(GL_COLOR, 1, value);
3334 		ClearBuffer(GL_COLOR, 2, value);
3335 		glDeleteFramebuffers(1, &fbo);
3336 
3337 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3338 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3339 
3340 		glUseProgram(program);
3341 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3342 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3343 
3344 		glClear(GL_COLOR_BUFFER_BIT);
3345 		glBindVertexArray(m_vao);
3346 		glViewport(0, 0, kSize, kSize);
3347 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3348 
3349 		bool status = true;
3350 
3351 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3352 		{
3353 			status = false;
3354 		}
3355 
3356 		std::map<std::string, GLuint> name_index_map;
3357 		GLint uniforms;
3358 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3359 		if (uniforms != 2)
3360 		{
3361 			status = false;
3362 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3363 												<< " should be 2." << tcu::TestLog::EndMessage;
3364 		}
3365 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3366 		{
3367 			GLchar name[32];
3368 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3369 			name_index_map.insert(std::make_pair(std::string(name), index));
3370 		}
3371 
3372 		if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3373 			status = false;
3374 		if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3375 						  ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3376 			status = false;
3377 
3378 		glDeleteTextures(2, textures);
3379 		glUseProgram(0);
3380 		glDeleteProgram(program);
3381 
3382 		return status;
3383 	}
3384 
3385 	template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3386 	std::string GenFSMS(GLenum internalformat, const T& expected_value)
3387 	{
3388 		std::ostringstream os;
3389 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3390 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3391 		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3392 		   << TypePrefix<T>()
3393 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3394 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3395 		   << TypePrefix<T>() << "vec4" << expected_value
3396 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3397 		   << TypePrefix<T>() << "vec4" << expected_value
3398 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3399 		   << TypePrefix<T>() << "vec4" << expected_value
3400 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3401 		   << TypePrefix<T>() << "vec4" << expected_value
3402 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3403 		   << TypePrefix<T>() << "vec4" << expected_value
3404 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3405 		   << TypePrefix<T>() << "vec4" << expected_value
3406 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3407 		   << TypePrefix<T>() << "vec4" << expected_value
3408 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3409 		   << TypePrefix<T>() << "vec4" << expected_value
3410 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3411 		   << TypePrefix<T>() << "vec4" << expected_value
3412 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3413 		   << TypePrefix<T>() << "vec4" << expected_value
3414 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3415 		   << TypePrefix<T>() << "vec4" << expected_value
3416 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3417 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3418 		return os.str();
3419 	}
3420 };
3421 //-----------------------------------------------------------------------------
3422 // 1.3.3 BasicAllTargetsAtomic
3423 //-----------------------------------------------------------------------------
3424 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3425 {
3426 	GLuint m_vao;
3427 	GLuint m_vbo;
3428 
Setup()3429 	virtual long Setup()
3430 	{
3431 		m_vao = 0;
3432 		m_vbo = 0;
3433 		return NO_ERROR;
3434 	}
3435 
Run()3436 	virtual long Run()
3437 	{
3438 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3439 
3440 		if (!Atomic<GLint>(GL_R32I))
3441 			return ERROR;
3442 		if (!Atomic<GLuint>(GL_R32UI))
3443 			return ERROR;
3444 
3445 		if (!AtomicCube<GLint>(GL_R32I))
3446 			return ERROR;
3447 		if (!AtomicCube<GLuint>(GL_R32UI))
3448 			return ERROR;
3449 
3450 		GLint isamples;
3451 		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3452 		if (SupportedSamples(4) && isamples >= 4)
3453 		{
3454 			if (!AtomicMS<GLint>(GL_R32I))
3455 				return ERROR;
3456 			if (!AtomicMS<GLuint>(GL_R32UI))
3457 				return ERROR;
3458 		}
3459 
3460 		return NO_ERROR;
3461 	}
3462 
Cleanup()3463 	virtual long Cleanup()
3464 	{
3465 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3466 		glDeleteVertexArrays(1, &m_vao);
3467 		glDeleteBuffers(1, &m_vbo);
3468 		return NO_ERROR;
3469 	}
3470 
3471 	template <typename T>
Atomic(GLenum internalformat)3472 	bool Atomic(GLenum internalformat)
3473 	{
3474 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3475 							 "  gl_Position = i_position;" NL "}";
3476 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3477 		GLuint		 textures[7];
3478 		GLuint		 buffer;
3479 		glGenTextures(7, textures);
3480 		glGenBuffers(1, &buffer);
3481 
3482 		const int	  kSize = 16;
3483 		std::vector<T> data(kSize * kSize * 2);
3484 
3485 		glBindTexture(GL_TEXTURE_1D, textures[0]);
3486 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3487 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3488 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3489 		glBindTexture(GL_TEXTURE_1D, 0);
3490 
3491 		glBindTexture(GL_TEXTURE_2D, textures[1]);
3492 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3493 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3494 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3495 		glBindTexture(GL_TEXTURE_2D, 0);
3496 
3497 		glBindTexture(GL_TEXTURE_3D, textures[2]);
3498 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3499 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3500 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3501 		glBindTexture(GL_TEXTURE_3D, 0);
3502 
3503 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3504 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3505 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3506 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3507 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3508 
3509 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3510 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3511 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
3512 		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3513 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3514 		glBindTexture(GL_TEXTURE_BUFFER, 0);
3515 
3516 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3517 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3518 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3519 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3520 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3521 
3522 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3523 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3524 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3525 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3526 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3527 
3528 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3530 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3531 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532 		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3533 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3535 
3536 		glClear(GL_COLOR_BUFFER_BIT);
3537 
3538 		glUseProgram(program);
3539 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3540 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3541 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3542 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3543 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3544 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3545 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3546 
3547 		glBindVertexArray(m_vao);
3548 		glViewport(0, 0, kSize, 1);
3549 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3550 
3551 		bool status = true;
3552 
3553 		if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3554 		{
3555 			status = false;
3556 		}
3557 
3558 		glUseProgram(0);
3559 		glDeleteProgram(program);
3560 		glDeleteTextures(7, textures);
3561 		glDeleteBuffers(1, &buffer);
3562 
3563 		return status;
3564 	}
3565 
3566 	template <typename T>
AtomicCube(GLenum internalformat)3567 	bool AtomicCube(GLenum internalformat)
3568 	{
3569 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3570 							 "  gl_Position = i_position;" NL "}";
3571 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3572 		GLuint		 textures[2];
3573 		glGenTextures(2, textures);
3574 
3575 		const int	  kSize = 16;
3576 		std::vector<T> data(kSize * kSize * 12);
3577 
3578 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3579 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3580 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3581 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3582 					 &data[0]);
3583 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3584 					 &data[0]);
3585 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3586 					 &data[0]);
3587 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3588 					 &data[0]);
3589 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3590 					 &data[0]);
3591 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3592 					 &data[0]);
3593 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3594 
3595 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3596 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3597 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3598 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3599 					 &data[0]);
3600 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3601 
3602 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603 		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3604 
3605 		glClear(GL_COLOR_BUFFER_BIT);
3606 
3607 		glUseProgram(program);
3608 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3609 		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3610 
3611 		glBindVertexArray(m_vao);
3612 		glViewport(0, 0, kSize, kSize);
3613 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3614 
3615 		bool status = true;
3616 
3617 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3618 		{
3619 			status = false;
3620 		}
3621 
3622 		glUseProgram(0);
3623 		glDeleteProgram(program);
3624 		glDeleteTextures(2, textures);
3625 
3626 		return status;
3627 	}
3628 
3629 	template <typename T>
AtomicMS(GLenum internalformat)3630 	bool AtomicMS(GLenum internalformat)
3631 	{
3632 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3633 							 "  gl_Position = i_position;" NL "}";
3634 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3635 		GLuint		 textures[2];
3636 		glGenTextures(2, textures);
3637 
3638 		const int kSize = 16;
3639 
3640 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3641 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3642 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3643 
3644 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3645 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3646 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3647 
3648 		GLuint fbo;
3649 		glGenFramebuffers(1, &fbo);
3650 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3651 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3652 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3653 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3654 		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3655 		glDrawBuffers(3, draw_buffers);
3656 		if (internalformat == GL_R32I)
3657 		{
3658 			const GLint value[4] = { 0, 0, 0, 0 };
3659 			glClearBufferiv(GL_COLOR, 0, value);
3660 			glClearBufferiv(GL_COLOR, 1, value);
3661 			glClearBufferiv(GL_COLOR, 2, value);
3662 		}
3663 		else
3664 		{
3665 			const GLuint value[4] = { 0, 0, 0, 0 };
3666 			glClearBufferuiv(GL_COLOR, 0, value);
3667 			glClearBufferuiv(GL_COLOR, 1, value);
3668 			glClearBufferuiv(GL_COLOR, 2, value);
3669 		}
3670 		glDeleteFramebuffers(1, &fbo);
3671 
3672 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3673 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3674 
3675 		glUseProgram(program);
3676 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3677 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3678 
3679 		glClear(GL_COLOR_BUFFER_BIT);
3680 		glBindVertexArray(m_vao);
3681 		glViewport(0, 0, kSize, kSize);
3682 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3683 
3684 		bool status = true;
3685 
3686 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3687 		{
3688 			status = false;
3689 		}
3690 
3691 		glDeleteTextures(2, textures);
3692 		glUseProgram(0);
3693 		glDeleteProgram(program);
3694 
3695 		return status;
3696 	}
3697 
3698 	template <typename T>
GenFS(GLenum internalformat)3699 	std::string GenFS(GLenum internalformat)
3700 	{
3701 		std::ostringstream os;
3702 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3703 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3704 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3705 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3706 		   << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3707 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3708 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3709 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3710 		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3711 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3712 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3713 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3714 
3715 			NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 			  "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 			  "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 			  "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 			  "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720 			  "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721 			  "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722 			  "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723 			  "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3724 
3725 			NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 			  "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 			  "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 			  "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 			  "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 			  "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 			  "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 			  "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733 			  "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3734 
3735 			NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 			  "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 			  "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 			  "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 			  "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 			  "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742 			  "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3743 			  "1.0);" NL
3744 			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3745 
3746 			NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 			  "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 			  "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 			  "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 			  "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 			  "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 			  "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753 			  "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3754 			  "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3755 
3756 			NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 			  "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 			  "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 			  "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 			  "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 			  "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 			  "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764 			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3765 
3766 			NL
3767 			  "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 			  "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 			  "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 			  "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 			  "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 			  "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773 			  "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3774 			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3775 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3776 			  "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3777 
3778 			NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 			  "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 			  "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 			  "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 			  "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 			  "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3784 			  "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3785 			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3786 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3787 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3788 		return os.str();
3789 	}
3790 
3791 	template <typename T>
GenFSCube(GLenum internalformat)3792 	std::string GenFSCube(GLenum internalformat)
3793 	{
3794 		std::ostringstream os;
3795 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3796 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3797 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3798 		   << TypePrefix<T>()
3799 		   << "imageCube g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3800 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3801 
3802 			NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803 			  "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804 			  "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805 			  "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806 			  "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 			  "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808 			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3809 			  "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3810 			  "1.0);" NL
3811 			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3812 
3813 			NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3814 			  "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3815 			  "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3816 			  "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3817 			  "ivec3(coord, 0), 0) != 4) o_color = "
3818 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 			  "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3820 			  "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3821 			  "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3822 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3823 			  "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3824 			  "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3825 			  "1.0);" NL "}";
3826 		return os.str();
3827 	}
3828 
3829 	template <typename T>
GenFSMS(GLenum internalformat)3830 	std::string GenFSMS(GLenum internalformat)
3831 	{
3832 		std::ostringstream os;
3833 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3834 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3835 		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3836 		   << TypePrefix<T>()
3837 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3838 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3839 			  "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840 			  "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841 			  "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842 			  "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843 			  "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844 			  "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845 			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846 			  "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3847 			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3848 			  "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3849 			  "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3850 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3851 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852 			  "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3853 			  "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3854 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3855 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856 			  "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3857 			  "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3858 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3859 			  "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3860 			  "0.0, 1.0);" NL "}";
3861 		return os.str();
3862 	}
3863 };
3864 //-----------------------------------------------------------------------------
3865 // LoadStoreMachine
3866 //-----------------------------------------------------------------------------
3867 class LoadStoreMachine : public ShaderImageLoadStoreBase
3868 {
3869 	GLuint m_vao;
3870 	int	m_stage;
3871 
Setup()3872 	virtual long Setup()
3873 	{
3874 		glGenVertexArrays(1, &m_vao);
3875 		return NO_ERROR;
3876 	}
3877 
Cleanup()3878 	virtual long Cleanup()
3879 	{
3880 		glDisable(GL_RASTERIZER_DISCARD);
3881 		glDeleteVertexArrays(1, &m_vao);
3882 		return NO_ERROR;
3883 	}
3884 
3885 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3886 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3887 	{
3888 		const GLenum targets[] = { GL_TEXTURE_1D,		GL_TEXTURE_2D,
3889 								   GL_TEXTURE_3D,		GL_TEXTURE_RECTANGLE,
3890 								   GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3891 								   GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3892 		const int kTargets		= sizeof(targets) / sizeof(targets[0]);
3893 		GLuint	program_store = 0;
3894 		GLuint	program_load  = 0;
3895 		if (m_stage == 0)
3896 		{ // VS
3897 			program_store =
3898 				BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3899 			program_load =
3900 				BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3901 		}
3902 		else if (m_stage == 1)
3903 		{ // TCS
3904 			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
3905 			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3906 			program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3907 										 glsl_tes, NULL, NULL);
3908 			program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3909 										glsl_tes, NULL, NULL);
3910 		}
3911 		else if (m_stage == 2)
3912 		{ // TES
3913 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3914 			program_store =
3915 				BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3916 			program_load =
3917 				BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3918 		}
3919 		else if (m_stage == 3)
3920 		{ // GS
3921 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3922 			program_store =
3923 				BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3924 			program_load =
3925 				BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3926 		}
3927 		else if (m_stage == 4)
3928 		{ // CS
3929 			{
3930 				std::string		  source = GenStoreShader(m_stage, internalformat, write_value);
3931 				const char* const src	= source.c_str();
3932 				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3933 				glShaderSource(sh, 1, &src, NULL);
3934 				glCompileShader(sh);
3935 				program_store = glCreateProgram();
3936 				glAttachShader(program_store, sh);
3937 				glLinkProgram(program_store);
3938 				glDeleteShader(sh);
3939 			}
3940 			{
3941 				std::string		  source = GenLoadShader(m_stage, internalformat, expected_value);
3942 				const char* const src	= source.c_str();
3943 				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3944 				glShaderSource(sh, 1, &src, NULL);
3945 				glCompileShader(sh);
3946 				program_load = glCreateProgram();
3947 				glAttachShader(program_load, sh);
3948 				glLinkProgram(program_load);
3949 				glDeleteShader(sh);
3950 			}
3951 		}
3952 		GLuint textures[kTargets], texture_result;
3953 		glGenTextures(kTargets, textures);
3954 		glGenTextures(1, &texture_result);
3955 
3956 		glBindTexture(GL_TEXTURE_2D, texture_result);
3957 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3958 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3959 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3960 
3961 		for (int i = 0; i < kTargets; ++i)
3962 		{
3963 			glBindTexture(targets[i], textures[i]);
3964 			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3965 			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3966 
3967 			if (targets[i] == GL_TEXTURE_1D)
3968 			{
3969 				glTexStorage1D(targets[i], 1, internalformat, 1);
3970 			}
3971 			else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3972 			{
3973 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3974 			}
3975 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3976 			{
3977 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3978 			}
3979 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3980 			{
3981 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3982 			}
3983 			else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3984 			{
3985 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3986 			}
3987 			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3988 			{
3989 				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3990 			}
3991 		}
3992 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3994 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3995 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3996 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4000 
4001 		glUseProgram(program_store);
4002 		glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4003 		glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4004 		glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4005 		glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4006 		glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4007 		glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4008 		glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4009 		glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4010 
4011 		glBindVertexArray(m_vao);
4012 		if (m_stage == 1 || m_stage == 2)
4013 		{ // TCS or TES
4014 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4015 			glDrawArrays(GL_PATCHES, 0, 1);
4016 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4017 		}
4018 		else if (m_stage == 4)
4019 		{ // CS
4020 			glDispatchCompute(1, 1, 1);
4021 		}
4022 		else
4023 		{
4024 			glDrawArrays(GL_POINTS, 0, 1);
4025 		}
4026 
4027 		bool status = true;
4028 		for (int i = 0; i < kTargets; ++i)
4029 		{
4030 			glBindTexture(targets[i], textures[i]);
4031 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4032 
4033 			if (targets[i] == GL_TEXTURE_CUBE_MAP)
4034 			{
4035 				for (int face = 0; face < 6; ++face)
4036 				{
4037 					T data;
4038 					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4039 					if (!Equal(data, expected_value, internalformat))
4040 					{
4041 						status = false;
4042 						m_context.getTestContext().getLog()
4043 							<< tcu::TestLog::Message << "Value is: " << ToString(data)
4044 							<< ". Value should be: " << ToString(expected_value)
4045 							<< ". Format is: " << FormatEnumToString(internalformat)
4046 							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4047 							<< tcu::TestLog::EndMessage;
4048 					}
4049 				}
4050 			}
4051 			else
4052 			{
4053 				T data[12];
4054 
4055 				for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4056 					data[ndx] = T(0);
4057 
4058 				glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4059 
4060 				int count = 1;
4061 				if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4062 					count = 2;
4063 				else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4064 					count = 12;
4065 				else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4066 					count = 2;
4067 
4068 				for (int j = 0; j < count; ++j)
4069 				{
4070 					if (!Equal(data[j], expected_value, internalformat))
4071 					{
4072 						status = false;
4073 						m_context.getTestContext().getLog()
4074 							<< tcu::TestLog::Message << "Value is: " << ToString(data[j])
4075 							<< ". Value should be: " << ToString(expected_value)
4076 							<< ". Format is: " << FormatEnumToString(internalformat)
4077 							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4078 							<< tcu::TestLog::EndMessage;
4079 					}
4080 				}
4081 			}
4082 		}
4083 		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4084 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4085 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4086 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4087 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4090 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4091 
4092 		glUseProgram(program_load);
4093 		glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4094 		glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4095 		glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4096 		glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4097 		glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4098 		glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4099 		glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4100 		glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4101 
4102 		if (m_stage == 1 || m_stage == 2)
4103 		{ // TCS or TES
4104 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4105 			glDrawArrays(GL_PATCHES, 0, 1);
4106 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4107 		}
4108 		else if (m_stage == 4)
4109 		{ // CS
4110 			glDispatchCompute(1, 1, 1);
4111 		}
4112 		else
4113 		{
4114 			glDrawArrays(GL_POINTS, 0, 1);
4115 		}
4116 		{
4117 			vec4 color;
4118 			glBindTexture(GL_TEXTURE_2D, texture_result);
4119 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4120 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4121 			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4122 			{
4123 				status = false;
4124 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4125 													<< ". Format is: " << FormatEnumToString(internalformat)
4126 													<< ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4127 			}
4128 		}
4129 		glUseProgram(0);
4130 		glDeleteProgram(program_store);
4131 		glDeleteProgram(program_load);
4132 		glDeleteTextures(kTargets, textures);
4133 		glDeleteTextures(1, &texture_result);
4134 		return status;
4135 	}
4136 
4137 	template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4138 	std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4139 	{
4140 		std::ostringstream os;
4141 		os << "#version 420 core";
4142 		if (stage == 4)
4143 		{ // CS
4144 			os << NL "#extension GL_ARB_compute_shader : require";
4145 		}
4146 		os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4147 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4148 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4149 		   << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4150 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4151 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4152 		   << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4153 		   << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4154 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4155 		   << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4156 		   << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4157 		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4158 		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4159 		if (stage == 0)
4160 		{ // VS
4161 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4162 		}
4163 		else if (stage == 1)
4164 		{ // TCS
4165 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4166 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4167 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4168 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4169 		}
4170 		else if (stage == 2)
4171 		{ // TES
4172 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4173 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4174 		}
4175 		else if (stage == 3)
4176 		{ // GS
4177 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4178 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4179 		}
4180 		else if (stage == 4)
4181 		{ // CS
4182 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4183 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4184 		}
4185 		os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4186 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4187 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4188 				 "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4189 				 "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4190 				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4191 				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4192 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4193 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4194 				 "  for (int i = 0; i < 6; ++i) {" NL
4195 				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4196 				 "  for (int i = 0; i < 6; ++i) {" NL
4197 				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4198 		return os.str();
4199 	}
4200 
4201 	template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4202 	std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4203 	{
4204 		std::ostringstream os;
4205 		os << "#version 420 core";
4206 		if (stage == 4)
4207 		{ // CS
4208 			os << NL "#extension GL_ARB_compute_shader : require";
4209 		}
4210 		os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4211 		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4212 		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4213 		   << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4214 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4215 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4216 		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4217 		   << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4218 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4219 		   << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4220 			  "uniform "
4221 		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4222 		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4223 		if (stage == 0)
4224 		{ // VS
4225 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4226 		}
4227 		else if (stage == 1)
4228 		{ // TCS
4229 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4230 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4231 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4232 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4233 		}
4234 		else if (stage == 2)
4235 		{ // TES
4236 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4237 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4238 		}
4239 		else if (stage == 3)
4240 		{ // GS
4241 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4242 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4243 		}
4244 		else if (stage == 4)
4245 		{ // CS
4246 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4247 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4248 		}
4249 		os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4250 		   << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4251 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4252 			  "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4253 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4254 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4255 			  "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4256 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4257 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4258 			  "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4259 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4260 			  "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4261 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4262 		return os.str();
4263 	}
4264 
4265 protected:
RunStage(int stage)4266 	long RunStage(int stage)
4267 	{
4268 		if (!SupportedInStage(stage, 8))
4269 			return NOT_SUPPORTED;
4270 
4271 		glEnable(GL_RASTERIZER_DISCARD);
4272 		m_stage = stage;
4273 
4274 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4275 			return ERROR;
4276 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4277 			return ERROR;
4278 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4279 			return ERROR;
4280 
4281 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4282 			return ERROR;
4283 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4284 			return ERROR;
4285 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4286 			return ERROR;
4287 
4288 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4289 			return ERROR;
4290 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4291 			return ERROR;
4292 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4293 			return ERROR;
4294 
4295 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4296 			return ERROR;
4297 
4298 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4299 			return ERROR;
4300 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4301 			return ERROR;
4302 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4303 			return ERROR;
4304 
4305 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4306 			return ERROR;
4307 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4308 			return ERROR;
4309 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4310 			return ERROR;
4311 
4312 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4313 			return ERROR;
4314 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4315 			return ERROR;
4316 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4317 			return ERROR;
4318 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4319 			return ERROR;
4320 
4321 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4322 			return ERROR;
4323 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4324 			return ERROR;
4325 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4326 			return ERROR;
4327 
4328 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4329 			return ERROR;
4330 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4331 			return ERROR;
4332 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4333 			return ERROR;
4334 
4335 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4336 			return ERROR;
4337 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4338 			return ERROR;
4339 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4340 			return ERROR;
4341 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4342 			return ERROR;
4343 
4344 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4345 			return ERROR;
4346 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4347 			return ERROR;
4348 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4349 			return ERROR;
4350 
4351 		//
4352 		{
4353 			if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4354 				return ERROR;
4355 			if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4356 				return ERROR;
4357 			if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4358 				return ERROR;
4359 
4360 			if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4361 				return ERROR;
4362 			if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4363 				return ERROR;
4364 			if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4365 				return ERROR;
4366 		}
4367 		return NO_ERROR;
4368 	}
4369 };
4370 //-----------------------------------------------------------------------------
4371 // AtomicMachine
4372 //-----------------------------------------------------------------------------
4373 class AtomicMachine : public ShaderImageLoadStoreBase
4374 {
4375 	GLuint m_vao;
4376 
Setup()4377 	virtual long Setup()
4378 	{
4379 		glEnable(GL_RASTERIZER_DISCARD);
4380 		glGenVertexArrays(1, &m_vao);
4381 		return NO_ERROR;
4382 	}
4383 
Cleanup()4384 	virtual long Cleanup()
4385 	{
4386 		glDisable(GL_RASTERIZER_DISCARD);
4387 		glDeleteVertexArrays(1, &m_vao);
4388 		return NO_ERROR;
4389 	}
4390 
4391 	template <typename T>
Atomic(int stage,GLenum internalformat)4392 	bool Atomic(int stage, GLenum internalformat)
4393 	{
4394 		GLuint program = 0;
4395 		if (stage == 0)
4396 		{ // VS
4397 			program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4398 		}
4399 		else if (stage == 1)
4400 		{ // TCS
4401 			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
4402 			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4403 			program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4404 		}
4405 		else if (stage == 2)
4406 		{ // TES
4407 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4408 			program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4409 		}
4410 		else if (stage == 3)
4411 		{ // GS
4412 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4413 			program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4414 		}
4415 		else if (stage == 4)
4416 		{ // CS
4417 			std::string		  source = GenShader<T>(stage, internalformat);
4418 			const char* const src	= source.c_str();
4419 			GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
4420 			glShaderSource(sh, 1, &src, NULL);
4421 			glCompileShader(sh);
4422 			program = glCreateProgram();
4423 			glAttachShader(program, sh);
4424 			glLinkProgram(program);
4425 			glDeleteShader(sh);
4426 		}
4427 		GLuint texture_result;
4428 		glGenTextures(1, &texture_result);
4429 		glBindTexture(GL_TEXTURE_2D, texture_result);
4430 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4431 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4432 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4433 
4434 		const GLenum targets[] = { GL_TEXTURE_2D,	 GL_TEXTURE_3D,	   GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4435 								   GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4436 		const int kTargets = sizeof(targets) / sizeof(targets[0]);
4437 
4438 		GLuint textures[kTargets];
4439 		GLuint buffer;
4440 		glGenTextures(kTargets, textures);
4441 		glGenBuffers(1, &buffer);
4442 
4443 		for (int i = 0; i < kTargets; ++i)
4444 		{
4445 			glBindTexture(targets[i], textures[i]);
4446 			if (targets[i] != GL_TEXTURE_BUFFER)
4447 			{
4448 				glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4449 				glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4450 			}
4451 			if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4452 			{
4453 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4454 			}
4455 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4456 			{
4457 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4458 			}
4459 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4460 			{
4461 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4462 			}
4463 			else if (targets[i] == GL_TEXTURE_BUFFER)
4464 			{
4465 				glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4466 				glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4467 				glBindBuffer(GL_TEXTURE_BUFFER, 0);
4468 				glTexBuffer(targets[i], internalformat, buffer);
4469 			}
4470 			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4471 			{
4472 				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4473 			}
4474 		}
4475 		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4476 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4477 		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4478 		glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4479 		glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4480 		glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4481 		glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4482 		glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4483 
4484 		glUseProgram(program);
4485 		glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4486 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4487 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4488 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4489 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4490 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4491 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4492 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4493 
4494 		glBindVertexArray(m_vao);
4495 		if (stage == 1 || stage == 2)
4496 		{ // TCS or TES
4497 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4498 			glDrawArrays(GL_PATCHES, 0, 1);
4499 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4500 		}
4501 		else if (stage == 4)
4502 		{ // CS
4503 			glDispatchCompute(1, 1, 1);
4504 		}
4505 		else
4506 		{
4507 			glDrawArrays(GL_POINTS, 0, 1);
4508 		}
4509 
4510 		bool status = true;
4511 		{
4512 			vec4 color;
4513 			glBindTexture(GL_TEXTURE_2D, texture_result);
4514 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4515 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4516 			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4517 			{
4518 				status = false;
4519 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4520 													<< ". Format is: " << FormatEnumToString(internalformat)
4521 													<< ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4522 			}
4523 		}
4524 		glUseProgram(0);
4525 		glDeleteProgram(program);
4526 		glDeleteTextures(7, textures);
4527 		glDeleteTextures(1, &texture_result);
4528 		glDeleteBuffers(1, &buffer);
4529 		return status;
4530 	}
4531 
4532 	template <typename T>
GenShader(int stage,GLenum internalformat)4533 	std::string GenShader(int stage, GLenum internalformat)
4534 	{
4535 		std::ostringstream os;
4536 		os << "#version 420 core";
4537 		if (stage == 4)
4538 		{ // CS
4539 			os << NL "#extension GL_ARB_compute_shader : require";
4540 		}
4541 		os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4542 		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4543 		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4544 		   << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4545 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4546 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4547 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4548 		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4549 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4550 		   << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4551 			  "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4552 		if (stage == 0)
4553 		{ // VS
4554 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4555 		}
4556 		else if (stage == 1)
4557 		{ // TCS
4558 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4559 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4560 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4561 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4562 		}
4563 		else if (stage == 2)
4564 		{ // TES
4565 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4566 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4567 		}
4568 		else if (stage == 3)
4569 		{ // GS
4570 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4571 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4572 		}
4573 		else if (stage == 4)
4574 		{ // CS
4575 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4576 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4577 		}
4578 		os << NL
4579 			"  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4580 			"  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 			"  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 			"  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 			"  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 			"  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585 			"  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4586 			"  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587 			"  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4588 			"  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4589 
4590 			NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4591 			"  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 			"  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 			"  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 			"  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 			"  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 			"  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4598 			"  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4599 			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4600 
4601 			NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4602 			"  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 			"  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 			"  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 			"  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 			"  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 			"  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 			"  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4609 			"  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4610 			"1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4611 
4612 			NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4613 			"ivec3(coord, 0), g_value[2]) != 0) "
4614 			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 			"  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 			"  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 			"  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 			"  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4619 			"  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4620 			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4621 			"  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4622 			"0.0, 1.0);" NL
4623 			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4624 
4625 			NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4626 			"  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 			"  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 			"  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 			"  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630 			"  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4631 			"  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4632 			"  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4633 			"1.0);" NL
4634 			"  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4635 			"  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4636 
4637 			NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4638 			"  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639 			"  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640 			"  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4641 			"1.0);" NL
4642 			"  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4643 			"  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644 			"  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4645 			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4646 			"1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4647 			"0.0, 0.0, 1.0);" NL
4648 			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4649 
4650 			NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4651 			"  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 			"  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 			"  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654 			"  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4655 			"  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4656 			"  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4657 			"1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4658 			"0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4659 			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4660 			"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4661 
4662 			NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4663 		return os.str();
4664 	}
4665 
4666 protected:
RunStage(int stage)4667 	long RunStage(int stage)
4668 	{
4669 		if (!SupportedInStage(stage, 8))
4670 			return NOT_SUPPORTED;
4671 		if (!Atomic<GLint>(stage, GL_R32I))
4672 			return ERROR;
4673 		if (!Atomic<GLuint>(stage, GL_R32UI))
4674 			return ERROR;
4675 		return NO_ERROR;
4676 	}
4677 };
4678 //-----------------------------------------------------------------------------
4679 // 1.3.4 BasicAllTargetsLoadStoreVS
4680 //-----------------------------------------------------------------------------
4681 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4682 {
Run()4683 	virtual long Run()
4684 	{
4685 		return RunStage(0);
4686 	}
4687 };
4688 //-----------------------------------------------------------------------------
4689 // 1.3.5 BasicAllTargetsLoadStoreTCS
4690 //-----------------------------------------------------------------------------
4691 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4692 {
Run()4693 	virtual long Run()
4694 	{
4695 		return RunStage(1);
4696 	}
4697 };
4698 //-----------------------------------------------------------------------------
4699 // 1.3.6 BasicAllTargetsLoadStoreTES
4700 //-----------------------------------------------------------------------------
4701 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4702 {
Run()4703 	virtual long Run()
4704 	{
4705 		return RunStage(2);
4706 	}
4707 };
4708 //-----------------------------------------------------------------------------
4709 // 1.3.7 BasicAllTargetsLoadStoreGS
4710 //-----------------------------------------------------------------------------
4711 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4712 {
Run()4713 	virtual long Run()
4714 	{
4715 		return RunStage(3);
4716 	}
4717 };
4718 //-----------------------------------------------------------------------------
4719 // 1.3.8 BasicAllTargetsLoadStoreCS
4720 //-----------------------------------------------------------------------------
4721 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4722 {
Run()4723 	virtual long Run()
4724 	{
4725 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4726 		{
4727 			m_context.getTestContext().getLog()
4728 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4729 				<< tcu::TestLog::EndMessage;
4730 			return NO_ERROR;
4731 		}
4732 
4733 		return RunStage(4);
4734 	}
4735 };
4736 //-----------------------------------------------------------------------------
4737 // 1.3.9 BasicAllTargetsAtomicVS
4738 //-----------------------------------------------------------------------------
4739 class BasicAllTargetsAtomicVS : public AtomicMachine
4740 {
Run()4741 	virtual long Run()
4742 	{
4743 		return RunStage(0);
4744 	}
4745 };
4746 //-----------------------------------------------------------------------------
4747 // 1.3.10 BasicAllTargetsAtomicTCS
4748 //-----------------------------------------------------------------------------
4749 class BasicAllTargetsAtomicTCS : public AtomicMachine
4750 {
Run()4751 	virtual long Run()
4752 	{
4753 		return RunStage(1);
4754 	}
4755 };
4756 //-----------------------------------------------------------------------------
4757 // 1.3.11 BasicAllTargetsAtomicTES
4758 //-----------------------------------------------------------------------------
4759 class BasicAllTargetsAtomicTES : public AtomicMachine
4760 {
Run()4761 	virtual long Run()
4762 	{
4763 		return RunStage(2);
4764 	}
4765 };
4766 //-----------------------------------------------------------------------------
4767 // 1.3.12 BasicAllTargetsAtomicGS
4768 //-----------------------------------------------------------------------------
4769 class BasicAllTargetsAtomicGS : public AtomicMachine
4770 {
Run()4771 	virtual long Run()
4772 	{
4773 		return RunStage(3);
4774 	}
4775 };
4776 //-----------------------------------------------------------------------------
4777 // 1.3.13 BasicAllTargetsAtomicCS
4778 //-----------------------------------------------------------------------------
4779 class BasicAllTargetsAtomicCS : public AtomicMachine
4780 {
Run()4781 	virtual long Run()
4782 	{
4783 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4784 		{
4785 			m_context.getTestContext().getLog()
4786 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4787 				<< tcu::TestLog::EndMessage;
4788 			return NO_ERROR;
4789 		}
4790 
4791 		return RunStage(4);
4792 	}
4793 };
4794 //-----------------------------------------------------------------------------
4795 // 1.4.1 BasicGLSLMisc
4796 //-----------------------------------------------------------------------------
4797 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4798 {
4799 	GLuint m_texture;
4800 	GLuint m_program;
4801 	GLuint m_vao, m_vbo;
4802 
Setup()4803 	virtual long Setup()
4804 	{
4805 		m_texture = 0;
4806 		m_program = 0;
4807 		m_vao = m_vbo = 0;
4808 		return NO_ERROR;
4809 	}
4810 
Run()4811 	virtual long Run()
4812 	{
4813 		const int		  kSize = 32;
4814 		std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4815 
4816 		glGenTextures(1, &m_texture);
4817 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4818 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4819 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4820 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4821 
4822 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4823 							 "  gl_Position = i_position;" NL "}";
4824 		const char* src_fs =
4825 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4826 			"layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4827 			"layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4828 			"void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4829 			"  imageStore(g_image_layer0, coord, vec4(1.0));" NL "  memoryBarrier();" NL
4830 			"  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4831 			"  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4832 			"  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4833 		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4834 
4835 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4836 
4837 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4838 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4839 
4840 		glClear(GL_COLOR_BUFFER_BIT);
4841 		glViewport(0, 0, kSize, kSize);
4842 
4843 		glUseProgram(m_program);
4844 		glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4845 		glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4846 
4847 		glBindVertexArray(m_vao);
4848 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4849 
4850 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4851 		{
4852 			return ERROR;
4853 		}
4854 		return NO_ERROR;
4855 	}
4856 
Cleanup()4857 	virtual long Cleanup()
4858 	{
4859 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4860 		glDeleteTextures(1, &m_texture);
4861 		glDeleteVertexArrays(1, &m_vao);
4862 		glDeleteBuffers(1, &m_vbo);
4863 		glUseProgram(0);
4864 		glDeleteProgram(m_program);
4865 		return NO_ERROR;
4866 	}
4867 };
4868 //-----------------------------------------------------------------------------
4869 // 1.4.2 BasicGLSLEarlyFragTests
4870 //-----------------------------------------------------------------------------
4871 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4872 {
4873 	GLuint m_texture[2];
4874 	GLuint m_program[2];
4875 	GLuint m_vao, m_vbo;
4876 
Setup()4877 	virtual long Setup()
4878 	{
4879 		m_texture[0] = m_texture[1] = 0;
4880 		m_program[0] = m_program[1] = 0;
4881 		m_vao = m_vbo = 0;
4882 		return NO_ERROR;
4883 	}
4884 
Run()4885 	virtual long Run()
4886 	{
4887 		int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4888 
4889 		const int		  kSize = 32;
4890 		std::vector<vec4> data(kSize * kSize);
4891 
4892 		glGenTextures(2, m_texture);
4893 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4894 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4895 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4896 		glBindTexture(GL_TEXTURE_2D, 0);
4897 
4898 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4899 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4900 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4901 		glBindTexture(GL_TEXTURE_2D, 0);
4902 
4903 		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4904 							  "  gl_Position = i_position;" NL "}";
4905 		const char* glsl_early_frag_tests_fs =
4906 			"#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4907 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4908 			"  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4909 			"  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4910 		const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4911 							  "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4912 							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4913 							  "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4914 		m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4915 		m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4916 
4917 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4918 
4919 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4920 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4921 
4922 		glViewport(0, 0, kSize, kSize);
4923 		glBindVertexArray(m_vao);
4924 
4925 		glEnable(GL_DEPTH_TEST);
4926 		glClearColor(0.0, 1.0f, 0.0, 1.0f);
4927 		glClearDepthf(0.0f);
4928 
4929 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4930 		glUseProgram(m_program[0]);
4931 		glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4932 
4933 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4934 
4935 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4936 		glUseProgram(m_program[1]);
4937 		glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4938 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4939 
4940 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4941 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4942 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4943 		for (int i = 0; i < kSize * kSize; ++i)
4944 		{
4945 			if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4946 				return ERROR;
4947 		}
4948 
4949 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4950 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4951 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4952 		for (int i = 0; i < kSize * kSize; ++i)
4953 		{
4954 			if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4955 				return ERROR;
4956 		}
4957 
4958 		return NO_ERROR;
4959 	}
4960 
Cleanup()4961 	virtual long Cleanup()
4962 	{
4963 		glDisable(GL_DEPTH_TEST);
4964 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4965 		glClearDepthf(1.0f);
4966 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4967 		glDeleteTextures(2, m_texture);
4968 		glDeleteVertexArrays(1, &m_vao);
4969 		glDeleteBuffers(1, &m_vbo);
4970 		glUseProgram(0);
4971 		glDeleteProgram(m_program[0]);
4972 		glDeleteProgram(m_program[1]);
4973 		return NO_ERROR;
4974 	}
4975 };
4976 //-----------------------------------------------------------------------------
4977 // 1.4.3 BasicGLSLConst
4978 //-----------------------------------------------------------------------------
4979 class BasicGLSLConst : public ShaderImageLoadStoreBase
4980 {
4981 	GLuint m_program;
4982 	GLuint m_vao, m_vbo;
4983 
Setup()4984 	virtual long Setup()
4985 	{
4986 		m_program = 0;
4987 		m_vao = m_vbo = 0;
4988 		return NO_ERROR;
4989 	}
4990 
Run()4991 	virtual long Run()
4992 	{
4993 		bool isAtLeast44Context =
4994 			glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4995 
4996 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4997 							 "  gl_Position = i_position;" NL "}";
4998 		std::ostringstream src_fs;
4999 		src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
5000 		src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5001 					 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5002 					 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5003 					 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5004 					 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5005 					 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5006 					 "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5007 		if (isAtLeast44Context)
5008 			src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5009 						 "vec4(0.2, 0.0, 0.0, 0.2);";
5010 		else
5011 			src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5012 						 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5013 		src_fs << NL
5014 			"  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5015 			"  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5016 			"  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5017 			"0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5018 			"0.0, 0.0, 0.6);" NL
5019 			"  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5020 			"  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5021 			"  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5022 
5023 		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5024 		glUseProgram(m_program);
5025 
5026 		GLint i;
5027 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5028 		glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5029 
5030 		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5031 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5032 
5033 		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5034 		glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5035 
5036 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5037 		glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5038 
5039 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5040 		glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5041 
5042 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5043 		glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5044 
5045 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5046 		glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5047 
5048 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5049 		glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5050 
5051 		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5052 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5053 
5054 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5055 
5056 		glClear(GL_COLOR_BUFFER_BIT);
5057 		glBindVertexArray(m_vao);
5058 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5059 
5060 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5061 		{
5062 			return ERROR;
5063 		}
5064 		return NO_ERROR;
5065 	}
5066 
Cleanup()5067 	virtual long Cleanup()
5068 	{
5069 		glDeleteVertexArrays(1, &m_vao);
5070 		glDeleteBuffers(1, &m_vbo);
5071 		glUseProgram(0);
5072 		glDeleteProgram(m_program);
5073 		return NO_ERROR;
5074 	}
5075 };
5076 //-----------------------------------------------------------------------------
5077 // 2.1.1 AdvancedSyncImageAccess
5078 //-----------------------------------------------------------------------------
5079 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5080 {
5081 	GLuint m_buffer;
5082 	GLuint m_buffer_tex;
5083 	GLuint m_store_program;
5084 	GLuint m_draw_program;
5085 	GLuint m_attribless_vao;
5086 
Setup()5087 	virtual long Setup()
5088 	{
5089 		m_buffer		 = 0;
5090 		m_buffer_tex	 = 0;
5091 		m_store_program  = 0;
5092 		m_draw_program   = 0;
5093 		m_attribless_vao = 0;
5094 		return NO_ERROR;
5095 	}
5096 
Run()5097 	virtual long Run()
5098 	{
5099 		if (!SupportedInVS(1))
5100 			return NOT_SUPPORTED;
5101 		const char* const glsl_store_vs =
5102 			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5103 			"  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5104 			"  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5105 		const char* const glsl_draw_vs =
5106 			"#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5107 			"uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5108 			"  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5109 			"  if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5110 			"  gl_Position = pi;" NL "}";
5111 		const char* const glsl_draw_fs =
5112 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5113 			"  o_color = vs_color;" NL "}";
5114 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5115 		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5116 
5117 		glGenVertexArrays(1, &m_attribless_vao);
5118 		glBindVertexArray(m_attribless_vao);
5119 
5120 		glGenBuffers(1, &m_buffer);
5121 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5122 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5123 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5124 
5125 		glGenTextures(1, &m_buffer_tex);
5126 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5127 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5128 
5129 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5130 
5131 		glEnable(GL_RASTERIZER_DISCARD);
5132 		glUseProgram(m_store_program);
5133 		glDrawArrays(GL_POINTS, 0, 4);
5134 
5135 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5136 
5137 		glDisable(GL_RASTERIZER_DISCARD);
5138 		glClear(GL_COLOR_BUFFER_BIT);
5139 		glUseProgram(m_draw_program);
5140 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5141 
5142 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5143 		{
5144 			return ERROR;
5145 		}
5146 		return NO_ERROR;
5147 	}
5148 
Cleanup()5149 	virtual long Cleanup()
5150 	{
5151 		glUseProgram(0);
5152 		glDeleteBuffers(1, &m_buffer);
5153 		glDeleteTextures(1, &m_buffer_tex);
5154 		glDeleteProgram(m_store_program);
5155 		glDeleteProgram(m_draw_program);
5156 		glDeleteVertexArrays(1, &m_attribless_vao);
5157 		return NO_ERROR;
5158 	}
5159 };
5160 //-----------------------------------------------------------------------------
5161 // 2.1.2 AdvancedSyncVertexArray
5162 //-----------------------------------------------------------------------------
5163 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5164 {
5165 	GLuint m_position_buffer;
5166 	GLuint m_color_buffer;
5167 	GLuint m_element_buffer;
5168 	GLuint m_position_buffer_tex;
5169 	GLuint m_color_buffer_tex;
5170 	GLuint m_element_buffer_tex;
5171 	GLuint m_store_program;
5172 	GLuint m_draw_program;
5173 	GLuint m_attribless_vao;
5174 	GLuint m_draw_vao;
5175 
Setup()5176 	virtual long Setup()
5177 	{
5178 		m_position_buffer	 = 0;
5179 		m_color_buffer		  = 0;
5180 		m_element_buffer	  = 0;
5181 		m_position_buffer_tex = 0;
5182 		m_color_buffer_tex	= 0;
5183 		m_element_buffer_tex  = 0;
5184 		m_store_program		  = 0;
5185 		m_draw_program		  = 0;
5186 		m_attribless_vao	  = 0;
5187 		m_draw_vao			  = 0;
5188 		return NO_ERROR;
5189 	}
5190 
Run()5191 	virtual long Run()
5192 	{
5193 		if (!SupportedInVS(3))
5194 			return NOT_SUPPORTED;
5195 		const char* const glsl_store_vs =
5196 			"#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5197 			"layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5198 			"layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5199 			"void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5200 			"  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5201 			"  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5202 			"  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5203 		const char* const glsl_draw_vs =
5204 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5205 			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5206 			"  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5207 		const char* const glsl_draw_fs =
5208 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5209 			"  o_color = vs_color;" NL "}";
5210 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5211 		glUseProgram(m_store_program);
5212 		glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5213 		glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5214 		glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5215 		glUseProgram(0);
5216 
5217 		m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5218 
5219 		glGenBuffers(1, &m_position_buffer);
5220 		glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5221 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5222 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5223 
5224 		glGenBuffers(1, &m_color_buffer);
5225 		glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5226 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5227 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5228 
5229 		glGenBuffers(1, &m_element_buffer);
5230 		glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5231 		glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5232 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5233 
5234 		glGenTextures(1, &m_position_buffer_tex);
5235 		glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5236 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5237 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5238 
5239 		glGenTextures(1, &m_color_buffer_tex);
5240 		glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5241 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5242 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5243 
5244 		glGenTextures(1, &m_element_buffer_tex);
5245 		glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5246 		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5247 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5248 
5249 		glGenVertexArrays(1, &m_attribless_vao);
5250 
5251 		glGenVertexArrays(1, &m_draw_vao);
5252 		glBindVertexArray(m_draw_vao);
5253 		glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5254 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5255 		glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5256 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5257 		glBindBuffer(GL_ARRAY_BUFFER, 0);
5258 		glEnableVertexAttribArray(0);
5259 		glEnableVertexAttribArray(1);
5260 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5261 		glBindVertexArray(0);
5262 
5263 		glEnable(GL_RASTERIZER_DISCARD);
5264 		glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5265 		glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5266 		glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5267 		glUseProgram(m_store_program);
5268 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5269 		glBindVertexArray(m_attribless_vao);
5270 		glDrawArrays(GL_POINTS, 0, 4);
5271 
5272 		glDisable(GL_RASTERIZER_DISCARD);
5273 		glClear(GL_COLOR_BUFFER_BIT);
5274 		glUseProgram(m_draw_program);
5275 		glBindVertexArray(m_draw_vao);
5276 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5277 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5278 
5279 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5280 		{
5281 			return ERROR;
5282 		}
5283 
5284 		glEnable(GL_RASTERIZER_DISCARD);
5285 		glUseProgram(m_store_program);
5286 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5287 		glBindVertexArray(m_attribless_vao);
5288 		glDrawArrays(GL_POINTS, 0, 4);
5289 
5290 		glDisable(GL_RASTERIZER_DISCARD);
5291 		glClear(GL_COLOR_BUFFER_BIT);
5292 		glUseProgram(m_draw_program);
5293 		glBindVertexArray(m_draw_vao);
5294 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5295 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5296 
5297 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5298 		{
5299 			return ERROR;
5300 		}
5301 		return NO_ERROR;
5302 	}
5303 
Cleanup()5304 	virtual long Cleanup()
5305 	{
5306 		glDisable(GL_RASTERIZER_DISCARD);
5307 		glUseProgram(0);
5308 		glDeleteBuffers(1, &m_position_buffer);
5309 		glDeleteBuffers(1, &m_color_buffer);
5310 		glDeleteBuffers(1, &m_element_buffer);
5311 		glDeleteTextures(1, &m_position_buffer_tex);
5312 		glDeleteTextures(1, &m_color_buffer_tex);
5313 		glDeleteTextures(1, &m_element_buffer_tex);
5314 		glDeleteProgram(m_store_program);
5315 		glDeleteProgram(m_draw_program);
5316 		glDeleteVertexArrays(1, &m_attribless_vao);
5317 		glDeleteVertexArrays(1, &m_draw_vao);
5318 		return NO_ERROR;
5319 	}
5320 };
5321 
5322 //-----------------------------------------------------------------------------
5323 // 2.1.4 AdvancedSyncDrawIndirect
5324 //-----------------------------------------------------------------------------
5325 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5326 {
5327 	GLuint m_draw_command_buffer;
5328 	GLuint m_draw_command_buffer_tex;
5329 	GLuint m_store_program;
5330 	GLuint m_draw_program;
5331 	GLuint m_attribless_vao;
5332 	GLuint m_draw_vao;
5333 	GLuint m_draw_vbo;
5334 
Setup()5335 	virtual long Setup()
5336 	{
5337 		m_draw_command_buffer	 = 0;
5338 		m_draw_command_buffer_tex = 0;
5339 		m_store_program			  = 0;
5340 		m_draw_program			  = 0;
5341 		m_attribless_vao		  = 0;
5342 		m_draw_vao				  = 0;
5343 		m_draw_vbo				  = 0;
5344 		return NO_ERROR;
5345 	}
5346 
Run()5347 	virtual long Run()
5348 	{
5349 		if (!SupportedInVS(1))
5350 			return NOT_SUPPORTED;
5351 		const char* const glsl_store_vs =
5352 			"#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5353 			"  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5354 		const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5355 										 "void main() {" NL "  gl_Position = i_position;" NL "}";
5356 		const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5357 										 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5358 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5359 		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5360 
5361 		glGenBuffers(1, &m_draw_command_buffer);
5362 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5363 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5364 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5365 
5366 		glGenTextures(1, &m_draw_command_buffer_tex);
5367 		glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5368 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5369 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5370 
5371 		glGenVertexArrays(1, &m_attribless_vao);
5372 		CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5373 
5374 		glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5375 
5376 		glEnable(GL_RASTERIZER_DISCARD);
5377 		glUseProgram(m_store_program);
5378 		glBindVertexArray(m_attribless_vao);
5379 		glDrawArrays(GL_POINTS, 0, 1);
5380 
5381 		glDisable(GL_RASTERIZER_DISCARD);
5382 		glClear(GL_COLOR_BUFFER_BIT);
5383 		glUseProgram(m_draw_program);
5384 		glBindVertexArray(m_draw_vao);
5385 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5386 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5387 		glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5388 
5389 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5390 		{
5391 			return ERROR;
5392 		}
5393 		return NO_ERROR;
5394 	}
5395 
Cleanup()5396 	virtual long Cleanup()
5397 	{
5398 		glUseProgram(0);
5399 		glDeleteBuffers(1, &m_draw_command_buffer);
5400 		glDeleteTextures(1, &m_draw_command_buffer_tex);
5401 		glDeleteProgram(m_store_program);
5402 		glDeleteProgram(m_draw_program);
5403 		glDeleteVertexArrays(1, &m_attribless_vao);
5404 		glDeleteVertexArrays(1, &m_draw_vao);
5405 		glDeleteBuffers(1, &m_draw_vbo);
5406 		return NO_ERROR;
5407 	}
5408 };
5409 //-----------------------------------------------------------------------------
5410 // 2.1.5 AdvancedSyncTextureUpdate
5411 //-----------------------------------------------------------------------------
5412 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5413 {
5414 	GLuint m_texture;
5415 	GLuint m_store_program;
5416 	GLuint m_draw_program;
5417 	GLuint m_vao;
5418 	GLuint m_vbo;
5419 	GLuint m_pbo;
5420 
Setup()5421 	virtual long Setup()
5422 	{
5423 		m_texture		= 0;
5424 		m_store_program = 0;
5425 		m_draw_program  = 0;
5426 		m_vao			= 0;
5427 		m_vbo			= 0;
5428 		m_pbo			= 0;
5429 		return NO_ERROR;
5430 	}
5431 
Run()5432 	virtual long Run()
5433 	{
5434 		const char* const glsl_vs =
5435 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5436 			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5437 		const char* const glsl_store_fs =
5438 			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5439 			"  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5440 		const char* const glsl_draw_fs =
5441 			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5442 			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5443 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5444 		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5445 
5446 		std::vector<vec4> data(16 * 16, vec4(1.0f));
5447 		glGenBuffers(1, &m_pbo);
5448 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5449 		glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5450 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5451 
5452 		glGenTextures(1, &m_texture);
5453 		glBindTexture(GL_TEXTURE_2D, m_texture);
5454 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5455 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5456 		glBindTexture(GL_TEXTURE_2D, 0);
5457 
5458 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5459 
5460 		glViewport(0, 0, 16, 16);
5461 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5462 		glUseProgram(m_store_program);
5463 		glBindVertexArray(m_vao);
5464 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5465 
5466 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5467 		glBindTexture(GL_TEXTURE_2D, m_texture);
5468 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5469 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5470 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5471 
5472 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5473 		glClear(GL_COLOR_BUFFER_BIT);
5474 		glUseProgram(m_draw_program);
5475 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5476 
5477 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5478 		{
5479 			return ERROR;
5480 		}
5481 		return NO_ERROR;
5482 	}
5483 
Cleanup()5484 	virtual long Cleanup()
5485 	{
5486 		glUseProgram(0);
5487 		glDeleteBuffers(1, &m_vbo);
5488 		glDeleteBuffers(1, &m_pbo);
5489 		glDeleteTextures(1, &m_texture);
5490 		glDeleteProgram(m_store_program);
5491 		glDeleteProgram(m_draw_program);
5492 		glDeleteVertexArrays(1, &m_vao);
5493 		return NO_ERROR;
5494 	}
5495 };
5496 //-----------------------------------------------------------------------------
5497 // 2.1.6 AdvancedSyncImageAccess2
5498 //-----------------------------------------------------------------------------
5499 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5500 {
5501 	GLuint m_texture;
5502 	GLuint m_store_program;
5503 	GLuint m_draw_program;
5504 	GLuint m_vao;
5505 	GLuint m_vbo;
5506 
Setup()5507 	virtual long Setup()
5508 	{
5509 		m_texture		= 0;
5510 		m_store_program = 0;
5511 		m_draw_program  = 0;
5512 		m_vao			= 0;
5513 		m_vbo			= 0;
5514 		return NO_ERROR;
5515 	}
5516 
Run()5517 	virtual long Run()
5518 	{
5519 		const char* const glsl_vs =
5520 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5521 			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5522 		const char* const glsl_store_fs =
5523 			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5524 			"  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5525 		const char* const glsl_draw_fs =
5526 			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5527 			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5528 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5529 		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5530 
5531 		int width  = getWindowWidth();
5532 		int height = getWindowHeight();
5533 		scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5534 
5535 		glGenTextures(1, &m_texture);
5536 		glBindTexture(GL_TEXTURE_2D, m_texture);
5537 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5538 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5539 		glBindTexture(GL_TEXTURE_2D, 0);
5540 
5541 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5542 
5543 		glViewport(0, 0, width, height);
5544 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5545 		glUseProgram(m_store_program);
5546 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5547 		glBindVertexArray(m_vao);
5548 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5549 
5550 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5551 
5552 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5553 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5554 
5555 		glClear(GL_COLOR_BUFFER_BIT);
5556 		glBindTexture(GL_TEXTURE_2D, m_texture);
5557 		glUseProgram(m_draw_program);
5558 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5559 
5560 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5561 		{
5562 			return ERROR;
5563 		}
5564 		return NO_ERROR;
5565 	}
5566 
Cleanup()5567 	virtual long Cleanup()
5568 	{
5569 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5570 		glUseProgram(0);
5571 		glDeleteBuffers(1, &m_vbo);
5572 		glDeleteTextures(1, &m_texture);
5573 		glDeleteProgram(m_store_program);
5574 		glDeleteProgram(m_draw_program);
5575 		glDeleteVertexArrays(1, &m_vao);
5576 		return NO_ERROR;
5577 	}
5578 };
5579 //-----------------------------------------------------------------------------
5580 // 2.1.7 AdvancedSyncBufferUpdate
5581 //-----------------------------------------------------------------------------
5582 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5583 {
5584 	GLuint m_buffer;
5585 	GLuint m_buffer_tex;
5586 	GLuint m_store_program;
5587 	GLuint m_attribless_vao;
5588 
Setup()5589 	virtual long Setup()
5590 	{
5591 		m_buffer		 = 0;
5592 		m_buffer_tex	 = 0;
5593 		m_store_program  = 0;
5594 		m_attribless_vao = 0;
5595 		return NO_ERROR;
5596 	}
5597 
Run()5598 	virtual long Run()
5599 	{
5600 		if (!SupportedInVS(1))
5601 			return NOT_SUPPORTED;
5602 		const char* const glsl_store_vs =
5603 			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5604 			"  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5605 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5606 
5607 		glGenVertexArrays(1, &m_attribless_vao);
5608 		glBindVertexArray(m_attribless_vao);
5609 
5610 		glGenBuffers(1, &m_buffer);
5611 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5612 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5613 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5614 
5615 		glGenTextures(1, &m_buffer_tex);
5616 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5617 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5618 
5619 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5620 
5621 		glEnable(GL_RASTERIZER_DISCARD);
5622 		glUseProgram(m_store_program);
5623 		glDrawArrays(GL_POINTS, 0, 1000);
5624 
5625 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5626 
5627 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5628 		vec4* ptr =
5629 			reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5630 		for (int i = 0; i < 1000; ++i)
5631 		{
5632 			if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5633 			{
5634 				m_context.getTestContext().getLog()
5635 					<< tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5636 				return ERROR;
5637 			}
5638 		}
5639 		return NO_ERROR;
5640 	}
5641 
Cleanup()5642 	virtual long Cleanup()
5643 	{
5644 		glDisable(GL_RASTERIZER_DISCARD);
5645 		glUseProgram(0);
5646 		glDeleteBuffers(1, &m_buffer);
5647 		glDeleteTextures(1, &m_buffer_tex);
5648 		glDeleteProgram(m_store_program);
5649 		glDeleteVertexArrays(1, &m_attribless_vao);
5650 		return NO_ERROR;
5651 	}
5652 };
5653 //-----------------------------------------------------------------------------
5654 // 2.2.1 AdvancedAllStagesOneImage
5655 //-----------------------------------------------------------------------------
5656 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5657 {
5658 	GLuint m_program;
5659 	GLuint m_vao;
5660 	GLuint m_vbo;
5661 	GLuint m_ebo;
5662 	GLuint m_buffer;
5663 	GLuint m_buffer_tex;
5664 	GLuint m_texture;
5665 
Setup()5666 	virtual long Setup()
5667 	{
5668 		m_program	= 0;
5669 		m_vao		 = 0;
5670 		m_vbo		 = 0;
5671 		m_ebo		 = 0;
5672 		m_buffer	 = 0;
5673 		m_buffer_tex = 0;
5674 		m_texture	= 0;
5675 		return NO_ERROR;
5676 	}
5677 
Run()5678 	virtual long Run()
5679 	{
5680 		if (!SupportedInGeomStages(2))
5681 			return NOT_SUPPORTED;
5682 		const char* const glsl_vs =
5683 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5684 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5685 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5686 			"  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5687 			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5688 		const char* const glsl_tcs =
5689 			"#version 420 core" NL "layout(vertices = 1) out;" NL
5690 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5691 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5692 			"  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5693 			"  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5694 			"  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5695 			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5696 		const char* const glsl_tes =
5697 			"#version 420 core" NL "layout(triangles, point_mode) in;" NL
5698 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5699 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5700 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5701 			"  gl_Position = gl_in[0].gl_Position;" NL "}";
5702 		const char* const glsl_gs =
5703 			"#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5704 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5705 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5706 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5707 			"  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5708 		const char* const glsl_fs =
5709 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5710 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5711 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5712 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5713 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5714 		m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5715 		glUseProgram(m_program);
5716 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5717 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5718 
5719 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5720 
5721 		GLint i32 = 0;
5722 		glGenBuffers(1, &m_buffer);
5723 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5724 		glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5725 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5726 
5727 		glGenTextures(1, &m_buffer_tex);
5728 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5729 		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5730 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5731 
5732 		GLuint ui32 = 0;
5733 		glGenTextures(1, &m_texture);
5734 		glBindTexture(GL_TEXTURE_2D, m_texture);
5735 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5736 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5737 		glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5738 		glBindTexture(GL_TEXTURE_2D, 0);
5739 
5740 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5741 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5742 
5743 		glBindVertexArray(m_vao);
5744 		glPatchParameteri(GL_PATCH_VERTICES, 1);
5745 
5746 		glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5747 		glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5748 
5749 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5750 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5751 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5752 		if (i32 < 20 || i32 > 50)
5753 		{
5754 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5755 												<< " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5756 			return ERROR;
5757 		}
5758 
5759 		glBindTexture(GL_TEXTURE_2D, m_texture);
5760 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5761 		if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5762 		{
5763 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5764 												<< (2 * i32) << tcu::TestLog::EndMessage;
5765 			return ERROR;
5766 		}
5767 
5768 		return NO_ERROR;
5769 	}
5770 
Cleanup()5771 	virtual long Cleanup()
5772 	{
5773 		glPatchParameteri(GL_PATCH_VERTICES, 3);
5774 		glUseProgram(0);
5775 		glDeleteBuffers(1, &m_buffer);
5776 		glDeleteBuffers(1, &m_vbo);
5777 		glDeleteBuffers(1, &m_ebo);
5778 		glDeleteTextures(1, &m_buffer_tex);
5779 		glDeleteTextures(1, &m_texture);
5780 		glDeleteProgram(m_program);
5781 		glDeleteVertexArrays(1, &m_vao);
5782 		return NO_ERROR;
5783 	}
5784 };
5785 //-----------------------------------------------------------------------------
5786 // 2.3.1 AdvancedMemoryDependentInvocation
5787 //-----------------------------------------------------------------------------
5788 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5789 {
5790 	GLuint m_buffer;
5791 	GLuint m_buffer_tex;
5792 	GLuint m_texture;
5793 	GLuint m_program;
5794 	GLuint m_vao;
5795 	GLuint m_vbo;
5796 
Setup()5797 	virtual long Setup()
5798 	{
5799 		m_buffer	 = 0;
5800 		m_buffer_tex = 0;
5801 		m_texture	= 0;
5802 		m_program	= 0;
5803 		m_vao		 = 0;
5804 		m_vbo		 = 0;
5805 		return NO_ERROR;
5806 	}
5807 
Run()5808 	virtual long Run()
5809 	{
5810 		if (!SupportedInVS(2))
5811 			return NOT_SUPPORTED;
5812 		const char* const glsl_vs =
5813 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5814 			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5815 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5816 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5817 			"  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5818 			"  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5819 		const char* const glsl_fs =
5820 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5821 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5822 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5823 			"  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5824 			"  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5825 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5826 		glUseProgram(m_program);
5827 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5828 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5829 
5830 		vec4 zero(0);
5831 		glGenBuffers(1, &m_buffer);
5832 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5833 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5834 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5835 
5836 		glGenTextures(1, &m_buffer_tex);
5837 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5838 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5839 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5840 
5841 		glGenTextures(1, &m_texture);
5842 		glBindTexture(GL_TEXTURE_2D, m_texture);
5843 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5844 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5845 		glBindTexture(GL_TEXTURE_2D, 0);
5846 
5847 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5848 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5849 
5850 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5851 
5852 		glClear(GL_COLOR_BUFFER_BIT);
5853 		glBindVertexArray(m_vao);
5854 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5855 
5856 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5857 		{
5858 			return ERROR;
5859 		}
5860 		return NO_ERROR;
5861 	}
5862 
Cleanup()5863 	virtual long Cleanup()
5864 	{
5865 		glUseProgram(0);
5866 		glDeleteBuffers(1, &m_vbo);
5867 		glDeleteBuffers(1, &m_buffer);
5868 		glDeleteTextures(1, &m_texture);
5869 		glDeleteTextures(1, &m_buffer_tex);
5870 		glDeleteProgram(m_program);
5871 		glDeleteVertexArrays(1, &m_vao);
5872 		return NO_ERROR;
5873 	}
5874 };
5875 //-----------------------------------------------------------------------------
5876 // 2.3.2 AdvancedMemoryOrder
5877 //-----------------------------------------------------------------------------
5878 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5879 {
5880 	GLuint m_buffer;
5881 	GLuint m_buffer_tex;
5882 	GLuint m_texture;
5883 	GLuint m_program;
5884 	GLuint m_vao;
5885 	GLuint m_vbo;
5886 
Setup()5887 	virtual long Setup()
5888 	{
5889 		m_buffer	 = 0;
5890 		m_buffer_tex = 0;
5891 		m_texture	= 0;
5892 		m_program	= 0;
5893 		m_vao		 = 0;
5894 		m_vbo		 = 0;
5895 		return NO_ERROR;
5896 	}
5897 
Run()5898 	virtual long Run()
5899 	{
5900 		if (!SupportedInVS(1))
5901 			return NOT_SUPPORTED;
5902 		const char* const glsl_vs =
5903 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5904 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5905 			"  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5906 			"  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5907 			"  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5908 			"  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5909 		const char* const glsl_fs =
5910 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5911 			"layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5912 			"  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5913 			"    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5914 			"    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5915 			"}";
5916 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5917 		glUseProgram(m_program);
5918 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5919 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5920 
5921 		glGenBuffers(1, &m_buffer);
5922 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5923 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5924 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5925 
5926 		glGenTextures(1, &m_buffer_tex);
5927 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5928 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5929 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5930 
5931 		int width  = getWindowWidth();
5932 		int height = getWindowHeight();
5933 		scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5934 
5935 		std::vector<vec4> data(width * height);
5936 		glGenTextures(1, &m_texture);
5937 		glBindTexture(GL_TEXTURE_2D, m_texture);
5938 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5939 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5940 		glBindTexture(GL_TEXTURE_2D, 0);
5941 
5942 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5943 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5944 
5945 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5946 
5947 		glClear(GL_COLOR_BUFFER_BIT);
5948 		glViewport(0, 0, width, height);
5949 		glBindVertexArray(m_vao);
5950 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5951 
5952 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5953 		{
5954 			return ERROR;
5955 		}
5956 		return NO_ERROR;
5957 	}
5958 
Cleanup()5959 	virtual long Cleanup()
5960 	{
5961 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5962 		glUseProgram(0);
5963 		glDeleteBuffers(1, &m_vbo);
5964 		glDeleteBuffers(1, &m_buffer);
5965 		glDeleteTextures(1, &m_texture);
5966 		glDeleteTextures(1, &m_buffer_tex);
5967 		glDeleteProgram(m_program);
5968 		glDeleteVertexArrays(1, &m_vao);
5969 		return NO_ERROR;
5970 	}
5971 };
5972 //-----------------------------------------------------------------------------
5973 // 2.4.1 AdvancedSSOSimple
5974 //-----------------------------------------------------------------------------
5975 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5976 {
5977 	GLuint m_texture;
5978 	GLuint m_pipeline[2];
5979 	GLuint m_vsp, m_fsp0, m_fsp1;
5980 	GLuint m_vao, m_vbo;
5981 
Setup()5982 	virtual long Setup()
5983 	{
5984 		glGenTextures(1, &m_texture);
5985 		glGenProgramPipelines(2, m_pipeline);
5986 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5987 
5988 		const char* const glsl_vs =
5989 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5990 			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5991 		const char* const glsl_fs0 =
5992 			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5993 			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5994 			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
5995 		const char* const glsl_fs1 =
5996 			"#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5997 			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5998 			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
5999 		m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6000 		m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6001 		m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6002 
6003 		return NO_ERROR;
6004 	}
6005 
Run()6006 	virtual long Run()
6007 	{
6008 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6009 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6010 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6011 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6012 
6013 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6014 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6015 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6016 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6017 
6018 		glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6019 		glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6020 
6021 		glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6022 		glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6023 
6024 		int width  = getWindowWidth();
6025 		int height = getWindowHeight();
6026 		scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6027 
6028 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6029 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6030 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6031 
6032 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6033 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6034 		glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6035 		glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6036 		glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6037 		glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6038 		glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6039 		glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6040 
6041 		glBindVertexArray(m_vao);
6042 
6043 		glViewport(0, 0, width, height);
6044 		glBindProgramPipeline(m_pipeline[0]);
6045 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6046 
6047 		glBindProgramPipeline(m_pipeline[1]);
6048 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6049 
6050 		std::vector<vec4> data(width * height * 8);
6051 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6052 
6053 		for (int layer = 0; layer < 8; ++layer)
6054 		{
6055 			for (int h = 0; h < height; ++h)
6056 			{
6057 				for (int w = 0; w < width; ++w)
6058 				{
6059 					const vec4 c = data[layer * width * height + h * width + w];
6060 					if (layer % 2)
6061 					{
6062 						if (!IsEqual(c, vec4(2.0f)))
6063 						{
6064 							return ERROR;
6065 						}
6066 					}
6067 					else
6068 					{
6069 						if (!IsEqual(c, vec4(1.0f)))
6070 						{
6071 							return ERROR;
6072 						}
6073 					}
6074 				}
6075 			}
6076 		}
6077 		return NO_ERROR;
6078 	}
6079 
Cleanup()6080 	virtual long Cleanup()
6081 	{
6082 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6083 		glDeleteBuffers(1, &m_vbo);
6084 		glDeleteTextures(1, &m_texture);
6085 		glDeleteProgram(m_vsp);
6086 		glDeleteProgram(m_fsp0);
6087 		glDeleteProgram(m_fsp1);
6088 		glDeleteVertexArrays(1, &m_vao);
6089 		glDeleteProgramPipelines(2, m_pipeline);
6090 		return NO_ERROR;
6091 	}
6092 };
6093 //-----------------------------------------------------------------------------
6094 // 2.4.2 AdvancedSSOAtomicCounters
6095 //-----------------------------------------------------------------------------
6096 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6097 {
6098 	GLuint m_buffer, m_buffer_tex;
6099 	GLuint m_counter_buffer;
6100 	GLuint m_transform_buffer;
6101 	GLuint m_pipeline;
6102 	GLuint m_vao, m_vbo;
6103 	GLuint m_vsp, m_fsp;
6104 
Setup()6105 	virtual long Setup()
6106 	{
6107 		m_vao = 0;
6108 		m_vbo = 0;
6109 		m_vsp = 0;
6110 		m_fsp = 0;
6111 		glGenBuffers(1, &m_buffer);
6112 		glGenTextures(1, &m_buffer_tex);
6113 		glGenBuffers(1, &m_counter_buffer);
6114 		glGenBuffers(1, &m_transform_buffer);
6115 		glGenProgramPipelines(1, &m_pipeline);
6116 		return NO_ERROR;
6117 	}
6118 
Run()6119 	virtual long Run()
6120 	{
6121 		if (!SupportedInVS(1))
6122 			return NOT_SUPPORTED;
6123 
6124 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6125 		const char* const glsl_vs =
6126 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6127 			"layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6128 			"out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6129 			"  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6130 			"layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6131 			"  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6132 			"  const uint index = atomicCounterIncrement(g_counter);" NL
6133 			"  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6134 		const char* const glsl_fs =
6135 			"#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6136 			"layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6137 		m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6138 		m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6139 
6140 		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6141 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6142 
6143 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6144 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6145 
6146 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6147 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6148 
6149 		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6150 		vec4 zero(0);
6151 		glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6152 
6153 		glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6154 		mat4 identity(1);
6155 		glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6156 
6157 		glClear(GL_COLOR_BUFFER_BIT);
6158 		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6159 		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6160 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6161 		glBindVertexArray(m_vao);
6162 		glBindProgramPipeline(m_pipeline);
6163 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6164 
6165 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6166 		{
6167 			return ERROR;
6168 		}
6169 
6170 		std::vector<vec4> data(4);
6171 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6172 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6173 
6174 		for (int i = 0; i < 4; ++i)
6175 		{
6176 			if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6177 				!IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6178 			{
6179 				return ERROR;
6180 			}
6181 		}
6182 
6183 		return NO_ERROR;
6184 	}
6185 
Cleanup()6186 	virtual long Cleanup()
6187 	{
6188 		glDeleteBuffers(1, &m_buffer);
6189 		glDeleteBuffers(1, &m_vbo);
6190 		glDeleteBuffers(1, &m_counter_buffer);
6191 		glDeleteBuffers(1, &m_transform_buffer);
6192 		glDeleteTextures(1, &m_buffer_tex);
6193 		glDeleteProgram(m_vsp);
6194 		glDeleteProgram(m_fsp);
6195 		glDeleteVertexArrays(1, &m_vao);
6196 		glDeleteProgramPipelines(1, &m_pipeline);
6197 		return NO_ERROR;
6198 	}
6199 };
6200 //-----------------------------------------------------------------------------
6201 // 2.4.3 AdvancedSSOSubroutine
6202 //-----------------------------------------------------------------------------
6203 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6204 {
6205 	GLuint m_texture;
6206 	GLuint m_attribless_vao;
6207 	GLuint m_program;
6208 	GLint  m_draw_buffer;
6209 
Setup()6210 	virtual long Setup()
6211 	{
6212 		glGenTextures(1, &m_texture);
6213 		glGenVertexArrays(1, &m_attribless_vao);
6214 
6215 		const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6216 									"const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6217 									"void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6218 		const char* const glsl_fs =
6219 			"#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6220 			"writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6221 			"subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6222 			"  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6223 			"  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6224 			"  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6225 			"subroutine(Brush) void Brush1(ivec2 coord) {" NL
6226 			"  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6227 			"  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6228 			"  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6229 			"  g_brush(ivec2(gl_FragCoord));" NL "}";
6230 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6231 
6232 		return NO_ERROR;
6233 	}
6234 
Run()6235 	virtual long Run()
6236 	{
6237 		int width  = getWindowWidth();
6238 		int height = getWindowHeight();
6239 		scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6240 
6241 		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6242 		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6243 
6244 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6245 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6246 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6247 
6248 		glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6249 
6250 		glDrawBuffer(GL_NONE);
6251 		glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6252 		glUseProgram(m_program);
6253 		glBindVertexArray(m_attribless_vao);
6254 
6255 		const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6256 									glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6257 
6258 		glViewport(0, 0, width, height);
6259 		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6260 		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6261 
6262 		std::vector<vec4> data(width * height * 3);
6263 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6264 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6265 
6266 		for (int layer = 0; layer < 3; ++layer)
6267 		{
6268 			for (int h = 0; h < height; ++h)
6269 			{
6270 				for (int w = 0; w < width; ++w)
6271 				{
6272 					const vec4 c = data[layer * width * height + h * width + w];
6273 					if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6274 					{
6275 						m_context.getTestContext().getLog()
6276 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6277 							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6278 						return ERROR;
6279 					}
6280 					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6281 					{
6282 						m_context.getTestContext().getLog()
6283 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6284 							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6285 						return ERROR;
6286 					}
6287 					else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6288 					{
6289 						m_context.getTestContext().getLog()
6290 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6291 							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6292 						return ERROR;
6293 					}
6294 				}
6295 			}
6296 		}
6297 
6298 		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6299 		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6300 
6301 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6302 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6303 
6304 		for (int layer = 0; layer < 3; ++layer)
6305 		{
6306 			for (int h = 0; h < height; ++h)
6307 			{
6308 				for (int w = 0; w < width; ++w)
6309 				{
6310 					const vec4 c = data[layer * width * height + h * width + w];
6311 					if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6312 					{
6313 						m_context.getTestContext().getLog()
6314 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6315 							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6316 						return ERROR;
6317 					}
6318 					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6319 					{
6320 						m_context.getTestContext().getLog()
6321 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6322 							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6323 						return ERROR;
6324 					}
6325 					else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6326 					{
6327 						m_context.getTestContext().getLog()
6328 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6329 							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6330 						return ERROR;
6331 					}
6332 				}
6333 			}
6334 		}
6335 		return NO_ERROR;
6336 	}
6337 
Cleanup()6338 	virtual long Cleanup()
6339 	{
6340 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6341 		glDrawBuffer(m_draw_buffer);
6342 		glDeleteTextures(1, &m_texture);
6343 		glUseProgram(0);
6344 		glDeleteProgram(m_program);
6345 		glDeleteVertexArrays(1, &m_attribless_vao);
6346 		return NO_ERROR;
6347 	}
6348 };
6349 //-----------------------------------------------------------------------------
6350 // 2.4.4 AdvancedSSOPerSample
6351 //-----------------------------------------------------------------------------
6352 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6353 {
6354 	GLuint m_texture;
6355 	GLuint m_pipeline;
6356 	GLuint m_vao, m_vbo, m_ebo;
6357 	GLuint m_vsp, m_store_fsp, m_load_fsp;
6358 
Setup()6359 	virtual long Setup()
6360 	{
6361 		m_vao		= 0;
6362 		m_vbo		= 0;
6363 		m_ebo		= 0;
6364 		m_vsp		= 0;
6365 		m_store_fsp = 0;
6366 		m_load_fsp  = 0;
6367 		glGenTextures(1, &m_texture);
6368 		glGenProgramPipelines(1, &m_pipeline);
6369 
6370 		return NO_ERROR;
6371 	}
6372 
Run()6373 	virtual long Run()
6374 	{
6375 		if (!SupportedSamples(4))
6376 			return NOT_SUPPORTED;
6377 
6378 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6379 
6380 		const char* const glsl_vs =
6381 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6382 			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6383 		const char* const glsl_store_fs =
6384 			"#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6385 			"  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6386 		const char* const glsl_load_fs =
6387 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6388 			"layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6389 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6390 			"vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6391 		m_vsp		= BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6392 		m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6393 		m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6394 
6395 		int width  = getWindowWidth();
6396 		int height = getWindowHeight();
6397 		scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6398 
6399 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6400 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6401 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6402 
6403 		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6404 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6405 
6406 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6407 
6408 		glClear(GL_COLOR_BUFFER_BIT);
6409 		glViewport(0, 0, width, height);
6410 		glBindVertexArray(m_vao);
6411 		glBindProgramPipeline(m_pipeline);
6412 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6413 
6414 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6415 
6416 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6417 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6418 
6419 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6420 		{
6421 			return ERROR;
6422 		}
6423 		return NO_ERROR;
6424 	}
6425 
Cleanup()6426 	virtual long Cleanup()
6427 	{
6428 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6429 		glDeleteBuffers(1, &m_vbo);
6430 		glDeleteBuffers(1, &m_ebo);
6431 		glDeleteTextures(1, &m_texture);
6432 		glDeleteProgram(m_vsp);
6433 		glDeleteProgram(m_store_fsp);
6434 		glDeleteProgram(m_load_fsp);
6435 		glDeleteVertexArrays(1, &m_vao);
6436 		glDeleteProgramPipelines(1, &m_pipeline);
6437 		return NO_ERROR;
6438 	}
6439 };
6440 
6441 //-----------------------------------------------------------------------------
6442 // 2.5 AdvancedCopyImage
6443 //-----------------------------------------------------------------------------
6444 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6445 {
6446 	GLuint m_texture[2];
6447 	GLuint m_program;
6448 	GLuint m_vao, m_vbo, m_ebo;
6449 
Setup()6450 	virtual long Setup()
6451 	{
6452 		glGenTextures(2, m_texture);
6453 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6454 
6455 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6456 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6457 		const char* const glsl_fs =
6458 			"#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6459 			"layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6460 			"  ivec2 coord = ivec2(gl_FragCoord);" NL
6461 			"  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6462 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6463 
6464 		return NO_ERROR;
6465 	}
6466 
Run()6467 	virtual long Run()
6468 	{
6469 		int width  = getWindowWidth();
6470 		int height = getWindowHeight();
6471 		scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6472 
6473 		glUseProgram(m_program);
6474 		glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6475 		glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6476 
6477 		std::vector<vec4> data(width * height, vec4(7.0f));
6478 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6479 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6480 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6481 
6482 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6483 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6484 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6485 
6486 		glBindTexture(GL_TEXTURE_2D, 0);
6487 
6488 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6489 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6490 
6491 		glClear(GL_COLOR_BUFFER_BIT);
6492 		glViewport(0, 0, width, height);
6493 		glBindVertexArray(m_vao);
6494 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6495 
6496 		std::vector<vec4> rdata(width * height);
6497 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6498 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6499 
6500 		for (int h = 0; h < height; ++h)
6501 		{
6502 			for (int w = 0; w < width; ++w)
6503 			{
6504 				if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6505 				{
6506 					return ERROR;
6507 				}
6508 			}
6509 		}
6510 		return NO_ERROR;
6511 	}
6512 
Cleanup()6513 	virtual long Cleanup()
6514 	{
6515 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6516 		glUseProgram(0);
6517 		glDeleteBuffers(1, &m_vbo);
6518 		glDeleteBuffers(1, &m_ebo);
6519 		glDeleteTextures(2, m_texture);
6520 		glDeleteProgram(m_program);
6521 		glDeleteVertexArrays(1, &m_vao);
6522 		return NO_ERROR;
6523 	}
6524 };
6525 //-----------------------------------------------------------------------------
6526 // 2.6 AdvancedAllMips
6527 //-----------------------------------------------------------------------------
6528 class AdvancedAllMips : public ShaderImageLoadStoreBase
6529 {
6530 	GLuint m_texture;
6531 	GLuint m_store_program, m_load_program;
6532 	GLuint m_vao, m_vbo, m_ebo;
6533 
Setup()6534 	virtual long Setup()
6535 	{
6536 		glGenTextures(1, &m_texture);
6537 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6538 
6539 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6540 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6541 		const char* const glsl_store_fs =
6542 			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6543 			"  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6544 			"  discard;" NL "}";
6545 		const char* const glsl_load_fs =
6546 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6547 			"layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6548 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6549 			"    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6550 			"    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6551 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6552 		m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6553 
6554 		return NO_ERROR;
6555 	}
6556 
Run()6557 	virtual long Run()
6558 	{
6559 		glUseProgram(m_store_program);
6560 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6561 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6562 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6563 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6564 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6565 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6566 		glUseProgram(0);
6567 
6568 		glUseProgram(m_load_program);
6569 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6570 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6571 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6572 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6573 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6574 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6575 		glUseProgram(0);
6576 
6577 		glBindTexture(GL_TEXTURE_2D, m_texture);
6578 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6579 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6580 		glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6581 		glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6582 		glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6583 		glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6584 		glBindTexture(GL_TEXTURE_2D, 0);
6585 
6586 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587 		glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588 		glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589 		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590 		glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6591 		glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6592 
6593 		glViewport(0, 0, 32, 32);
6594 		glBindVertexArray(m_vao);
6595 
6596 		glClear(GL_COLOR_BUFFER_BIT);
6597 		glUseProgram(m_store_program);
6598 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6599 
6600 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6601 
6602 		glUseProgram(m_load_program);
6603 		glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6604 
6605 		if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6606 		{
6607 			return ERROR;
6608 		}
6609 		return NO_ERROR;
6610 	}
6611 
Cleanup()6612 	virtual long Cleanup()
6613 	{
6614 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6615 		glUseProgram(0);
6616 		glDeleteBuffers(1, &m_vbo);
6617 		glDeleteBuffers(1, &m_ebo);
6618 		glDeleteTextures(1, &m_texture);
6619 		glDeleteProgram(m_store_program);
6620 		glDeleteProgram(m_load_program);
6621 		glDeleteVertexArrays(1, &m_vao);
6622 		return NO_ERROR;
6623 	}
6624 };
6625 //-----------------------------------------------------------------------------
6626 // 2.7 AdvancedCast
6627 //-----------------------------------------------------------------------------
6628 class AdvancedCast : public ShaderImageLoadStoreBase
6629 {
6630 	GLuint m_texture[2];
6631 	GLuint m_program;
6632 	GLuint m_vao, m_vbo, m_ebo;
6633 
Setup()6634 	virtual long Setup()
6635 	{
6636 		glGenTextures(2, m_texture);
6637 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6638 
6639 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6640 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6641 		const char* const glsl_fs =
6642 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6643 			"layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6644 			"void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6645 			"  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6646 			"  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6647 			"  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6648 			"  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6649 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6650 
6651 		return NO_ERROR;
6652 	}
6653 
Run()6654 	virtual long Run()
6655 	{
6656 		glUseProgram(m_program);
6657 		glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6658 		glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6659 
6660 		{
6661 			std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6662 			glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6663 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6664 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6665 						 &data[0]);
6666 
6667 			glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6668 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6669 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6670 						 &data[0]);
6671 
6672 			glBindTexture(GL_TEXTURE_2D, 0);
6673 		}
6674 
6675 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6676 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6677 
6678 		glClear(GL_COLOR_BUFFER_BIT);
6679 		glBindVertexArray(m_vao);
6680 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6681 
6682 		std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6683 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6684 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6685 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6686 
6687 		for (int h = 0; h < getWindowHeight(); ++h)
6688 		{
6689 			for (int w = 0; w < getWindowWidth(); ++w)
6690 			{
6691 				const GLubyte c[4] = {
6692 					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6693 					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6694 				};
6695 				if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6696 				{
6697 					m_context.getTestContext().getLog()
6698 						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6699 						<< ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6700 					return ERROR;
6701 				}
6702 			}
6703 		}
6704 
6705 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6706 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6707 
6708 		for (int h = 0; h < getWindowHeight(); ++h)
6709 		{
6710 			for (int w = 0; w < getWindowWidth(); ++w)
6711 			{
6712 				const GLubyte c[4] = {
6713 					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6714 					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6715 				};
6716 				if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6717 				{
6718 					m_context.getTestContext().getLog()
6719 						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6720 						<< ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6721 					return ERROR;
6722 				}
6723 			}
6724 		}
6725 
6726 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6727 		{
6728 			return ERROR;
6729 		}
6730 		return NO_ERROR;
6731 	}
6732 
Cleanup()6733 	virtual long Cleanup()
6734 	{
6735 		glUseProgram(0);
6736 		glDeleteBuffers(1, &m_vbo);
6737 		glDeleteBuffers(1, &m_ebo);
6738 		glDeleteTextures(2, m_texture);
6739 		glDeleteProgram(m_program);
6740 		glDeleteVertexArrays(1, &m_vao);
6741 		return NO_ERROR;
6742 	}
6743 };
6744 
6745 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6746  *
6747  *  Steps:
6748  *  - create two textures: "source" and "destination". Fill "source"
6749  *  texture with unique values. Fill "destination" texture with zeros,
6750  *  - prepare a program object that will read texel from "source" image at given
6751  *  coordinates and write its value to "destination" image at same
6752  *  coordinates,
6753  *  - bind "source" and "destination" textures as "source" and "destination"
6754  *  image uniforms,
6755  *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6756  *  corner at 1,1),
6757  *  - verify that texel values in "destination" texture match those in
6758  *  "source" texture (use glGetTexImage).
6759  *
6760  *  Test with 2D R8UI textures with following dimensions:
6761  *  - 16x16,
6762  *  - 16x17,
6763  *  - 17x16,
6764  *  - 17x17,
6765  *  - 16x18,
6766  *  - 18x16,
6767  *  - 18x18,
6768  *  - 19x16,
6769  *  - 16x19,
6770  *  - 19x19.
6771  *
6772  *  Note that default data alignment should cause problems with packing/
6773  *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6774  *  of pixel storage mode have to be changed to one byte alignment.
6775  *
6776  *  Program should consist of vertex and fragment shader. Vertex shader should
6777  *  pass vertex position through. Fragment shader should do imageLoad() and
6778  *  imageStore() operations at coordinates gl_FragCoord.
6779  **/
6780 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6781 {
6782 private:
6783 	/* Structures */
6784 	struct TextureDimensions
6785 	{
6786 		GLuint m_width;
6787 		GLuint m_height;
6788 
TextureDimensionsgl4cts::__anonb00615420111::ImageLoadStoreDataAlignmentTest::TextureDimensions6789 		TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6790 		{
6791 		}
6792 	};
6793 
6794 	/* Typedefs */
6795 	typedef std::deque<TextureDimensions> TextureDimensionsList;
6796 
6797 	/* Fields */
6798 	GLuint				  m_destination_texture_id;
6799 	GLuint				  m_program_id;
6800 	TextureDimensionsList m_texture_dimensions;
6801 	GLuint				  m_source_texture_id;
6802 	GLuint				  m_vertex_array_object_id;
6803 	GLuint				  m_vertex_buffer_id;
6804 
6805 public:
6806 	/* Constructor */
ImageLoadStoreDataAlignmentTest()6807 	ImageLoadStoreDataAlignmentTest()
6808 		: m_destination_texture_id(0)
6809 		, m_program_id(0)
6810 		, m_source_texture_id(0)
6811 		, m_vertex_array_object_id(0)
6812 		, m_vertex_buffer_id(0)
6813 	{
6814 		/* Nothing to be done here */
6815 	}
6816 
6817 	/* Methods inherited from SubcaseBase */
Setup()6818 	virtual long Setup()
6819 	{
6820 		/* Shaders code */
6821 		const char* const vertex_shader_code = "#version 400 core\n"
6822 											   "#extension GL_ARB_shader_image_load_store : require\n"
6823 											   "\n"
6824 											   "precision highp float;\n"
6825 											   "\n"
6826 											   "in vec4 vs_in_position;\n"
6827 											   "\n"
6828 											   "void main()\n"
6829 											   "{\n"
6830 											   "    gl_Position = vs_in_position;\n"
6831 											   "}\n";
6832 
6833 		const char* const fragment_shader_code =
6834 			"#version 400 core\n"
6835 			"#extension GL_ARB_shader_image_load_store : require\n"
6836 			"\n"
6837 			"precision highp float;\n"
6838 			"\n"
6839 			"layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6840 			"layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6841 			"\n"
6842 			"void main()\n"
6843 			"{\n"
6844 			"    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6845 			"                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6846 			"\n"
6847 			"    discard;\n"
6848 			"}\n";
6849 
6850 		/* Vertex postions for "full screen" quad, made with triangle strip */
6851 		static const GLfloat m_vertex_buffer_data[] = {
6852 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6853 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6854 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6855 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6856 		};
6857 
6858 		/* Result of BuildProgram operation */
6859 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6860 
6861 		/* Add all tested texture dimensions */
6862 		m_texture_dimensions.push_back(TextureDimensions(16, 16));
6863 		m_texture_dimensions.push_back(TextureDimensions(16, 17));
6864 		m_texture_dimensions.push_back(TextureDimensions(17, 16));
6865 		m_texture_dimensions.push_back(TextureDimensions(17, 17));
6866 		m_texture_dimensions.push_back(TextureDimensions(16, 18));
6867 		m_texture_dimensions.push_back(TextureDimensions(18, 16));
6868 		m_texture_dimensions.push_back(TextureDimensions(18, 18));
6869 		m_texture_dimensions.push_back(TextureDimensions(16, 19));
6870 		m_texture_dimensions.push_back(TextureDimensions(19, 16));
6871 		m_texture_dimensions.push_back(TextureDimensions(19, 19));
6872 
6873 		/* Clean previous error */
6874 		glGetError();
6875 
6876 		/* Set single-byte data alignment */
6877 		glPixelStorei(GL_PACK_ALIGNMENT, 1);
6878 		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6879 		GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6880 
6881 		/* Prepare buffer with vertex positions of "full screen" quad" */
6882 		glGenBuffers(1, &m_vertex_buffer_id);
6883 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6884 
6885 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6886 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6887 
6888 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6889 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6890 
6891 		/* Generate vertex array object */
6892 		glGenVertexArrays(1, &m_vertex_array_object_id);
6893 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6894 
6895 		/* Prepare program object */
6896 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6897 									fragment_shader_code, &is_program_correct);
6898 		if (false == is_program_correct)
6899 		{
6900 			return ERROR;
6901 		}
6902 
6903 		/* Done */
6904 		return NO_ERROR;
6905 	}
6906 
Cleanup()6907 	virtual long Cleanup()
6908 	{
6909 		/* Reset OpenGL state */
6910 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6911 		glBindTexture(GL_TEXTURE_2D, 0);
6912 		glBindVertexArray(0);
6913 		glUseProgram(0);
6914 
6915 		/* Delete program */
6916 		if (0 != m_program_id)
6917 		{
6918 			glDeleteProgram(m_program_id);
6919 			m_program_id = 0;
6920 		}
6921 
6922 		/* Delete textures */
6923 		if (0 != m_destination_texture_id)
6924 		{
6925 			glDeleteTextures(1, &m_destination_texture_id);
6926 			m_destination_texture_id = 0;
6927 		}
6928 
6929 		if (0 != m_source_texture_id)
6930 		{
6931 			glDeleteTextures(1, &m_source_texture_id);
6932 			m_source_texture_id = 0;
6933 		}
6934 
6935 		/* Delete vertex array object */
6936 		if (0 != m_vertex_array_object_id)
6937 		{
6938 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
6939 			m_vertex_array_object_id = 0;
6940 		}
6941 
6942 		/* Delete buffer */
6943 		if (0 != m_vertex_buffer_id)
6944 		{
6945 			glDeleteBuffers(1, &m_vertex_buffer_id);
6946 			m_vertex_buffer_id = 0;
6947 		}
6948 
6949 		/* Done */
6950 		return NO_ERROR;
6951 	}
6952 
Run()6953 	virtual long Run()
6954 	{
6955 		bool result = true;
6956 
6957 		/* For each dimension */
6958 		for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6959 			 ++it)
6960 		{
6961 			/* Prepare "source" and "destination" textures */
6962 			GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6963 								"Create2DR8UIDestinationTexture");
6964 			GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6965 								"Create2DR8UISourceTexture");
6966 
6967 			/* Copy texture data with imageLoad() and imageStore() operations */
6968 			Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6969 
6970 			/* Compare "source" and "destination" textures */
6971 			if (false ==
6972 				Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6973 			{
6974 				m_context.getTestContext().getLog()
6975 					<< tcu::TestLog::Message
6976 					<< "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6977 					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6978 
6979 				result = false;
6980 			}
6981 
6982 			/* Destroy "source" and "destination" textures */
6983 			glDeleteTextures(1, &m_destination_texture_id);
6984 			glDeleteTextures(1, &m_source_texture_id);
6985 
6986 			m_destination_texture_id = 0;
6987 			m_source_texture_id		 = 0;
6988 		}
6989 
6990 		if (false == result)
6991 		{
6992 			return ERROR;
6993 		}
6994 
6995 		/* Done */
6996 		return NO_ERROR;
6997 	}
6998 
6999 private:
7000 	/* Private methods */
7001 
7002 	/** Binds a texture to user-specified image unit and updates relevant sampler uniform
7003 	 *
7004 	 * @param program_id   Program object id
7005 	 * @param texture_id   Texture id
7006 	 * @param image_unit   Index of image unit
7007 	 * @param uniform_name Name of image uniform
7008 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7009 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7010 	{
7011 		/* Uniform location and invalid value */
7012 		static const GLint invalid_uniform_location = -1;
7013 		GLint			   image_uniform_location   = 0;
7014 
7015 		/* Get uniform location */
7016 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7017 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7018 		if (invalid_uniform_location == image_uniform_location)
7019 		{
7020 			throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7021 		}
7022 
7023 		/* Bind texture to image unit */
7024 		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7025 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7026 
7027 		/* Set uniform to image unit */
7028 		glUniform1i(image_uniform_location, image_unit);
7029 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7030 	}
7031 
7032 	/** Compare two 2D R8UI textures
7033 	 *
7034 	 * @param left_texture_id  Id of "left" texture object
7035 	 * @param right_texture_id Id of "right" texture object
7036 	 * @param width            Width of the textures
7037 	 * @param height           Height of the textures
7038 	 *
7039 	 * @return true when texture data is identical, false otherwise
7040 	 **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7041 	bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7042 	{
7043 		/* Size of textures */
7044 		const GLuint texture_data_size = width * height;
7045 
7046 		/* Storage for texture data */
7047 		std::vector<GLubyte> left_texture_data;
7048 		std::vector<GLubyte> right_texture_data;
7049 
7050 		/* Alocate memory for texture data */
7051 		left_texture_data.resize(texture_data_size);
7052 		right_texture_data.resize(texture_data_size);
7053 
7054 		/* Get "left" texture data */
7055 		glBindTexture(GL_TEXTURE_2D, left_texture_id);
7056 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7057 
7058 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7059 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7060 
7061 		/* Get "right" texture data */
7062 		glBindTexture(GL_TEXTURE_2D, right_texture_id);
7063 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7064 
7065 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7066 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7067 
7068 		/* Compare texels */
7069 		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7070 	}
7071 
7072 	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7073 	 *
7074 	 * @param destination_texture_id Id of "destination" texture object
7075 	 * @param source_texture_id      Id of "source" texture object
7076 	 **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7077 	void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7078 	{
7079 		/* Uniform names */
7080 		static const char* const destination_image_uniform_name = "u_destination_image";
7081 		static const char* const source_image_uniform_name		= "u_source_image";
7082 
7083 		/* Attribute name */
7084 		static const char* const position_attribute_name = "vs_in_position";
7085 
7086 		/* Attribute location and invalid value */
7087 		static const GLint invalid_attribute_location  = -1;
7088 		GLint			   position_attribute_location = 0;
7089 
7090 		/* Set current program */
7091 		glUseProgram(m_program_id);
7092 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7093 
7094 		/* Bind vertex array object */
7095 		glBindVertexArray(m_vertex_array_object_id);
7096 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7097 
7098 		/* Bind buffer with quad vertex positions */
7099 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7100 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7101 
7102 		/* Set up position attribute */
7103 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7104 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7105 		if (invalid_attribute_location == position_attribute_location)
7106 		{
7107 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7108 									 __LINE__);
7109 		}
7110 
7111 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7112 							  0 /* stride */, 0);
7113 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7114 
7115 		glEnableVertexAttribArray(position_attribute_location);
7116 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7117 
7118 		/* Set up textures as source and destination images */
7119 		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7120 		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7121 
7122 		/* Execute draw */
7123 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7124 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7125 	}
7126 
7127 	/** Create 2D R8UI texture and fills it with zeros
7128 	 *
7129 	 * @param width          Width of created texture
7130 	 * @param height         Height of created texture
7131 	 * @param out_texture_id Id of created texture, not modified if operation fails
7132 	 *
7133 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7134 	 **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7135 	GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7136 	{
7137 		/* Texture size */
7138 		const GLuint texture_size = width * height;
7139 
7140 		/* Prepare storage for texture data */
7141 		std::vector<GLubyte> texture_data;
7142 		texture_data.resize(texture_size);
7143 
7144 		/* Set all texels */
7145 		for (GLuint i = 0; i < texture_size; ++i)
7146 		{
7147 			texture_data[i] = 0;
7148 		}
7149 
7150 		/* Create texture */
7151 		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7152 	}
7153 
7154 	/** Create 2D R8UI texture and fills it with increasing values, starting from 0
7155 	 *
7156 	 * @param width          Width of created texture
7157 	 * @param height         Height of created texture
7158 	 * @param out_texture_id Id of created texture, not modified if operation fails
7159 	 *
7160 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7161 	 **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7162 	GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7163 	{
7164 		/* Texture size */
7165 		const GLuint texture_size = width * height;
7166 
7167 		/* Value of texel */
7168 		GLubyte texel_value = 0;
7169 
7170 		/* Prepare storage for texture data */
7171 		std::vector<GLubyte> texture_data;
7172 		texture_data.resize(texture_size);
7173 
7174 		/* Set all texels */
7175 		for (GLuint i = 0; i < texture_size; ++i)
7176 		{
7177 			texture_data[i] = texel_value++;
7178 		}
7179 
7180 		/* Create texture */
7181 		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7182 	}
7183 
7184 	/** Create 2D R8UI texture and fills it with user-provided data
7185 	 *
7186 	 * @param width          Width of created texture
7187 	 * @param height         Height of created texture
7188 	 * @param texture_data   Texture data
7189 	 * @param out_texture_id Id of created texture, not modified if operation fails
7190 	 *
7191 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7192 	 **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7193 	GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7194 							   GLuint& out_texture_id)
7195 	{
7196 		GLenum err		  = 0;
7197 		GLuint texture_id = 0;
7198 
7199 		/* Generate texture */
7200 		glGenTextures(1, &texture_id);
7201 		err = glGetError();
7202 		if (GL_NO_ERROR != err)
7203 		{
7204 			return err;
7205 		}
7206 
7207 		/* Bind texture */
7208 		glBindTexture(GL_TEXTURE_2D, texture_id);
7209 		err = glGetError();
7210 		if (GL_NO_ERROR != err)
7211 		{
7212 			glDeleteTextures(1, &texture_id);
7213 			return err;
7214 		}
7215 
7216 		/* Allocate storage and fill texture */
7217 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7218 					 GL_UNSIGNED_BYTE, &texture_data[0]);
7219 		err = glGetError();
7220 		if (GL_NO_ERROR != err)
7221 		{
7222 			glDeleteTextures(1, &texture_id);
7223 			return err;
7224 		}
7225 
7226 		/* Make texture complete */
7227 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7228 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7229 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7230 		err = glGetError();
7231 		if (GL_NO_ERROR != err)
7232 		{
7233 			glDeleteTextures(1, &texture_id);
7234 			return err;
7235 		}
7236 
7237 		/* Set out_texture_id */
7238 		out_texture_id = texture_id;
7239 
7240 		/* Done */
7241 		return GL_NO_ERROR;
7242 	}
7243 };
7244 
7245 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7246  *
7247  *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7248  *
7249  *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7250  *  | Type           | Dimensions |
7251  *  | 2D_ARRAY       | 64x64x6    |
7252  *  | 3D             | 64x64x6    |
7253  *  | CUBE_MAP       | 64         |
7254  *  | CUBE_MAP_ARRAY | 64x3       |
7255  *
7256  *  Use RGBA8 format. All layers shall be tested.
7257  *
7258  *  Program should consist of vertex and fragment shader. Vertex shader should
7259  *  pass vertex position through. Fragment shader should do imageLoad() and
7260  *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7261  *  use image2D as image type.
7262  **/
7263 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7264 {
7265 private:
7266 	/* Structures */
7267 	struct TextureShapeDefinition
7268 	{
7269 		GLuint m_edge;
7270 		GLuint m_n_elements;
7271 		GLenum m_type;
7272 
TextureShapeDefinitiongl4cts::__anonb00615420111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7273 		TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7274 			: m_edge(edge), m_n_elements(n_elements), m_type(type)
7275 		{
7276 		}
7277 	};
7278 
7279 	/* Typedefs */
7280 	typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7281 
7282 	/* Fields */
7283 	GLuint					   m_destination_texture_id;
7284 	GLuint					   m_program_id;
7285 	TextureShapeDefinitionList m_texture_shape_definitions;
7286 	GLuint					   m_source_texture_id;
7287 	GLuint					   m_vertex_array_object_id;
7288 	GLuint					   m_vertex_buffer_id;
7289 
7290 public:
7291 	/* Constructor */
ImageLoadStoreNonLayeredBindingTest()7292 	ImageLoadStoreNonLayeredBindingTest()
7293 		: m_destination_texture_id(0)
7294 		, m_program_id(0)
7295 		, m_source_texture_id(0)
7296 		, m_vertex_array_object_id(0)
7297 		, m_vertex_buffer_id(0)
7298 	{
7299 		/* Nothing to be done here */
7300 	}
7301 
7302 	/* Methods inherited from SubcaseBase */
Setup()7303 	virtual long Setup()
7304 	{
7305 		/* Shaders code */
7306 		const char* const vertex_shader_code = "#version 400 core\n"
7307 											   "#extension GL_ARB_shader_image_load_store : require\n"
7308 											   "\n"
7309 											   "precision highp float;\n"
7310 											   "\n"
7311 											   "in vec4 vs_in_position;\n"
7312 											   "\n"
7313 											   "void main()\n"
7314 											   "{\n"
7315 											   "    gl_Position = vs_in_position;\n"
7316 											   "}\n";
7317 
7318 		const char* const fragment_shader_code =
7319 			"#version 400 core\n"
7320 			"#extension GL_ARB_shader_image_load_store : require\n"
7321 			"\n"
7322 			"precision highp float;\n"
7323 			"\n"
7324 			"layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7325 			"layout(rgba8) readonly  uniform image2D u_source_image;\n"
7326 			"\n"
7327 			"void main()\n"
7328 			"{\n"
7329 			"    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7330 			"                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7331 			"\n"
7332 			"    discard;\n"
7333 			"}\n";
7334 
7335 		/* Vertex postions for "full screen" quad, defined as a triangle strip */
7336 		static const GLfloat m_vertex_buffer_data[] = {
7337 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7338 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7339 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7340 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7341 		};
7342 
7343 		/* Result of BuildProgram operation */
7344 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7345 
7346 		/* Add all tested texture shapes */
7347 		int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7348 		m_texture_shape_definitions.push_back(
7349 			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7350 		m_texture_shape_definitions.push_back(
7351 			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7352 		m_texture_shape_definitions.push_back(
7353 			TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7354 		m_texture_shape_definitions.push_back(
7355 			TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7356 
7357 		/* Prepare buffer with vertex positions of "full screen" quad" */
7358 		glGenBuffers(1, &m_vertex_buffer_id);
7359 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7360 
7361 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7362 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7363 
7364 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7365 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7366 
7367 		/* Generate vertex array object */
7368 		glGenVertexArrays(1, &m_vertex_array_object_id);
7369 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7370 
7371 		/* Prepare program object */
7372 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7373 									fragment_shader_code, &is_program_correct);
7374 		if (false == is_program_correct)
7375 		{
7376 			return ERROR;
7377 		}
7378 
7379 		/* Done */
7380 		return NO_ERROR;
7381 	}
7382 
Cleanup()7383 	virtual long Cleanup()
7384 	{
7385 		/* Reset OpenGL state */
7386 		glBindBuffer(GL_ARRAY_BUFFER, 0);
7387 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7388 		glBindTexture(GL_TEXTURE_3D, 0);
7389 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7390 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7391 		glBindVertexArray(0);
7392 		glUseProgram(0);
7393 
7394 		/* Delete program */
7395 		if (0 != m_program_id)
7396 		{
7397 			glDeleteProgram(m_program_id);
7398 			m_program_id = 0;
7399 		}
7400 
7401 		/* Delete textures */
7402 		if (0 != m_destination_texture_id)
7403 		{
7404 			glDeleteTextures(1, &m_destination_texture_id);
7405 			m_destination_texture_id = 0;
7406 		}
7407 
7408 		if (0 != m_source_texture_id)
7409 		{
7410 			glDeleteTextures(1, &m_source_texture_id);
7411 			m_source_texture_id = 0;
7412 		}
7413 
7414 		/* Delete vertex array object */
7415 		if (0 != m_vertex_array_object_id)
7416 		{
7417 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
7418 			m_vertex_array_object_id = 0;
7419 		}
7420 
7421 		/* Delete buffer */
7422 		if (0 != m_vertex_buffer_id)
7423 		{
7424 			glDeleteBuffers(1, &m_vertex_buffer_id);
7425 			m_vertex_buffer_id = 0;
7426 		}
7427 
7428 		/* Done */
7429 		return NO_ERROR;
7430 	}
7431 
Run()7432 	virtual long Run()
7433 	{
7434 		bool result = true;
7435 
7436 		/* For each shape */
7437 		for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7438 			 m_texture_shape_definitions.end() != it; ++it)
7439 		{
7440 			const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7441 
7442 			/* Prepare "source" and "destination" textures */
7443 			GLU_EXPECT_NO_ERROR(
7444 				CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7445 				"Create2DR8UIDestinationTexture");
7446 			GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7447 								"Create2DR8UISourceTexture");
7448 
7449 			/* Copy texture data with imageLoad() and imageStore() operations */
7450 			CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7451 
7452 			/* Compare "source" and "destination" textures */
7453 			if (false ==
7454 				CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7455 			{
7456 				const char* texture_type = "";
7457 				switch (it->m_type)
7458 				{
7459 				case GL_TEXTURE_2D_ARRAY:
7460 					texture_type = "2d array";
7461 					break;
7462 				case GL_TEXTURE_3D:
7463 					texture_type = "3d";
7464 					break;
7465 				case GL_TEXTURE_CUBE_MAP:
7466 					texture_type = "Cube map";
7467 					break;
7468 				case GL_TEXTURE_CUBE_MAP_ARRAY:
7469 					texture_type = "Cube map array";
7470 					break;
7471 				}
7472 
7473 				m_context.getTestContext().getLog()
7474 					<< tcu::TestLog::Message
7475 					<< "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7476 					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7477 
7478 				result = false;
7479 			}
7480 
7481 			/* Destroy "source" and "destination" textures */
7482 			glDeleteTextures(1, &m_destination_texture_id);
7483 			glDeleteTextures(1, &m_source_texture_id);
7484 
7485 			m_destination_texture_id = 0;
7486 			m_source_texture_id		 = 0;
7487 		}
7488 
7489 		if (false == result)
7490 		{
7491 			return ERROR;
7492 		}
7493 
7494 		/* Done */
7495 		return NO_ERROR;
7496 	}
7497 
7498 private:
7499 	/* Private methods */
7500 
7501 	/** Binds a texture to user-specified image unit and update relevant sampler uniform
7502 	 *
7503 	 * @param program_id   Program object id
7504 	 * @param texture_id   Texture id
7505 	 * @param image_unit   Index of image unit
7506 	 * @param layer        Index of layer bound to unit
7507 	 * @param uniform_name Name of image uniform
7508 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7509 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7510 							const char* uniform_name)
7511 	{
7512 		static const GLint invalid_uniform_location = -1;
7513 		GLint			   image_uniform_location   = 0;
7514 
7515 		/* Get uniform location */
7516 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7517 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7518 		if (invalid_uniform_location == image_uniform_location)
7519 		{
7520 			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7521 		}
7522 
7523 		/* Bind texture to image unit */
7524 		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7525 						   GL_RGBA8);
7526 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7527 
7528 		/* Set uniform to image unit */
7529 		glUniform1i(image_uniform_location, image_unit);
7530 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7531 	}
7532 
7533 	/** Compare two 2D R8UI textures
7534 	 *
7535 	 * @param left_texture_id  Id of "left" texture object
7536 	 * @param right_texture_id Id of "right" texture object
7537 	 * @param edge             Length of texture edge
7538 	 * @param n_layers         Number of layers to compare
7539 	 * @param type             Type of texture
7540 	 *
7541 	 * @return true when texture data is found identical, false otherwise
7542 	 **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7543 	bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7544 							  GLenum type)
7545 	{
7546 		static const GLuint n_components	  = 4; /* RGBA */
7547 		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7548 
7549 		/* Storage for texture data */
7550 		std::vector<GLubyte> left_texture_data;
7551 		std::vector<GLubyte> right_texture_data;
7552 
7553 		ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7554 		ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7555 
7556 		/* Compare texels */
7557 		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7558 	}
7559 
7560 	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7561 	 *
7562 	 * @param destination_texture_id Id of "destination" texture object
7563 	 * @param source_texture_id      Id of "source" texture object
7564 	 * @param n_layers               Number of layers
7565 	 **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7566 	void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7567 	{
7568 		for (GLuint layer = 0; layer < n_layers; ++layer)
7569 		{
7570 			CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7571 		}
7572 	}
7573 
7574 	/** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7575 	 *
7576 	 * @param destination_texture_id Id of "destination" texture object
7577 	 * @param source_texture_id      Id of "source" texture object
7578 	 * @param layer                  Index of layer
7579 	 **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7580 	void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7581 	{
7582 		/* Uniform names */
7583 		static const char* const destination_image_uniform_name = "u_destination_image";
7584 		static const char* const source_image_uniform_name		= "u_source_image";
7585 
7586 		/* Attribute name */
7587 		static const char* const position_attribute_name = "vs_in_position";
7588 
7589 		/* Attribute location and invalid value */
7590 		static const GLint invalid_attribute_location  = -1;
7591 		GLint			   position_attribute_location = 0;
7592 
7593 		/* Set current program */
7594 		glUseProgram(m_program_id);
7595 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7596 
7597 		/* Bind vertex array object */
7598 		glBindVertexArray(m_vertex_array_object_id);
7599 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7600 
7601 		/* Bind buffer with quad vertex positions */
7602 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7603 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7604 
7605 		/* Set up vertex attribute array for position attribute */
7606 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7607 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7608 		if (invalid_attribute_location == position_attribute_location)
7609 		{
7610 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7611 									 __LINE__);
7612 		}
7613 
7614 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7615 							  0 /* stride */, 0 /* pointer */);
7616 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7617 
7618 		glEnableVertexAttribArray(position_attribute_location);
7619 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7620 
7621 		/* Set up textures as source and destination image samplers */
7622 		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7623 						   destination_image_uniform_name);
7624 		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7625 
7626 		/* Execute draw */
7627 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7628 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7629 	}
7630 
7631 	/** Creates RGBA8 texture of given type and fills it with zeros
7632 	 *
7633 	 * @param edge           Edge of created texture
7634 	 * @param n_elements     Number of elements in texture array
7635 	 * @param target         Target of created texture
7636 	 * @param out_texture_id Id of created texture, not modified if operation fails
7637 	 *
7638 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7639 	 **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7640 	GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7641 	{
7642 		/* Constasts to calculate texture size */
7643 		static const GLuint n_components = 4; /* RGBA */
7644 		const GLuint		layer_size   = edge * edge * n_components;
7645 		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7646 		const GLuint		texture_size = layer_size * n_layers;
7647 
7648 		/* Prepare storage for texture data */
7649 		std::vector<GLubyte> texture_data;
7650 		texture_data.resize(texture_size);
7651 
7652 		/* Set all texels */
7653 		for (GLuint i = 0; i < texture_size; ++i)
7654 		{
7655 			texture_data[i] = 0;
7656 		}
7657 
7658 		/* Create texture */
7659 		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7660 	}
7661 
7662 	/** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7663 	 *
7664 	 * @param edge           Edge of created texture
7665 	 * @param n_elements     Number of elements in texture array
7666 	 * @param target         Target of created texture
7667 	 * @param out_texture_id Id of created texture, not modified if operation fails
7668 	 *
7669 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7670 	 **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7671 	GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7672 	{
7673 		/* Constants to calculate texture size */
7674 		static const GLuint n_components = 4; /* RGBA */
7675 		const GLuint		layer_size   = edge * edge * n_components;
7676 		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7677 		const GLuint		texture_size = layer_size * n_layers;
7678 
7679 		/* Value of texel */
7680 		GLubyte texel[4] = { 0, 0, 0, 0xaa };
7681 
7682 		/* Prepare storage for texture data */
7683 		std::vector<GLubyte> texture_data;
7684 		texture_data.resize(texture_size);
7685 
7686 		/* Set all texels */
7687 		for (GLuint layer = 0; layer < n_layers; ++layer)
7688 		{
7689 			const GLuint layer_offset = layer_size * layer;
7690 
7691 			texel[2] = static_cast<GLubyte>(layer);
7692 
7693 			for (GLuint y = 0; y < edge; ++y)
7694 			{
7695 				const GLuint line_offset = y * edge * n_components + layer_offset;
7696 
7697 				texel[1] = static_cast<GLubyte>(y);
7698 
7699 				for (GLuint x = 0; x < edge; ++x)
7700 				{
7701 					const GLuint texel_offset = x * n_components + line_offset;
7702 					texel[0]				  = static_cast<GLubyte>(x);
7703 
7704 					for (GLuint component = 0; component < n_components; ++component)
7705 					{
7706 						texture_data[texel_offset + component] = texel[component];
7707 					}
7708 				}
7709 			}
7710 		}
7711 
7712 		/* Create texture */
7713 		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7714 	}
7715 
7716 	/** Creates RGBA8 texture of given type and fills it provided data
7717 	 *
7718 	 * @param edge           Edge of created texture
7719 	 * @param n_elements     Number of elements in texture array
7720 	 * @param target         Target of created texture
7721 	 * @param texture_data   Texture data
7722 	 * @param out_texture_id Id of created texture, not modified if operation fails
7723 	 *
7724 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7725 	 **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7726 	GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7727 							  GLuint& out_texture_id)
7728 	{
7729 		GLenum err		  = 0;
7730 		GLuint texture_id = 0;
7731 
7732 		/* Generate texture */
7733 		glGenTextures(1, &texture_id);
7734 		err = glGetError();
7735 		if (GL_NO_ERROR != err)
7736 		{
7737 			return err;
7738 		}
7739 
7740 		/* Bind texture */
7741 		glBindTexture(target, texture_id);
7742 		err = glGetError();
7743 		if (GL_NO_ERROR != err)
7744 		{
7745 			glDeleteTextures(1, &texture_id);
7746 			return err;
7747 		}
7748 
7749 		/* Allocate storage and fill texture */
7750 		if (GL_TEXTURE_CUBE_MAP != target)
7751 		{
7752 			glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7753 						 GL_UNSIGNED_BYTE, &texture_data[0]);
7754 		}
7755 		else
7756 		{
7757 			const GLuint n_components = 4;
7758 			const GLuint layer_size   = edge * edge * n_components;
7759 
7760 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7761 						 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7762 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7763 						 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7764 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7765 						 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7766 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7767 						 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7768 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7769 						 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7770 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7771 						 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7772 		}
7773 		err = glGetError();
7774 		if (GL_NO_ERROR != err)
7775 		{
7776 			glDeleteTextures(1, &texture_id);
7777 			return err;
7778 		}
7779 
7780 		/* Make texture complete */
7781 		glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7782 		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7783 		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7784 		err = glGetError();
7785 		if (GL_NO_ERROR != err)
7786 		{
7787 			glDeleteTextures(1, &texture_id);
7788 			return err;
7789 		}
7790 
7791 		/* Set out_texture_id */
7792 		out_texture_id = texture_id;
7793 
7794 		/* Done */
7795 		return GL_NO_ERROR;
7796 	}
7797 
7798 	/** Extracts texture data
7799 	 *
7800 	 * @param texture_id   Id of texture object
7801 	 * @param edge         Length of texture edge
7802 	 * @param n_layers     Number of layers
7803 	 * @param target       Target of texture
7804 	 * @param texture_data Extracted texture data
7805 	 **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7806 	void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7807 							std::vector<GLubyte>& texture_data)
7808 	{
7809 		static const GLuint n_components	  = 4; /* RGBA */
7810 		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7811 
7812 		/* Alocate memory for texture data */
7813 		texture_data.resize(texture_data_size);
7814 
7815 		/* Bind texture */
7816 		glBindTexture(target, texture_id);
7817 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7818 
7819 		/* Get data */
7820 		if (GL_TEXTURE_CUBE_MAP != target)
7821 		{
7822 			glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7823 		}
7824 		else
7825 		{
7826 			const GLuint layer_size = edge * edge * n_components;
7827 
7828 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7829 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7830 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7831 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7832 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7833 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7834 		}
7835 
7836 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7837 	}
7838 
7839 	/** Get number of layers per single element for given type of texture
7840 	 *
7841 	 * @param target Target of texture
7842 	 *
7843 	 * @return Number of layers
7844 	 **/
GetLayersPerElement(GLenum target)7845 	GLuint GetLayersPerElement(GLenum target)
7846 	{
7847 		switch (target)
7848 		{
7849 		case GL_TEXTURE_2D_ARRAY:
7850 		case GL_TEXTURE_3D:
7851 			return 1;
7852 			break;
7853 		case GL_TEXTURE_CUBE_MAP:
7854 		case GL_TEXTURE_CUBE_MAP_ARRAY:
7855 			return 6;
7856 			break;
7857 		default:
7858 			throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7859 			break;
7860 		}
7861 	}
7862 
7863 	/** Get total number of layers in texture of given type and number of array elements
7864 	 *
7865 	 * @param n_elements Number of elements in texture array
7866 	 * @param target     Target of texture
7867 	 *
7868 	 * @return Number of layers
7869 	 **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7870 	GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7871 	{
7872 		return GetLayersPerElement(target) * n_elements;
7873 	}
7874 };
7875 
7876 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7877  *
7878  *  Load from incomplete textures should return 0.
7879  *  Store to incomplete textures should be ignored.
7880  *
7881  *  Steps:
7882  *  - create two incomplete textures: "incomplete_source" and
7883  *  "incomplete_destination",
7884  *  - create two complete textures: "complete_source" and
7885  *  "complete_destination",
7886  *  - fill all textures with unique values,
7887  *  - prepare program that will:
7888  *      * load texel from "incomplete_source" and store its value to
7889  *      "complete_destination",
7890  *      * load texel from "complete_source" and store its value to
7891  *      "incomplete_destination".
7892  *  - bind textures to corresponding image uniforms
7893  *  - execute program for all texels,
7894  *  - verify that "incomplete_destination" was not modified and
7895  *  "complete_destination" is filled with zeros.
7896  *
7897  *  Texture is considered incomplete when it has enabled mipmaping (see below)
7898  *  and does not have all mipmap levels defined.  But for the case of Image
7899  *  accessing, it is considered invalid if it is mipmap-incomplete and the
7900  *  level is different to the base level (base-incomplete).
7901  *
7902  *  Creation of incomplete texture:
7903  *  - generate and bind texture object id,
7904  *  - call TexImage2D with <level>: 0,
7905  *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7906  *  sure, it should be initial value),
7907  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7908  *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7909  *  height)).
7910  *
7911  *  Creation of complete texture:
7912  *  - generate and bind texture object id,
7913  *  - call TexImage2D with <level>: 0,
7914  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7915  *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7916  *
7917  *  Binding:
7918  *  - Set level == base_level for complete destinations.
7919  *  - Set level != base_level for incomplete destinations that are using
7920  *    mipmap-incomplete textures.
7921  *
7922  *  Test with 2D 64x64 RGBA8 textures.
7923  *
7924  *  Program should consist of vertex and fragment shader. Vertex shader should
7925  *  pass vertex position through. Fragment shader should do imageLoad() and
7926  *  imageStore() operations at coordinates gl_FragCoord.
7927  **/
7928 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7929 {
7930 private:
7931 	/* Constants */
7932 	/* Magic numbers that will identify textures, which will be used as their
7933 	 * texel value.
7934 	 */
7935 	static const GLubyte m_complete_destination_magic_number   = 0x11;
7936 	static const GLubyte m_complete_source_magic_number		   = 0x22;
7937 	static const GLubyte m_incomplete_destination_magic_number = 0x33;
7938 	static const GLubyte m_incomplete_source_magic_number	  = 0x44;
7939 
7940 	/* Texture edge */
7941 	GLuint m_texture_edge;
7942 
7943 	/* Fields */
7944 	GLuint m_complete_destination_texture_id;
7945 	GLuint m_complete_source_texture_id;
7946 	GLuint m_incomplete_destination_texture_id;
7947 	GLuint m_incomplete_source_texture_id;
7948 	GLuint m_program_id;
7949 	GLuint m_vertex_array_object_id;
7950 	GLuint m_vertex_buffer_id;
7951 
7952 public:
7953 	/* Constructor */
ImageLoadStoreIncompleteTexturesTest()7954 	ImageLoadStoreIncompleteTexturesTest()
7955 		: m_texture_edge(0)
7956 		, m_complete_destination_texture_id(0)
7957 		, m_complete_source_texture_id(0)
7958 		, m_incomplete_destination_texture_id(0)
7959 		, m_incomplete_source_texture_id(0)
7960 		, m_program_id(0)
7961 		, m_vertex_array_object_id(0)
7962 		, m_vertex_buffer_id(0)
7963 	{
7964 		/* Nothing to be done here */
7965 	}
7966 
7967 	/* Methods inherited from SubcaseBase */
Setup()7968 	virtual long Setup()
7969 	{
7970 		/* Shaders code */
7971 		const char* const vertex_shader_code = "#version 400 core\n"
7972 											   "#extension GL_ARB_shader_image_load_store : require\n"
7973 											   "\n"
7974 											   "precision highp float;\n"
7975 											   "\n"
7976 											   "in vec4 vs_in_position;\n"
7977 											   "\n"
7978 											   "void main()\n"
7979 											   "{\n"
7980 											   "    gl_Position = vs_in_position;\n"
7981 											   "}\n";
7982 
7983 		const char* const fragment_shader_code =
7984 			"#version 400 core\n"
7985 			"#extension GL_ARB_shader_image_load_store : require\n"
7986 			"\n"
7987 			"precision highp float;\n"
7988 			"\n"
7989 			"layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7990 			"layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
7991 			"layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7992 			"layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
7993 			"\n"
7994 			"void main()\n"
7995 			"{\n"
7996 			"    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
7997 			"    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7998 
7999 			"    imageStore(u_complete_destination_image,\n"
8000 			"               ivec2(gl_FragCoord),\n"
8001 			"               incomplete_loaded_color);\n"
8002 			"    imageStore(u_incomplete_destination_image,\n"
8003 			"               ivec2(gl_FragCoord),\n"
8004 			"               complete_loaded_color);\n"
8005 			"\n"
8006 			"    discard;\n"
8007 			"}\n";
8008 
8009 		/* Vertex postions for "full screen" quad, made with triangle strip */
8010 		static const GLfloat m_vertex_buffer_data[] = {
8011 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8012 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
8013 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
8014 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
8015 		};
8016 
8017 		/* Result of BuildProgram operation */
8018 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8019 
8020 		/* Clean previous error */
8021 		glGetError();
8022 
8023 		m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8024 
8025 		/* Prepare textures */
8026 		GLU_EXPECT_NO_ERROR(
8027 			Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8028 			"Create2DRGBA8CompleteTexture");
8029 		GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8030 							"Create2DRGBA8CompleteTexture");
8031 		GLU_EXPECT_NO_ERROR(
8032 			Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8033 			"Create2DRGBA8IncompleteTexture");
8034 		GLU_EXPECT_NO_ERROR(
8035 			Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8036 			"Create2DRGBA8IncompleteTexture");
8037 
8038 		/* Prepare buffer with vertex positions of "full screen" quad" */
8039 		glGenBuffers(1, &m_vertex_buffer_id);
8040 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8041 
8042 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8043 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8044 
8045 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8046 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8047 
8048 		/* Generate vertex array object */
8049 		glGenVertexArrays(1, &m_vertex_array_object_id);
8050 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8051 
8052 		/* Prepare program object */
8053 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8054 									fragment_shader_code, &is_program_correct);
8055 
8056 		if (false == is_program_correct)
8057 		{
8058 			return ERROR;
8059 		}
8060 
8061 		/* Done */
8062 		return NO_ERROR;
8063 	}
8064 
Cleanup()8065 	virtual long Cleanup()
8066 	{
8067 		/* Reset OpenGL state */
8068 		glBindBuffer(GL_ARRAY_BUFFER, 0);
8069 		glBindTexture(GL_TEXTURE_2D, 0);
8070 		glBindVertexArray(0);
8071 		glUseProgram(0);
8072 
8073 		/* Delete program */
8074 		if (0 != m_program_id)
8075 		{
8076 			glDeleteProgram(m_program_id);
8077 			m_program_id = 0;
8078 		}
8079 
8080 		/* Delete textures */
8081 		if (0 != m_complete_destination_texture_id)
8082 		{
8083 			glDeleteTextures(1, &m_complete_destination_texture_id);
8084 			m_complete_destination_texture_id = 0;
8085 		}
8086 
8087 		if (0 != m_complete_source_texture_id)
8088 		{
8089 			glDeleteTextures(1, &m_complete_source_texture_id);
8090 			m_complete_source_texture_id = 0;
8091 		}
8092 
8093 		if (0 != m_incomplete_destination_texture_id)
8094 		{
8095 			glDeleteTextures(1, &m_incomplete_destination_texture_id);
8096 			m_incomplete_destination_texture_id = 0;
8097 		}
8098 
8099 		if (0 != m_incomplete_source_texture_id)
8100 		{
8101 			glDeleteTextures(1, &m_incomplete_source_texture_id);
8102 			m_incomplete_source_texture_id = 0;
8103 		}
8104 
8105 		/* Delete vertex array object */
8106 		if (0 != m_vertex_array_object_id)
8107 		{
8108 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8109 			m_vertex_array_object_id = 0;
8110 		}
8111 
8112 		/* Delete buffer */
8113 		if (0 != m_vertex_buffer_id)
8114 		{
8115 			glDeleteBuffers(1, &m_vertex_buffer_id);
8116 			m_vertex_buffer_id = 0;
8117 		}
8118 
8119 		/* Done */
8120 		return NO_ERROR;
8121 	}
8122 
Run()8123 	virtual long Run()
8124 	{
8125 		bool result = true;
8126 
8127 		/* Copy textures data with imageLoad() and imageStore() operations */
8128 		Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8129 							m_complete_source_texture_id, m_incomplete_source_texture_id);
8130 
8131 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
8132 
8133 		/* Verify that store to "incomplete destination" was ignored */
8134 		if (true ==
8135 			CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8136 		{
8137 			m_context.getTestContext().getLog()
8138 				<< tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8139 				<< tcu::TestLog::EndMessage;
8140 
8141 			result = false;
8142 		}
8143 
8144 		/* Verify that load from "incomplete source" returned 0 */
8145 		if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8146 		{
8147 			m_context.getTestContext().getLog()
8148 				<< tcu::TestLog::Message
8149 				<< "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8150 				<< tcu::TestLog::EndMessage;
8151 
8152 			result = false;
8153 		}
8154 
8155 		if (false == result)
8156 		{
8157 			return ERROR;
8158 		}
8159 
8160 		/* Done */
8161 		return NO_ERROR;
8162 	}
8163 
8164 private:
8165 	/* Private methods */
8166 
8167 	/** Bind texture to image unit and sets image uniform to that unit
8168 	 *
8169 	 * @param program_id   Program object id
8170 	 * @param texture_id   Texture id
8171 	 * @param level        Texture level
8172 	 * @param image_unit   Index of image unit
8173 	 * @param uniform_name Name of image uniform
8174 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8175 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8176 	{
8177 		/* Uniform location and invalid value */
8178 		static const GLint invalid_uniform_location = -1;
8179 		GLint			   image_uniform_location   = 0;
8180 
8181 		/* Get uniform location */
8182 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8183 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8184 		if (invalid_uniform_location == image_uniform_location)
8185 		{
8186 			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8187 		}
8188 
8189 		/* Bind texture to image unit */
8190 		glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8191 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8192 
8193 		/* Set uniform to image unit */
8194 		glUniform1i(image_uniform_location, image_unit);
8195 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8196 	}
8197 
8198 	/** Check if texture is filled with black color, zeros
8199 	 *
8200 	 * @param texture_id Id of texture object
8201 	 *
8202 	 * @return true when texture is fully black, false otherwise
8203 	 **/
CheckIfTextureIsBlack(GLuint texture_id)8204 	bool CheckIfTextureIsBlack(GLuint texture_id)
8205 	{
8206 		/* Constants to calculate size of texture */
8207 		static const GLuint n_components	  = 4; /* RGBA */
8208 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8209 
8210 		/* Storage for texture data */
8211 		std::vector<GLubyte> black_texture_data;
8212 		std::vector<GLubyte> texture_data;
8213 
8214 		/* Allocate memory */
8215 		black_texture_data.resize(texture_data_size);
8216 		texture_data.resize(texture_data_size);
8217 
8218 		/* Set all texels to black */
8219 		for (GLuint i = 0; i < texture_data_size; ++i)
8220 		{
8221 			black_texture_data[i] = 0;
8222 		}
8223 
8224 		/* Bind texture */
8225 		glBindTexture(GL_TEXTURE_2D, texture_id);
8226 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8227 
8228 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8229 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8230 
8231 		/* Compare texels */
8232 		return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8233 	}
8234 
8235 	/** Check if texture was modified
8236 	 *
8237 	 * @param texture_id   Id of texture object
8238 	 * @param nagic_number Magic number that was to create texture
8239 	 *
8240 	 * @return true if texture contents match expected values, false otherwise
8241 	 **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8242 	bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8243 	{
8244 		/* Constants to calculate size of texture */
8245 		static const GLuint n_components	  = 4; /* RGBA */
8246 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8247 
8248 		/* Storage for texture data */
8249 		std::vector<GLubyte> expected_texture_data;
8250 		std::vector<GLubyte> texture_data;
8251 
8252 		/* Allocate memory */
8253 		expected_texture_data.resize(texture_data_size);
8254 		texture_data.resize(texture_data_size);
8255 
8256 		/* Prepare expected texels */
8257 		for (GLuint y = 0; y < m_texture_edge; ++y)
8258 		{
8259 			const GLuint line_offset = y * m_texture_edge * n_components;
8260 
8261 			for (GLuint x = 0; x < m_texture_edge; ++x)
8262 			{
8263 				const GLuint texel_offset = x * n_components + line_offset;
8264 
8265 				SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8266 						 magic_number);
8267 			}
8268 		}
8269 
8270 		/* Bind texture */
8271 		glBindTexture(GL_TEXTURE_2D, texture_id);
8272 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8273 
8274 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8275 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8276 
8277 		/* Compare texels, true when textures are different */
8278 		return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8279 	}
8280 
8281 	/** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8282 	 *
8283 	 * @param complete_destination_texture_id   Id of "complete destination" texture object
8284 	 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8285 	 * @param complete_source_texture_id        Id of "complete source" texture object
8286 	 * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8287 	 **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8288 	void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8289 							 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8290 	{
8291 		/* Uniform names */
8292 		static const char* const complete_destination_image_uniform_name   = "u_complete_destination_image";
8293 		static const char* const complete_source_image_uniform_name		   = "u_complete_source_image";
8294 		static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8295 		static const char* const incomplete_source_image_uniform_name	  = "u_incomplete_source_image";
8296 
8297 		/* Attribute name */
8298 		static const char* const position_attribute_name = "vs_in_position";
8299 
8300 		/* Attribute location and invalid value */
8301 		static const GLint invalid_attribute_location  = -1;
8302 		GLint			   position_attribute_location = 0;
8303 
8304 		/* Set current program */
8305 		glUseProgram(m_program_id);
8306 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8307 
8308 		/* Bind vertex array object */
8309 		glBindVertexArray(m_vertex_array_object_id);
8310 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8311 
8312 		/* Bind buffer with quad vertex positions */
8313 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8314 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8315 
8316 		/* Setup position attribute */
8317 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8318 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8319 		if (invalid_attribute_location == position_attribute_location)
8320 		{
8321 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8322 									 __LINE__);
8323 		}
8324 
8325 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8326 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8327 
8328 		glEnableVertexAttribArray(position_attribute_location);
8329 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8330 
8331 		/* Setup textures as source and destination images */
8332 		BindTextureToImage(m_program_id, complete_destination_texture_id,
8333 						   0 /* texture level */, 0 /* image_unit */,
8334 						   complete_destination_image_uniform_name);
8335 		BindTextureToImage(m_program_id, complete_source_texture_id,
8336 						   0 /* texture level */, 1 /* image_unit */,
8337 						   complete_source_image_uniform_name);
8338 		BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8339 						   2 /* texture level */, 2 /* image_unit */,
8340 						   incomplete_destination_image_uniform_name);
8341 		BindTextureToImage(m_program_id, incomplete_source_texture_id,
8342 						   2 /* texture level */, 3 /* image_unit */,
8343 						   incomplete_source_image_uniform_name);
8344 
8345 		/* Execute draw */
8346 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8347 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8348 	}
8349 
8350 	/** Create complete 2D RGBA8 texture.
8351 	 *
8352 	 * @param magic_number   Magic number of texture
8353 	 * @param out_texture_id Id of created texture, not modified if operation fails
8354 	 *
8355 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8356 	 **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8357 	GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8358 	{
8359 		/* Constants to calculate size of texture */
8360 		static const GLuint n_components	  = 4; /* RGBA */
8361 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8362 
8363 		/* Error code */
8364 		GLenum err = 0;
8365 
8366 		/* Texture id */
8367 		GLuint texture_id = 0;
8368 
8369 		/* Prepare storage for texture data */
8370 		std::vector<GLubyte> texture_data;
8371 		texture_data.resize(texture_data_size);
8372 
8373 		/* Prepare texture data */
8374 		for (GLuint y = 0; y < m_texture_edge; ++y)
8375 		{
8376 			const GLuint line_offset = y * m_texture_edge * n_components;
8377 
8378 			for (GLuint x = 0; x < m_texture_edge; ++x)
8379 			{
8380 				const GLuint texel_offset = x * n_components + line_offset;
8381 
8382 				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8383 			}
8384 		}
8385 
8386 		/* Generate texture */
8387 		glGenTextures(1, &texture_id);
8388 		err = glGetError();
8389 		if (GL_NO_ERROR != err)
8390 		{
8391 			return err;
8392 		}
8393 
8394 		/* Bind texture */
8395 		glBindTexture(GL_TEXTURE_2D, texture_id);
8396 		err = glGetError();
8397 		if (GL_NO_ERROR != err)
8398 		{
8399 			glDeleteTextures(1, &texture_id);
8400 			return err;
8401 		}
8402 
8403 		/* Allocate storage and fill texture */
8404 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8405 					 GL_UNSIGNED_BYTE, &texture_data[0]);
8406 		err = glGetError();
8407 		if (GL_NO_ERROR != err)
8408 		{
8409 			glDeleteTextures(1, &texture_id);
8410 			return err;
8411 		}
8412 
8413 		/* Make texture complete */
8414 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8415 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8416 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8417 		err = glGetError();
8418 		if (GL_NO_ERROR != err)
8419 		{
8420 			glDeleteTextures(1, &texture_id);
8421 			return err;
8422 		}
8423 
8424 		/* Set out_texture_id */
8425 		out_texture_id = texture_id;
8426 
8427 		/* Done */
8428 		return GL_NO_ERROR;
8429 	}
8430 
8431 	/** Create incomplete 2D RGBA8 texture
8432 	 *
8433 	 * @param magic_number   Magic number of texture
8434 	 * @param out_texture_id Id of created texture, not modified if operation fails
8435 	 *
8436 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8437 	 **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8438 	GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8439 	{
8440 		/* Constants to calculate size of texture */
8441 		static const GLuint n_components	  = 4; /* RGBA */
8442 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8443 
8444 		/* Error code */
8445 		GLenum err = 0;
8446 
8447 		/* Texture id */
8448 		GLuint texture_id = 0;
8449 
8450 		/* Prepare storage for texture data */
8451 		std::vector<GLubyte> texture_data;
8452 		texture_data.resize(texture_data_size);
8453 
8454 		/* Prepare texture data */
8455 		for (GLuint y = 0; y < m_texture_edge; ++y)
8456 		{
8457 			const GLuint line_offset = y * m_texture_edge * n_components;
8458 
8459 			for (GLuint x = 0; x < m_texture_edge; ++x)
8460 			{
8461 				const GLuint texel_offset = x * n_components + line_offset;
8462 
8463 				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8464 			}
8465 		}
8466 
8467 		/* Generate texture */
8468 		glGenTextures(1, &texture_id);
8469 		err = glGetError();
8470 		if (GL_NO_ERROR != err)
8471 		{
8472 			return err;
8473 		}
8474 
8475 		/* Bind texture */
8476 		glBindTexture(GL_TEXTURE_2D, texture_id);
8477 		err = glGetError();
8478 		if (GL_NO_ERROR != err)
8479 		{
8480 			glDeleteTextures(1, &texture_id);
8481 			return err;
8482 		}
8483 
8484 		/* Allocate storage and fill texture */
8485 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8486 					 GL_UNSIGNED_BYTE, &texture_data[0]);
8487 		err = glGetError();
8488 		if (GL_NO_ERROR != err)
8489 		{
8490 			glDeleteTextures(1, &texture_id);
8491 			return err;
8492 		}
8493 
8494 		/* Make texture incomplete */
8495 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8496 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8497 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8498 		err = glGetError();
8499 		if (GL_NO_ERROR != err)
8500 		{
8501 			glDeleteTextures(1, &texture_id);
8502 			return err;
8503 		}
8504 
8505 		/* Set out_texture_id */
8506 		out_texture_id = texture_id;
8507 
8508 		/* Done */
8509 		return GL_NO_ERROR;
8510 	}
8511 
8512 	/** Prepare "unique" texels.
8513 	 *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8514 	 *
8515 	 * @param texel        Storage of texel
8516 	 * @param x_coordinate X coordiante of texel
8517 	 * @param y_coordinate Y coordinate of texel
8518 	 * @param magic_number Magic number of texture
8519 	 **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8520 	void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8521 	{
8522 		texel[0] = x_coordinate;
8523 		texel[1] = y_coordinate;
8524 		texel[2] = magic_number;
8525 		texel[3] = 0xcc;
8526 	}
8527 };
8528 
8529 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8530  *
8531  * Steps:
8532  * - prepare program object, see details below,
8533  * - prepare 2D R32I texture, width should be equal to the number of image
8534  * uniforms used by program object, height should be 2, fill first row with
8535  * unique values, fill second row with zeros,
8536  * - bind texture to first image unit,
8537  * - set all image uniforms to first image unit,
8538  * - execute program for a single vertex,
8539  * - verify that:
8540  *     - values in first row were negated,
8541  *     - values from first row were copied to second row,
8542  *
8543  * Repeat steps to test all shader stages that support at least 2 image
8544  * uniforms.
8545  *
8546  * Program has to contain all necessary shader stages. Use boilerplate shaders
8547  * for shader stages that are not important for the test.
8548  *
8549  * Tested shader stage should:
8550  * - Use as many different image formats as possible, image formats compatible
8551  * with R32I:
8552  *     * rg16f
8553  *     * r11f_g11f_b10f
8554  *     * r32f
8555  *     * rgb10_a2ui
8556  *     * rgba8ui
8557  *     * rg16ui
8558  *     * r32ui
8559  *     * rgba8i
8560  *     * rg16i
8561  *     * r32i
8562  *     * rgb10_a2
8563  *     * rgba8
8564  *     * rg16
8565  *     * rgba8_snorm
8566  *     * rg16_snorm.
8567  * - Declare maximum allowed number of image uniforms,
8568  *
8569  *     layout(format) uniform gimage2D u_image;
8570  *
8571  * where <format> is selected image format, <gimage2D> is type of 2D image
8572  * compatible with <format> and <u_image> is unique name of uniform.
8573  * Note that image uniforms cannot be declared as array, due to different image
8574  * formats. Therefore separate uniforms have to be used.
8575  * - Include following code snippet:
8576  * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8577  * {
8578  *     vec row_1_coord(i,0);
8579  *     vec row_2_coord(i,1);
8580  *
8581  *     row_1_value = imageLoad(u_image[i], row_1_coord);
8582  *     imageStore(u_image[i], row_1_coord, -row_1_value);
8583  *     imageStore(u_image[i], row_2_coord, row_1_value);
8584  * }
8585  * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8586  * stage.
8587  **/
8588 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8589 {
8590 private:
8591 	/* Types */
8592 	/** Details of image format
8593 	 *
8594 	 **/
8595 	struct imageFormatDetails
8596 	{
8597 		typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8598 
8599 		const char*			m_image_format;
8600 		const char*			m_image_type;
8601 		const char*			m_color_type;
8602 		GLenum				m_image_unit_format;
8603 		verificationRoutine m_verification_routine;
8604 	};
8605 
8606 	template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8607 	struct Masks
8608 	{
8609 		/** Get mask of bits used to store in bit-field
8610 		 *
8611 		 * @return Mask
8612 		 **/
RawMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8613 		static inline T RawMask()
8614 		{
8615 			static const T mask = ValueMask() << OFFSET;
8616 
8617 			return mask;
8618 		}
8619 
8620 		/** Get mask of bits used to store value.
8621 		 *
8622 		 * @return Mask
8623 		 **/
ValueMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8624 		static inline T ValueMask()
8625 		{
8626 			static const T mask = (1 << SIZE) - 1;
8627 
8628 			return mask;
8629 		}
8630 
8631 		/** Get offset.
8632 		 *
8633 		 * @return offset
8634 		 **/
Offsetgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8635 		static inline T Offset()
8636 		{
8637 			return OFFSET;
8638 		}
8639 	};
8640 
8641 	template <typename T, GLuint SIZE, GLuint OFFSET>
8642 	struct Masks<T, SIZE, OFFSET, false>
8643 	{
8644 		/** Get mask of bits used to store in bit-field
8645 		 *
8646 		 * @return Mask
8647 		 **/
RawMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8648 		static inline T RawMask()
8649 		{
8650 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8651 			return 0;
8652 		}
8653 
8654 		/** Get mask of bits used to store value.
8655 		 *
8656 		 * @return Mask
8657 		 **/
ValueMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8658 		static inline T ValueMask()
8659 		{
8660 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8661 			return 0;
8662 		}
8663 
8664 		/** Get offset.
8665 		 *
8666 		 * @return offset
8667 		 **/
Offsetgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8668 		static inline T Offset()
8669 		{
8670 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8671 			return 0;
8672 		}
8673 	};
8674 
8675 	/** Template class for accessing integer values stored in bit-fields
8676 	 *
8677 	 **/
8678 	template <typename T, GLuint SIZE, GLuint OFFSET>
8679 	class Integer
8680 	{
8681 	public:
8682 		/** Constructor
8683 		 *
8684 		 **/
Integer(T raw)8685 		Integer(T raw) : m_raw(raw)
8686 		{
8687 		}
8688 
8689 		/** Extract value from bit-field
8690 		 *
8691 		 * @return Value
8692 		 **/
Get() const8693 		T Get() const
8694 		{
8695 			const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8696 
8697 			const T bits   = m_raw & mask;
8698 			const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8699 
8700 			return result;
8701 		}
8702 
8703 		/** Extract value from bit-field and negate it
8704 		 *
8705 		 * @return Negated value
8706 		 **/
GetNegated() const8707 		T GetNegated() const
8708 		{
8709 			const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8710 			const T value = Get();
8711 
8712 			return Clamp((~value) + 1) & mask;
8713 		}
8714 
Clamp(T n) const8715 		T Clamp(T n) const
8716 		{
8717 			const bool isUnsigned = (T(0) < T(-1));
8718 			const T	min		  = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8719 			const T	max		  = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8720 			const T	x		  = n > max ? max : n;
8721 			return x < min ? min : x;
8722 		}
8723 
8724 	private:
8725 		T m_raw;
8726 	};
8727 
8728 	/* Enums */
8729 	/** Shader stage identification
8730 	 *
8731 	 **/
8732 	enum shaderStage
8733 	{
8734 		fragmentShaderStage				 = 2,
8735 		geometryShaderStage				 = 4,
8736 		tesselationControlShaderStage	= 8,
8737 		tesselationEvalutaionShaderStage = 16,
8738 		vertexShaderStage				 = 32,
8739 	};
8740 
8741 	/** Test result
8742 	 *
8743 	 **/
8744 	enum testResult
8745 	{
8746 		testFailed		 = -1,
8747 		testNotSupported = 1,
8748 		testPassed		 = 0
8749 	};
8750 
8751 	/* Constants */
8752 	static const GLint m_min_required_image_uniforms = 2;
8753 
8754 	/* Fields */
8755 	GLuint m_program_to_test_fs_stage_id;
8756 	GLuint m_program_to_test_gs_stage_id;
8757 	GLuint m_program_to_test_tcs_stage_id;
8758 	GLuint m_program_to_test_tes_stage_id;
8759 	GLuint m_program_to_test_vs_stage_id;
8760 	GLuint m_texture_to_test_fs_stage_id;
8761 	GLuint m_texture_to_test_gs_stage_id;
8762 	GLuint m_texture_to_test_tcs_stage_id;
8763 	GLuint m_texture_to_test_tes_stage_id;
8764 	GLuint m_texture_to_test_vs_stage_id;
8765 	GLuint m_vertex_array_object_id;
8766 
8767 public:
8768 	/* Constructor */
ImageLoadStoreMultipleUniformsTest()8769 	ImageLoadStoreMultipleUniformsTest()
8770 		: m_program_to_test_fs_stage_id(0)
8771 		, m_program_to_test_gs_stage_id(0)
8772 		, m_program_to_test_tcs_stage_id(0)
8773 		, m_program_to_test_tes_stage_id(0)
8774 		, m_program_to_test_vs_stage_id(0)
8775 		, m_texture_to_test_fs_stage_id(0)
8776 		, m_texture_to_test_gs_stage_id(0)
8777 		, m_texture_to_test_tcs_stage_id(0)
8778 		, m_texture_to_test_tes_stage_id(0)
8779 		, m_texture_to_test_vs_stage_id(0)
8780 		, m_vertex_array_object_id(0)
8781 	{
8782 		/* Nothing to be done here */
8783 	}
8784 
8785 	/* Methods inherited from SubcaseBase */
Setup()8786 	virtual long Setup()
8787 	{
8788 		/* Prepare programs */
8789 		m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8790 		m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8791 		m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8792 		m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8793 		m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8794 
8795 		/* Prepare textures */
8796 		m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8797 		m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8798 		m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8799 		m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8800 		m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8801 
8802 		/* Generate vertex array object */
8803 		glGenVertexArrays(1, &m_vertex_array_object_id);
8804 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8805 
8806 		/* Bind vertex array object */
8807 		glBindVertexArray(m_vertex_array_object_id);
8808 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8809 
8810 		/* Set vertices number for patches */
8811 		glPatchParameteri(GL_PATCH_VERTICES, 1);
8812 
8813 		/* Done */
8814 		return NO_ERROR;
8815 	}
8816 
Cleanup()8817 	virtual long Cleanup()
8818 	{
8819 		glUseProgram(0);
8820 
8821 		/* Delete programs */
8822 		if (0 != m_program_to_test_fs_stage_id)
8823 		{
8824 			glDeleteProgram(m_program_to_test_fs_stage_id);
8825 			m_program_to_test_fs_stage_id = 0;
8826 		}
8827 
8828 		if (0 != m_program_to_test_gs_stage_id)
8829 		{
8830 			glDeleteProgram(m_program_to_test_gs_stage_id);
8831 			m_program_to_test_gs_stage_id = 0;
8832 		}
8833 
8834 		if (0 != m_program_to_test_tcs_stage_id)
8835 		{
8836 			glDeleteProgram(m_program_to_test_tcs_stage_id);
8837 			m_program_to_test_tcs_stage_id = 0;
8838 		}
8839 
8840 		if (0 != m_program_to_test_tes_stage_id)
8841 		{
8842 			glDeleteProgram(m_program_to_test_tes_stage_id);
8843 			m_program_to_test_tes_stage_id = 0;
8844 		}
8845 
8846 		if (0 != m_program_to_test_vs_stage_id)
8847 		{
8848 			glDeleteProgram(m_program_to_test_vs_stage_id);
8849 			m_program_to_test_vs_stage_id = 0;
8850 		}
8851 
8852 		/* Delete textures */
8853 		if (0 != m_texture_to_test_fs_stage_id)
8854 		{
8855 			glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8856 			m_texture_to_test_fs_stage_id = 0;
8857 		}
8858 
8859 		if (0 != m_texture_to_test_gs_stage_id)
8860 		{
8861 			glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8862 			m_texture_to_test_gs_stage_id = 0;
8863 		}
8864 
8865 		if (0 != m_texture_to_test_tcs_stage_id)
8866 		{
8867 			glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8868 			m_texture_to_test_tcs_stage_id = 0;
8869 		}
8870 
8871 		if (0 != m_texture_to_test_tes_stage_id)
8872 		{
8873 			glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8874 			m_texture_to_test_tes_stage_id = 0;
8875 		}
8876 
8877 		if (0 != m_texture_to_test_vs_stage_id)
8878 		{
8879 			glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8880 			m_texture_to_test_vs_stage_id = 0;
8881 		}
8882 
8883 		/* Delete vertex array object id */
8884 		if (0 != m_vertex_array_object_id)
8885 		{
8886 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8887 			m_vertex_array_object_id = 0;
8888 		}
8889 
8890 		/* Done */
8891 		return NO_ERROR;
8892 	}
8893 
Run()8894 	virtual long Run()
8895 	{
8896 		bool result = true;
8897 
8898 		if (testFailed == testShaderStage(fragmentShaderStage))
8899 		{
8900 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8901 												<< tcu::TestLog::EndMessage;
8902 
8903 			result = false;
8904 		}
8905 
8906 		if (testFailed == testShaderStage(geometryShaderStage))
8907 		{
8908 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8909 												<< tcu::TestLog::EndMessage;
8910 
8911 			result = false;
8912 		}
8913 
8914 		if (testFailed == testShaderStage(tesselationControlShaderStage))
8915 		{
8916 			m_context.getTestContext().getLog() << tcu::TestLog::Message
8917 												<< "Problems with tesselation control shader stage!"
8918 												<< tcu::TestLog::EndMessage;
8919 
8920 			result = false;
8921 		}
8922 
8923 		if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8924 		{
8925 			m_context.getTestContext().getLog() << tcu::TestLog::Message
8926 												<< "Problems with tesselation evaluation shader stage!"
8927 												<< tcu::TestLog::EndMessage;
8928 
8929 			result = false;
8930 		}
8931 
8932 		if (testFailed == testShaderStage(vertexShaderStage))
8933 		{
8934 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8935 												<< tcu::TestLog::EndMessage;
8936 
8937 			result = false;
8938 		}
8939 
8940 		if (false == result)
8941 		{
8942 			return ERROR;
8943 		}
8944 
8945 		/* Done */
8946 		return NO_ERROR;
8947 	}
8948 
8949 private:
8950 	/* Static routines */
8951 	/** Provide image format details for given index
8952 	 *
8953 	 * @param index       Index
8954 	 * @param out_details Image format detail instance
8955 	 **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8956 	static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8957 	{
8958 		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8959 			"r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8960 		};
8961 
8962 		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8963 			{ "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8964 			{ "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8965 			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966 			{ "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8967 			{ "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8968 			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8969 			{ "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8970 			{ "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8971 			{ "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8972 			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8973 			{ "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8974 			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8975 			{ "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8976 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8977 			{ "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8978 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8979 			{ "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8980 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8981 			{ "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8982 			{ "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8983 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8984 			{ "rg16i", "iimage2D", "ivec4", GL_RG16I,
8985 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8986 		};
8987 
8988 		static const GLuint n_imageUniformFormatDetails =
8989 			sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8990 
8991 		if (n_imageUniformFormatDetails <= index)
8992 		{
8993 			out_details = default_format_details;
8994 		}
8995 		else
8996 		{
8997 			out_details = format_details[index];
8998 		}
8999 	}
9000 
9001 	/** Write name of image uniform at given index to output stream
9002 	 *
9003 	 * @param stream Output stream
9004 	 * @param index  Index
9005 	 **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9006 	static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9007 	{
9008 		/* u_image_0 */
9009 		stream << "u_image_" << index;
9010 	}
9011 
9012 	/** Write name of variable used to store value loaded from image at given index to output stream
9013 	 *
9014 	 * @param stream Output stream
9015 	 * @param index  Index
9016 	 **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9017 	static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9018 	{
9019 		/* loaded_value_0 */
9020 		stream << "loaded_value_" << index;
9021 	}
9022 
9023 	/** Write name of variable used to store coordinate of texel at given row to output stream
9024 	 *
9025 	 * @param stream Output stream
9026 	 * @param index  Index of image uniform
9027 	 * @param row    Row of image
9028 	 **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9029 	static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9030 	{
9031 		/* row_0_coordinates_0 */
9032 		stream << "row_" << row << "_coordinates_" << index;
9033 	}
9034 
9035 	struct imageUniformDeclaration
9036 	{
imageUniformDeclarationgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9037 		imageUniformDeclaration(GLuint index) : m_index(index)
9038 		{
9039 		}
9040 
9041 		GLuint m_index;
9042 	};
9043 
9044 	/** Write declaration of image uniform at given index to output stream
9045 	 *
9046 	 * @param stream                   Output stream
9047 	 * @param imageUniformDeclaration  Declaration details
9048 	 *
9049 	 * @return stream
9050 	 **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9051 	friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9052 	{
9053 		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9054 		getImageUniformDeclarationDetails(declaration.m_index, format_details);
9055 
9056 		/* layout(r32f) uniform image2D u_image_0; */
9057 		stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9058 
9059 		ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9060 
9061 		stream << ";";
9062 
9063 		return stream;
9064 	}
9065 
9066 	struct imageLoadCall
9067 	{
imageLoadCallgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9068 		imageLoadCall(GLuint index) : m_index(index)
9069 		{
9070 		}
9071 
9072 		GLuint m_index;
9073 	};
9074 
9075 	/* Stream operators */
9076 	/** Write code that execute imageLoad routine for image at given index to output stream
9077 	 *
9078 	 * @param stream Output stream
9079 	 * @param load   imageLoad call details
9080 	 *
9081 	 * @return stream
9082 	 **/
operator <<(std::ostream & stream,const imageLoadCall & load)9083 	friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9084 	{
9085 		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9086 		getImageUniformDeclarationDetails(load.m_index, format_details);
9087 
9088 		/* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9089 		stream << format_details.m_color_type << " ";
9090 
9091 		writeLoadedValueVariableNameToStream(stream, load.m_index);
9092 
9093 		stream << " = imageLoad(";
9094 
9095 		writeImageUniformNameToStream(stream, load.m_index);
9096 
9097 		stream << ", ";
9098 
9099 		writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9100 
9101 		stream << ");";
9102 
9103 		return stream;
9104 	}
9105 
9106 	struct imageStoreCall
9107 	{
imageStoreCallgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9108 		imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9109 		{
9110 		}
9111 
9112 		GLuint m_index;
9113 		GLuint m_row;
9114 	};
9115 
9116 	/** Write code that execute imageStore to image at given index to output stream
9117 	 *
9118 	 * @param stream Output stream
9119 	 * @param store  imageStore call details
9120 	 *
9121 	 * @return stream
9122 	 **/
operator <<(std::ostream & stream,const imageStoreCall & store)9123 	friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9124 	{
9125 		/* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9126 		stream << "imageStore(";
9127 
9128 		writeImageUniformNameToStream(stream, store.m_index);
9129 
9130 		stream << ", ";
9131 
9132 		writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9133 
9134 		if (0 == store.m_row)
9135 		{
9136 			stream << ", -";
9137 		}
9138 		else
9139 		{
9140 			stream << ", ";
9141 		}
9142 
9143 		writeLoadedValueVariableNameToStream(stream, store.m_index);
9144 		stream << ");";
9145 
9146 		return stream;
9147 	}
9148 
9149 	struct coordinatesVariableDeclaration
9150 	{
coordinatesVariableDeclarationgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9151 		coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9152 		{
9153 		}
9154 		GLuint m_index;
9155 		GLuint m_row;
9156 	};
9157 
9158 	/** Write declaration of variable for coordinate at given row to output stream
9159 	 *
9160 	 * @param stream      Output stream
9161 	 * @param declaration Declaration details
9162 	 *
9163 	 * @return stream
9164 	 **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9165 	friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9166 	{
9167 		stream << "const ivec2 ";
9168 
9169 		writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9170 
9171 		stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9172 
9173 		return stream;
9174 	}
9175 
9176 	/* Methods */
9177 	/** Build program to test specified shader stage
9178 	 *
9179 	 * Throws exception in case of any failure
9180 	 *
9181 	 * @param stage Stage id
9182 	 *
9183 	 * @return Program id
9184 	 **/
buildProgramToTestShaderStage(shaderStage stage)9185 	GLuint buildProgramToTestShaderStage(shaderStage stage)
9186 	{
9187 		static const char* const boilerplate_fragment_shader_code =
9188 			"#version 400 core\n"
9189 			"#extension GL_ARB_shader_image_load_store : require\n"
9190 			"\n"
9191 			"precision highp float;\n"
9192 			"\n"
9193 			"void main()\n"
9194 			"{\n"
9195 			"    discard;\n"
9196 			"}\n";
9197 
9198 		static const char* const boilerplate_tesselation_evaluation_shader_code =
9199 			"#version 400 core\n"
9200 			"#extension GL_ARB_shader_image_load_store : require\n"
9201 			"\n"
9202 			"precision highp float;\n"
9203 			"\n"
9204 			"layout(quads, equal_spacing, ccw) in;\n"
9205 			"\n"
9206 			"void main()\n"
9207 			"{\n"
9208 			"\n"
9209 			"}\n";
9210 
9211 		static const char* const boilerplate_vertex_shader_code =
9212 			"#version 400 core\n"
9213 			"#extension GL_ARB_shader_image_load_store : require\n"
9214 			"\n"
9215 			"precision highp float;\n"
9216 			"\n"
9217 			"layout(location = 0) in vec4 i_position;\n"
9218 			"\n"
9219 			"void main()\n"
9220 			"{\n"
9221 			"  gl_Position = i_position;\n"
9222 			"}\n";
9223 
9224 		const char* fragment_shader_code			   = boilerplate_fragment_shader_code;
9225 		const char* geometry_shader_code			   = 0;
9226 		bool		is_program_built				   = true;
9227 		GLuint		program_object_id				   = 0;
9228 		const char* tesselation_control_shader_code	= 0;
9229 		const char* tesselation_evaluation_shader_code = 0;
9230 		std::string tested_shader_stage_code;
9231 		const char* vertex_shader_code = boilerplate_vertex_shader_code;
9232 
9233 		/* Get source code for tested shader stage */
9234 		prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9235 
9236 		if (true == tested_shader_stage_code.empty())
9237 		{
9238 			return 0;
9239 		}
9240 
9241 		/* Set up source code for all required stages */
9242 		switch (stage)
9243 		{
9244 		case fragmentShaderStage:
9245 			fragment_shader_code = tested_shader_stage_code.c_str();
9246 			break;
9247 
9248 		case geometryShaderStage:
9249 			geometry_shader_code = tested_shader_stage_code.c_str();
9250 			break;
9251 
9252 		case tesselationControlShaderStage:
9253 			tesselation_control_shader_code	= tested_shader_stage_code.c_str();
9254 			tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9255 			break;
9256 
9257 		case tesselationEvalutaionShaderStage:
9258 			tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9259 			break;
9260 
9261 		case vertexShaderStage:
9262 			vertex_shader_code = tested_shader_stage_code.c_str();
9263 			break;
9264 
9265 		default:
9266 			TCU_FAIL("Invalid shader stage");
9267 		}
9268 
9269 		/* Build program */
9270 		program_object_id =
9271 			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9272 						 geometry_shader_code, fragment_shader_code, &is_program_built);
9273 
9274 		/* Check if program was built */
9275 		if (false == is_program_built)
9276 		{
9277 			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9278 		}
9279 
9280 		/* Done */
9281 		return program_object_id;
9282 	}
9283 
9284 	/** Create texture to test given shader stage
9285 	 *
9286 	 * Throws exception in case of any failure
9287 	 *
9288 	 * @param stage Stage id
9289 	 *
9290 	 * @return Texture id
9291 	 **/
createTextureToTestShaderStage(shaderStage stage)9292 	GLuint createTextureToTestShaderStage(shaderStage stage)
9293 	{
9294 		GLenum			   error			  = glGetError();
9295 		const GLint		   max_image_uniforms = getMaximumImageUniformsForStage(stage);
9296 		GLuint			   texture_id		  = 0;
9297 		std::vector<GLint> texture_data;
9298 
9299 		const GLsizei height = 2;
9300 		const GLsizei width  = max_image_uniforms;
9301 
9302 		if (m_min_required_image_uniforms > max_image_uniforms)
9303 		{
9304 			return 0;
9305 		}
9306 
9307 		/* Generate texture id */
9308 		glGenTextures(1, &texture_id);
9309 		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9310 
9311 		/* Bind texture */
9312 		glBindTexture(GL_TEXTURE_2D, texture_id);
9313 		error = glGetError();
9314 		if (GL_NO_ERROR != error)
9315 		{
9316 			glDeleteTextures(1, &texture_id);
9317 			GLU_EXPECT_NO_ERROR(error, "BindTexture");
9318 		}
9319 
9320 		/* Prepare storage for texture data */
9321 		texture_data.resize(width * height);
9322 		for (GLint i = 0; i < max_image_uniforms; ++i)
9323 		{
9324 			texture_data[i]			= getExpectedValue(i);
9325 			texture_data[i + width] = 0;
9326 		}
9327 
9328 		/* Create first level of texture */
9329 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9330 					 &texture_data[0]);
9331 		error = glGetError();
9332 		if (GL_NO_ERROR != error)
9333 		{
9334 			glDeleteTextures(1, &texture_id);
9335 			GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9336 		}
9337 
9338 		/* Make texture complete */
9339 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9340 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9341 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9342 		error = glGetError();
9343 		if (GL_NO_ERROR != error)
9344 		{
9345 			glDeleteTextures(1, &texture_id);
9346 			GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9347 		}
9348 
9349 		/* Done */
9350 		return texture_id;
9351 	}
9352 
9353 	/** Get value of texel for image at given index
9354 	 *
9355 	 * @param index Index of image uniform
9356 	 *
9357 	 * @return Value of texel
9358 	 **/
getExpectedValue(GLint index)9359 	GLint getExpectedValue(GLint index)
9360 	{
9361 		// To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9362 		// we set one bit in the exponent of each component of those pixel format
9363 		return 0x40104200 + index;
9364 	}
9365 
9366 	/** Get name of uniform at given index
9367 	 *
9368 	 * @param index    Index of uniform
9369 	 * @param out_name Name of uniform
9370 	 **/
getImageUniformName(GLuint index,std::string & out_name)9371 	void getImageUniformName(GLuint index, std::string& out_name)
9372 	{
9373 		std::stringstream stream;
9374 
9375 		writeImageUniformNameToStream(stream, index);
9376 
9377 		out_name = stream.str();
9378 	}
9379 
9380 	/** Get maximum number of image uniforms allowed for given shader stage
9381 	 *
9382 	 * @param stage Stage id
9383 	 *
9384 	 * @return Maximum allowed image uniforms
9385 	 **/
getMaximumImageUniformsForStage(shaderStage stage)9386 	GLint getMaximumImageUniformsForStage(shaderStage stage)
9387 	{
9388 		GLint  max_image_uniforms = 0;
9389 		GLenum pname			  = 0;
9390 
9391 		switch (stage)
9392 		{
9393 		case fragmentShaderStage:
9394 			pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9395 			break;
9396 
9397 		case geometryShaderStage:
9398 			pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9399 			break;
9400 
9401 		case tesselationControlShaderStage:
9402 			pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9403 			break;
9404 
9405 		case tesselationEvalutaionShaderStage:
9406 			pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9407 			break;
9408 
9409 		case vertexShaderStage:
9410 			pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9411 			break;
9412 
9413 		default:
9414 			TCU_FAIL("Invalid shader stage");
9415 		}
9416 
9417 		glGetIntegerv(pname, &max_image_uniforms);
9418 		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9419 
9420 		return max_image_uniforms;
9421 	}
9422 
9423 	/** Prepare source for tested shader stage
9424 	 *
9425 	 * @param stage    Stage id
9426 	 * @param out_code Source code
9427 	 **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9428 	void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9429 	{
9430 		GLint			  max_image_uniforms	= getMaximumImageUniformsForStage(stage);
9431 		const char*		  stage_specific_layout = "";
9432 		const char*		  stage_specific_predicate = "true";
9433 		std::stringstream stream;
9434 
9435 		if (m_min_required_image_uniforms > max_image_uniforms)
9436 		{
9437 			return;
9438 		}
9439 
9440 		/* Expected result follows
9441 		 *
9442 		 * #version 400 core
9443 		 * #extension GL_ARB_shader_image_load_store : require
9444 		 *
9445 		 * precision highp float;
9446 		 *
9447 		 * stage_specific_layout goes here
9448 		 *
9449 		 * Uniform declarations go here
9450 		 *
9451 		 * void main()
9452 		 * {
9453 		 *     const ivec2 row_0_coordinates(0, 0);
9454 		 *     const ivec2 row_1_coordinates(0, 1);
9455 		 *
9456 		 *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9457 		 *
9458 		 *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9459 		 *
9460 		 *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9461 		 *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9462 		 * }
9463 		 */
9464 
9465 		/* Get piece of code specific for stage */
9466 		switch (stage)
9467 		{
9468 		case fragmentShaderStage:
9469 			break;
9470 
9471 		case geometryShaderStage:
9472 			stage_specific_layout = "layout(points) in;\n"
9473 									"layout(points, max_vertices = 1) out;\n"
9474 									"\n";
9475 			break;
9476 
9477 		case tesselationControlShaderStage:
9478 			stage_specific_layout = "layout(vertices = 4) out;\n"
9479 									"\n";
9480 			stage_specific_predicate = "gl_InvocationID == 0";
9481 			break;
9482 
9483 		case tesselationEvalutaionShaderStage:
9484 			stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9485 									"\n";
9486 			break;
9487 
9488 		case vertexShaderStage:
9489 			break;
9490 
9491 		default:
9492 			TCU_FAIL("Invalid shader stage");
9493 		}
9494 
9495 		/* Preamble */
9496 		stream << "#version 400 core\n"
9497 				  "#extension GL_ARB_shader_image_load_store : require\n"
9498 				  "\n"
9499 				  "precision highp float;\n"
9500 				  "\n"
9501 			   << stage_specific_layout;
9502 
9503 		/* Image uniforms declarations */
9504 		for (GLint i = 0; i < max_image_uniforms; ++i)
9505 		{
9506 			stream << imageUniformDeclaration(i) << "\n";
9507 		}
9508 
9509 		/* Main opening */
9510 		stream << "\n"
9511 				  "void main()\n"
9512 				  "{\n";
9513 
9514 		stream << "    if (" << stage_specific_predicate << ")\n";
9515 		stream << "    {\n";
9516 
9517 		/* imageLoad and imageStores for each uniform */
9518 		for (GLint i = 0; i < max_image_uniforms; ++i)
9519 		{
9520 			stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9521 				   << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9522 				   << "\n"
9523 				   << "        " << imageLoadCall(i) << "\n"
9524 				   << "\n"
9525 				   << "        " << imageStoreCall(i, 0) << "\n"
9526 				   << "        " << imageStoreCall(i, 1) << "\n";
9527 
9528 			if (max_image_uniforms > i + 1)
9529 			{
9530 				stream << "\n";
9531 			}
9532 		}
9533 
9534 		stream << "    }\n";
9535 
9536 		/* Main closing */
9537 		stream << "}\n\n";
9538 
9539 		/* Done */
9540 		out_code = stream.str();
9541 	}
9542 
9543 	/** Test given shader stage
9544 	 *
9545 	 * @param stage Stage id
9546 	 *
9547 	 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9548 	 *         testFailed when test result is negative;
9549 	 *         m_test_passed when test result is positive;
9550 	 **/
testShaderStage(shaderStage stage)9551 	testResult testShaderStage(shaderStage stage)
9552 	{
9553 		std::string		   image_uniform_name;
9554 		static const GLint invalid_uniform_location = -1;
9555 		const GLint		   max_image_uniforms		= getMaximumImageUniformsForStage(stage);
9556 		GLenum			   primitive_mode			= GL_POINTS;
9557 		GLuint			   program_id				= 0;
9558 		testResult		   result					= testPassed;
9559 		std::vector<GLint> texture_data;
9560 		GLuint			   texture_id = 0;
9561 
9562 		static const GLuint height = 2;
9563 		const GLuint		width  = max_image_uniforms;
9564 
9565 		const GLuint		positive_value_index = width;
9566 		static const GLuint negated_value_index  = 0;
9567 
9568 		if (m_min_required_image_uniforms > max_image_uniforms)
9569 		{
9570 			return testNotSupported;
9571 		}
9572 
9573 		/* Select program and texture ids for given stage */
9574 		switch (stage)
9575 		{
9576 		case fragmentShaderStage:
9577 			program_id = m_program_to_test_fs_stage_id;
9578 			texture_id = m_texture_to_test_fs_stage_id;
9579 			break;
9580 
9581 		case geometryShaderStage:
9582 			program_id = m_program_to_test_gs_stage_id;
9583 			texture_id = m_texture_to_test_gs_stage_id;
9584 			break;
9585 
9586 		case tesselationControlShaderStage:
9587 			primitive_mode = GL_PATCHES;
9588 			program_id	 = m_program_to_test_tcs_stage_id;
9589 			texture_id	 = m_texture_to_test_tcs_stage_id;
9590 			break;
9591 
9592 		case tesselationEvalutaionShaderStage:
9593 			primitive_mode = GL_PATCHES;
9594 			program_id	 = m_program_to_test_tes_stage_id;
9595 			texture_id	 = m_texture_to_test_tes_stage_id;
9596 			break;
9597 
9598 		case vertexShaderStage:
9599 			program_id = m_program_to_test_vs_stage_id;
9600 			texture_id = m_texture_to_test_vs_stage_id;
9601 			break;
9602 
9603 		default:
9604 			TCU_FAIL("Invalid shader stage");
9605 		}
9606 
9607 		/* Set program */
9608 		glUseProgram(program_id);
9609 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9610 
9611 		/* Bind texture to image units */
9612 		for (GLint i = 0; i < max_image_uniforms; ++i)
9613 		{
9614 			imageFormatDetails format_details;
9615 			getImageUniformDeclarationDetails(i, format_details);
9616 
9617 			glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9618 							   GL_READ_WRITE, format_details.m_image_unit_format);
9619 			GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9620 		}
9621 
9622 		/* Set all image uniforms to corresponding image units */
9623 		for (GLint i = 0; i < max_image_uniforms; ++i)
9624 		{
9625 			/* Get name */
9626 			getImageUniformName(i, image_uniform_name);
9627 
9628 			/* Get location */
9629 			GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9630 			GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9631 
9632 			if (invalid_uniform_location == image_uniform_location)
9633 			{
9634 				throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9635 										 __LINE__);
9636 			}
9637 
9638 			/* Set uniform value */
9639 			glUniform1i(image_uniform_location, i /* image_unit */);
9640 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9641 		}
9642 
9643 		/* Execute draw */
9644 		glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9645 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9646 
9647 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
9648 
9649 		texture_data.resize(width * height);
9650 
9651 		/* Get texture data */
9652 		glBindTexture(GL_TEXTURE_2D, texture_id);
9653 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9654 
9655 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9656 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9657 
9658 		/* Verify each image uniform */
9659 		for (GLint i = 0; i < max_image_uniforms; ++i)
9660 		{
9661 			imageFormatDetails format_details;
9662 			getImageUniformDeclarationDetails(i, format_details);
9663 
9664 			if (false ==
9665 				format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9666 													  texture_data[negated_value_index + i]))
9667 			{
9668 				m_context.getTestContext().getLog()
9669 					<< tcu::TestLog::Message << "Invalid result!"
9670 					<< " Image format: " << format_details.m_image_format << " Original value: "
9671 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9672 					<< " Copied value: "
9673 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9674 					<< texture_data[positive_value_index + i] << " Negated value: "
9675 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9676 					<< texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9677 
9678 				result = testFailed;
9679 			}
9680 		}
9681 
9682 		/* Done */
9683 		return result;
9684 	}
9685 
9686 	/** Verifies if original_value, positive_value and negated_value match
9687 	 *
9688 	 * @tparam T Type used during verification process, it should match float values by size
9689 	 *
9690 	 * @param original_value Original value of texel, used when creating a texture
9691 	 * @param positive_value Value stored by shader as read
9692 	 * @param negated_value  Value stored by shader after negation
9693 	 *
9694 	 * @return true if values match, false otherwise
9695 	 **/
9696 	template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9697 	static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9698 	{
9699 		if (original_value != positive_value)
9700 		{
9701 			return false;
9702 		}
9703 
9704 		static const GLuint n_elements		  = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9705 		static const GLuint sign_bit_index	= sizeof(T) * 8 - 1;		   /* 7, 15, 31 */
9706 		static const T		sign_bit_mask	 = 1 << sign_bit_index;	   /* 0x80.. */
9707 		static const T		sign_bit_inv_mask = (T)~sign_bit_mask;		   /* 0x7f.. */
9708 
9709 		const T* positive_elements = (T*)&positive_value;
9710 		const T* negated_elements  = (T*)&negated_value;
9711 
9712 		for (GLuint i = 0; i < n_elements; ++i)
9713 		{
9714 			const T positive_element = positive_elements[i];
9715 			const T negated_element  = negated_elements[i];
9716 
9717 			const T positive_sign_bit = positive_element & sign_bit_mask;
9718 			const T negated_sign_bit  = negated_element & sign_bit_mask;
9719 
9720 			const T positive_data = positive_element & sign_bit_inv_mask;
9721 			const T negated_data  = negated_element & sign_bit_inv_mask;
9722 
9723 			/* Compare data bits */
9724 			if (positive_data != negated_data)
9725 			{
9726 				return false;
9727 			}
9728 
9729 			/* Verify that sign bit is inverted */
9730 			if (positive_sign_bit == negated_sign_bit)
9731 			{
9732 				return false;
9733 			}
9734 		}
9735 
9736 		return true;
9737 	}
9738 
9739 	/** Verifies if original_value, positive_value and negated_value match
9740 	 *
9741 	 * @tparam T Type used during verification process, it should match float values by size
9742 	 *
9743 	 * @param original_value Original value of texel, used when creating a texture
9744 	 * @param positive_value Value stored by shader as read
9745 	 * @param negated_value  Value stored by shader after negation
9746 	 *
9747 	 * @return true if values match, false otherwise
9748 	 **/
9749 	template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9750 	static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9751 	{
9752 		if (original_value != positive_value)
9753 		{
9754 			return false;
9755 		}
9756 
9757 		static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9758 
9759 		const T* positive_elements = (T*)&positive_value;
9760 		const T* negated_elements  = (T*)&negated_value;
9761 
9762 		for (GLuint i = 0; i < n_elements; ++i)
9763 		{
9764 			const T positive_element = positive_elements[i];
9765 			const T negated_element  = negated_elements[i];
9766 
9767 			/* Compare data bits */
9768 			if (positive_element != -negated_element)
9769 			{
9770 				return false;
9771 			}
9772 		}
9773 
9774 		return true;
9775 	}
9776 
9777 	/** Verifies if original_value, positive_value and negated_value match
9778 	 *
9779 	 * @tparam R Number of bits for red channel
9780 	 * @tparam G Number of bits for green channel
9781 	 * @tparam B Number of bits for blue channel
9782 	 * @tparam A Number of bits for alpha channel
9783 	 *
9784 	 * @param original_value Original value of texel, used when creating a texture
9785 	 * @param positive_value Value stored by shader as read
9786 	 * @param negated_value  Value stored by shader after negation
9787 	 *
9788 	 * @return true if values match, false otherwise
9789 	 **/
9790 	template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9791 	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9792 	{
9793 		if (original_value != positive_value)
9794 		{
9795 			return false;
9796 		}
9797 
9798 		Integer<T, R, 0> positive_red(positive_value);
9799 		Integer<T, R, 0> negated_red(negated_value);
9800 
9801 		Integer<T, G, R> positive_green(positive_value);
9802 		Integer<T, G, R> negated_green(negated_value);
9803 
9804 		Integer<T, B, R + G> positive_blue(positive_value);
9805 		Integer<T, B, R + G> negated_blue(negated_value);
9806 
9807 		Integer<T, A, R + G + B> positive_alpha(positive_value);
9808 		Integer<T, A, R + G + B> negated_alpha(negated_value);
9809 
9810 		if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9811 			((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9812 			((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9813 			((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9814 		{
9815 			return false;
9816 		}
9817 
9818 		return true;
9819 	}
9820 
9821 	/** Verifies if original_value, positive_value and negated_value match
9822 	 *
9823 	 * @param original_value Original value of texel, used when creating a texture
9824 	 * @param positive_value Value stored by shader as read
9825 	 * @param negated_value  Value stored by shader after negation
9826 	 *
9827 	 * @return true if values match, false otherwise
9828 	 **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9829 	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9830 	{
9831 		if (original_value != positive_value)
9832 		{
9833 			return false;
9834 		}
9835 
9836 		if (positive_value != -negated_value)
9837 		{
9838 			return false;
9839 		}
9840 
9841 		return true;
9842 	}
9843 
9844 	/** Verifies if original_value, positive_value and negated_value match
9845 	 *
9846 	 * @param original_value Original value of texel, used when creating a texture
9847 	 * @param positive_value Value stored by shader as read
9848 	 * @param negated_value  Value stored by shader after negation
9849 	 *
9850 	 * @return true if values match, false otherwise
9851 	 **/
9852 	template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9853 	static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9854 	{
9855 		if (original_value != positive_value)
9856 		{
9857 			return false;
9858 		}
9859 
9860 		if (0 != negated_value)
9861 		{
9862 			return false;
9863 		}
9864 
9865 		return true;
9866 	}
9867 };
9868 
9869 /** Test "Early fragment tests" description follows.
9870  *
9871  *  BasicGLSLEarlyFragTests verifies that:
9872  *  - early z test is applied when enabled,
9873  *  - early z test is not applied when disabled.
9874  *
9875  *  Proposed modifications:
9876  *  - verify that early z test does not discard all fragments when enabled,
9877  *  - verify that early stencil test is applied when enabled,
9878  *  - verify that early stencil test does not discard all fragments when
9879  *  enabled,
9880  *  - verify that early stencil test is not applied when disabled.
9881  *
9882  *  Steps:
9883  *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9884  *  shader stage:
9885  *      a) one program should enable early fragment tests
9886  *      ("layout(early_fragment_tests) in;"),
9887  *      b) second program should disable early fragment tests,
9888  *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9889  *  depth-stencil attachments,
9890  *  - prepare 2D texture 64x64 R32F,
9891  *  - enable depth test,
9892  *  - verify that early z test is applied when enabled:
9893  *      - use program enabling early fragment tests,
9894  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9895  *      - fill texture with zeros,
9896  *      - bind texture to image uniform,
9897  *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9898  *      corner at 1,1) at z: 0.75
9899  *      - verify that texture is still filled with zeros,
9900  *  - verify that early z test does not discard all fragments:
9901  *      - use program enabling early fragment tests,
9902  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9903  *      - fill texture with zeros,
9904  *      - bind texture to image uniform,
9905  *      - draw "full screen" quad at z: 0.25
9906  *      - verify that texture is now filled with 1.0,
9907  *  -verify that early z test is not applied when disabled:
9908  *      - use program disabling early fragment tests,
9909  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9910  *      - fill texture with zeros,
9911  *      - bind texture to image uniform,
9912  *      - draw "full screen" quad at z: 0.75
9913  *      - verify that texture is now filled with 1.0.
9914  *  - disable depth test
9915  *  - enable stencil test
9916  *  - verify that early stencil test is applied when enabled:
9917  *      - use program enabling early fragment tests,
9918  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9919  *      - fill texture with zeros,
9920  *      - set stencil test to:
9921  *          - <func> to GL_LESS,
9922  *          - <ref> to 128,
9923  *          - <mask> 0xffffffff,
9924  *      - bind texture to image uniform,
9925  *      - draw "full screen" quad at z: 0,
9926  *      - verify that texture is still filled with zeros,
9927  *  - verify that early stencil test does not discard all fragments:
9928  *      - use program enabling early fragment tests,
9929  *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9930  *      - fill texture with zeros,
9931  *      - set stencil test to:
9932  *          - <func> to GL_LESS,
9933  *          - <ref> to 0,
9934  *          - <mask> 0xffffffff,
9935  *      - bind texture to image uniform,
9936  *      - draw "full screen" quad at z: 0,
9937  *      - verify that texture is now filled with 1.0,
9938  *  - verify that early stencil test is not applied when disabled:
9939  *      - use program disabling early fragment tests,
9940  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9941  *      - fill texture with zeros,
9942  *      - set stencil test to:
9943  *          - <func> to GL_LESS,
9944  *          - <ref> to 128,
9945  *          - <mask> 0xffffffff,
9946  *      - bind texture to image uniform,
9947  *      - draw "full screen" quad at z: 0,
9948  *      - verify that texture is now filled with 1.0
9949  **/
9950 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9951 {
9952 private:
9953 	/* Constants */
9954 	GLuint			   m_image_edge;
9955 	static const GLint m_invalid_uniform_location = -1;
9956 
9957 	/* Types */
9958 	/** Store id and uniform locations for a single program object
9959 	 *
9960 	 **/
9961 	struct programDetails
9962 	{
9963 		GLint  m_depth_uniform_location;
9964 		GLint  m_image_uniform_location;
9965 		GLuint m_program_id;
9966 
programDetailsgl4cts::__anonb00615420111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9967 		programDetails()
9968 			: m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9969 			, m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9970 			, m_program_id(0)
9971 		{
9972 			/* Nothing to be done here */
9973 		}
9974 	};
9975 
9976 	/* Fileds */
9977 	/* Storage for texture data */
9978 	std::vector<GLfloat> m_clean_texture_data;
9979 	std::vector<GLfloat> m_extracted_texture_data;
9980 
9981 	/* Program details */
9982 	programDetails m_disabled_early_tests;
9983 	programDetails m_enabled_early_tests;
9984 
9985 	/* Ids of GL objects */
9986 	GLuint m_color_renderbuffer_id;
9987 	GLuint m_depth_stencil_renderbuffer_id;
9988 	GLuint m_framebuffer_id;
9989 	GLuint m_texture_id;
9990 	GLuint m_vertex_array_object_id;
9991 
9992 public:
9993 	/* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()9994 	ImageLoadStoreEarlyFragmentTestsTest()
9995 		: m_image_edge(0)
9996 		, m_color_renderbuffer_id(0)
9997 		, m_depth_stencil_renderbuffer_id(0)
9998 		, m_framebuffer_id(0)
9999 		, m_texture_id(0)
10000 		, m_vertex_array_object_id(0)
10001 	{
10002 		/* Nothing to be done here */
10003 	}
10004 
10005 	/* Methods inherited from SubcaseBase */
Cleanup()10006 	virtual long Cleanup()
10007 	{
10008 		/* Restore defaults */
10009 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10010 		glBindRenderbuffer(GL_RENDERBUFFER, 0);
10011 		glBindTexture(GL_TEXTURE_2D, 0);
10012 		glBindVertexArray(0);
10013 		glDisable(GL_DEPTH_TEST);
10014 		glDisable(GL_STENCIL_TEST);
10015 		glUseProgram(0);
10016 
10017 		/* Delete objects */
10018 		if (0 != m_disabled_early_tests.m_program_id)
10019 		{
10020 			glDeleteProgram(m_disabled_early_tests.m_program_id);
10021 			m_disabled_early_tests.m_program_id = 0;
10022 		}
10023 
10024 		if (0 != m_enabled_early_tests.m_program_id)
10025 		{
10026 			glDeleteProgram(m_enabled_early_tests.m_program_id);
10027 			m_enabled_early_tests.m_program_id = 0;
10028 		}
10029 
10030 		if (0 != m_color_renderbuffer_id)
10031 		{
10032 			glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10033 			m_color_renderbuffer_id = 0;
10034 		}
10035 
10036 		if (0 != m_depth_stencil_renderbuffer_id)
10037 		{
10038 			glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10039 			m_depth_stencil_renderbuffer_id = 0;
10040 		}
10041 
10042 		if (0 != m_framebuffer_id)
10043 		{
10044 			glDeleteFramebuffers(1, &m_framebuffer_id);
10045 			m_framebuffer_id = 0;
10046 		}
10047 
10048 		if (0 != m_texture_id)
10049 		{
10050 			glDeleteTextures(1, &m_texture_id);
10051 			m_texture_id = 0;
10052 		}
10053 
10054 		if (0 != m_vertex_array_object_id)
10055 		{
10056 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
10057 			m_vertex_array_object_id = 0;
10058 		}
10059 
10060 		/* Done */
10061 		return NO_ERROR;
10062 	}
10063 
Run()10064 	virtual long Run()
10065 	{
10066 		bool result = true;
10067 
10068 		/* Bind texture to first image unit */
10069 		glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10070 						   GL_READ_WRITE, GL_R32F);
10071 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10072 
10073 		/* Run tests for depth test */
10074 		if (false == testEarlyZ())
10075 		{
10076 			result = false;
10077 		}
10078 
10079 		/* Run tests for stencil test */
10080 		if (false == testEarlyStencil())
10081 		{
10082 			result = false;
10083 		}
10084 
10085 		/* Return ERROR if any problem was found */
10086 		if (false == result)
10087 		{
10088 			return ERROR;
10089 		}
10090 
10091 		/* Done */
10092 		return NO_ERROR;
10093 	}
10094 
Setup()10095 	virtual long Setup()
10096 	{
10097 		m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10098 
10099 		/* Prepare storage for texture data */
10100 		m_clean_texture_data.resize(m_image_edge * m_image_edge);
10101 		m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10102 
10103 		/* Prepare programs, framebuffer and texture */
10104 		buildPrograms();
10105 		createFramebuffer();
10106 		createTexture();
10107 
10108 		/* Generate vertex array object */
10109 		glGenVertexArrays(1, &m_vertex_array_object_id);
10110 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10111 
10112 		/* Bind vertex array object */
10113 		glBindVertexArray(m_vertex_array_object_id);
10114 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10115 
10116 		/* Set clear color */
10117 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10118 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10119 
10120 		/* Done */
10121 		return NO_ERROR;
10122 	}
10123 
10124 private:
10125 	/** Build two programs: with enabled and disabled early fragment tests
10126 	 *
10127 	 **/
buildPrograms()10128 	void buildPrograms()
10129 	{
10130 		static const char* const fragment_shader_with_disabled_early_tests =
10131 			"#version 400 core\n"
10132 			"#extension GL_ARB_shader_image_load_store : require\n"
10133 			"\n"
10134 			"precision highp float;\n"
10135 			"\n"
10136 			"layout(r32f) uniform image2D u_image;\n"
10137 			"\n"
10138 			"void main()\n"
10139 			"{\n"
10140 			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10141 			"\n"
10142 			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10143 			"\n"
10144 			"    discard;\n"
10145 			"}\n\n";
10146 
10147 		static const char* const fragment_shader_with_enabled_early_tests =
10148 			"#version 400 core\n"
10149 			"#extension GL_ARB_shader_image_load_store : require\n"
10150 			"\n"
10151 			"precision highp float;\n"
10152 			"\n"
10153 			"layout(early_fragment_tests) in;\n"
10154 			"\n"
10155 			"layout(r32f) uniform image2D u_image;\n"
10156 			"\n"
10157 			"void main()\n"
10158 			"{\n"
10159 			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10160 			"\n"
10161 			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10162 			"\n"
10163 			"    discard;\n"
10164 			"}\n\n";
10165 
10166 		static const char* const geometry_shader_code = "#version 400 core\n"
10167 														"#extension GL_ARB_shader_image_load_store : require\n"
10168 														"\n"
10169 														"precision highp float;\n"
10170 														"\n"
10171 														"layout(points)                           in;\n"
10172 														"layout(triangle_strip, max_vertices = 4) out;\n"
10173 														"\n"
10174 														"uniform float u_depth;\n"
10175 														"\n"
10176 														"void main()\n"
10177 														"{\n"
10178 														"    // Left-bottom\n"
10179 														"    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10180 														"    EmitVertex();\n"
10181 														"\n"
10182 														"    // Left-top\n"
10183 														"    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10184 														"    EmitVertex();\n"
10185 														"\n"
10186 														"    // Right-bottom\n"
10187 														"    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10188 														"    EmitVertex();\n"
10189 														"\n"
10190 														"    // Right-top\n"
10191 														"    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10192 														"    EmitVertex();\n"
10193 														"}\n\n";
10194 
10195 		static const char* const vertex_shader_code = "#version 400 core\n"
10196 													  "#extension GL_ARB_shader_image_load_store : require\n"
10197 													  "\n"
10198 													  "precision highp float;\n"
10199 													  "\n"
10200 													  "void main()\n"
10201 													  "{\n"
10202 													  "}\n\n";
10203 
10204 		prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10205 							  m_disabled_early_tests);
10206 
10207 		prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10208 							  m_enabled_early_tests);
10209 	}
10210 
10211 	/** Fill texture with zeros
10212 	 *
10213 	 **/
cleanTexture()10214 	void cleanTexture()
10215 	{
10216 		glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10217 						GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10218 		GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10219 	}
10220 
10221 	/** Create and bind (draw) framebuffer with color and depth-stencil attachments
10222 	 *
10223 	 **/
createFramebuffer()10224 	void createFramebuffer()
10225 	{
10226 		/* Generate render buffers */
10227 		glGenRenderbuffers(1, &m_color_renderbuffer_id);
10228 		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10229 
10230 		glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10231 		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10232 
10233 		/* Generate and bind framebuffer object */
10234 		glGenFramebuffers(1, &m_framebuffer_id);
10235 		GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10236 
10237 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10238 		GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10239 
10240 		/* Prepare color render buffer */
10241 		glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10242 		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10243 
10244 		glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10245 		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10246 
10247 		/* Set up color attachment */
10248 		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10249 		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10250 
10251 		/* Prepare depth-stencil render buffer */
10252 		glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10253 		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10254 
10255 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10256 		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10257 
10258 		/* Set up depth-stencil attachment */
10259 		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10260 								  m_depth_stencil_renderbuffer_id);
10261 		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10262 	}
10263 
10264 	/** Create 2D R32F texture
10265 	 *
10266 	 **/
createTexture()10267 	void createTexture()
10268 	{
10269 		glGenTextures(1, &m_texture_id);
10270 		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10271 
10272 		glBindTexture(GL_TEXTURE_2D, m_texture_id);
10273 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10274 
10275 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10276 		GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10277 	}
10278 
10279 	/** Extracts red channel from texture and verify if all texels are set to specified value
10280 	 *
10281 	 * @param value Expected value
10282 	 *
10283 	 * @return true if all texel match expected value, false otherwise
10284 	 **/
isTextureFilledWithValue(GLfloat value)10285 	bool isTextureFilledWithValue(GLfloat value)
10286 	{
10287 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10288 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10289 
10290 		for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10291 		{
10292 			if (value != m_extracted_texture_data[i])
10293 			{
10294 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10295 													<< " has invalid value: " << m_extracted_texture_data[i]
10296 													<< " expected: " << value << tcu::TestLog::EndMessage;
10297 
10298 				return false;
10299 			}
10300 		}
10301 
10302 		return true;
10303 	}
10304 
10305 	/** Build program, extract location of uniforms and store results in programDetails instance
10306 	 *
10307 	 * Throws tcu::InternalError if uniforms are inactive
10308 	 *
10309 	 * @param fragment_shader_code Source of fragment shader
10310 	 * @param geometry_shader_code Source of geometry shader
10311 	 * @param vertex_shader_code   Source of vertex shader
10312 	 * @param out_program_details  Instance of programDetails
10313 	 **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10314 	void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10315 							   const char* vertex_shader_code, programDetails& out_program_details)
10316 	{
10317 		static const char* const depth_uniform_name = "u_depth";
10318 		static const char* const image_uniform_name = "u_image";
10319 		bool					 is_program_built   = true;
10320 
10321 		GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10322 										 fragment_shader_code, &is_program_built);
10323 
10324 		if (false == is_program_built)
10325 		{
10326 			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10327 		}
10328 
10329 		/* Get depth uniform location */
10330 		GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10331 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10332 
10333 		if (m_invalid_uniform_location == depth_uniform_location)
10334 		{
10335 			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10336 		}
10337 
10338 		/* Get image uniform location */
10339 		GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10340 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10341 
10342 		if (m_invalid_uniform_location == image_uniform_location)
10343 		{
10344 			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10345 		}
10346 
10347 		/* Store results */
10348 		out_program_details.m_depth_uniform_location = depth_uniform_location;
10349 		out_program_details.m_image_uniform_location = image_uniform_location;
10350 		out_program_details.m_program_id			 = program_id;
10351 	}
10352 
10353 	/** Test if early fragment stencil test works as expected.
10354 	 *
10355 	 * @return true if successful, false otherwise
10356 	 **/
testEarlyStencil()10357 	bool testEarlyStencil()
10358 	{
10359 		bool result = true;
10360 
10361 		glEnable(GL_STENCIL_TEST);
10362 		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10363 
10364 		glClearDepthf(1.0f);
10365 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10366 
10367 		/* verify that early stencil test is applied when enabled */
10368 		{
10369 			glUseProgram(m_enabled_early_tests.m_program_id);
10370 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10371 
10372 			glClearStencil(0);
10373 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10374 
10375 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10376 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10377 
10378 			cleanTexture();
10379 
10380 			glStencilFunc(GL_LESS, 128, 0xffffffff);
10381 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10382 
10383 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10384 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10385 
10386 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10387 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10388 
10389 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10390 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10391 
10392 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10393 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10394 
10395 			if (false == isTextureFilledWithValue(0.0f))
10396 			{
10397 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10398 													<< "Problem with early stencil test. It is not applied"
10399 													<< tcu::TestLog::EndMessage;
10400 
10401 				result = false;
10402 			}
10403 		}
10404 
10405 		/* verify that early stencil test does not discard all fragments */
10406 		{
10407 			glClearStencil(128);
10408 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10409 
10410 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10411 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10412 
10413 			cleanTexture();
10414 
10415 			glStencilFunc(GL_LESS, 0, 0xffffffff);
10416 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10417 
10418 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10419 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10420 
10421 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10422 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10423 
10424 			if (false == isTextureFilledWithValue(1.0f))
10425 			{
10426 				m_context.getTestContext().getLog()
10427 					<< tcu::TestLog::Message
10428 					<< "Problem with early stencil test. It discards fragments, that shall be drawn"
10429 					<< tcu::TestLog::EndMessage;
10430 
10431 				result = false;
10432 			}
10433 		}
10434 
10435 		/* verify that early stencil test is not applied when disabled */
10436 		{
10437 			glUseProgram(m_disabled_early_tests.m_program_id);
10438 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10439 
10440 			glClearStencil(0);
10441 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10442 
10443 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10444 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10445 
10446 			cleanTexture();
10447 
10448 			glStencilFunc(GL_LESS, 128, 0xffffffff);
10449 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10450 
10451 			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10452 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10453 
10454 			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10455 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10456 
10457 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10458 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10459 
10460 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10461 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10462 
10463 			if (false == isTextureFilledWithValue(1.0f))
10464 			{
10465 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10466 													<< "Problem with early stencil test. It is applied when disabled"
10467 													<< tcu::TestLog::EndMessage;
10468 
10469 				result = false;
10470 			}
10471 		}
10472 
10473 		glDisable(GL_STENCIL_TEST);
10474 		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10475 
10476 		/* Done */
10477 		return result;
10478 	}
10479 
10480 	/** Test if early fragment depth test works as expected.
10481 	 *
10482 	 * @return true if successful, false otherwise
10483 	 **/
testEarlyZ()10484 	bool testEarlyZ()
10485 	{
10486 		bool result = true;
10487 
10488 		glEnable(GL_DEPTH_TEST);
10489 		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10490 
10491 		glClearDepthf(0.5f);
10492 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10493 
10494 		glClearStencil(0);
10495 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10496 
10497 		/* verify that early z test is applied when enabled */
10498 		{
10499 			glUseProgram(m_enabled_early_tests.m_program_id);
10500 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10501 
10502 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10503 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10504 
10505 			cleanTexture();
10506 
10507 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10508 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10509 
10510 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10511 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10512 
10513 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10514 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10515 
10516 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10517 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10518 
10519 			if (false == isTextureFilledWithValue(0.0f))
10520 			{
10521 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10522 													<< "Problem with early z test. It is not applied"
10523 													<< tcu::TestLog::EndMessage;
10524 
10525 				result = false;
10526 			}
10527 		}
10528 
10529 		/* verify that early z test does not discard all fragments */
10530 		{
10531 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10532 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10533 
10534 			cleanTexture();
10535 
10536 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10537 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10538 
10539 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10540 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10541 
10542 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10543 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10544 
10545 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10546 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10547 
10548 			if (false == isTextureFilledWithValue(1.0f))
10549 			{
10550 				m_context.getTestContext().getLog()
10551 					<< tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10552 					<< tcu::TestLog::EndMessage;
10553 
10554 				result = false;
10555 			}
10556 		}
10557 
10558 		/* verify that early z test is not applied when disabled */
10559 		{
10560 			glUseProgram(m_disabled_early_tests.m_program_id);
10561 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10562 
10563 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10564 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10565 
10566 			cleanTexture();
10567 
10568 			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10569 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10570 
10571 			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10572 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10573 
10574 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10575 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10576 
10577 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10578 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10579 
10580 			if (false == isTextureFilledWithValue(1.0f))
10581 			{
10582 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10583 													<< "Problem with early z test. It is applied when disabled"
10584 													<< tcu::TestLog::EndMessage;
10585 
10586 				result = false;
10587 			}
10588 		}
10589 
10590 		glDisable(GL_DEPTH_TEST);
10591 		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10592 
10593 		/* Done */
10594 		return result;
10595 	}
10596 };
10597 
10598 //-----------------------------------------------------------------------------
10599 // 4.1 NegativeUniform
10600 //-----------------------------------------------------------------------------
10601 class NegativeUniform : public ShaderImageLoadStoreBase
10602 {
10603 	GLuint m_program;
10604 
Setup()10605 	virtual long Setup()
10606 	{
10607 		m_program = 0;
10608 		return NO_ERROR;
10609 	}
10610 
Run()10611 	virtual long Run()
10612 	{
10613 		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10614 							  "  gl_Position = i_position;" NL "}";
10615 		const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10616 							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10617 							  "  discard;" NL "}";
10618 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10619 
10620 		GLint max_image_units;
10621 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10622 		glUseProgram(m_program);
10623 
10624 		glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10625 		if (glGetError() != GL_INVALID_VALUE)
10626 		{
10627 			m_context.getTestContext().getLog()
10628 				<< tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10629 				<< tcu::TestLog::EndMessage;
10630 			return ERROR;
10631 		}
10632 		glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10633 		if (glGetError() != GL_INVALID_VALUE)
10634 		{
10635 			m_context.getTestContext().getLog()
10636 				<< tcu::TestLog::Message
10637 				<< "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10638 				<< "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10639 			return ERROR;
10640 		}
10641 
10642 		GLint i = -3;
10643 		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10644 		if (glGetError() != GL_INVALID_VALUE)
10645 		{
10646 			m_context.getTestContext().getLog()
10647 				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10648 				<< tcu::TestLog::EndMessage;
10649 			return ERROR;
10650 		}
10651 		i = max_image_units + 1;
10652 		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10653 		if (glGetError() != GL_INVALID_VALUE)
10654 		{
10655 			m_context.getTestContext().getLog()
10656 				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10657 											"than or equal to the value of MAX_IMAGE_UNITS."
10658 				<< tcu::TestLog::EndMessage;
10659 			return ERROR;
10660 		}
10661 
10662 		glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10663 		if (glGetError() != GL_INVALID_OPERATION)
10664 		{
10665 			m_context.getTestContext().getLog()
10666 				<< tcu::TestLog::Message
10667 				<< "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10668 				<< tcu::TestLog::EndMessage;
10669 			return ERROR;
10670 		}
10671 		glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10672 		if (glGetError() != GL_INVALID_OPERATION)
10673 		{
10674 			m_context.getTestContext().getLog()
10675 				<< tcu::TestLog::Message
10676 				<< "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10677 				<< tcu::TestLog::EndMessage;
10678 			return ERROR;
10679 		}
10680 
10681 		{
10682 			glUseProgram(0);
10683 
10684 			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10685 			if (glGetError() != GL_INVALID_VALUE)
10686 			{
10687 				m_context.getTestContext().getLog()
10688 					<< tcu::TestLog::Message
10689 					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10690 					<< tcu::TestLog::EndMessage;
10691 				return ERROR;
10692 			}
10693 			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10694 			if (glGetError() != GL_INVALID_VALUE)
10695 			{
10696 				m_context.getTestContext().getLog()
10697 					<< tcu::TestLog::Message
10698 					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10699 					   "value of MAX_IMAGE_UNITS."
10700 					<< tcu::TestLog::EndMessage;
10701 				return ERROR;
10702 			}
10703 
10704 			GLint ii = -3;
10705 			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10706 			if (glGetError() != GL_INVALID_VALUE)
10707 			{
10708 				m_context.getTestContext().getLog()
10709 					<< tcu::TestLog::Message
10710 					<< "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10711 					<< tcu::TestLog::EndMessage;
10712 				return ERROR;
10713 			}
10714 			ii = max_image_units + 1;
10715 			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10716 			if (glGetError() != GL_INVALID_VALUE)
10717 			{
10718 				m_context.getTestContext().getLog()
10719 					<< tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10720 												"is greater than or equal to the value of MAX_IMAGE_UNITS."
10721 					<< tcu::TestLog::EndMessage;
10722 				return ERROR;
10723 			}
10724 
10725 			glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10726 			if (glGetError() != GL_INVALID_OPERATION)
10727 			{
10728 				m_context.getTestContext().getLog()
10729 					<< tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10730 												"location refers to an image variable."
10731 					<< tcu::TestLog::EndMessage;
10732 				return ERROR;
10733 			}
10734 			glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10735 			if (glGetError() != GL_INVALID_OPERATION)
10736 			{
10737 				m_context.getTestContext().getLog()
10738 					<< tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10739 												"location refers to an image variable."
10740 					<< tcu::TestLog::EndMessage;
10741 				return ERROR;
10742 			}
10743 		}
10744 
10745 		return NO_ERROR;
10746 	}
10747 
Cleanup()10748 	virtual long Cleanup()
10749 	{
10750 		glUseProgram(0);
10751 		glDeleteProgram(m_program);
10752 		return NO_ERROR;
10753 	}
10754 };
10755 //-----------------------------------------------------------------------------
10756 // 4.2 NegativeBind
10757 //-----------------------------------------------------------------------------
10758 class NegativeBind : public ShaderImageLoadStoreBase
10759 {
Setup()10760 	virtual long Setup()
10761 	{
10762 		return NO_ERROR;
10763 	}
10764 
Run()10765 	virtual long Run()
10766 	{
10767 		glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10768 		if (glGetError() != GL_INVALID_VALUE)
10769 		{
10770 			m_context.getTestContext().getLog()
10771 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10772 											"greater than or equal to the value of MAX_IMAGE_UNITS."
10773 				<< tcu::TestLog::EndMessage;
10774 			return ERROR;
10775 		}
10776 
10777 		glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10778 		if (glGetError() != GL_INVALID_VALUE)
10779 		{
10780 			m_context.getTestContext().getLog()
10781 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10782 											"the name of an existing texture object."
10783 				<< tcu::TestLog::EndMessage;
10784 			return ERROR;
10785 		}
10786 
10787 		glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10788 		if (glGetError() != GL_INVALID_VALUE)
10789 		{
10790 			m_context.getTestContext().getLog()
10791 				<< tcu::TestLog::Message
10792 				<< "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10793 				<< tcu::TestLog::EndMessage;
10794 			return ERROR;
10795 		}
10796 		return NO_ERROR;
10797 	}
10798 
Cleanup()10799 	virtual long Cleanup()
10800 	{
10801 		return NO_ERROR;
10802 	}
10803 };
10804 //-----------------------------------------------------------------------------
10805 // 4.3 NegativeCompileErrors
10806 //-----------------------------------------------------------------------------
10807 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10808 {
Run()10809 	virtual long Run()
10810 	{
10811 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10812 					 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10813 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10814 			return ERROR;
10815 
10816 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10817 					 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10818 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10819 			return ERROR;
10820 
10821 		if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10822 					 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10823 					 "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10824 			return ERROR;
10825 
10826 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10827 					 "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10828 			return ERROR;
10829 
10830 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10831 					 "readonly uniform image2D g_image;" NL "void main() {" NL
10832 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10833 			return ERROR;
10834 
10835 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10836 					 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10837 			return ERROR;
10838 
10839 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10840 					 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10841 			return ERROR;
10842 
10843 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10844 					 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10845 					 "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10846 			return ERROR;
10847 
10848 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10849 					 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10850 					 "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10851 			return ERROR;
10852 
10853 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10854 					 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10855 					 "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10856 			return ERROR;
10857 
10858 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10859 					 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10860 					 "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10861 			return ERROR;
10862 
10863 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10864 					 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10865 					 "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10866 					 "}"))
10867 			return ERROR;
10868 
10869 		return NO_ERROR;
10870 	}
10871 
Compile(const std::string & source)10872 	bool Compile(const std::string& source)
10873 	{
10874 		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10875 
10876 		const char* const src = source.c_str();
10877 		glShaderSource(sh, 1, &src, NULL);
10878 		glCompileShader(sh);
10879 
10880 		GLchar log[1024];
10881 		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10882 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10883 											<< log << tcu::TestLog::EndMessage;
10884 
10885 		GLint status;
10886 		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10887 		glDeleteShader(sh);
10888 
10889 		if (status == GL_TRUE)
10890 		{
10891 			m_context.getTestContext().getLog()
10892 				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10893 			return false;
10894 		}
10895 
10896 		return true;
10897 	}
10898 };
10899 //-----------------------------------------------------------------------------
10900 // 4.4 NegativeLinkErrors
10901 //-----------------------------------------------------------------------------
10902 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10903 {
Run()10904 	virtual long Run()
10905 	{
10906 		if (!SupportedInVS(1))
10907 			return NOT_SUPPORTED;
10908 
10909 		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10910 				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10911 				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10912 				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10913 				  "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10914 				  "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10915 			return ERROR;
10916 
10917 		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10918 				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10919 				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10920 				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10921 				  "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10922 				  "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10923 			return ERROR;
10924 
10925 		return NO_ERROR;
10926 	}
10927 
Link(const std::string & vs,const std::string & fs)10928 	bool Link(const std::string& vs, const std::string& fs)
10929 	{
10930 		const GLuint p = glCreateProgram();
10931 
10932 		const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10933 		glAttachShader(p, vsh);
10934 		glDeleteShader(vsh);
10935 		const char* const vssrc = vs.c_str();
10936 		glShaderSource(vsh, 1, &vssrc, NULL);
10937 		glCompileShader(vsh);
10938 
10939 		const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10940 		glAttachShader(p, fsh);
10941 		glDeleteShader(fsh);
10942 		const char* const fssrc = fs.c_str();
10943 		glShaderSource(fsh, 1, &fssrc, NULL);
10944 		glCompileShader(fsh);
10945 
10946 		GLint status;
10947 		glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10948 		if (status == GL_FALSE)
10949 		{
10950 			glDeleteProgram(p);
10951 			m_context.getTestContext().getLog()
10952 				<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10953 			return false;
10954 		}
10955 		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10956 		if (status == GL_FALSE)
10957 		{
10958 			glDeleteProgram(p);
10959 			m_context.getTestContext().getLog()
10960 				<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10961 			return false;
10962 		}
10963 
10964 		glLinkProgram(p);
10965 
10966 		GLchar log[1024];
10967 		glGetProgramInfoLog(p, sizeof(log), NULL, log);
10968 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10969 											<< log << tcu::TestLog::EndMessage;
10970 
10971 		glGetProgramiv(p, GL_LINK_STATUS, &status);
10972 		glDeleteProgram(p);
10973 
10974 		if (status == GL_TRUE)
10975 		{
10976 			m_context.getTestContext().getLog()
10977 				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10978 			return false;
10979 		}
10980 
10981 		return true;
10982 	}
10983 };
10984 
10985 /** Negative Test "Active image uniform limits", description follows.
10986  *
10987  *  Program that exceeds resource limits should not compile and/or link.
10988  *
10989  *  Steps:
10990  *  - try to compile and link a program that uses too many image uniforms in
10991  *  fragment shader stage,
10992  *  - try to compile and link a program that uses too many image uniforms in
10993  *  vertex shader stage,
10994  *  - try to compile and link a program that uses too many image uniforms in
10995  *  tessellation control shader stage,
10996  *  - try to compile and link a program that uses too many image uniforms in
10997  *  tessellation evaluation shader stage,
10998  *  - try to compile and link a program that uses too many image uniforms in
10999  *  geometry shader stage,
11000  *  - try to compile and link a program that uses too many image uniforms in all
11001  *  shader stages combined, any single stage should not exceed its limits, this
11002  *  step might be impossible to fulfill.
11003  *
11004  *  Test should use the following declaration of image uniforms:
11005  *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11006  *
11007  *  For cases where limit for single stage is tested, N_UNIFORMS should be
11008  *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11009  *  corresponding to tested shader stage.
11010  *
11011  *  For case where limit for combined stages is tested:
11012  *  - u_image name should be appended with the name of shader stage, like
11013  *  u_image_vertex,
11014  *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11015  *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11016  *  - compilation and linking shall succeed, when sum of all
11017  *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11018  *  gl_MaxCombinedImageUniforms.
11019  *
11020  *  All defined image uniforms have to be active. Each shader stage that declare
11021  *  image uniforms should include following code snippet:
11022  *  value = 1;
11023  *  for (int i = 0; i < N_UNIFORMS; ++i)
11024  *  {
11025  *      value = imageAtomicAdd(u_image[i], coord, value);
11026  *  }
11027  **/
11028 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11029 {
11030 private:
11031 	/* Fields */
11032 	/* Results */
11033 	bool m_result_for_combined;
11034 	bool m_result_for_fragment_shader;
11035 	bool m_result_for_geometry_shader;
11036 	bool m_result_for_tesselation_control_shader;
11037 	bool m_result_for_tesselatioon_evaluation_shader;
11038 	bool m_result_for_vertex_shader;
11039 
11040 public:
11041 	/* Constructor */
ImageLoadStoreUniformLimitsTest()11042 	ImageLoadStoreUniformLimitsTest()
11043 		: m_result_for_combined(false)
11044 		, m_result_for_fragment_shader(false)
11045 		, m_result_for_geometry_shader(false)
11046 		, m_result_for_tesselation_control_shader(false)
11047 		, m_result_for_tesselatioon_evaluation_shader(false)
11048 		, m_result_for_vertex_shader(false)
11049 	{
11050 		/* Nothing to be done */
11051 	}
11052 
11053 	/* Methods inherited from SubcaseBase */
Cleanup()11054 	virtual long Cleanup()
11055 	{
11056 		/* Done */
11057 		return NO_ERROR;
11058 	}
11059 
Run()11060 	virtual long Run()
11061 	{
11062 		m_context.getTestContext().getLog() << tcu::TestLog::Message
11063 											<< "This test tries to build invalid programs, expect error messages about "
11064 											   "exceeded number of active image uniforms"
11065 											<< tcu::TestLog::EndMessage;
11066 
11067 		testFragmentShaderStage();
11068 		testGeometryShaderStage();
11069 		testTesselationControlShaderStage();
11070 		testTesselationEvaluationShaderStage();
11071 		testVertexShaderStage();
11072 		testCombinedShaderStages();
11073 
11074 		/* Return error if any stage failed */
11075 		if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11076 			(false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11077 			(false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11078 		{
11079 			return ERROR;
11080 		}
11081 
11082 		/* Done */
11083 		return NO_ERROR;
11084 	}
11085 
Setup()11086 	virtual long Setup()
11087 	{
11088 		/* Done */
11089 		return NO_ERROR;
11090 	}
11091 
11092 private:
11093 	/** Test fragment shader stage
11094 	 *
11095 	 **/
testFragmentShaderStage()11096 	void testFragmentShaderStage()
11097 	{
11098 		static const char* const fragment_shader_code =
11099 			"#version 400 core\n"
11100 			"#extension GL_ARB_shader_image_load_store : require\n"
11101 			"\n"
11102 			"precision highp float;\n"
11103 			"\n"
11104 			"#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11105 			"\n"
11106 			"flat in ivec2 vs_fs_coord;\n"
11107 			"\n"
11108 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11109 			"\n"
11110 			"void main()\n"
11111 			"{\n"
11112 			"    int value = 1;\n"
11113 			"\n"
11114 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11115 			"    {\n"
11116 			"        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11117 			"    }\n"
11118 			"\n"
11119 			"    discard;\n"
11120 			"}\n\n";
11121 
11122 		static const char* const vertex_shader_code = "#version 400 core\n"
11123 													  "#extension GL_ARB_shader_image_load_store : require\n"
11124 													  "\n"
11125 													  "precision highp float;\n"
11126 													  "\n"
11127 													  "     in  ivec2 vs_in_coord;\n"
11128 													  "flat out ivec2 vs_fs_coord;\n"
11129 													  "\n"
11130 													  "void main()\n"
11131 													  "{\n"
11132 													  "    vs_fs_coord = vs_in_coord;\n"
11133 													  "}\n\n";
11134 
11135 		m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11136 														0 /* tesselation_control_shader_code */,
11137 														0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11138 
11139 		if (false == m_result_for_fragment_shader)
11140 		{
11141 			m_context.getTestContext().getLog()
11142 				<< tcu::TestLog::Message
11143 				<< "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11144 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11145 				<< fragment_shader_code << tcu::TestLog::EndMessage;
11146 		}
11147 	}
11148 
11149 	/** Test geometry shader stage
11150 	 *
11151 	 **/
testGeometryShaderStage()11152 	void testGeometryShaderStage()
11153 	{
11154 		static const char* const fragment_shader_code = "#version 400 core\n"
11155 														"#extension GL_ARB_shader_image_load_store : require\n"
11156 														"\n"
11157 														"precision highp float;\n"
11158 														"\n"
11159 														"void main()\n"
11160 														"{\n"
11161 														"    discard;\n"
11162 														"}\n\n";
11163 
11164 		static const char* const geometry_shader_code =
11165 			"#version 400 core\n"
11166 			"#extension GL_ARB_shader_image_load_store : require\n"
11167 			"\n"
11168 			"precision highp float;\n"
11169 			"\n"
11170 			"layout(points)                   in;\n"
11171 			"layout(points, max_vertices = 1) out;\n"
11172 			"\n"
11173 			"#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11174 			"\n"
11175 			"in ivec2 vs_gs_coord[];\n"
11176 			"\n"
11177 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11178 			"\n"
11179 			"void main()\n"
11180 			"{\n"
11181 			"    int value = 1;\n"
11182 			"\n"
11183 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11184 			"    {\n"
11185 			"        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11186 			"    }\n"
11187 			"}\n\n";
11188 
11189 		static const char* const vertex_shader_code = "#version 400 core\n"
11190 													  "#extension GL_ARB_shader_image_load_store : require\n"
11191 													  "\n"
11192 													  "precision highp float;\n"
11193 													  "\n"
11194 													  "in  ivec2 vs_in_coord;\n"
11195 													  "out ivec2 vs_gs_coord;\n"
11196 													  "\n"
11197 													  "void main()\n"
11198 													  "{\n"
11199 													  "    vs_gs_coord = vs_in_coord;\n"
11200 													  "}\n\n";
11201 
11202 		m_result_for_geometry_shader =
11203 			!doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11204 							 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11205 
11206 		if (false == m_result_for_geometry_shader)
11207 		{
11208 			m_context.getTestContext().getLog()
11209 				<< tcu::TestLog::Message
11210 				<< "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11211 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11212 				<< geometry_shader_code << tcu::TestLog::EndMessage;
11213 		}
11214 	}
11215 
11216 	/** Test tesselation control shader stage
11217 	 *
11218 	 **/
testTesselationControlShaderStage()11219 	void testTesselationControlShaderStage()
11220 	{
11221 		static const char* const fragment_shader_code = "#version 400 core\n"
11222 														"#extension GL_ARB_shader_image_load_store : require\n"
11223 														"\n"
11224 														"precision highp float;\n"
11225 														"\n"
11226 														"void main()\n"
11227 														"{\n"
11228 														"    discard;\n"
11229 														"}\n\n";
11230 
11231 		static const char* const tesselation_control_shader_code =
11232 			"#version 400 core\n"
11233 			"#extension GL_ARB_shader_image_load_store : require\n"
11234 			"\n"
11235 			"precision highp float;\n"
11236 			"\n"
11237 			"layout(vertices = 4) out;\n"
11238 			"\n"
11239 			"#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11240 			"\n"
11241 			"in ivec2 vs_tcs_coord[];\n"
11242 			"\n"
11243 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11244 			"\n"
11245 			"void main()\n"
11246 			"{\n"
11247 			"    int value = 1;\n"
11248 			"\n"
11249 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11250 			"    {\n"
11251 			"        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11252 			"    }\n"
11253 			"}\n\n";
11254 
11255 		static const char* const tesselation_evaluation_shader_code =
11256 			"#version 400 core\n"
11257 			"#extension GL_ARB_shader_image_load_store : require\n"
11258 			"\n"
11259 			"precision highp float;\n"
11260 			"\n"
11261 			"layout(quads, equal_spacing, ccw) in;\n"
11262 			"\n"
11263 			"void main()\n"
11264 			"{\n"
11265 			"}\n";
11266 
11267 		static const char* const vertex_shader_code = "#version 400 core\n"
11268 													  "#extension GL_ARB_shader_image_load_store : require\n"
11269 													  "\n"
11270 													  "precision highp float;\n"
11271 													  "\n"
11272 													  "in  ivec2 vs_in_coord;\n"
11273 													  "out ivec2 vs_tcs_coord;\n"
11274 													  "\n"
11275 													  "void main()\n"
11276 													  "{\n"
11277 													  "    vs_tcs_coord = vs_in_coord;\n"
11278 													  "}\n\n";
11279 
11280 		m_result_for_tesselation_control_shader =
11281 			!doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11282 							 tesselation_evaluation_shader_code, vertex_shader_code);
11283 
11284 		if (false == m_result_for_tesselation_control_shader)
11285 		{
11286 			m_context.getTestContext().getLog()
11287 				<< tcu::TestLog::Message
11288 				<< "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11289 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11290 				<< tesselation_control_shader_code << tcu::TestLog::EndMessage;
11291 		}
11292 	}
11293 
11294 	/** Test teselation evaluation shader stage
11295 	 *
11296 	 **/
testTesselationEvaluationShaderStage()11297 	void testTesselationEvaluationShaderStage()
11298 	{
11299 		static const char* const fragment_shader_code = "#version 400 core\n"
11300 														"#extension GL_ARB_shader_image_load_store : require\n"
11301 														"\n"
11302 														"precision highp float;\n"
11303 														"\n"
11304 														"void main()\n"
11305 														"{\n"
11306 														"    discard;\n"
11307 														"}\n\n";
11308 
11309 		static const char* const tesselation_evaluation_shader_code =
11310 			"#version 400 core\n"
11311 			"#extension GL_ARB_shader_image_load_store : require\n"
11312 			"\n"
11313 			"precision highp float;\n"
11314 			"\n"
11315 			"layout(quads, equal_spacing, ccw) in;\n"
11316 			"\n"
11317 			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11318 			"\n"
11319 			"in ivec2 vs_tes_coord[];\n"
11320 			"\n"
11321 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11322 			"\n"
11323 			"void main()\n"
11324 			"{\n"
11325 			"    int value = 1;\n"
11326 			"\n"
11327 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11328 			"    {\n"
11329 			"        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11330 			"    }\n"
11331 			"}\n\n";
11332 
11333 		static const char* const vertex_shader_code = "#version 400 core\n"
11334 													  "#extension GL_ARB_shader_image_load_store : require\n"
11335 													  "\n"
11336 													  "precision highp float;\n"
11337 													  "\n"
11338 													  "in  ivec2 vs_in_coord;\n"
11339 													  "out ivec2 vs_tes_coord;\n"
11340 													  "\n"
11341 													  "void main()\n"
11342 													  "{\n"
11343 													  "    vs_tes_coord = vs_in_coord;\n"
11344 													  "}\n\n";
11345 
11346 		m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11347 			fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11348 			tesselation_evaluation_shader_code, vertex_shader_code);
11349 
11350 		if (false == m_result_for_tesselatioon_evaluation_shader)
11351 		{
11352 			m_context.getTestContext().getLog()
11353 				<< tcu::TestLog::Message
11354 				<< "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11355 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11356 				<< tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11357 		}
11358 	}
11359 
11360 	/** Test vertex shader stage
11361 	 *
11362 	 **/
testVertexShaderStage()11363 	void testVertexShaderStage()
11364 	{
11365 		static const char* const fragment_shader_code = "#version 400 core\n"
11366 														"#extension GL_ARB_shader_image_load_store : require\n"
11367 														"\n"
11368 														"precision highp float;\n"
11369 														"\n"
11370 														"void main()\n"
11371 														"{\n"
11372 														"    discard;\n"
11373 														"}\n\n";
11374 
11375 		static const char* const vertex_shader_code =
11376 			"#version 400 core\n"
11377 			"#extension GL_ARB_shader_image_load_store : require\n"
11378 			"\n"
11379 			"precision highp float;\n"
11380 			"\n"
11381 			"in ivec2 vs_in_coord;\n"
11382 			"\n"
11383 			"#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11384 			"\n"
11385 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11386 			"\n"
11387 			"void main()\n"
11388 			"{\n"
11389 			"    int value = 1;\n"
11390 			"\n"
11391 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11392 			"    {\n"
11393 			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11394 			"    }\n"
11395 			"}\n\n";
11396 
11397 		m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11398 													  0 /* tesselation_control_shader_code */,
11399 													  0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11400 
11401 		if (false == m_result_for_vertex_shader)
11402 		{
11403 			m_context.getTestContext().getLog()
11404 				<< tcu::TestLog::Message
11405 				<< "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11406 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11407 				<< vertex_shader_code << tcu::TestLog::EndMessage;
11408 		}
11409 	}
11410 
11411 	/** Test combined shader stages
11412 	 *
11413 	 **/
testCombinedShaderStages()11414 	void testCombinedShaderStages()
11415 	{
11416 		std::string fragment_shader_code =
11417 			"#version 400 core\n"
11418 			"#extension GL_ARB_shader_image_load_store : require\n"
11419 			"\n"
11420 			"precision highp float;\n"
11421 			"\n"
11422 			"#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11423 			"\n"
11424 			"flat in ivec2 gs_fs_coord;\n"
11425 			"\n"
11426 			"layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11427 			"\n"
11428 			"void main()\n"
11429 			"{\n"
11430 			"    int value = 1;\n"
11431 			"\n"
11432 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11433 			"    {\n"
11434 			"        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11435 			"    }\n"
11436 			"\n"
11437 			"    discard;\n"
11438 			"}\n\n";
11439 
11440 		std::string geometry_shader_code =
11441 			"#version 400 core\n"
11442 			"#extension GL_ARB_shader_image_load_store : require\n"
11443 			"\n"
11444 			"precision highp float;\n"
11445 			"\n"
11446 			"layout(points)                   in;\n"
11447 			"layout(points, max_vertices = 1) out;\n"
11448 			"\n"
11449 			"#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11450 			"\n"
11451 			"flat in  ivec2 tes_gs_coord[];\n"
11452 			"flat out ivec2 gs_fs_coord;\n"
11453 			"\n"
11454 			"#ifdef IMAGES\n"
11455 			"layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11456 			"#endif\n"
11457 			"\n"
11458 			"void main()\n"
11459 			"{\n"
11460 			"#ifdef IMAGES\n"
11461 			"    int value = 1;\n"
11462 			"\n"
11463 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11464 			"    {\n"
11465 			"        value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11466 			"    }\n"
11467 			"\n"
11468 			"#endif\n"
11469 			"    gs_fs_coord = tes_gs_coord[0];\n"
11470 			"    EmitVertex();\n"
11471 			"}\n\n";
11472 
11473 		std::string tesselation_control_shader_code =
11474 			"#version 400 core\n"
11475 			"#extension GL_ARB_shader_image_load_store : require\n"
11476 			"\n"
11477 			"precision highp float;\n"
11478 			"\n"
11479 			"layout(vertices = 4) out;\n"
11480 			"\n"
11481 			"#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11482 			"\n"
11483 			"flat in  ivec2 vs_tcs_coord[];\n"
11484 			"flat out ivec2 tcs_tes_coord[];\n"
11485 			"\n"
11486 			"#ifdef IMAGES\n"
11487 			"layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11488 			"#endif\n"
11489 			"\n"
11490 			"void main()\n"
11491 			"{\n"
11492 			"#ifdef IMAGES\n"
11493 			"    int value = 1;\n"
11494 			"\n"
11495 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11496 			"    {\n"
11497 			"        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11498 			"    }\n"
11499 			"\n"
11500 			"#endif\n"
11501 			"    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11502 			"}\n\n";
11503 
11504 		std::string tesselation_evaluation_shader_code =
11505 			"#version 400 core\n"
11506 			"#extension GL_ARB_shader_image_load_store : require\n"
11507 			"\n"
11508 			"precision highp float;\n"
11509 			"\n"
11510 			"layout(quads, equal_spacing, ccw) in;\n"
11511 			"\n"
11512 			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11513 			"\n"
11514 			"flat in  ivec2 tcs_tes_coord[];\n"
11515 			"flat out ivec2 tes_gs_coord;\n"
11516 			"\n"
11517 			"#ifdef IMAGES\n"
11518 			"layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11519 			"#endif\n"
11520 			"\n"
11521 			"void main()\n"
11522 			"{\n"
11523 			"#ifdef IMAGES\n"
11524 			"    int value = 1;\n"
11525 			"\n"
11526 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11527 			"    {\n"
11528 			"        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11529 			"    }\n"
11530 			"\n"
11531 			"#endif\n"
11532 			"    tes_gs_coord = tcs_tes_coord[0];\n"
11533 			"}\n\n";
11534 
11535 		std::string vertex_shader_code =
11536 			"#version 400 core\n"
11537 			"#extension GL_ARB_shader_image_load_store : require\n"
11538 			"\n"
11539 			"precision highp float;\n"
11540 			"\n"
11541 			"     in  ivec2 vs_in_coord;\n"
11542 			"flat out ivec2 vs_tcs_coord;\n"
11543 			"\n"
11544 			"#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11545 			"\n"
11546 			"#ifdef IMAGES\n"
11547 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11548 			"#endif\n"
11549 			"\n"
11550 			"void main()\n"
11551 			"{\n"
11552 			"#ifdef IMAGES\n"
11553 			"    int value = 1;\n"
11554 			"\n"
11555 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11556 			"    {\n"
11557 			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11558 			"    }\n"
11559 			"\n"
11560 			"#endif\n"
11561 			"    vs_tcs_coord = vs_tcs_coord;\n"
11562 			"}\n\n";
11563 
11564 		/* Active image uniform limits */
11565 		GLint max_combined_image_uniforms				= 0;
11566 		GLint max_fragment_image_uniforms				= 0;
11567 		GLint max_geometry_image_uniforms				= 0;
11568 		GLint max_tesselation_control_image_uniforms	= 0;
11569 		GLint max_tesselation_evaluation_image_uniforms = 0;
11570 		GLint max_vertex_image_uniforms					= 0;
11571 
11572 		/* Get limit values */
11573 		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11574 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11575 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11576 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11577 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11578 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11579 		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11580 
11581 		if (max_vertex_image_uniforms)
11582 			vertex_shader_code.insert(18, "#define IMAGES\n");
11583 		if (max_geometry_image_uniforms)
11584 			geometry_shader_code.insert(18, "#define IMAGES\n");
11585 		if (max_tesselation_control_image_uniforms)
11586 			tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11587 		if (max_tesselation_evaluation_image_uniforms)
11588 			tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11589 
11590 		/* Check if program builds */
11591 		m_result_for_combined =
11592 			!doesProgramLink(fragment_shader_code.c_str(),
11593 							 geometry_shader_code.c_str(),
11594 							 tesselation_control_shader_code.c_str(),
11595 							 tesselation_evaluation_shader_code.c_str(),
11596 							 vertex_shader_code.c_str());
11597 
11598 		/* Result depends on the limit values */
11599 		if (max_combined_image_uniforms >=
11600 			(max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11601 			 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11602 		{
11603 			/* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11604 			m_result_for_combined = !m_result_for_combined;
11605 
11606 			if (false == m_result_for_combined)
11607 			{
11608 				m_context.getTestContext().getLog()
11609 					<< tcu::TestLog::Message << "There was an error while building a program."
11610 					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11611 					<< vertex_shader_code << "\nTesselation control shader code:\n"
11612 					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11613 					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11614 					<< geometry_shader_code << "\nFragment shader code:\n"
11615 					<< fragment_shader_code << tcu::TestLog::EndMessage;
11616 			}
11617 		}
11618 		else
11619 		{
11620 			/* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11621 			if (false == m_result_for_combined)
11622 			{
11623 				m_context.getTestContext().getLog()
11624 					<< tcu::TestLog::Message
11625 					<< "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11626 					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11627 					<< vertex_shader_code << "\nTesselation control shader code:\n"
11628 					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11629 					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11630 					<< geometry_shader_code << "\nFragment shader code:\n"
11631 					<< fragment_shader_code << tcu::TestLog::EndMessage;
11632 			}
11633 		}
11634 	}
11635 
11636 	/** Check if program builds successfully
11637 	 *
11638 	 * @param fragment_shader_code               Source code for fragment shader stage
11639 	 * @param geometry_shader_code               Source code for geometry shader stage
11640 	 * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11641 	 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11642 	 * @param vertex_shader_code                 Source code for vertex shader stage
11643 	 *
11644 	 * @return true if program was built without errors, false otherwise
11645 	 **/
doesProgramLink(const char * fragment_shader_code,const char * geometry_shader_code,const char * tesselation_control_shader_code,const char * tesselation_evaluation_shader_code,const char * vertex_shader_code)11646 	bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11647 						 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11648 						 const char* vertex_shader_code)
11649 	{
11650 		bool   is_program_built = true;
11651 		GLuint program_id		= 0;
11652 
11653 		program_id =
11654 			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11655 						 geometry_shader_code, fragment_shader_code, &is_program_built);
11656 
11657 		if (0 != program_id)
11658 		{
11659 			glDeleteProgram(program_id);
11660 		}
11661 
11662 		return is_program_built;
11663 	}
11664 };
11665 }
11666 
ShaderImageLoadStoreTests(deqp::Context & context)11667 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11668 	: TestCaseGroup(context, "shader_image_load_store", "")
11669 {
11670 }
11671 
~ShaderImageLoadStoreTests(void)11672 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11673 {
11674 }
11675 
init()11676 void ShaderImageLoadStoreTests::init()
11677 {
11678 	using namespace deqp;
11679 	addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11680 	addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11681 	addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11682 	addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11683 	addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11684 	addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11685 	addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11686 							 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11687 	addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11688 							 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11689 	addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11690 							 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11691 	addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11692 	addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11693 	addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11694 	addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11695 	addChild(
11696 		new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11697 	addChild(
11698 		new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11699 	addChild(
11700 		new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11701 	addChild(
11702 		new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11703 	addChild(
11704 		new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11705 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11706 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11707 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11708 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11709 	addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11710 	addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11711 	addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11712 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11713 	addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11714 	addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11715 	addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11716 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11717 	addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11718 	addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11719 	addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11720 							 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11721 	addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11722 	addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11723 	addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11724 	addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11725 	addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11726 	addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11727 	addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11728 	addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11729 	addChild(
11730 		new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11731 	addChild(
11732 		new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11733 	addChild(
11734 		new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11735 	addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11736 	addChild(
11737 		new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11738 	addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11739 	addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11740 	addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11741 	addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11742 	addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11743 }
11744 }
11745