• 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 <assert.h>
32 #include <climits>
33 #include <cmath>
34 #include <cstdarg>
35 #include <deque>
36 #include <iomanip>
37 #include <map>
38 #include <sstream>
39 #include <tcuFloat.hpp>
40 
41 namespace gl4cts
42 {
43 using namespace glw;
44 
45 namespace
46 {
47 typedef tcu::Vec2  vec2;
48 typedef tcu::Vec4  vec4;
49 typedef tcu::IVec4 ivec4;
50 typedef tcu::UVec4 uvec4;
51 typedef tcu::Mat4  mat4;
52 
53 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
54 {
Title()55 	virtual std::string Title()
56 	{
57 		return "";
58 	}
59 
Purpose()60 	virtual std::string Purpose()
61 	{
62 		return "";
63 	}
64 
Method()65 	virtual std::string Method()
66 	{
67 		return "";
68 	}
69 
PassCriteria()70 	virtual std::string PassCriteria()
71 	{
72 		return "";
73 	}
74 
75 public:
SupportedInVS(int requiredVS)76 	bool SupportedInVS(int requiredVS)
77 	{
78 		GLint imagesVS;
79 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
80 		if (imagesVS >= requiredVS)
81 			return true;
82 		else
83 		{
84 			std::ostringstream reason;
85 			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
86 				   << std::endl;
87 			OutputNotSupported(reason.str());
88 			return false;
89 		}
90 	}
91 
SupportedInTCS(int requiredTCS)92 	bool SupportedInTCS(int requiredTCS)
93 	{
94 		GLint imagesTCS;
95 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
96 		if (imagesTCS >= requiredTCS)
97 			return true;
98 		else
99 		{
100 			std::ostringstream reason;
101 			reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
102 				   << std::endl;
103 			OutputNotSupported(reason.str());
104 			return false;
105 		}
106 	}
107 
SupportedInTES(int requiredTES)108 	bool SupportedInTES(int requiredTES)
109 	{
110 		GLint imagesTES;
111 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
112 		if (imagesTES >= requiredTES)
113 			return true;
114 		else
115 		{
116 			std::ostringstream reason;
117 			reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
118 				   << std::endl;
119 			OutputNotSupported(reason.str());
120 			return false;
121 		}
122 	}
123 
SupportedInGS(int requiredGS)124 	bool SupportedInGS(int requiredGS)
125 	{
126 		GLint imagesGS;
127 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
128 		if (imagesGS >= requiredGS)
129 			return true;
130 		else
131 		{
132 			std::ostringstream reason;
133 			reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
134 				   << std::endl;
135 			OutputNotSupported(reason.str());
136 			return false;
137 		}
138 	}
139 
SupportedInGeomStages(int required)140 	bool SupportedInGeomStages(int required)
141 	{
142 		return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
143 			   SupportedInGS(required);
144 	}
145 
SupportedInStage(int stage,int required)146 	bool SupportedInStage(int stage, int required)
147 	{
148 		switch (stage)
149 		{
150 		case 0:
151 			return SupportedInVS(required);
152 		case 1:
153 			return SupportedInTCS(required);
154 		case 2:
155 			return SupportedInTES(required);
156 		case 3:
157 			return SupportedInGS(required);
158 		default:
159 			return true;
160 		}
161 	}
162 
SupportedSamples(int required)163 	bool SupportedSamples(int required)
164 	{
165 		int i;
166 		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
167 		if (i >= required)
168 			return true;
169 		else
170 		{
171 			std::ostringstream reason;
172 			reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
173 			OutputNotSupported(reason.str());
174 			return false;
175 		}
176 	}
177 
getWindowWidth()178 	int getWindowWidth()
179 	{
180 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
181 		return renderTarget.getWidth();
182 	}
183 
getWindowHeight()184 	int getWindowHeight()
185 	{
186 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
187 		return renderTarget.getHeight();
188 	}
189 
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)190 	void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
191 	{
192 		tcu::PlatformMemoryLimits memoryLimits;
193 		m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
194 		GLsizeiptr sysSpace		  = memoryLimits.totalSystemMemory;
195 		GLsizeiptr devSpace		  = memoryLimits.totalDeviceLocalMemory;
196 		int		   devInSysLayers = 0;
197 
198 		if (devSpace == 0)
199 		{
200 			devInSysLayers = devLayers;
201 			devLayers	  = 0;
202 		}
203 
204 		// Check if available memory is enough
205 		GLsizeiptr pixelsPerLayer = width * height;
206 		GLsizeiptr sysRequired	= pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
207 		GLsizeiptr devRequired	= pixelsPerLayer * devBPP * devLayers;
208 		if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
209 		{
210 			return;
211 		}
212 
213 		// Scales the width and height such that the overall texture fits into
214 		// the available space for both system and device.
215 		GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
216 		if (devSpace != 0)
217 		{
218 			GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
219 			scale			  = de::min(devScale, scale);
220 		}
221 		int newWidth  = int(width * scale);
222 		int newHeight = int(height * scale);
223 
224 		m_context.getTestContext().getLog()
225 			<< tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
226 			<< " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
227 
228 		width  = newWidth;
229 		height = newHeight;
230 	}
231 
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)232 	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
233 	{
234 		if (fabs(c0[0] - c1[0]) > epsilon[0])
235 			return false;
236 		if (fabs(c0[1] - c1[1]) > epsilon[1])
237 			return false;
238 		if (fabs(c0[2] - c1[2]) > epsilon[2])
239 			return false;
240 		if (fabs(c0[3] - c1[3]) > epsilon[3])
241 			return false;
242 		return true;
243 	}
244 
IsEqual(vec4 a,vec4 b)245 	bool IsEqual(vec4 a, vec4 b)
246 	{
247 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
248 	}
249 
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)250 	bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
251 	{
252 		if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
253 		{
254 			return ColorEqual(v0, v1, vec4(0.0001f));
255 		}
256 		else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
257 		{
258 			return ColorEqual(v0, v1, vec4(0.01f));
259 		}
260 		return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
261 	}
262 
Equal(const ivec4 & a,const ivec4 & b,GLenum)263 	bool Equal(const ivec4& a, const ivec4& b, GLenum)
264 	{
265 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
266 	}
267 
Equal(const uvec4 & a,const uvec4 & b,GLenum)268 	bool Equal(const uvec4& a, const uvec4& b, GLenum)
269 	{
270 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
271 	}
272 
273 	template <class T>
ToString(T v)274 	std::string ToString(T v)
275 	{
276 		std::ostringstream s;
277 		s << "[";
278 		for (int i = 0; i < 4; ++i)
279 			s << v[i] << (i == 3 ? "" : ",");
280 		s << "]";
281 		return s.str();
282 	}
283 
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)284 	bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
285 	{
286 		bool					 status		  = true;
287 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
288 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
289 		vec4					 g_color_eps  = vec4(
290 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
291 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
292 
293 		std::vector<vec4> fb(w * h);
294 		glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
295 
296 		for (int yy = 0; yy < h; ++yy)
297 		{
298 			for (int xx = 0; xx < w; ++xx)
299 			{
300 				const int idx = yy * w + xx;
301 				if (!ColorEqual(fb[idx], expected, g_color_eps))
302 				{
303 					m_context.getTestContext().getLog()
304 						<< tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
305 						<< tcu::TestLog::EndMessage;
306 					status = false;
307 					return status;
308 				}
309 			}
310 		}
311 		return status;
312 	}
313 
CompileShader(GLuint shader)314 	bool CompileShader(GLuint shader)
315 	{
316 		glCompileShader(shader);
317 
318 		GLint status;
319 		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
320 		if (status == GL_FALSE)
321 		{
322 			GLsizei length;
323 			GLchar  log[1024];
324 			glGetShaderInfoLog(shader, sizeof(log), &length, log);
325 			if (length > 1)
326 			{
327 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
328 													<< log << tcu::TestLog::EndMessage;
329 			}
330 			return false;
331 		}
332 		return true;
333 	}
334 
LinkProgram(GLuint program)335 	bool LinkProgram(GLuint program)
336 	{
337 		glLinkProgram(program);
338 
339 		GLint status;
340 		glGetProgramiv(program, GL_LINK_STATUS, &status);
341 		if (status == GL_FALSE)
342 		{
343 			GLsizei length;
344 			GLchar  log[1024];
345 			glGetProgramInfoLog(program, sizeof(log), &length, log);
346 			if (length > 1)
347 			{
348 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
349 													<< log << tcu::TestLog::EndMessage;
350 			}
351 			return false;
352 		}
353 		return true;
354 	}
355 
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)356 	GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
357 						const char* src_fs, bool* result = NULL)
358 	{
359 		const GLuint p = glCreateProgram();
360 
361 		if (src_vs)
362 		{
363 			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
364 			glAttachShader(p, sh);
365 			glDeleteShader(sh);
366 			glShaderSource(sh, 1, &src_vs, NULL);
367 			if (!CompileShader(sh))
368 			{
369 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
370 				if (result)
371 					*result = false;
372 				return p;
373 			}
374 		}
375 		if (src_tcs)
376 		{
377 			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
378 			glAttachShader(p, sh);
379 			glDeleteShader(sh);
380 			glShaderSource(sh, 1, &src_tcs, NULL);
381 			if (!CompileShader(sh))
382 			{
383 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
384 				if (result)
385 					*result = false;
386 				return p;
387 			}
388 		}
389 		if (src_tes)
390 		{
391 			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
392 			glAttachShader(p, sh);
393 			glDeleteShader(sh);
394 			glShaderSource(sh, 1, &src_tes, NULL);
395 			if (!CompileShader(sh))
396 			{
397 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
398 				if (result)
399 					*result = false;
400 				return p;
401 			}
402 		}
403 		if (src_gs)
404 		{
405 			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
406 			glAttachShader(p, sh);
407 			glDeleteShader(sh);
408 			glShaderSource(sh, 1, &src_gs, NULL);
409 			if (!CompileShader(sh))
410 			{
411 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
412 				if (result)
413 					*result = false;
414 				return p;
415 			}
416 		}
417 		if (src_fs)
418 		{
419 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
420 			glAttachShader(p, sh);
421 			glDeleteShader(sh);
422 			glShaderSource(sh, 1, &src_fs, NULL);
423 			if (!CompileShader(sh))
424 			{
425 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
426 				if (result)
427 					*result = false;
428 				return p;
429 			}
430 		}
431 		if (!LinkProgram(p))
432 		{
433 			if (src_vs)
434 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
435 			if (src_tcs)
436 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
437 			if (src_tes)
438 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
439 			if (src_gs)
440 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
441 			if (src_fs)
442 				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
443 			if (result)
444 				*result = false;
445 			return p;
446 		}
447 
448 		return p;
449 	}
450 
BuildShaderProgram(GLenum type,const char * src)451 	GLuint BuildShaderProgram(GLenum type, const char* src)
452 	{
453 		const GLuint p = glCreateShaderProgramv(type, 1, &src);
454 
455 		GLint status;
456 		glGetProgramiv(p, GL_LINK_STATUS, &status);
457 		if (status == GL_FALSE)
458 		{
459 			GLchar log[1024];
460 			glGetProgramInfoLog(p, sizeof(log), NULL, log);
461 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
462 												<< log << "\n"
463 												<< src << tcu::TestLog::EndMessage;
464 		}
465 
466 		return p;
467 	}
468 
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)469 	void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
470 	{
471 		assert(vao && vbo);
472 
473 		// interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
474 		const float v[] = {
475 			-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,
476 			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,
477 			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,
478 		};
479 		glGenBuffers(1, vbo);
480 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
481 		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
482 		glBindBuffer(GL_ARRAY_BUFFER, 0);
483 
484 		if (ebo)
485 		{
486 			std::vector<GLushort> index_data(4);
487 			for (int i = 0; i < 4; ++i)
488 			{
489 				index_data[i] = static_cast<GLushort>(i);
490 			}
491 			glGenBuffers(1, ebo);
492 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
493 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
494 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
495 		}
496 
497 		glGenVertexArrays(1, vao);
498 		glBindVertexArray(*vao);
499 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
500 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
501 		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
502 		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
503 		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
504 		glBindBuffer(GL_ARRAY_BUFFER, 0);
505 		glEnableVertexAttribArray(0);
506 		glEnableVertexAttribArray(1);
507 		glEnableVertexAttribArray(2);
508 		glEnableVertexAttribArray(3);
509 		if (ebo)
510 		{
511 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
512 		}
513 		glBindVertexArray(0);
514 	}
515 
FormatEnumToString(GLenum e)516 	std::string FormatEnumToString(GLenum e)
517 	{
518 		switch (e)
519 		{
520 		case GL_RGBA32F:
521 			return "rgba32f";
522 		case GL_RGBA16F:
523 			return "rgba16f";
524 		case GL_RG32F:
525 			return "rg32f";
526 		case GL_RG16F:
527 			return "rg16f";
528 		case GL_R11F_G11F_B10F:
529 			return "r11f_g11f_b10f";
530 		case GL_R32F:
531 			return "r32f";
532 		case GL_R16F:
533 			return "r16f";
534 
535 		case GL_RGBA32UI:
536 			return "rgba32ui";
537 		case GL_RGBA16UI:
538 			return "rgba16ui";
539 		case GL_RGB10_A2UI:
540 			return "rgb10_a2ui";
541 		case GL_RGBA8UI:
542 			return "rgba8ui";
543 		case GL_RG32UI:
544 			return "rg32ui";
545 		case GL_RG16UI:
546 			return "rg16ui";
547 		case GL_RG8UI:
548 			return "rg8ui";
549 		case GL_R32UI:
550 			return "r32ui";
551 		case GL_R16UI:
552 			return "r16ui";
553 		case GL_R8UI:
554 			return "r8ui";
555 
556 		case GL_RGBA32I:
557 			return "rgba32i";
558 		case GL_RGBA16I:
559 			return "rgba16i";
560 		case GL_RGBA8I:
561 			return "rgba8i";
562 		case GL_RG32I:
563 			return "rg32i";
564 		case GL_RG16I:
565 			return "rg16i";
566 		case GL_RG8I:
567 			return "rg8i";
568 		case GL_R32I:
569 			return "r32i";
570 		case GL_R16I:
571 			return "r16i";
572 		case GL_R8I:
573 			return "r8i";
574 
575 		case GL_RGBA16:
576 			return "rgba16";
577 		case GL_RGB10_A2:
578 			return "rgb10_a2";
579 		case GL_RGBA8:
580 			return "rgba8";
581 		case GL_RG16:
582 			return "rg16";
583 		case GL_RG8:
584 			return "rg8";
585 		case GL_R16:
586 			return "r16";
587 		case GL_R8:
588 			return "r8";
589 
590 		case GL_RGBA16_SNORM:
591 			return "rgba16_snorm";
592 		case GL_RGBA8_SNORM:
593 			return "rgba8_snorm";
594 		case GL_RG16_SNORM:
595 			return "rg16_snorm";
596 		case GL_RG8_SNORM:
597 			return "rg8_snorm";
598 		case GL_R16_SNORM:
599 			return "r16_snorm";
600 		case GL_R8_SNORM:
601 			return "r8_snorm";
602 		}
603 
604 		assert(0);
605 		return "";
606 	}
607 
StageName(int stage)608 	const char* StageName(int stage)
609 	{
610 		switch (stage)
611 		{
612 		case 0:
613 			return "Vertex Shader";
614 		case 1:
615 			return "Tessellation Control Shader";
616 		case 2:
617 			return "Tessellation Evaluation Shader";
618 		case 3:
619 			return "Geometry Shader";
620 		case 4:
621 			return "Compute Shader";
622 		}
623 		assert(0);
624 		return NULL;
625 	}
626 
627 	template <typename T>
628 	GLenum Format();
629 
630 	template <typename T>
631 	GLenum Type();
632 
633 	template <typename T>
634 	std::string TypePrefix();
635 
636 	template <typename T>
637 	GLenum ImageType(GLenum target);
638 
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)639 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
640 	{
641 		glClearBufferfv(buffer, drawbuffer, &color[0]);
642 	}
643 
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)644 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
645 	{
646 		glClearBufferiv(buffer, drawbuffer, &color[0]);
647 	}
648 
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)649 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
650 	{
651 		glClearBufferuiv(buffer, drawbuffer, &color[0]);
652 	}
653 
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)654 	bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
655 					  GLint size, GLenum type)
656 	{
657 		std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
658 		assert(iter != name_index_map.end());
659 
660 		GLchar  name_gl[32];
661 		GLsizei length_gl;
662 		GLint   size_gl;
663 		GLenum  type_gl;
664 
665 		glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
666 
667 		if (std::string(name_gl) != name)
668 		{
669 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
670 												<< " should be " << name << tcu::TestLog::EndMessage;
671 			return false;
672 		}
673 		if (length_gl != static_cast<GLsizei>(name.length()))
674 		{
675 			m_context.getTestContext().getLog()
676 				<< tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
677 				<< ")" << tcu::TestLog::EndMessage;
678 			return false;
679 		}
680 		if (size_gl != size)
681 		{
682 			m_context.getTestContext().getLog()
683 				<< tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
684 				<< ")" << tcu::TestLog::EndMessage;
685 			return false;
686 		}
687 		if (type_gl != type)
688 		{
689 			m_context.getTestContext().getLog()
690 				<< tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
691 				<< ")" << tcu::TestLog::EndMessage;
692 			return false;
693 		}
694 
695 		return true;
696 	}
697 
CheckMax(GLenum pname,GLint min_value)698 	bool CheckMax(GLenum pname, GLint min_value)
699 	{
700 		GLboolean b;
701 		GLint	 i;
702 		GLfloat   f;
703 		GLdouble  d;
704 		GLint64   i64;
705 
706 		glGetIntegerv(pname, &i);
707 		if (i < min_value)
708 			return false;
709 
710 		glGetBooleanv(pname, &b);
711 		if (b != (i ? GL_TRUE : GL_FALSE))
712 			return false;
713 
714 		glGetFloatv(pname, &f);
715 		if (static_cast<GLint>(f) < min_value)
716 			return false;
717 
718 		glGetDoublev(pname, &d);
719 		if (static_cast<GLint>(d) < min_value)
720 			return false;
721 
722 		glGetInteger64v(pname, &i64);
723 		if (static_cast<GLint>(i64) < min_value)
724 			return false;
725 
726 		return true;
727 	}
728 
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)729 	bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
730 					  GLenum format)
731 	{
732 		GLint	 i;
733 		GLboolean b;
734 
735 		glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
736 		if (static_cast<GLuint>(i) != texture)
737 		{
738 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
739 												<< " should be " << texture << tcu::TestLog::EndMessage;
740 			return false;
741 		}
742 		glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
743 		if (b != (i ? GL_TRUE : GL_FALSE))
744 		{
745 			m_context.getTestContext().getLog()
746 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
747 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
748 			return false;
749 		}
750 
751 		glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
752 		if (i != level)
753 		{
754 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
755 												<< " should be " << level << tcu::TestLog::EndMessage;
756 			return false;
757 		}
758 		glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
759 		if (b != (i ? GL_TRUE : GL_FALSE))
760 		{
761 			m_context.getTestContext().getLog()
762 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
763 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
764 			return false;
765 		}
766 
767 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
768 		if (i != layered)
769 		{
770 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
771 												<< " should be " << layered << tcu::TestLog::EndMessage;
772 			return false;
773 		}
774 		glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
775 		if (b != (i ? GL_TRUE : GL_FALSE))
776 		{
777 			m_context.getTestContext().getLog()
778 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
779 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
780 			return false;
781 		}
782 
783 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
784 		if (i != layer)
785 		{
786 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
787 												<< " should be " << layer << tcu::TestLog::EndMessage;
788 			return false;
789 		}
790 		glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
791 		if (b != (i ? GL_TRUE : GL_FALSE))
792 		{
793 			m_context.getTestContext().getLog()
794 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
795 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
796 			return false;
797 		}
798 
799 		glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
800 		if (static_cast<GLenum>(i) != access)
801 		{
802 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
803 												<< " should be " << access << tcu::TestLog::EndMessage;
804 			return false;
805 		}
806 		glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
807 		if (b != (i ? GL_TRUE : GL_FALSE))
808 		{
809 			m_context.getTestContext().getLog()
810 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
811 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
812 			return false;
813 		}
814 
815 		glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
816 		if (static_cast<GLenum>(i) != format)
817 		{
818 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
819 												<< " should be " << format << tcu::TestLog::EndMessage;
820 			return false;
821 		}
822 		glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
823 		if (b != (i ? GL_TRUE : GL_FALSE))
824 		{
825 			m_context.getTestContext().getLog()
826 				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
827 				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
828 			return false;
829 		}
830 
831 		return true;
832 	}
EnumToString(GLenum e)833 	const char* EnumToString(GLenum e)
834 	{
835 		switch (e)
836 		{
837 		case GL_TEXTURE_1D:
838 			return "GL_TEXTURE_1D";
839 		case GL_TEXTURE_2D:
840 			return "GL_TEXTURE_2D";
841 		case GL_TEXTURE_3D:
842 			return "GL_TEXTURE_3D";
843 		case GL_TEXTURE_RECTANGLE:
844 			return "GL_TEXTURE_RECTANGLE";
845 		case GL_TEXTURE_CUBE_MAP:
846 			return "GL_TEXTURE_CUBE_MAP";
847 		case GL_TEXTURE_1D_ARRAY:
848 			return "GL_TEXTURE_1D_ARRAY";
849 		case GL_TEXTURE_2D_ARRAY:
850 			return "GL_TEXTURE_2D_ARRAY";
851 		case GL_TEXTURE_CUBE_MAP_ARRAY:
852 			return "GL_TEXTURE_CUBE_MAP_ARRAY";
853 
854 		default:
855 			assert(0);
856 			break;
857 		}
858 		return NULL;
859 	}
860 };
861 
862 template <>
Format()863 GLenum ShaderImageLoadStoreBase::Format<vec4>()
864 {
865 	return GL_RGBA;
866 }
867 
868 template <>
Format()869 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
870 {
871 	return GL_RGBA_INTEGER;
872 }
873 
874 template <>
Format()875 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
876 {
877 	return GL_RGBA_INTEGER;
878 }
879 
880 template <>
Format()881 GLenum ShaderImageLoadStoreBase::Format<GLint>()
882 {
883 	return GL_RED_INTEGER;
884 }
885 
886 template <>
Format()887 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
888 {
889 	return GL_RED_INTEGER;
890 }
891 
892 template <>
Type()893 GLenum ShaderImageLoadStoreBase::Type<vec4>()
894 {
895 	return GL_FLOAT;
896 }
897 
898 template <>
Type()899 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
900 {
901 	return GL_INT;
902 }
903 
904 template <>
Type()905 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
906 {
907 	return GL_UNSIGNED_INT;
908 }
909 
910 template <>
Type()911 GLenum ShaderImageLoadStoreBase::Type<GLint>()
912 {
913 	return GL_INT;
914 }
915 
916 template <>
Type()917 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
918 {
919 	return GL_UNSIGNED_INT;
920 }
921 
922 template <>
TypePrefix()923 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
924 {
925 	return "";
926 }
927 
928 template <>
TypePrefix()929 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
930 {
931 	return "i";
932 }
933 
934 template <>
TypePrefix()935 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
936 {
937 	return "u";
938 }
939 
940 template <>
TypePrefix()941 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
942 {
943 	return "i";
944 }
945 
946 template <>
TypePrefix()947 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
948 {
949 	return "u";
950 }
951 
952 template <>
ImageType(GLenum target)953 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
954 {
955 	switch (target)
956 	{
957 	case GL_TEXTURE_1D:
958 		return GL_IMAGE_1D;
959 	case GL_TEXTURE_2D:
960 		return GL_IMAGE_2D;
961 	case GL_TEXTURE_3D:
962 		return GL_IMAGE_3D;
963 	case GL_TEXTURE_RECTANGLE:
964 		return GL_IMAGE_2D_RECT;
965 	case GL_TEXTURE_CUBE_MAP:
966 		return GL_IMAGE_CUBE;
967 	case GL_TEXTURE_BUFFER:
968 		return GL_IMAGE_BUFFER;
969 	case GL_TEXTURE_1D_ARRAY:
970 		return GL_IMAGE_1D_ARRAY;
971 	case GL_TEXTURE_2D_ARRAY:
972 		return GL_IMAGE_2D_ARRAY;
973 	case GL_TEXTURE_CUBE_MAP_ARRAY:
974 		return GL_IMAGE_CUBE_MAP_ARRAY;
975 	case GL_TEXTURE_2D_MULTISAMPLE:
976 		return GL_IMAGE_2D_MULTISAMPLE;
977 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
978 		return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
979 	}
980 	assert(0);
981 	return 0;
982 }
983 
984 template <>
ImageType(GLenum target)985 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
986 {
987 	switch (target)
988 	{
989 	case GL_TEXTURE_1D:
990 		return GL_INT_IMAGE_1D;
991 	case GL_TEXTURE_2D:
992 		return GL_INT_IMAGE_2D;
993 	case GL_TEXTURE_3D:
994 		return GL_INT_IMAGE_3D;
995 	case GL_TEXTURE_RECTANGLE:
996 		return GL_INT_IMAGE_2D_RECT;
997 	case GL_TEXTURE_CUBE_MAP:
998 		return GL_INT_IMAGE_CUBE;
999 	case GL_TEXTURE_BUFFER:
1000 		return GL_INT_IMAGE_BUFFER;
1001 	case GL_TEXTURE_1D_ARRAY:
1002 		return GL_INT_IMAGE_1D_ARRAY;
1003 	case GL_TEXTURE_2D_ARRAY:
1004 		return GL_INT_IMAGE_2D_ARRAY;
1005 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1006 		return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1007 	case GL_TEXTURE_2D_MULTISAMPLE:
1008 		return GL_INT_IMAGE_2D_MULTISAMPLE;
1009 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1010 		return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1011 	}
1012 	assert(0);
1013 	return 0;
1014 }
1015 
1016 template <>
ImageType(GLenum target)1017 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1018 {
1019 	switch (target)
1020 	{
1021 	case GL_TEXTURE_1D:
1022 		return GL_UNSIGNED_INT_IMAGE_1D;
1023 	case GL_TEXTURE_2D:
1024 		return GL_UNSIGNED_INT_IMAGE_2D;
1025 	case GL_TEXTURE_3D:
1026 		return GL_UNSIGNED_INT_IMAGE_3D;
1027 	case GL_TEXTURE_RECTANGLE:
1028 		return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1029 	case GL_TEXTURE_CUBE_MAP:
1030 		return GL_UNSIGNED_INT_IMAGE_CUBE;
1031 	case GL_TEXTURE_BUFFER:
1032 		return GL_UNSIGNED_INT_IMAGE_BUFFER;
1033 	case GL_TEXTURE_1D_ARRAY:
1034 		return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1035 	case GL_TEXTURE_2D_ARRAY:
1036 		return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1037 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1038 		return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1039 	case GL_TEXTURE_2D_MULTISAMPLE:
1040 		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1041 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1042 		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1043 	}
1044 	assert(0);
1045 	return 0;
1046 }
1047 
1048 //-----------------------------------------------------------------------------
1049 // 1.1.1 BasicAPIGet
1050 //-----------------------------------------------------------------------------
1051 class BasicAPIGet : public ShaderImageLoadStoreBase
1052 {
Run()1053 	virtual long Run()
1054 	{
1055 		if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1056 		{
1057 			m_context.getTestContext().getLog()
1058 				<< tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1059 			return ERROR;
1060 		}
1061 		if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1062 		{
1063 			m_context.getTestContext().getLog()
1064 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1065 				<< tcu::TestLog::EndMessage;
1066 			return ERROR;
1067 		}
1068 		if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1069 		{
1070 			m_context.getTestContext().getLog()
1071 				<< tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1072 			return ERROR;
1073 		}
1074 		if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1075 		{
1076 			m_context.getTestContext().getLog()
1077 				<< tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1078 				<< tcu::TestLog::EndMessage;
1079 			return ERROR;
1080 		}
1081 		if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1082 		{
1083 			m_context.getTestContext().getLog()
1084 				<< tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1085 				<< tcu::TestLog::EndMessage;
1086 			return ERROR;
1087 		}
1088 		if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1089 		{
1090 			m_context.getTestContext().getLog()
1091 				<< tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1092 				<< tcu::TestLog::EndMessage;
1093 			return ERROR;
1094 		}
1095 		if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1096 		{
1097 			m_context.getTestContext().getLog()
1098 				<< tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1099 				<< tcu::TestLog::EndMessage;
1100 			return ERROR;
1101 		}
1102 		if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1103 		{
1104 			m_context.getTestContext().getLog()
1105 				<< tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1106 				<< tcu::TestLog::EndMessage;
1107 			return ERROR;
1108 		}
1109 		if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1110 		{
1111 			m_context.getTestContext().getLog()
1112 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1113 				<< tcu::TestLog::EndMessage;
1114 			return ERROR;
1115 		}
1116 		return NO_ERROR;
1117 	}
1118 };
1119 //-----------------------------------------------------------------------------
1120 // 1.1.2 BasicAPIBind
1121 //-----------------------------------------------------------------------------
1122 class BasicAPIBind : public ShaderImageLoadStoreBase
1123 {
1124 	GLuint m_texture;
1125 
Setup()1126 	virtual long Setup()
1127 	{
1128 		m_texture = 0;
1129 		return NO_ERROR;
1130 	}
1131 
Run()1132 	virtual long Run()
1133 	{
1134 		for (GLuint index = 0; index < 8; ++index)
1135 		{
1136 			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1137 			{
1138 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1139 													<< " has invalid default state." << tcu::TestLog::EndMessage;
1140 				return ERROR;
1141 			}
1142 		}
1143 
1144 		glGenTextures(1, &m_texture);
1145 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1146 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1147 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1148 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1149 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1152 
1153 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1154 		if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1155 			return ERROR;
1156 
1157 		glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1158 		if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1159 			return ERROR;
1160 
1161 		glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1162 		if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1163 			return ERROR;
1164 
1165 		glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1166 		if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1167 			return ERROR;
1168 
1169 		glDeleteTextures(1, &m_texture);
1170 		m_texture = 0;
1171 
1172 		for (GLuint index = 0; index < 8; ++index)
1173 		{
1174 			GLint name;
1175 			glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1176 			if (name != 0)
1177 			{
1178 				m_context.getTestContext().getLog()
1179 					<< tcu::TestLog::Message << "Binding point " << index
1180 					<< " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1181 				return ERROR;
1182 			}
1183 		}
1184 
1185 		return NO_ERROR;
1186 	}
1187 
Cleanup()1188 	virtual long Cleanup()
1189 	{
1190 		glDeleteTextures(1, &m_texture);
1191 		return NO_ERROR;
1192 	}
1193 };
1194 //-----------------------------------------------------------------------------
1195 // 1.1.3 BasicAPIBarrier
1196 //-----------------------------------------------------------------------------
1197 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1198 {
Run()1199 	virtual long Run()
1200 	{
1201 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1202 		glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1203 		glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1204 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1205 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1206 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1207 		glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1208 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1209 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1210 		glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1211 		glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1212 		glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1213 
1214 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1215 						GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1216 						GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1217 						GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1218 
1219 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
1220 
1221 		return NO_ERROR;
1222 	}
1223 };
1224 //-----------------------------------------------------------------------------
1225 // 1.1.4 BasicAPITexParam
1226 //-----------------------------------------------------------------------------
1227 class BasicAPITexParam : public ShaderImageLoadStoreBase
1228 {
1229 	GLuint m_texture;
1230 
Setup()1231 	virtual long Setup()
1232 	{
1233 		m_texture = 0;
1234 		return NO_ERROR;
1235 	}
1236 
Run()1237 	virtual long Run()
1238 	{
1239 		glGenTextures(1, &m_texture);
1240 		glBindTexture(GL_TEXTURE_2D, m_texture);
1241 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1242 
1243 		GLint   i;
1244 		GLfloat f;
1245 		GLuint  ui;
1246 
1247 		glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1248 		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1249 		{
1250 			m_context.getTestContext().getLog()
1251 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1252 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1253 				<< tcu::TestLog::EndMessage;
1254 			return ERROR;
1255 		}
1256 		glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1257 		if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1258 		{
1259 			m_context.getTestContext().getLog()
1260 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1261 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1262 				<< tcu::TestLog::EndMessage;
1263 			return ERROR;
1264 		}
1265 		glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1266 		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1267 		{
1268 			m_context.getTestContext().getLog()
1269 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1270 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1271 				<< tcu::TestLog::EndMessage;
1272 			return ERROR;
1273 		}
1274 		glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1275 		if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1276 		{
1277 			m_context.getTestContext().getLog()
1278 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1279 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1280 				<< tcu::TestLog::EndMessage;
1281 			return ERROR;
1282 		}
1283 
1284 		return NO_ERROR;
1285 	}
1286 
Cleanup()1287 	virtual long Cleanup()
1288 	{
1289 		glDeleteTextures(1, &m_texture);
1290 		return NO_ERROR;
1291 	}
1292 };
1293 //-----------------------------------------------------------------------------
1294 // 1.2.1 BasicAllFormatsStore
1295 //-----------------------------------------------------------------------------
1296 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1297 {
1298 	GLuint m_vao;
1299 	GLuint m_vbo;
1300 
Setup()1301 	virtual long Setup()
1302 	{
1303 		m_vao = 0;
1304 		m_vbo = 0;
1305 		return NO_ERROR;
1306 	}
1307 
Run()1308 	virtual long Run()
1309 	{
1310 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1311 
1312 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1313 			return ERROR;
1314 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1315 			return ERROR;
1316 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1317 			return ERROR;
1318 
1319 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1320 			return ERROR;
1321 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1322 			return ERROR;
1323 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1324 			return ERROR;
1325 
1326 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1327 			return ERROR;
1328 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1329 			return ERROR;
1330 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1331 			return ERROR;
1332 
1333 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1334 			return ERROR;
1335 
1336 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1337 			return ERROR;
1338 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1339 			return ERROR;
1340 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1341 			return ERROR;
1342 
1343 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1344 			return ERROR;
1345 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1346 			return ERROR;
1347 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1348 			return ERROR;
1349 
1350 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1351 			return ERROR;
1352 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1353 			return ERROR;
1354 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1355 			return ERROR;
1356 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1357 			return ERROR;
1358 
1359 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1360 			return ERROR;
1361 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1362 			return ERROR;
1363 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1364 			return ERROR;
1365 
1366 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1367 			return ERROR;
1368 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1369 			return ERROR;
1370 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1371 			return ERROR;
1372 
1373 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1374 			return ERROR;
1375 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1376 			return ERROR;
1377 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1378 			return ERROR;
1379 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1380 			return ERROR;
1381 
1382 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1383 			return ERROR;
1384 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1385 			return ERROR;
1386 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1387 			return ERROR;
1388 
1389 		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1390 			return ERROR;
1391 		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1392 			return ERROR;
1393 		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1394 			return ERROR;
1395 
1396 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1397 			return ERROR;
1398 		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1399 			return ERROR;
1400 		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1401 			return ERROR;
1402 
1403 		return NO_ERROR;
1404 	}
1405 
1406 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1407 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1408 	{
1409 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1410 							 "  gl_Position = i_position;" NL "}";
1411 		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1412 		const int	  kSize   = 16;
1413 		std::vector<T> data(kSize * kSize);
1414 		GLuint		   texture;
1415 		glGenTextures(1, &texture);
1416 
1417 		for (GLuint unit = 0; unit < 8; ++unit)
1418 		{
1419 			glBindTexture(GL_TEXTURE_2D, texture);
1420 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1421 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1422 			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1423 			glBindTexture(GL_TEXTURE_2D, 0);
1424 
1425 			glViewport(0, 0, kSize, kSize);
1426 			glUseProgram(program);
1427 			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1428 			glBindVertexArray(m_vao);
1429 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1430 
1431 			glBindTexture(GL_TEXTURE_2D, texture);
1432 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1433 			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1434 
1435 			for (int i = 0; i < kSize * kSize; ++i)
1436 			{
1437 				if (!Equal(data[i], expected_value, internalformat))
1438 				{
1439 					glDeleteTextures(1, &texture);
1440 					glUseProgram(0);
1441 					glDeleteProgram(program);
1442 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1443 														<< ". Value should be: " << ToString(expected_value)
1444 														<< ". Format is: " << FormatEnumToString(internalformat)
1445 														<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1446 					return false;
1447 				}
1448 			}
1449 
1450 			if (unit < 7)
1451 			{
1452 				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1453 			}
1454 		}
1455 
1456 		glDeleteTextures(1, &texture);
1457 		glUseProgram(0);
1458 		glDeleteProgram(program);
1459 
1460 		return true;
1461 	}
1462 
Cleanup()1463 	virtual long Cleanup()
1464 	{
1465 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1466 		glDeleteVertexArrays(1, &m_vao);
1467 		glDeleteBuffers(1, &m_vbo);
1468 		return NO_ERROR;
1469 	}
1470 
1471 	template <typename T>
GenFS(GLenum internalformat,const T & value)1472 	std::string GenFS(GLenum internalformat, const T& value)
1473 	{
1474 		std::ostringstream os;
1475 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1476 		   << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1477 								 "  imageStore(g_image, coord, "
1478 		   << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1479 		return os.str();
1480 	}
1481 };
1482 //-----------------------------------------------------------------------------
1483 // 1.2.2 BasicAllFormatsLoad
1484 //-----------------------------------------------------------------------------
1485 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1486 {
1487 	GLuint m_vao;
1488 	GLuint m_vbo;
1489 
Setup()1490 	virtual long Setup()
1491 	{
1492 		m_vao = 0;
1493 		m_vbo = 0;
1494 		return NO_ERROR;
1495 	}
1496 
Run()1497 	virtual long Run()
1498 	{
1499 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1500 
1501 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1502 			return ERROR;
1503 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1504 			return ERROR;
1505 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1506 			return ERROR;
1507 
1508 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1509 			return ERROR;
1510 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1511 			return ERROR;
1512 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1513 			return ERROR;
1514 
1515 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1516 			return ERROR;
1517 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1518 			return ERROR;
1519 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1520 			return ERROR;
1521 
1522 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1523 			return ERROR;
1524 
1525 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1526 			return ERROR;
1527 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1528 			return ERROR;
1529 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1530 			return ERROR;
1531 
1532 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1533 			return ERROR;
1534 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1535 			return ERROR;
1536 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1537 			return ERROR;
1538 
1539 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1540 			return ERROR;
1541 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1542 			return ERROR;
1543 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1544 			return ERROR;
1545 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1546 			return ERROR;
1547 
1548 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1549 			return ERROR;
1550 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1551 			return ERROR;
1552 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1553 			return ERROR;
1554 
1555 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1556 			return ERROR;
1557 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1558 			return ERROR;
1559 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1560 			return ERROR;
1561 
1562 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1563 			return ERROR;
1564 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1565 			return ERROR;
1566 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1567 			return ERROR;
1568 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1569 			return ERROR;
1570 
1571 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1572 			return ERROR;
1573 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1574 			return ERROR;
1575 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1576 			return ERROR;
1577 
1578 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1579 			return ERROR;
1580 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1581 			return ERROR;
1582 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1583 			return ERROR;
1584 
1585 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1586 			return ERROR;
1587 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1588 			return ERROR;
1589 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1590 			return ERROR;
1591 
1592 		return NO_ERROR;
1593 	}
1594 
1595 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1596 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
1597 	{
1598 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1599 							 "  gl_Position = i_position;" NL "}";
1600 		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1601 		const int	  kSize   = 16;
1602 		std::vector<T> data(kSize * kSize, value);
1603 		GLuint		   texture;
1604 		glGenTextures(1, &texture);
1605 
1606 		for (GLuint unit = 0; unit < 8; ++unit)
1607 		{
1608 			glBindTexture(GL_TEXTURE_2D, texture);
1609 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1610 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1611 			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1612 			glBindTexture(GL_TEXTURE_2D, 0);
1613 
1614 			glViewport(0, 0, kSize, kSize);
1615 			glClear(GL_COLOR_BUFFER_BIT);
1616 			glUseProgram(program);
1617 			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1618 			glBindVertexArray(m_vao);
1619 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1620 
1621 			if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1622 			{
1623 				glDeleteTextures(1, &texture);
1624 				glUseProgram(0);
1625 				glDeleteProgram(program);
1626 				m_context.getTestContext().getLog()
1627 					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1628 					<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1629 				return false;
1630 			}
1631 
1632 			if (unit < 7)
1633 			{
1634 				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1635 			}
1636 		}
1637 
1638 		glDeleteTextures(1, &texture);
1639 		glUseProgram(0);
1640 		glDeleteProgram(program);
1641 
1642 		return true;
1643 	}
1644 
Cleanup()1645 	virtual long Cleanup()
1646 	{
1647 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1648 		glDeleteVertexArrays(1, &m_vao);
1649 		glDeleteBuffers(1, &m_vbo);
1650 		return NO_ERROR;
1651 	}
1652 
1653 	template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1654 	std::string GenFS(GLenum internalformat, const T& expected_value)
1655 	{
1656 		std::ostringstream os;
1657 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1658 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1659 		   << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1660 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1661 		   << expected_value
1662 		   << ") 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 "}";
1663 		return os.str();
1664 	}
1665 };
1666 //-----------------------------------------------------------------------------
1667 // 1.2.3 BasicAllFormatsStoreGeometryStages
1668 //-----------------------------------------------------------------------------
1669 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1670 {
1671 	GLuint m_vao;
1672 
Setup()1673 	virtual long Setup()
1674 	{
1675 		glGenVertexArrays(1, &m_vao);
1676 		return NO_ERROR;
1677 	}
1678 
Run()1679 	virtual long Run()
1680 	{
1681 		if (!SupportedInGeomStages(1))
1682 			return NOT_SUPPORTED;
1683 		glEnable(GL_RASTERIZER_DISCARD);
1684 
1685 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1686 			return ERROR;
1687 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1688 			return ERROR;
1689 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1690 			return ERROR;
1691 
1692 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1693 			return ERROR;
1694 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1695 			return ERROR;
1696 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1697 			return ERROR;
1698 
1699 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1700 			return ERROR;
1701 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1702 			return ERROR;
1703 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1704 			return ERROR;
1705 
1706 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1707 			return ERROR;
1708 
1709 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1710 			return ERROR;
1711 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1712 			return ERROR;
1713 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1714 			return ERROR;
1715 
1716 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1717 			return ERROR;
1718 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1719 			return ERROR;
1720 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1721 			return ERROR;
1722 
1723 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1724 			return ERROR;
1725 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1726 			return ERROR;
1727 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1728 			return ERROR;
1729 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1730 			return ERROR;
1731 
1732 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1733 			return ERROR;
1734 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1735 			return ERROR;
1736 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1737 			return ERROR;
1738 
1739 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1740 			return ERROR;
1741 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1742 			return ERROR;
1743 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1744 			return ERROR;
1745 
1746 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1747 			return ERROR;
1748 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1749 			return ERROR;
1750 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1751 			return ERROR;
1752 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1753 			return ERROR;
1754 
1755 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1756 			return ERROR;
1757 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1758 			return ERROR;
1759 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1760 			return ERROR;
1761 
1762 		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1763 			return ERROR;
1764 		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1765 			return ERROR;
1766 		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1767 			return ERROR;
1768 
1769 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1770 			return ERROR;
1771 		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1772 			return ERROR;
1773 		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1774 			return ERROR;
1775 
1776 		return NO_ERROR;
1777 	}
1778 
1779 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1780 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1781 	{
1782 		const GLuint program =
1783 			BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1784 						 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1785 		const int	  kSize = 1;
1786 		std::vector<T> data(kSize * kSize);
1787 		GLuint		   texture[4];
1788 		glGenTextures(4, texture);
1789 
1790 		for (int i = 0; i < 4; ++i)
1791 		{
1792 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1793 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1794 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1795 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1796 		}
1797 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1798 
1799 		glUseProgram(program);
1800 		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1801 		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1802 		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1803 		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1804 		for (GLuint i = 0; i < 4; ++i)
1805 		{
1806 			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1807 		}
1808 		glBindVertexArray(m_vao);
1809 		glPatchParameteri(GL_PATCH_VERTICES, 1);
1810 		glDrawArrays(GL_PATCHES, 0, 1);
1811 		glPatchParameteri(GL_PATCH_VERTICES, 3);
1812 
1813 		for (int i = 0; i < 4; ++i)
1814 		{
1815 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1816 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1817 			glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1818 
1819 			if (!Equal(data[0], expected_value, internalformat))
1820 			{
1821 				glDeleteTextures(4, texture);
1822 				glUseProgram(0);
1823 				glDeleteProgram(program);
1824 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1825 													<< ". Value should be: " << ToString(expected_value)
1826 													<< ". Format is: " << FormatEnumToString(internalformat)
1827 													<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1828 				return false;
1829 			}
1830 		}
1831 		glDeleteTextures(4, texture);
1832 		glUseProgram(0);
1833 		glDeleteProgram(program);
1834 		return true;
1835 	}
1836 
Cleanup()1837 	virtual long Cleanup()
1838 	{
1839 		glDisable(GL_RASTERIZER_DISCARD);
1840 		glDeleteVertexArrays(1, &m_vao);
1841 		return NO_ERROR;
1842 	}
1843 
1844 	template <typename T>
GenVS(GLenum internalformat,const T & value)1845 	std::string GenVS(GLenum internalformat, const T& value)
1846 	{
1847 		std::ostringstream os;
1848 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1849 		   << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1850 								 "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  imageStore(g_image0, coord, "
1851 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1852 		return os.str();
1853 	}
1854 
1855 	template <typename T>
GenTCS(GLenum internalformat,const T & value)1856 	std::string GenTCS(GLenum internalformat, const T& value)
1857 	{
1858 		std::ostringstream os;
1859 		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1860 		   << ") writeonly uniform " << TypePrefix<T>()
1861 		   << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1862 			  "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1863 			  "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1864 			  "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1865 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1866 		return os.str();
1867 	}
1868 
1869 	template <typename T>
GenTES(GLenum internalformat,const T & value)1870 	std::string GenTES(GLenum internalformat, const T& value)
1871 	{
1872 		std::ostringstream os;
1873 		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1874 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1875 		   << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1876 			  "  imageStore(g_image2, coord, "
1877 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1878 		return os.str();
1879 	}
1880 
1881 	template <typename T>
GenGS(GLenum internalformat,const T & value)1882 	std::string GenGS(GLenum internalformat, const T& value)
1883 	{
1884 		std::ostringstream os;
1885 		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1886 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1887 		   << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1888 			  "  imageStore(g_image3, coord, "
1889 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1890 		return os.str();
1891 	}
1892 };
1893 //-----------------------------------------------------------------------------
1894 // 1.2.4 BasicAllFormatsLoadGeometryStages
1895 //-----------------------------------------------------------------------------
1896 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1897 {
1898 	GLuint m_vao;
1899 
Setup()1900 	virtual long Setup()
1901 	{
1902 		glGenVertexArrays(1, &m_vao);
1903 		return NO_ERROR;
1904 	}
1905 
Run()1906 	virtual long Run()
1907 	{
1908 		if (!SupportedInGeomStages(2))
1909 			return NOT_SUPPORTED;
1910 		glEnable(GL_RASTERIZER_DISCARD);
1911 
1912 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1913 			return ERROR;
1914 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1915 			return ERROR;
1916 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1917 			return ERROR;
1918 
1919 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1920 			return ERROR;
1921 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1922 			return ERROR;
1923 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1924 			return ERROR;
1925 
1926 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1927 			return ERROR;
1928 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1929 			return ERROR;
1930 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1931 			return ERROR;
1932 
1933 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1934 			return ERROR;
1935 
1936 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1937 			return ERROR;
1938 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1939 			return ERROR;
1940 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1941 			return ERROR;
1942 
1943 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1944 			return ERROR;
1945 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1946 			return ERROR;
1947 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1948 			return ERROR;
1949 
1950 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1951 			return ERROR;
1952 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1953 			return ERROR;
1954 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1955 			return ERROR;
1956 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1957 			return ERROR;
1958 
1959 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1960 			return ERROR;
1961 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1962 			return ERROR;
1963 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1964 			return ERROR;
1965 
1966 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1967 			return ERROR;
1968 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1969 			return ERROR;
1970 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1971 			return ERROR;
1972 
1973 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1974 			return ERROR;
1975 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1976 			return ERROR;
1977 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1978 			return ERROR;
1979 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1980 			return ERROR;
1981 
1982 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1983 			return ERROR;
1984 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1985 			return ERROR;
1986 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1987 			return ERROR;
1988 
1989 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1990 			return ERROR;
1991 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1992 			return ERROR;
1993 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1994 			return ERROR;
1995 
1996 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1997 			return ERROR;
1998 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1999 			return ERROR;
2000 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2001 			return ERROR;
2002 
2003 		return NO_ERROR;
2004 	}
2005 
2006 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2007 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2008 	{
2009 		const GLuint program = BuildProgram(
2010 			GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2011 			GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2012 		const int	  kSize = 1;
2013 		std::vector<T> data(kSize * kSize, value);
2014 		GLuint		   texture[8];
2015 		glGenTextures(8, texture);
2016 
2017 		for (int i = 0; i < 4; ++i)
2018 		{
2019 			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2020 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2021 			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2022 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2023 		}
2024 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2025 		vec4 zero(0);
2026 		for (int i = 4; i < 8; ++i)
2027 		{
2028 			glBindTexture(GL_TEXTURE_2D, texture[i]);
2029 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2030 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2031 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2032 		}
2033 		glBindTexture(GL_TEXTURE_2D, 0);
2034 
2035 		glUseProgram(program);
2036 		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2037 		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2038 		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2039 		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2040 		glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2041 		glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2042 		glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2043 		glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2044 
2045 		for (GLuint i = 0; i < 4; ++i)
2046 		{
2047 			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2048 		}
2049 		for (GLuint i = 4; i < 8; ++i)
2050 		{
2051 			glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2052 		}
2053 		glBindVertexArray(m_vao);
2054 		glPatchParameteri(GL_PATCH_VERTICES, 1);
2055 		glDrawArrays(GL_PATCHES, 0, 1);
2056 		glPatchParameteri(GL_PATCH_VERTICES, 3);
2057 
2058 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2059 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
2060 		vec4					 g_color_eps  = vec4(
2061 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2062 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2063 
2064 		for (int i = 0; i < 4; ++i)
2065 		{
2066 			glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2067 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2068 			vec4 result;
2069 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2070 			if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2071 			{
2072 				glDeleteTextures(8, texture);
2073 				glUseProgram(0);
2074 				glDeleteProgram(program);
2075 				m_context.getTestContext().getLog()
2076 					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2077 					<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2078 				return false;
2079 			}
2080 		}
2081 		glDeleteTextures(8, texture);
2082 		glUseProgram(0);
2083 		glDeleteProgram(program);
2084 		return true;
2085 	}
2086 
Cleanup()2087 	virtual long Cleanup()
2088 	{
2089 		glDisable(GL_RASTERIZER_DISCARD);
2090 		glDeleteVertexArrays(1, &m_vao);
2091 		return NO_ERROR;
2092 	}
2093 
2094 	template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2095 	std::string GenVS(GLenum internalformat, const T& expected_value)
2096 	{
2097 		std::ostringstream os;
2098 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2099 		   << TypePrefix<T>()
2100 		   << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2101 			  "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2102 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2103 		   << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2104 								"  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2105 		return os.str();
2106 	}
2107 
2108 	template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2109 	std::string GenTCS(GLenum internalformat, const T& expected_value)
2110 	{
2111 		std::ostringstream os;
2112 		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2113 		   << ") readonly uniform " << TypePrefix<T>()
2114 		   << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2115 			  "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2116 			  "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2117 			  "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2118 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2119 		   << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2120 								"  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2121 		return os.str();
2122 	}
2123 
2124 	template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2125 	std::string GenTES(GLenum internalformat, const T& expected_value)
2126 	{
2127 		std::ostringstream os;
2128 		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2129 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2130 		   << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2131 			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2132 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2133 		   << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2134 								"  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2135 		return os.str();
2136 	}
2137 
2138 	template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2139 	std::string GenGS(GLenum internalformat, const T& expected_value)
2140 	{
2141 		std::ostringstream os;
2142 		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2143 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2144 		   << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2145 			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2146 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2147 		   << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2148 								"  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2149 		return os.str();
2150 	}
2151 };
2152 //-----------------------------------------------------------------------------
2153 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2154 //-----------------------------------------------------------------------------
2155 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2156 {
Run()2157 	virtual long Run()
2158 	{
2159 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2160 		{
2161 			m_context.getTestContext().getLog()
2162 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2163 				<< tcu::TestLog::EndMessage;
2164 			return NOT_SUPPORTED;
2165 		}
2166 
2167 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2168 			return ERROR;
2169 		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2170 			return ERROR;
2171 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2172 			return ERROR;
2173 
2174 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2175 			return ERROR;
2176 		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2177 			return ERROR;
2178 		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2179 			return ERROR;
2180 
2181 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2182 			return ERROR;
2183 		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2184 			return ERROR;
2185 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2186 			return ERROR;
2187 
2188 		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2189 			return ERROR;
2190 
2191 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2192 			return ERROR;
2193 		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2194 			return ERROR;
2195 		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2196 			return ERROR;
2197 
2198 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2199 			return ERROR;
2200 		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2201 			return ERROR;
2202 		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2203 			return ERROR;
2204 
2205 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2206 			return ERROR;
2207 		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2208 			return ERROR;
2209 		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2210 			return ERROR;
2211 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2212 			return ERROR;
2213 
2214 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2215 			return ERROR;
2216 		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2217 			return ERROR;
2218 		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2219 			return ERROR;
2220 
2221 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2222 			return ERROR;
2223 		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2224 			return ERROR;
2225 		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2226 			return ERROR;
2227 
2228 		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2229 			return ERROR;
2230 		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2231 			return ERROR;
2232 		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2233 			return ERROR;
2234 		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2235 			return ERROR;
2236 
2237 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2238 			return ERROR;
2239 		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2240 			return ERROR;
2241 		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2242 			return ERROR;
2243 
2244 		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2245 			return ERROR;
2246 		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2247 			return ERROR;
2248 		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2249 			return ERROR;
2250 
2251 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2252 			return ERROR;
2253 		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2254 			return ERROR;
2255 		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2256 			return ERROR;
2257 
2258 		return NO_ERROR;
2259 	}
2260 
2261 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2262 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2263 	{
2264 		GLuint			  program;
2265 		std::string		  source = GenCS<T>(internalformat);
2266 		const char* const src	= source.c_str();
2267 		GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
2268 		glShaderSource(sh, 1, &src, NULL);
2269 		glCompileShader(sh);
2270 		program = glCreateProgram();
2271 		glAttachShader(program, sh);
2272 		glLinkProgram(program);
2273 		glDeleteShader(sh);
2274 
2275 		const int	  kSize = 1;
2276 		std::vector<T> data(kSize * kSize, value);
2277 		GLuint		   texture[2];
2278 		glGenTextures(2, texture);
2279 
2280 		glBindTexture(GL_TEXTURE_2D, texture[0]);
2281 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2282 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2283 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2284 		glBindTexture(GL_TEXTURE_2D, texture[1]);
2285 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2286 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2287 		vec4 zero(0);
2288 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2289 
2290 		glBindTexture(GL_TEXTURE_2D, 0);
2291 
2292 		glUseProgram(program);
2293 		glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2294 		glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2295 
2296 		glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2297 		glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2298 
2299 		glDispatchCompute(1, 1, 1);
2300 
2301 		for (int i = 0; i < 2; ++i)
2302 		{
2303 			glBindTexture(GL_TEXTURE_2D, texture[i]);
2304 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2305 			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2306 
2307 			if (!Equal(data[0], expected_value, internalformat))
2308 			{
2309 				glDeleteTextures(4, texture);
2310 				glUseProgram(0);
2311 				glDeleteProgram(program);
2312 				m_context.getTestContext().getLog()
2313 					<< tcu::TestLog::Message << "Value is: " << ToString(data[0])
2314 					<< ". Value should be: " << ToString(expected_value)
2315 					<< ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2316 				return false;
2317 			}
2318 		}
2319 		glDeleteTextures(2, texture);
2320 		glUseProgram(0);
2321 		glDeleteProgram(program);
2322 		return true;
2323 	}
2324 
2325 	template <typename T>
GenCS(GLenum internalformat)2326 	std::string GenCS(GLenum internalformat)
2327 	{
2328 		std::ostringstream os;
2329 		os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2330 			  "layout("
2331 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2332 		   << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2333 		   << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2334 								 "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2335 		   << TypePrefix<T>()
2336 		   << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2337 		return os.str();
2338 	}
2339 };
2340 //-----------------------------------------------------------------------------
2341 // 1.3.1 BasicAllTargetsStore
2342 //-----------------------------------------------------------------------------
2343 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2344 {
2345 	GLuint m_vao;
2346 	GLuint m_vbo;
2347 
Setup()2348 	virtual long Setup()
2349 	{
2350 		m_vao = 0;
2351 		m_vbo = 0;
2352 		return NO_ERROR;
2353 	}
2354 
Run()2355 	virtual long Run()
2356 	{
2357 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2358 
2359 		if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2360 			return ERROR;
2361 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2362 			return ERROR;
2363 		if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2364 			return ERROR;
2365 
2366 		if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2367 			return ERROR;
2368 		if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2369 			return ERROR;
2370 		if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2371 			return ERROR;
2372 
2373 		if (SupportedSamples(4))
2374 		{
2375 			if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2376 				return ERROR;
2377 
2378 			GLint isamples;
2379 			glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2380 			if (isamples >= 4)
2381 			{
2382 				if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2383 					return ERROR;
2384 				if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2385 					return ERROR;
2386 			}
2387 		}
2388 		return NO_ERROR;
2389 	}
2390 
Cleanup()2391 	virtual long Cleanup()
2392 	{
2393 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2394 		glDeleteVertexArrays(1, &m_vao);
2395 		glDeleteBuffers(1, &m_vbo);
2396 		return NO_ERROR;
2397 	}
2398 
2399 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2400 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2401 	{
2402 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2403 							 "  gl_Position = i_position;" NL "}";
2404 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2405 		GLuint		 textures[8];
2406 		GLuint		 buffer;
2407 		glGenTextures(8, textures);
2408 		glGenBuffers(1, &buffer);
2409 
2410 		const int	  kSize = 16;
2411 		std::vector<T> data(kSize * kSize * 2);
2412 
2413 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2414 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2415 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2416 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2417 		glBindTexture(GL_TEXTURE_1D, 0);
2418 
2419 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2420 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2421 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2422 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2423 		glBindTexture(GL_TEXTURE_2D, 0);
2424 
2425 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2426 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2427 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2428 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2429 		glBindTexture(GL_TEXTURE_3D, 0);
2430 
2431 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2432 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2433 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2434 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2435 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2436 
2437 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2438 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2439 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2440 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2441 					 &data[0]);
2442 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2443 					 &data[0]);
2444 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2445 					 &data[0]);
2446 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2447 					 &data[0]);
2448 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2449 					 &data[0]);
2450 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451 					 &data[0]);
2452 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2453 
2454 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2455 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2456 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2457 		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2458 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2459 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2460 
2461 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2462 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2463 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2464 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2465 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2466 
2467 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2468 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2469 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2470 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2471 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2472 
2473 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2474 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2476 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2477 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2478 		glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2479 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2480 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481 
2482 		glUseProgram(program);
2483 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2484 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2485 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2486 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2487 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2488 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2489 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2490 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2491 
2492 		glBindVertexArray(m_vao);
2493 		glViewport(0, 0, kSize, kSize);
2494 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2495 
2496 		bool status = true;
2497 
2498 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2499 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2500 		glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2501 		glBindTexture(GL_TEXTURE_1D, 0);
2502 		for (int i = 0; i < kSize; ++i)
2503 		{
2504 			if (!tcu::allEqual(data[i], expected_value))
2505 			{
2506 				status = false;
2507 				m_context.getTestContext().getLog()
2508 					<< tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2509 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2510 				break;
2511 			}
2512 		}
2513 		std::fill(data.begin(), data.end(), T(0));
2514 
2515 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2516 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2517 		glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2518 		glBindTexture(GL_TEXTURE_2D, 0);
2519 		for (int i = 0; i < kSize * kSize; ++i)
2520 		{
2521 			if (!tcu::allEqual(data[i], expected_value))
2522 			{
2523 				status = false;
2524 				m_context.getTestContext().getLog()
2525 					<< tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2526 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2527 				break;
2528 			}
2529 		}
2530 
2531 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2532 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2533 		glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2534 		glBindTexture(GL_TEXTURE_3D, 0);
2535 		for (int i = 0; i < kSize * kSize * 2; ++i)
2536 		{
2537 			if (!tcu::allEqual(data[i], expected_value))
2538 			{
2539 				status = false;
2540 				m_context.getTestContext().getLog()
2541 					<< tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2542 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2543 				break;
2544 			}
2545 		}
2546 
2547 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2548 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2549 		glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2550 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2551 		for (int i = 0; i < kSize * kSize; ++i)
2552 		{
2553 			if (!tcu::allEqual(data[i], expected_value))
2554 			{
2555 				status = false;
2556 				m_context.getTestContext().getLog()
2557 					<< tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2558 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2559 				break;
2560 			}
2561 		}
2562 
2563 		{
2564 			glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2565 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2566 			for (int face = 0; face < 6; ++face)
2567 			{
2568 				glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2569 				for (int i = 0; i < kSize * kSize; ++i)
2570 				{
2571 					if (!tcu::allEqual(data[i], expected_value))
2572 					{
2573 						status = false;
2574 						m_context.getTestContext().getLog()
2575 							<< tcu::TestLog::Message
2576 							<< "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2577 							<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2578 						break;
2579 					}
2580 				}
2581 			}
2582 			glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2583 		}
2584 
2585 		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2586 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2587 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2588 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2589 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2590 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2591 		for (int i = 0; i < kSize; ++i)
2592 		{
2593 			if (!tcu::allEqual(data[i], expected_value))
2594 			{
2595 				status = false;
2596 				m_context.getTestContext().getLog()
2597 					<< tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2598 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2599 				break;
2600 			}
2601 		}
2602 
2603 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2604 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2605 		glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2606 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2607 		for (int i = 0; i < kSize * 2; ++i)
2608 		{
2609 			if (!tcu::allEqual(data[i], expected_value))
2610 			{
2611 				status = false;
2612 				m_context.getTestContext().getLog()
2613 					<< tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2614 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2615 				break;
2616 			}
2617 		}
2618 
2619 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2620 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2621 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2622 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2623 		for (int i = 0; i < kSize * kSize * 2; ++i)
2624 		{
2625 			if (!tcu::allEqual(data[i], expected_value))
2626 			{
2627 				status = false;
2628 				m_context.getTestContext().getLog()
2629 					<< tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2630 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2631 				break;
2632 			}
2633 		}
2634 
2635 		glUseProgram(0);
2636 		glDeleteProgram(program);
2637 		glDeleteTextures(8, textures);
2638 		glDeleteBuffers(1, &buffer);
2639 
2640 		return status;
2641 	}
2642 
2643 	template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2644 	bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2645 	{
2646 
2647 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2648 							 "  gl_Position = i_position;" NL "}";
2649 		const GLuint program	 = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2650 		const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2651 		GLuint		 textures[2];
2652 		glGenTextures(2, textures);
2653 
2654 		const int kSize = 16;
2655 
2656 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2657 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2658 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2659 
2660 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2661 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2662 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2663 
2664 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2665 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2666 
2667 		glClear(GL_COLOR_BUFFER_BIT);
2668 		glUseProgram(program);
2669 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2670 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2671 
2672 		glBindVertexArray(m_vao);
2673 		glViewport(0, 0, kSize, kSize);
2674 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2675 
2676 		bool status = true;
2677 
2678 		glActiveTexture(GL_TEXTURE0);
2679 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2680 		glActiveTexture(GL_TEXTURE1);
2681 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2682 
2683 		glUseProgram(val_program);
2684 		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2685 		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2686 
2687 		glBindVertexArray(m_vao);
2688 		glViewport(0, 0, kSize, kSize);
2689 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2690 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2691 
2692 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2693 		{
2694 			status = false;
2695 			m_context.getTestContext().getLog()
2696 				<< tcu::TestLog::Message
2697 				<< "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2698 				<< tcu::TestLog::EndMessage;
2699 		}
2700 
2701 		glActiveTexture(GL_TEXTURE0);
2702 		glDeleteTextures(2, textures);
2703 		glUseProgram(0);
2704 		glDeleteProgram(program);
2705 		glDeleteProgram(val_program);
2706 
2707 		return status;
2708 	}
2709 
2710 	template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2711 	bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2712 	{
2713 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2714 							 "  gl_Position = i_position;" NL "}";
2715 		const GLuint program =
2716 			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2717 		GLuint textures[1];
2718 		glGenTextures(1, textures);
2719 
2720 		const int kSize = 16;
2721 
2722 		std::vector<T> data(kSize * kSize * 12);
2723 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2724 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2725 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2726 					 &data[0]);
2727 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2728 
2729 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2730 
2731 		glUseProgram(program);
2732 		glBindVertexArray(m_vao);
2733 		glViewport(0, 0, kSize, kSize);
2734 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2735 
2736 		bool status = true;
2737 
2738 		std::fill(data.begin(), data.end(), T(0));
2739 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2740 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2741 		glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2742 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2743 		for (int i = 0; i < kSize * kSize * 12; ++i)
2744 		{
2745 			if (!tcu::allEqual(data[i], expected_value))
2746 			{
2747 				status = false;
2748 				m_context.getTestContext().getLog()
2749 					<< tcu::TestLog::Message
2750 					<< "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2751 					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2752 				break;
2753 			}
2754 		}
2755 
2756 		glDeleteTextures(1, textures);
2757 		glUseProgram(0);
2758 		glDeleteProgram(program);
2759 
2760 		return status;
2761 	}
2762 
2763 	template <typename T>
GenFS(GLenum internalformat,const T & write_value)2764 	std::string GenFS(GLenum internalformat, const T& write_value)
2765 	{
2766 		std::ostringstream os;
2767 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2768 		   << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2769 		   << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2770 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2771 		   << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2772 		   << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2773 		   << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2774 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2775 		   << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2776 		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2777 		   << ") writeonly uniform " << TypePrefix<T>()
2778 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2779 			  "  imageStore(g_image_1d, coord.x, "
2780 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2781 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2782 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2783 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2784 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2785 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2786 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2787 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2788 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2789 		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2790 		   << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2791 		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2792 		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2793 		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2794 		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2795 		   << write_value << ");" NL "  discard;" NL "}";
2796 		return os.str();
2797 	}
2798 
2799 	template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2800 	std::string GenFSMS(GLenum internalformat, const T& write_value)
2801 	{
2802 		std::ostringstream os;
2803 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2804 		   << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2805 		   << ") writeonly uniform " << TypePrefix<T>()
2806 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2807 			  "  imageStore(g_image_2dms, coord, 0, "
2808 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2809 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2810 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2811 		   << TypePrefix<T>() << "vec4" << write_value
2812 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2813 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2814 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2815 		   << TypePrefix<T>() << "vec4" << write_value
2816 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2817 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2818 		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2819 		   << TypePrefix<T>() << "vec4" << write_value
2820 		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2821 		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2822 		   << "vec4" << write_value << ");" NL "  discard;" NL "}";
2823 		return os.str();
2824 	}
2825 
2826 	template <typename T>
GenFSMSVal(const T & expected_value)2827 	std::string GenFSMSVal(const T& expected_value)
2828 	{
2829 		std::ostringstream os;
2830 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2831 		   << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2832 		   << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2833 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2834 		   << TypePrefix<T>() << "vec4" << expected_value
2835 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2836 		   << TypePrefix<T>() << "vec4" << expected_value
2837 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2838 		   << TypePrefix<T>() << "vec4" << expected_value
2839 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2840 		   << TypePrefix<T>() << "vec4" << expected_value
2841 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2842 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2843 		   << TypePrefix<T>() << "vec4" << expected_value
2844 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2845 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2846 		   << TypePrefix<T>() << "vec4" << expected_value
2847 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2848 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2849 		   << TypePrefix<T>() << "vec4" << expected_value
2850 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2851 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2852 		   << TypePrefix<T>() << "vec4" << expected_value
2853 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2854 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2855 		   << TypePrefix<T>() << "vec4" << expected_value
2856 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2857 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2858 		   << TypePrefix<T>() << "vec4" << expected_value
2859 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2860 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2861 		   << TypePrefix<T>() << "vec4" << expected_value
2862 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2863 			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2864 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2865 		return os.str();
2866 	}
2867 
2868 	template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2869 	std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2870 	{
2871 		std::ostringstream os;
2872 		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2873 		   << TypePrefix<T>()
2874 		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2875 			  "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2876 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2877 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2878 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2879 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2880 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2881 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2882 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2883 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2884 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2885 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2886 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2887 		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2888 		return os.str();
2889 	}
2890 };
2891 //-----------------------------------------------------------------------------
2892 // 1.3.2.1 BasicAllTargetsLoadNonMS
2893 //-----------------------------------------------------------------------------
2894 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2895 {
2896 	GLuint m_vao;
2897 	GLuint m_vbo;
2898 
Setup()2899 	virtual long Setup()
2900 	{
2901 		m_vao = 0;
2902 		m_vbo = 0;
2903 		return NO_ERROR;
2904 	}
2905 
Run()2906 	virtual long Run()
2907 	{
2908 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2909 
2910 		if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2911 			return ERROR;
2912 		if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2913 			return ERROR;
2914 		if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2915 			return ERROR;
2916 
2917 		if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2918 			return ERROR;
2919 		if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2920 			return ERROR;
2921 		if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2922 			return ERROR;
2923 
2924 		return NO_ERROR;
2925 	}
2926 
Cleanup()2927 	virtual long Cleanup()
2928 	{
2929 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2930 		glDeleteVertexArrays(1, &m_vao);
2931 		glDeleteBuffers(1, &m_vbo);
2932 		return NO_ERROR;
2933 	}
2934 
2935 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2936 	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2937 	{
2938 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2939 							 "  gl_Position = i_position;" NL "}";
2940 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2941 		GLuint		 textures[7];
2942 		GLuint		 buffer;
2943 		glGenTextures(7, textures);
2944 		glGenBuffers(1, &buffer);
2945 
2946 		const int	  kSize = 16;
2947 		std::vector<T> data(kSize * kSize * 2, value);
2948 
2949 		glBindTexture(GL_TEXTURE_1D, textures[0]);
2950 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2951 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2952 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2953 		glBindTexture(GL_TEXTURE_1D, 0);
2954 
2955 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2956 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2957 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2958 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2959 		glBindTexture(GL_TEXTURE_2D, 0);
2960 
2961 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2962 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2963 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2964 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2965 		glBindTexture(GL_TEXTURE_3D, 0);
2966 
2967 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2968 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2969 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2970 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2971 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2972 
2973 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2974 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2975 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2976 		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2977 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2978 		glBindTexture(GL_TEXTURE_BUFFER, 0);
2979 
2980 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2981 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2982 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2983 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2984 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2985 
2986 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2987 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2988 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2989 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2990 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2991 
2992 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2993 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2995 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2996 		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2998 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999 
3000 		glClear(GL_COLOR_BUFFER_BIT);
3001 
3002 		glUseProgram(program);
3003 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3004 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3005 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3006 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3007 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3008 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3009 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3010 
3011 		glBindVertexArray(m_vao);
3012 		glViewport(0, 0, kSize, kSize);
3013 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3014 
3015 		bool status = true;
3016 
3017 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3018 		{
3019 			status = false;
3020 		}
3021 
3022 		std::map<std::string, GLuint> name_index_map;
3023 		GLint uniforms;
3024 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3025 		if (uniforms != 7)
3026 		{
3027 			status = false;
3028 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3029 												<< " should be 7." << tcu::TestLog::EndMessage;
3030 		}
3031 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3032 		{
3033 			GLchar name[32];
3034 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3035 			name_index_map.insert(std::make_pair(std::string(name), index));
3036 		}
3037 
3038 		if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3039 			status = false;
3040 		if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3041 			status = false;
3042 		if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3043 			status = false;
3044 		if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3045 			status = false;
3046 		if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3047 			status = false;
3048 		if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3049 			status = false;
3050 		if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3051 			status = false;
3052 
3053 		glUseProgram(0);
3054 		glDeleteProgram(program);
3055 		glDeleteTextures(7, textures);
3056 		glDeleteBuffers(1, &buffer);
3057 
3058 		return status;
3059 	}
3060 
3061 	template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3062 	bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3063 	{
3064 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3065 							 "  gl_Position = i_position;" NL "}";
3066 		const GLuint program =
3067 			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3068 		GLuint textures[2];
3069 		glGenTextures(2, textures);
3070 
3071 		const int	  kSize = 16;
3072 		std::vector<T> data(kSize * kSize * 12, value);
3073 
3074 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3075 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3076 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3077 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3078 					 &data[0]);
3079 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3080 					 &data[0]);
3081 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3082 					 &data[0]);
3083 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3084 					 &data[0]);
3085 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3086 					 &data[0]);
3087 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088 					 &data[0]);
3089 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3090 
3091 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3092 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3093 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3094 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3095 					 &data[0]);
3096 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3097 
3098 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3099 		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100 
3101 		glClear(GL_COLOR_BUFFER_BIT);
3102 
3103 		glUseProgram(program);
3104 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3105 		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3106 
3107 		glBindVertexArray(m_vao);
3108 		glViewport(0, 0, kSize, kSize);
3109 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3110 
3111 		bool status = true;
3112 
3113 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3114 		{
3115 			status = false;
3116 		}
3117 
3118 		std::map<std::string, GLuint> name_index_map;
3119 		GLint uniforms;
3120 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3121 		if (uniforms != 2)
3122 		{
3123 			status = false;
3124 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3125 												<< " should be 2." << tcu::TestLog::EndMessage;
3126 		}
3127 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3128 		{
3129 			GLchar name[32];
3130 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3131 			name_index_map.insert(std::make_pair(std::string(name), index));
3132 		}
3133 
3134 		if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3135 			status = false;
3136 		if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3137 			status = false;
3138 
3139 		glUseProgram(0);
3140 		glDeleteProgram(program);
3141 		glDeleteTextures(2, textures);
3142 
3143 		return status;
3144 	}
3145 
3146 	template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3147 	std::string GenFS(GLenum internalformat, const T& expected_value)
3148 	{
3149 		std::ostringstream os;
3150 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3151 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3152 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3153 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3154 		   << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3155 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3156 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3157 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3158 		   << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3159 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3160 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3161 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3162 		   << TypePrefix<T>()
3163 		   << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3164 		   << expected_value
3165 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3166 		   << TypePrefix<T>() << "vec4" << expected_value
3167 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3168 			  "  if (v != "
3169 		   << TypePrefix<T>() << "vec4" << expected_value
3170 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3171 			  "  if (v != "
3172 		   << TypePrefix<T>() << "vec4" << expected_value
3173 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3174 		   << TypePrefix<T>() << "vec4" << expected_value
3175 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3176 		   << TypePrefix<T>() << "vec4" << expected_value
3177 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3178 			  "  if (v != "
3179 		   << TypePrefix<T>() << "vec4" << expected_value
3180 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3181 			  "  if (v != "
3182 		   << TypePrefix<T>() << "vec4" << expected_value
3183 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3184 			  "  if (v != "
3185 		   << TypePrefix<T>() << "vec4" << expected_value
3186 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3187 			  "  if (v != "
3188 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3189 		return os.str();
3190 	}
3191 
3192 	template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3193 	std::string GenFSCube(GLenum internalformat, const T& expected_value)
3194 	{
3195 		std::ostringstream os;
3196 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3197 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3198 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3199 		   << TypePrefix<T>()
3200 		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3201 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3202 		   << TypePrefix<T>()
3203 		   << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3204 		   << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3205 										  "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  if (v != "
3206 		   << TypePrefix<T>() << "vec4" << expected_value
3207 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3208 			  "  if (v != "
3209 		   << TypePrefix<T>() << "vec4" << expected_value
3210 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3211 			  "  if (v != "
3212 		   << TypePrefix<T>() << "vec4" << expected_value
3213 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3214 			  "  if (v != "
3215 		   << TypePrefix<T>() << "vec4" << expected_value
3216 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3217 			  "  if (v != "
3218 		   << TypePrefix<T>() << "vec4" << expected_value
3219 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3220 			  "  if (v != "
3221 		   << TypePrefix<T>() << "vec4" << expected_value
3222 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3223 			  "  if (v != "
3224 		   << TypePrefix<T>() << "vec4" << expected_value
3225 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3226 			  "  if (v != "
3227 		   << TypePrefix<T>() << "vec4" << expected_value
3228 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3229 			  "  if (v != "
3230 		   << TypePrefix<T>() << "vec4" << expected_value
3231 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3232 			  "  if (v != "
3233 		   << TypePrefix<T>() << "vec4" << expected_value
3234 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3235 			  "  if (v != "
3236 		   << TypePrefix<T>() << "vec4" << expected_value
3237 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3238 			  "  if (v != "
3239 		   << TypePrefix<T>() << "vec4" << expected_value
3240 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3241 			  "  if (v != "
3242 		   << TypePrefix<T>() << "vec4" << expected_value
3243 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3244 			  "  if (v != "
3245 		   << TypePrefix<T>() << "vec4" << expected_value
3246 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3247 			  "  if (v != "
3248 		   << TypePrefix<T>() << "vec4" << expected_value
3249 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3250 			  "  if (v != "
3251 		   << TypePrefix<T>() << "vec4" << expected_value
3252 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3253 			  "  if (v != "
3254 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3255 		return os.str();
3256 	}
3257 };
3258 //-----------------------------------------------------------------------------
3259 // 1.3.2.2 BasicAllTargetsLoadMS
3260 //-----------------------------------------------------------------------------
3261 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3262 {
3263 	GLuint m_vao;
3264 	GLuint m_vbo;
3265 
Setup()3266 	virtual long Setup()
3267 	{
3268 		m_vao = 0;
3269 		m_vbo = 0;
3270 		return NO_ERROR;
3271 	}
3272 
Run()3273 	virtual long Run()
3274 	{
3275 		if (!SupportedSamples(4))
3276 			return NOT_SUPPORTED;
3277 
3278 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3279 
3280 		if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3281 			return ERROR;
3282 
3283 		GLint isamples;
3284 		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3285 		if (isamples >= 4)
3286 		{
3287 			if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3288 				return ERROR;
3289 			if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3290 				return ERROR;
3291 		}
3292 
3293 		return NO_ERROR;
3294 	}
3295 
Cleanup()3296 	virtual long Cleanup()
3297 	{
3298 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3299 		glDeleteVertexArrays(1, &m_vao);
3300 		glDeleteBuffers(1, &m_vbo);
3301 		return NO_ERROR;
3302 	}
3303 
3304 	template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3305 	bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3306 	{
3307 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3308 							 "  gl_Position = i_position;" NL "}";
3309 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3310 		GLuint		 textures[2];
3311 		glGenTextures(2, textures);
3312 
3313 		const int kSize = 16;
3314 
3315 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3316 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3317 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3318 
3319 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3320 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3321 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3322 
3323 		GLuint fbo;
3324 		glGenFramebuffers(1, &fbo);
3325 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3326 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3327 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3328 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3329 		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3330 		glDrawBuffers(3, draw_buffers);
3331 		ClearBuffer(GL_COLOR, 0, value);
3332 		ClearBuffer(GL_COLOR, 1, value);
3333 		ClearBuffer(GL_COLOR, 2, value);
3334 		glDeleteFramebuffers(1, &fbo);
3335 
3336 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3337 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3338 
3339 		glUseProgram(program);
3340 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3341 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3342 
3343 		glClear(GL_COLOR_BUFFER_BIT);
3344 		glBindVertexArray(m_vao);
3345 		glViewport(0, 0, kSize, kSize);
3346 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3347 
3348 		bool status = true;
3349 
3350 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3351 		{
3352 			status = false;
3353 		}
3354 
3355 		std::map<std::string, GLuint> name_index_map;
3356 		GLint uniforms;
3357 		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3358 		if (uniforms != 2)
3359 		{
3360 			status = false;
3361 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3362 												<< " should be 2." << tcu::TestLog::EndMessage;
3363 		}
3364 		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3365 		{
3366 			GLchar name[32];
3367 			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3368 			name_index_map.insert(std::make_pair(std::string(name), index));
3369 		}
3370 
3371 		if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3372 			status = false;
3373 		if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3374 						  ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3375 			status = false;
3376 
3377 		glDeleteTextures(2, textures);
3378 		glUseProgram(0);
3379 		glDeleteProgram(program);
3380 
3381 		return status;
3382 	}
3383 
3384 	template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3385 	std::string GenFSMS(GLenum internalformat, const T& expected_value)
3386 	{
3387 		std::ostringstream os;
3388 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3389 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3390 		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3391 		   << TypePrefix<T>()
3392 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3393 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3394 		   << TypePrefix<T>() << "vec4" << expected_value
3395 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3396 		   << TypePrefix<T>() << "vec4" << expected_value
3397 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3398 		   << TypePrefix<T>() << "vec4" << expected_value
3399 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3400 		   << TypePrefix<T>() << "vec4" << expected_value
3401 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3402 		   << TypePrefix<T>() << "vec4" << expected_value
3403 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3404 		   << TypePrefix<T>() << "vec4" << expected_value
3405 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3406 		   << TypePrefix<T>() << "vec4" << expected_value
3407 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3408 		   << TypePrefix<T>() << "vec4" << expected_value
3409 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3410 		   << TypePrefix<T>() << "vec4" << expected_value
3411 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3412 		   << TypePrefix<T>() << "vec4" << expected_value
3413 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3414 		   << TypePrefix<T>() << "vec4" << expected_value
3415 		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3416 		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3417 		return os.str();
3418 	}
3419 };
3420 //-----------------------------------------------------------------------------
3421 // 1.3.3 BasicAllTargetsAtomic
3422 //-----------------------------------------------------------------------------
3423 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3424 {
3425 	GLuint m_vao;
3426 	GLuint m_vbo;
3427 
Setup()3428 	virtual long Setup()
3429 	{
3430 		m_vao = 0;
3431 		m_vbo = 0;
3432 		return NO_ERROR;
3433 	}
3434 
Run()3435 	virtual long Run()
3436 	{
3437 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3438 
3439 		if (!Atomic<GLint>(GL_R32I))
3440 			return ERROR;
3441 		if (!Atomic<GLuint>(GL_R32UI))
3442 			return ERROR;
3443 
3444 		if (!AtomicCube<GLint>(GL_R32I))
3445 			return ERROR;
3446 		if (!AtomicCube<GLuint>(GL_R32UI))
3447 			return ERROR;
3448 
3449 		GLint isamples;
3450 		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3451 		if (SupportedSamples(4) && isamples >= 4)
3452 		{
3453 			if (!AtomicMS<GLint>(GL_R32I))
3454 				return ERROR;
3455 			if (!AtomicMS<GLuint>(GL_R32UI))
3456 				return ERROR;
3457 		}
3458 
3459 		return NO_ERROR;
3460 	}
3461 
Cleanup()3462 	virtual long Cleanup()
3463 	{
3464 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3465 		glDeleteVertexArrays(1, &m_vao);
3466 		glDeleteBuffers(1, &m_vbo);
3467 		return NO_ERROR;
3468 	}
3469 
3470 	template <typename T>
Atomic(GLenum internalformat)3471 	bool Atomic(GLenum internalformat)
3472 	{
3473 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3474 							 "  gl_Position = i_position;" NL "}";
3475 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3476 		GLuint		 textures[7];
3477 		GLuint		 buffer;
3478 		glGenTextures(7, textures);
3479 		glGenBuffers(1, &buffer);
3480 
3481 		const int	  kSize = 16;
3482 		std::vector<T> data(kSize * kSize * 2);
3483 
3484 		glBindTexture(GL_TEXTURE_1D, textures[0]);
3485 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3486 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3487 		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3488 		glBindTexture(GL_TEXTURE_1D, 0);
3489 
3490 		glBindTexture(GL_TEXTURE_2D, textures[1]);
3491 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3492 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3493 		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3494 		glBindTexture(GL_TEXTURE_2D, 0);
3495 
3496 		glBindTexture(GL_TEXTURE_3D, textures[2]);
3497 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3498 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3499 		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3500 		glBindTexture(GL_TEXTURE_3D, 0);
3501 
3502 		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3503 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3504 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3505 		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3506 		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3507 
3508 		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3509 		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3510 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
3511 		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3512 		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3513 		glBindTexture(GL_TEXTURE_BUFFER, 0);
3514 
3515 		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3516 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3517 		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3518 		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3519 		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3520 
3521 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3522 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3523 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3524 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3525 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3526 
3527 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3528 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3530 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3531 		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3533 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534 
3535 		glClear(GL_COLOR_BUFFER_BIT);
3536 
3537 		glUseProgram(program);
3538 		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3539 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3540 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3541 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3542 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3543 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3544 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3545 
3546 		glBindVertexArray(m_vao);
3547 		glViewport(0, 0, kSize, 1);
3548 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3549 
3550 		bool status = true;
3551 
3552 		if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3553 		{
3554 			status = false;
3555 		}
3556 
3557 		glUseProgram(0);
3558 		glDeleteProgram(program);
3559 		glDeleteTextures(7, textures);
3560 		glDeleteBuffers(1, &buffer);
3561 
3562 		return status;
3563 	}
3564 
3565 	template <typename T>
AtomicCube(GLenum internalformat)3566 	bool AtomicCube(GLenum internalformat)
3567 	{
3568 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3569 							 "  gl_Position = i_position;" NL "}";
3570 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3571 		GLuint		 textures[2];
3572 		glGenTextures(2, textures);
3573 
3574 		const int	  kSize = 16;
3575 		std::vector<T> data(kSize * kSize * 12);
3576 
3577 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3578 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3579 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3580 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3581 					 &data[0]);
3582 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3583 					 &data[0]);
3584 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3585 					 &data[0]);
3586 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3587 					 &data[0]);
3588 		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3589 					 &data[0]);
3590 		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3591 					 &data[0]);
3592 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3593 
3594 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3595 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3596 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3597 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3598 					 &data[0]);
3599 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3600 
3601 		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3602 		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603 
3604 		glClear(GL_COLOR_BUFFER_BIT);
3605 
3606 		glUseProgram(program);
3607 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3608 		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3609 
3610 		glBindVertexArray(m_vao);
3611 		glViewport(0, 0, kSize, kSize);
3612 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3613 
3614 		bool status = true;
3615 
3616 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3617 		{
3618 			status = false;
3619 		}
3620 
3621 		glUseProgram(0);
3622 		glDeleteProgram(program);
3623 		glDeleteTextures(2, textures);
3624 
3625 		return status;
3626 	}
3627 
3628 	template <typename T>
AtomicMS(GLenum internalformat)3629 	bool AtomicMS(GLenum internalformat)
3630 	{
3631 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3632 							 "  gl_Position = i_position;" NL "}";
3633 		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3634 		GLuint		 textures[2];
3635 		glGenTextures(2, textures);
3636 
3637 		const int kSize = 16;
3638 
3639 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3640 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3641 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3642 
3643 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3644 		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3645 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3646 
3647 		GLuint fbo;
3648 		glGenFramebuffers(1, &fbo);
3649 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3650 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3651 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3652 		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3653 		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3654 		glDrawBuffers(3, draw_buffers);
3655 		if (internalformat == GL_R32I)
3656 		{
3657 			const GLint value[4] = { 0, 0, 0, 0 };
3658 			glClearBufferiv(GL_COLOR, 0, value);
3659 			glClearBufferiv(GL_COLOR, 1, value);
3660 			glClearBufferiv(GL_COLOR, 2, value);
3661 		}
3662 		else
3663 		{
3664 			const GLuint value[4] = { 0, 0, 0, 0 };
3665 			glClearBufferuiv(GL_COLOR, 0, value);
3666 			glClearBufferuiv(GL_COLOR, 1, value);
3667 			glClearBufferuiv(GL_COLOR, 2, value);
3668 		}
3669 		glDeleteFramebuffers(1, &fbo);
3670 
3671 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3672 		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3673 
3674 		glUseProgram(program);
3675 		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3676 		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3677 
3678 		glClear(GL_COLOR_BUFFER_BIT);
3679 		glBindVertexArray(m_vao);
3680 		glViewport(0, 0, kSize, kSize);
3681 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3682 
3683 		bool status = true;
3684 
3685 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3686 		{
3687 			status = false;
3688 		}
3689 
3690 		glDeleteTextures(2, textures);
3691 		glUseProgram(0);
3692 		glDeleteProgram(program);
3693 
3694 		return status;
3695 	}
3696 
3697 	template <typename T>
GenFS(GLenum internalformat)3698 	std::string GenFS(GLenum internalformat)
3699 	{
3700 		std::ostringstream os;
3701 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3702 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3703 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3704 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3705 		   << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3706 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3707 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3708 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3709 		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3710 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3711 		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3712 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3713 
3714 			NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3715 			  "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 			  "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 			  "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 			  "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 			  "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720 			  "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721 			  "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722 			  "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3723 
3724 			NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3725 			  "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 			  "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 			  "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 			  "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 			  "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 			  "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 			  "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 			  "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3733 
3734 			NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3735 			  "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 			  "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 			  "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 			  "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 			  "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 			  "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3742 			  "1.0);" NL
3743 			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3744 
3745 			NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3746 			  "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 			  "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 			  "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 			  "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 			  "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 			  "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 			  "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753 			  "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3754 
3755 			NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3756 			  "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 			  "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 			  "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 			  "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 			  "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 			  "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3764 
3765 			NL
3766 			  "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3767 			  "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 			  "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 			  "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 			  "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 			  "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 			  "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3773 			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3774 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3775 			  "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3776 
3777 			NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3778 			  "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 			  "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 			  "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 			  "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 			  "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 			  "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3784 			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3785 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3786 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3787 		return os.str();
3788 	}
3789 
3790 	template <typename T>
GenFSCube(GLenum internalformat)3791 	std::string GenFSCube(GLenum internalformat)
3792 	{
3793 		std::ostringstream os;
3794 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3795 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3796 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3797 		   << TypePrefix<T>()
3798 		   << "imageCube g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3799 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3800 
3801 			NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3802 			  "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803 			  "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804 			  "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805 			  "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806 			  "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808 			  "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3809 			  "1.0);" NL
3810 			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3811 
3812 			NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3813 			  "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3814 			  "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3815 			  "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3816 			  "ivec3(coord, 0), 0) != 4) o_color = "
3817 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL
3818 			  "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 			  "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3820 			  "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3821 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3822 			  "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3823 			  "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3824 			  "1.0);" NL "}";
3825 		return os.str();
3826 	}
3827 
3828 	template <typename T>
GenFSMS(GLenum internalformat)3829 	std::string GenFSMS(GLenum internalformat)
3830 	{
3831 		std::ostringstream os;
3832 		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3833 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3834 		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3835 		   << TypePrefix<T>()
3836 		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3837 			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3838 			  "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3839 			  "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840 			  "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841 			  "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842 			  "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843 			  "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844 			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845 			  "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846 			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3847 			  "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3848 			  "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3849 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3850 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3851 			  "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3852 			  "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3853 			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3854 			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3855 			  "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3856 			  "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3857 			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3858 			  "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3859 			  "0.0, 1.0);" NL "}";
3860 		return os.str();
3861 	}
3862 };
3863 //-----------------------------------------------------------------------------
3864 // LoadStoreMachine
3865 //-----------------------------------------------------------------------------
3866 class LoadStoreMachine : public ShaderImageLoadStoreBase
3867 {
3868 	GLuint m_vao;
3869 	int	m_stage;
3870 
Setup()3871 	virtual long Setup()
3872 	{
3873 		glGenVertexArrays(1, &m_vao);
3874 		return NO_ERROR;
3875 	}
3876 
Cleanup()3877 	virtual long Cleanup()
3878 	{
3879 		glDisable(GL_RASTERIZER_DISCARD);
3880 		glDeleteVertexArrays(1, &m_vao);
3881 		return NO_ERROR;
3882 	}
3883 
3884 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3885 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3886 	{
3887 		const GLenum targets[] = { GL_TEXTURE_1D,		GL_TEXTURE_2D,
3888 								   GL_TEXTURE_3D,		GL_TEXTURE_RECTANGLE,
3889 								   GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3890 								   GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3891 		const int kTargets		= sizeof(targets) / sizeof(targets[0]);
3892 		GLuint	program_store = 0;
3893 		GLuint	program_load  = 0;
3894 		if (m_stage == 0)
3895 		{ // VS
3896 			program_store =
3897 				BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3898 			program_load =
3899 				BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3900 		}
3901 		else if (m_stage == 1)
3902 		{ // TCS
3903 			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
3904 			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3905 			program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3906 										 glsl_tes, NULL, NULL);
3907 			program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3908 										glsl_tes, NULL, NULL);
3909 		}
3910 		else if (m_stage == 2)
3911 		{ // TES
3912 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3913 			program_store =
3914 				BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3915 			program_load =
3916 				BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3917 		}
3918 		else if (m_stage == 3)
3919 		{ // GS
3920 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3921 			program_store =
3922 				BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3923 			program_load =
3924 				BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3925 		}
3926 		else if (m_stage == 4)
3927 		{ // CS
3928 			{
3929 				std::string		  source = GenStoreShader(m_stage, internalformat, write_value);
3930 				const char* const src	= source.c_str();
3931 				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3932 				glShaderSource(sh, 1, &src, NULL);
3933 				glCompileShader(sh);
3934 				program_store = glCreateProgram();
3935 				glAttachShader(program_store, sh);
3936 				glLinkProgram(program_store);
3937 				glDeleteShader(sh);
3938 			}
3939 			{
3940 				std::string		  source = GenLoadShader(m_stage, internalformat, expected_value);
3941 				const char* const src	= source.c_str();
3942 				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3943 				glShaderSource(sh, 1, &src, NULL);
3944 				glCompileShader(sh);
3945 				program_load = glCreateProgram();
3946 				glAttachShader(program_load, sh);
3947 				glLinkProgram(program_load);
3948 				glDeleteShader(sh);
3949 			}
3950 		}
3951 		GLuint textures[kTargets], texture_result;
3952 		glGenTextures(kTargets, textures);
3953 		glGenTextures(1, &texture_result);
3954 
3955 		glBindTexture(GL_TEXTURE_2D, texture_result);
3956 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3957 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3958 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3959 
3960 		for (int i = 0; i < kTargets; ++i)
3961 		{
3962 			glBindTexture(targets[i], textures[i]);
3963 			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3964 			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3965 
3966 			if (targets[i] == GL_TEXTURE_1D)
3967 			{
3968 				glTexStorage1D(targets[i], 1, internalformat, 1);
3969 			}
3970 			else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3971 			{
3972 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3973 			}
3974 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3975 			{
3976 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3977 			}
3978 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3979 			{
3980 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3981 			}
3982 			else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3983 			{
3984 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3985 			}
3986 			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3987 			{
3988 				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3989 			}
3990 		}
3991 		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3992 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3994 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3995 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3996 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999 
4000 		glUseProgram(program_store);
4001 		glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4002 		glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4003 		glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4004 		glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4005 		glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4006 		glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4007 		glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4008 		glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4009 
4010 		glBindVertexArray(m_vao);
4011 		if (m_stage == 1 || m_stage == 2)
4012 		{ // TCS or TES
4013 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4014 			glDrawArrays(GL_PATCHES, 0, 1);
4015 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4016 		}
4017 		else if (m_stage == 4)
4018 		{ // CS
4019 			glDispatchCompute(1, 1, 1);
4020 		}
4021 		else
4022 		{
4023 			glDrawArrays(GL_POINTS, 0, 1);
4024 		}
4025 
4026 		bool status = true;
4027 		for (int i = 0; i < kTargets; ++i)
4028 		{
4029 			glBindTexture(targets[i], textures[i]);
4030 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4031 
4032 			if (targets[i] == GL_TEXTURE_CUBE_MAP)
4033 			{
4034 				for (int face = 0; face < 6; ++face)
4035 				{
4036 					T data;
4037 					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4038 					if (!Equal(data, expected_value, internalformat))
4039 					{
4040 						status = false;
4041 						m_context.getTestContext().getLog()
4042 							<< tcu::TestLog::Message << "Value is: " << ToString(data)
4043 							<< ". Value should be: " << ToString(expected_value)
4044 							<< ". Format is: " << FormatEnumToString(internalformat)
4045 							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4046 							<< tcu::TestLog::EndMessage;
4047 					}
4048 				}
4049 			}
4050 			else
4051 			{
4052 				T data[12];
4053 
4054 				for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4055 					data[ndx] = T(0);
4056 
4057 				glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4058 
4059 				int count = 1;
4060 				if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4061 					count = 2;
4062 				else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4063 					count = 12;
4064 				else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4065 					count = 2;
4066 
4067 				for (int j = 0; j < count; ++j)
4068 				{
4069 					if (!Equal(data[j], expected_value, internalformat))
4070 					{
4071 						status = false;
4072 						m_context.getTestContext().getLog()
4073 							<< tcu::TestLog::Message << "Value is: " << ToString(data[j])
4074 							<< ". Value should be: " << ToString(expected_value)
4075 							<< ". Format is: " << FormatEnumToString(internalformat)
4076 							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4077 							<< tcu::TestLog::EndMessage;
4078 					}
4079 				}
4080 			}
4081 		}
4082 		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4083 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4084 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4085 		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4086 		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4087 		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088 		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089 		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4090 
4091 		glUseProgram(program_load);
4092 		glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4093 		glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4094 		glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4095 		glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4096 		glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4097 		glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4098 		glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4099 		glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4100 
4101 		if (m_stage == 1 || m_stage == 2)
4102 		{ // TCS or TES
4103 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4104 			glDrawArrays(GL_PATCHES, 0, 1);
4105 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4106 		}
4107 		else if (m_stage == 4)
4108 		{ // CS
4109 			glDispatchCompute(1, 1, 1);
4110 		}
4111 		else
4112 		{
4113 			glDrawArrays(GL_POINTS, 0, 1);
4114 		}
4115 		{
4116 			vec4 color;
4117 			glBindTexture(GL_TEXTURE_2D, texture_result);
4118 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4119 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4120 			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4121 			{
4122 				status = false;
4123 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4124 													<< ". Format is: " << FormatEnumToString(internalformat)
4125 													<< ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4126 			}
4127 		}
4128 		glUseProgram(0);
4129 		glDeleteProgram(program_store);
4130 		glDeleteProgram(program_load);
4131 		glDeleteTextures(kTargets, textures);
4132 		glDeleteTextures(1, &texture_result);
4133 		return status;
4134 	}
4135 
4136 	template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4137 	std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4138 	{
4139 		std::ostringstream os;
4140 		os << "#version 420 core";
4141 		if (stage == 4)
4142 		{ // CS
4143 			os << NL "#extension GL_ARB_compute_shader : require";
4144 		}
4145 		os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4146 		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4147 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4148 		   << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4149 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4150 		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4151 		   << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4152 		   << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4153 		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4154 		   << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4155 		   << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4156 		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4157 		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4158 		if (stage == 0)
4159 		{ // VS
4160 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4161 		}
4162 		else if (stage == 1)
4163 		{ // TCS
4164 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4165 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4166 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4167 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4168 		}
4169 		else if (stage == 2)
4170 		{ // TES
4171 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4172 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4173 		}
4174 		else if (stage == 3)
4175 		{ // GS
4176 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4177 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4178 		}
4179 		else if (stage == 4)
4180 		{ // CS
4181 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4182 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4183 		}
4184 		os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4185 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4186 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4187 				 "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4188 				 "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4189 				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4190 				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4191 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4192 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4193 				 "  for (int i = 0; i < 6; ++i) {" NL
4194 				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4195 				 "  for (int i = 0; i < 6; ++i) {" NL
4196 				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4197 		return os.str();
4198 	}
4199 
4200 	template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4201 	std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4202 	{
4203 		std::ostringstream os;
4204 		os << "#version 420 core";
4205 		if (stage == 4)
4206 		{ // CS
4207 			os << NL "#extension GL_ARB_compute_shader : require";
4208 		}
4209 		os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4210 		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4211 		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4212 		   << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4213 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4214 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4215 		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4216 		   << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4217 		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4218 		   << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4219 			  "uniform "
4220 		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4221 		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4222 		if (stage == 0)
4223 		{ // VS
4224 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4225 		}
4226 		else if (stage == 1)
4227 		{ // TCS
4228 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4229 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4230 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4231 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4232 		}
4233 		else if (stage == 2)
4234 		{ // TES
4235 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4236 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4237 		}
4238 		else if (stage == 3)
4239 		{ // GS
4240 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4241 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4242 		}
4243 		else if (stage == 4)
4244 		{ // CS
4245 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4246 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4247 		}
4248 		os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4249 		   << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4250 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4251 			  "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4252 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4253 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4254 			  "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4255 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4256 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4257 			  "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4258 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4259 			  "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4260 			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4261 		return os.str();
4262 	}
4263 
4264 protected:
RunStage(int stage)4265 	long RunStage(int stage)
4266 	{
4267 		if (!SupportedInStage(stage, 8))
4268 			return NOT_SUPPORTED;
4269 
4270 		glEnable(GL_RASTERIZER_DISCARD);
4271 		m_stage = stage;
4272 
4273 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4274 			return ERROR;
4275 		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4276 			return ERROR;
4277 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4278 			return ERROR;
4279 
4280 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4281 			return ERROR;
4282 		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4283 			return ERROR;
4284 		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4285 			return ERROR;
4286 
4287 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4288 			return ERROR;
4289 		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4290 			return ERROR;
4291 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4292 			return ERROR;
4293 
4294 		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4295 			return ERROR;
4296 
4297 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4298 			return ERROR;
4299 		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4300 			return ERROR;
4301 		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302 			return ERROR;
4303 
4304 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4305 			return ERROR;
4306 		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4307 			return ERROR;
4308 		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4309 			return ERROR;
4310 
4311 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4312 			return ERROR;
4313 		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4314 			return ERROR;
4315 		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4316 			return ERROR;
4317 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4318 			return ERROR;
4319 
4320 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4321 			return ERROR;
4322 		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4323 			return ERROR;
4324 		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4325 			return ERROR;
4326 
4327 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4328 			return ERROR;
4329 		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4330 			return ERROR;
4331 		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4332 			return ERROR;
4333 
4334 		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4335 			return ERROR;
4336 		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4337 			return ERROR;
4338 		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4339 			return ERROR;
4340 		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4341 			return ERROR;
4342 
4343 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4344 			return ERROR;
4345 		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4346 			return ERROR;
4347 		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4348 			return ERROR;
4349 
4350 		//
4351 		{
4352 			if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4353 				return ERROR;
4354 			if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4355 				return ERROR;
4356 			if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4357 				return ERROR;
4358 
4359 			if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4360 				return ERROR;
4361 			if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4362 				return ERROR;
4363 			if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4364 				return ERROR;
4365 		}
4366 		return NO_ERROR;
4367 	}
4368 };
4369 //-----------------------------------------------------------------------------
4370 // AtomicMachine
4371 //-----------------------------------------------------------------------------
4372 class AtomicMachine : public ShaderImageLoadStoreBase
4373 {
4374 	GLuint m_vao;
4375 
Setup()4376 	virtual long Setup()
4377 	{
4378 		glEnable(GL_RASTERIZER_DISCARD);
4379 		glGenVertexArrays(1, &m_vao);
4380 		return NO_ERROR;
4381 	}
4382 
Cleanup()4383 	virtual long Cleanup()
4384 	{
4385 		glDisable(GL_RASTERIZER_DISCARD);
4386 		glDeleteVertexArrays(1, &m_vao);
4387 		return NO_ERROR;
4388 	}
4389 
4390 	template <typename T>
Atomic(int stage,GLenum internalformat)4391 	bool Atomic(int stage, GLenum internalformat)
4392 	{
4393 		GLuint program = 0;
4394 		if (stage == 0)
4395 		{ // VS
4396 			program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4397 		}
4398 		else if (stage == 1)
4399 		{ // TCS
4400 			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
4401 			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4402 			program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4403 		}
4404 		else if (stage == 2)
4405 		{ // TES
4406 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4407 			program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4408 		}
4409 		else if (stage == 3)
4410 		{ // GS
4411 			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4412 			program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4413 		}
4414 		else if (stage == 4)
4415 		{ // CS
4416 			std::string		  source = GenShader<T>(stage, internalformat);
4417 			const char* const src	= source.c_str();
4418 			GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
4419 			glShaderSource(sh, 1, &src, NULL);
4420 			glCompileShader(sh);
4421 			program = glCreateProgram();
4422 			glAttachShader(program, sh);
4423 			glLinkProgram(program);
4424 			glDeleteShader(sh);
4425 		}
4426 		GLuint texture_result;
4427 		glGenTextures(1, &texture_result);
4428 		glBindTexture(GL_TEXTURE_2D, texture_result);
4429 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4430 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4431 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4432 
4433 		const GLenum targets[] = { GL_TEXTURE_2D,	 GL_TEXTURE_3D,	   GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4434 								   GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4435 		const int kTargets = sizeof(targets) / sizeof(targets[0]);
4436 
4437 		GLuint textures[kTargets];
4438 		GLuint buffer;
4439 		glGenTextures(kTargets, textures);
4440 		glGenBuffers(1, &buffer);
4441 
4442 		for (int i = 0; i < kTargets; ++i)
4443 		{
4444 			glBindTexture(targets[i], textures[i]);
4445 			if (targets[i] != GL_TEXTURE_BUFFER)
4446 			{
4447 				glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4448 				glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4449 			}
4450 			if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4451 			{
4452 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4453 			}
4454 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4455 			{
4456 				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4457 			}
4458 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4459 			{
4460 				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4461 			}
4462 			else if (targets[i] == GL_TEXTURE_BUFFER)
4463 			{
4464 				glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4465 				glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4466 				glBindBuffer(GL_TEXTURE_BUFFER, 0);
4467 				glTexBuffer(targets[i], internalformat, buffer);
4468 			}
4469 			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4470 			{
4471 				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4472 			}
4473 		}
4474 		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4475 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4476 		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4477 		glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4478 		glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4479 		glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4480 		glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4481 		glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4482 
4483 		glUseProgram(program);
4484 		glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4485 		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4486 		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4487 		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4488 		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4489 		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4490 		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4491 		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4492 
4493 		glBindVertexArray(m_vao);
4494 		if (stage == 1 || stage == 2)
4495 		{ // TCS or TES
4496 			glPatchParameteri(GL_PATCH_VERTICES, 1);
4497 			glDrawArrays(GL_PATCHES, 0, 1);
4498 			glPatchParameteri(GL_PATCH_VERTICES, 3);
4499 		}
4500 		else if (stage == 4)
4501 		{ // CS
4502 			glDispatchCompute(1, 1, 1);
4503 		}
4504 		else
4505 		{
4506 			glDrawArrays(GL_POINTS, 0, 1);
4507 		}
4508 
4509 		bool status = true;
4510 		{
4511 			vec4 color;
4512 			glBindTexture(GL_TEXTURE_2D, texture_result);
4513 			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4514 			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4515 			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4516 			{
4517 				status = false;
4518 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4519 													<< ". Format is: " << FormatEnumToString(internalformat)
4520 													<< ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4521 			}
4522 		}
4523 		glUseProgram(0);
4524 		glDeleteProgram(program);
4525 		glDeleteTextures(7, textures);
4526 		glDeleteTextures(1, &texture_result);
4527 		glDeleteBuffers(1, &buffer);
4528 		return status;
4529 	}
4530 
4531 	template <typename T>
GenShader(int stage,GLenum internalformat)4532 	std::string GenShader(int stage, GLenum internalformat)
4533 	{
4534 		std::ostringstream os;
4535 		os << "#version 420 core";
4536 		if (stage == 4)
4537 		{ // CS
4538 			os << NL "#extension GL_ARB_compute_shader : require";
4539 		}
4540 		os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4541 		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4542 		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4543 		   << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4544 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4545 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4546 		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4547 		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4548 		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4549 		   << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4550 			  "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4551 		if (stage == 0)
4552 		{ // VS
4553 			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4554 		}
4555 		else if (stage == 1)
4556 		{ // TCS
4557 			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4558 					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4559 					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4560 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4561 		}
4562 		else if (stage == 2)
4563 		{ // TES
4564 			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4565 					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4566 		}
4567 		else if (stage == 3)
4568 		{ // GS
4569 			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4570 					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4571 		}
4572 		else if (stage == 4)
4573 		{ // CS
4574 			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4575 					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4576 		}
4577 		os << NL
4578 			"  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4579 			"  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580 			"  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 			"  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 			"  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 			"  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 			"  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585 			"  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4586 			"  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587 			"  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4588 
4589 			NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4590 			"  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591 			"  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 			"  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 			"  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 			"  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 			"  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 			"  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4598 			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4599 
4600 			NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4601 			"  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602 			"  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 			"  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 			"  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 			"  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 			"  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 			"  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 			"  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4609 			"1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4610 
4611 			NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4612 			"ivec3(coord, 0), g_value[2]) != 0) "
4613 			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614 			"  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 			"  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 			"  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 			"  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 			"  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4619 			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4620 			"  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4621 			"0.0, 1.0);" NL
4622 			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4623 
4624 			NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4625 			"  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626 			"  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 			"  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 			"  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 			"  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630 			"  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4631 			"  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4632 			"1.0);" NL
4633 			"  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4634 			"  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4635 
4636 			NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4637 			"  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4638 			"  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639 			"  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4640 			"1.0);" NL
4641 			"  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4642 			"  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4643 			"  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644 			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4645 			"1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4646 			"0.0, 0.0, 1.0);" NL
4647 			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4648 
4649 			NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4650 			"  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4651 			"  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 			"  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 			"  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654 			"  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4655 			"  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4656 			"1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4657 			"0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4658 			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4659 			"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4660 
4661 			NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4662 		return os.str();
4663 	}
4664 
4665 protected:
RunStage(int stage)4666 	long RunStage(int stage)
4667 	{
4668 		if (!SupportedInStage(stage, 8))
4669 			return NOT_SUPPORTED;
4670 		if (!Atomic<GLint>(stage, GL_R32I))
4671 			return ERROR;
4672 		if (!Atomic<GLuint>(stage, GL_R32UI))
4673 			return ERROR;
4674 		return NO_ERROR;
4675 	}
4676 };
4677 //-----------------------------------------------------------------------------
4678 // 1.3.4 BasicAllTargetsLoadStoreVS
4679 //-----------------------------------------------------------------------------
4680 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4681 {
Run()4682 	virtual long Run()
4683 	{
4684 		return RunStage(0);
4685 	}
4686 };
4687 //-----------------------------------------------------------------------------
4688 // 1.3.5 BasicAllTargetsLoadStoreTCS
4689 //-----------------------------------------------------------------------------
4690 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4691 {
Run()4692 	virtual long Run()
4693 	{
4694 		return RunStage(1);
4695 	}
4696 };
4697 //-----------------------------------------------------------------------------
4698 // 1.3.6 BasicAllTargetsLoadStoreTES
4699 //-----------------------------------------------------------------------------
4700 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4701 {
Run()4702 	virtual long Run()
4703 	{
4704 		return RunStage(2);
4705 	}
4706 };
4707 //-----------------------------------------------------------------------------
4708 // 1.3.7 BasicAllTargetsLoadStoreGS
4709 //-----------------------------------------------------------------------------
4710 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4711 {
Run()4712 	virtual long Run()
4713 	{
4714 		return RunStage(3);
4715 	}
4716 };
4717 //-----------------------------------------------------------------------------
4718 // 1.3.8 BasicAllTargetsLoadStoreCS
4719 //-----------------------------------------------------------------------------
4720 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4721 {
Run()4722 	virtual long Run()
4723 	{
4724 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4725 		{
4726 			m_context.getTestContext().getLog()
4727 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4728 				<< tcu::TestLog::EndMessage;
4729 			return NO_ERROR;
4730 		}
4731 
4732 		return RunStage(4);
4733 	}
4734 };
4735 //-----------------------------------------------------------------------------
4736 // 1.3.9 BasicAllTargetsAtomicVS
4737 //-----------------------------------------------------------------------------
4738 class BasicAllTargetsAtomicVS : public AtomicMachine
4739 {
Run()4740 	virtual long Run()
4741 	{
4742 		return RunStage(0);
4743 	}
4744 };
4745 //-----------------------------------------------------------------------------
4746 // 1.3.10 BasicAllTargetsAtomicTCS
4747 //-----------------------------------------------------------------------------
4748 class BasicAllTargetsAtomicTCS : public AtomicMachine
4749 {
Run()4750 	virtual long Run()
4751 	{
4752 		return RunStage(1);
4753 	}
4754 };
4755 //-----------------------------------------------------------------------------
4756 // 1.3.11 BasicAllTargetsAtomicTES
4757 //-----------------------------------------------------------------------------
4758 class BasicAllTargetsAtomicTES : public AtomicMachine
4759 {
Run()4760 	virtual long Run()
4761 	{
4762 		return RunStage(2);
4763 	}
4764 };
4765 //-----------------------------------------------------------------------------
4766 // 1.3.12 BasicAllTargetsAtomicGS
4767 //-----------------------------------------------------------------------------
4768 class BasicAllTargetsAtomicGS : public AtomicMachine
4769 {
Run()4770 	virtual long Run()
4771 	{
4772 		return RunStage(3);
4773 	}
4774 };
4775 //-----------------------------------------------------------------------------
4776 // 1.3.13 BasicAllTargetsAtomicCS
4777 //-----------------------------------------------------------------------------
4778 class BasicAllTargetsAtomicCS : public AtomicMachine
4779 {
Run()4780 	virtual long Run()
4781 	{
4782 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4783 		{
4784 			m_context.getTestContext().getLog()
4785 				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4786 				<< tcu::TestLog::EndMessage;
4787 			return NO_ERROR;
4788 		}
4789 
4790 		return RunStage(4);
4791 	}
4792 };
4793 //-----------------------------------------------------------------------------
4794 // 1.4.1 BasicGLSLMisc
4795 //-----------------------------------------------------------------------------
4796 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4797 {
4798 	GLuint m_texture;
4799 	GLuint m_program;
4800 	GLuint m_vao, m_vbo;
4801 
Setup()4802 	virtual long Setup()
4803 	{
4804 		m_texture = 0;
4805 		m_program = 0;
4806 		m_vao = m_vbo = 0;
4807 		return NO_ERROR;
4808 	}
4809 
Run()4810 	virtual long Run()
4811 	{
4812 		const int		  kSize = 32;
4813 		std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4814 
4815 		glGenTextures(1, &m_texture);
4816 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4817 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4818 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4819 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4820 
4821 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4822 							 "  gl_Position = i_position;" NL "}";
4823 		const char* src_fs =
4824 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4825 			"layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4826 			"layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4827 			"void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4828 			"  imageStore(g_image_layer0, coord, vec4(1.0));" NL "  memoryBarrier();" NL
4829 			"  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4830 			"  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4831 			"  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4832 		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4833 
4834 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4835 
4836 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4837 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4838 
4839 		glClear(GL_COLOR_BUFFER_BIT);
4840 		glViewport(0, 0, kSize, kSize);
4841 
4842 		glUseProgram(m_program);
4843 		glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4844 		glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4845 
4846 		glBindVertexArray(m_vao);
4847 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4848 
4849 		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4850 		{
4851 			return ERROR;
4852 		}
4853 		return NO_ERROR;
4854 	}
4855 
Cleanup()4856 	virtual long Cleanup()
4857 	{
4858 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4859 		glDeleteTextures(1, &m_texture);
4860 		glDeleteVertexArrays(1, &m_vao);
4861 		glDeleteBuffers(1, &m_vbo);
4862 		glUseProgram(0);
4863 		glDeleteProgram(m_program);
4864 		return NO_ERROR;
4865 	}
4866 };
4867 //-----------------------------------------------------------------------------
4868 // 1.4.2 BasicGLSLEarlyFragTests
4869 //-----------------------------------------------------------------------------
4870 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4871 {
4872 	GLuint m_texture[2];
4873 	GLuint m_program[2];
4874 	GLuint m_vao, m_vbo;
4875 
Setup()4876 	virtual long Setup()
4877 	{
4878 		m_texture[0] = m_texture[1] = 0;
4879 		m_program[0] = m_program[1] = 0;
4880 		m_vao = m_vbo = 0;
4881 		return NO_ERROR;
4882 	}
4883 
Run()4884 	virtual long Run()
4885 	{
4886 		int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4887 
4888 		const int		  kSize = 32;
4889 		std::vector<vec4> data(kSize * kSize);
4890 
4891 		glGenTextures(2, m_texture);
4892 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4893 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4894 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4895 		glBindTexture(GL_TEXTURE_2D, 0);
4896 
4897 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4898 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4899 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4900 		glBindTexture(GL_TEXTURE_2D, 0);
4901 
4902 		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4903 							  "  gl_Position = i_position;" NL "}";
4904 		const char* glsl_early_frag_tests_fs =
4905 			"#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4906 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4907 			"  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4908 			"  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4909 		const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4910 							  "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4911 							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4912 							  "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4913 		m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4914 		m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4915 
4916 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4917 
4918 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4919 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4920 
4921 		glViewport(0, 0, kSize, kSize);
4922 		glBindVertexArray(m_vao);
4923 
4924 		glEnable(GL_DEPTH_TEST);
4925 		glClearColor(0.0, 1.0f, 0.0, 1.0f);
4926 		glClearDepthf(0.0f);
4927 
4928 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4929 		glUseProgram(m_program[0]);
4930 		glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4931 
4932 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4933 
4934 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4935 		glUseProgram(m_program[1]);
4936 		glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4937 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4938 
4939 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4940 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4941 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4942 		for (int i = 0; i < kSize * kSize; ++i)
4943 		{
4944 			if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4945 				return ERROR;
4946 		}
4947 
4948 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4949 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4950 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4951 		for (int i = 0; i < kSize * kSize; ++i)
4952 		{
4953 			if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4954 				return ERROR;
4955 		}
4956 
4957 		return NO_ERROR;
4958 	}
4959 
Cleanup()4960 	virtual long Cleanup()
4961 	{
4962 		glDisable(GL_DEPTH_TEST);
4963 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4964 		glClearDepthf(1.0f);
4965 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4966 		glDeleteTextures(2, m_texture);
4967 		glDeleteVertexArrays(1, &m_vao);
4968 		glDeleteBuffers(1, &m_vbo);
4969 		glUseProgram(0);
4970 		glDeleteProgram(m_program[0]);
4971 		glDeleteProgram(m_program[1]);
4972 		return NO_ERROR;
4973 	}
4974 };
4975 //-----------------------------------------------------------------------------
4976 // 1.4.3 BasicGLSLConst
4977 //-----------------------------------------------------------------------------
4978 class BasicGLSLConst : public ShaderImageLoadStoreBase
4979 {
4980 	GLuint m_program;
4981 	GLuint m_vao, m_vbo;
4982 
Setup()4983 	virtual long Setup()
4984 	{
4985 		m_program = 0;
4986 		m_vao = m_vbo = 0;
4987 		return NO_ERROR;
4988 	}
4989 
Run()4990 	virtual long Run()
4991 	{
4992 		bool isAtLeast44Context =
4993 			glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4994 
4995 		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4996 							 "  gl_Position = i_position;" NL "}";
4997 		std::ostringstream src_fs;
4998 		src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4999 		src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5000 					 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5001 					 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5002 					 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5003 					 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5004 					 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5005 					 "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5006 		if (isAtLeast44Context)
5007 			src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5008 						 "vec4(0.2, 0.0, 0.0, 0.2);";
5009 		else
5010 			src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5011 						 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5012 		src_fs << NL
5013 			"  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5014 			"  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5015 			"  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5016 			"0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5017 			"0.0, 0.0, 0.6);" NL
5018 			"  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5019 			"  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5020 			"  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5021 
5022 		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5023 		glUseProgram(m_program);
5024 
5025 		GLint i;
5026 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5027 		glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5028 
5029 		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5030 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5031 
5032 		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5033 		glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5034 
5035 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5036 		glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5037 
5038 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5039 		glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5040 
5041 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5042 		glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5043 
5044 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5045 		glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5046 
5047 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5048 		glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5049 
5050 		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5051 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5052 
5053 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5054 
5055 		glClear(GL_COLOR_BUFFER_BIT);
5056 		glBindVertexArray(m_vao);
5057 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5058 
5059 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5060 		{
5061 			return ERROR;
5062 		}
5063 		return NO_ERROR;
5064 	}
5065 
Cleanup()5066 	virtual long Cleanup()
5067 	{
5068 		glDeleteVertexArrays(1, &m_vao);
5069 		glDeleteBuffers(1, &m_vbo);
5070 		glUseProgram(0);
5071 		glDeleteProgram(m_program);
5072 		return NO_ERROR;
5073 	}
5074 };
5075 //-----------------------------------------------------------------------------
5076 // 2.1.1 AdvancedSyncImageAccess
5077 //-----------------------------------------------------------------------------
5078 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5079 {
5080 	GLuint m_buffer;
5081 	GLuint m_buffer_tex;
5082 	GLuint m_store_program;
5083 	GLuint m_draw_program;
5084 	GLuint m_attribless_vao;
5085 
Setup()5086 	virtual long Setup()
5087 	{
5088 		m_buffer		 = 0;
5089 		m_buffer_tex	 = 0;
5090 		m_store_program  = 0;
5091 		m_draw_program   = 0;
5092 		m_attribless_vao = 0;
5093 		return NO_ERROR;
5094 	}
5095 
Run()5096 	virtual long Run()
5097 	{
5098 		if (!SupportedInVS(1))
5099 			return NOT_SUPPORTED;
5100 		const char* const glsl_store_vs =
5101 			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5102 			"  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5103 			"  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5104 		const char* const glsl_draw_vs =
5105 			"#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5106 			"uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5107 			"  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5108 			"  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
5109 			"  gl_Position = pi;" NL "}";
5110 		const char* const glsl_draw_fs =
5111 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5112 			"  o_color = vs_color;" NL "}";
5113 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5114 		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5115 
5116 		glGenVertexArrays(1, &m_attribless_vao);
5117 		glBindVertexArray(m_attribless_vao);
5118 
5119 		glGenBuffers(1, &m_buffer);
5120 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5121 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5122 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5123 
5124 		glGenTextures(1, &m_buffer_tex);
5125 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5126 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5127 
5128 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5129 
5130 		glEnable(GL_RASTERIZER_DISCARD);
5131 		glUseProgram(m_store_program);
5132 		glDrawArrays(GL_POINTS, 0, 4);
5133 
5134 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5135 
5136 		glDisable(GL_RASTERIZER_DISCARD);
5137 		glClear(GL_COLOR_BUFFER_BIT);
5138 		glUseProgram(m_draw_program);
5139 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5140 
5141 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5142 		{
5143 			return ERROR;
5144 		}
5145 		return NO_ERROR;
5146 	}
5147 
Cleanup()5148 	virtual long Cleanup()
5149 	{
5150 		glUseProgram(0);
5151 		glDeleteBuffers(1, &m_buffer);
5152 		glDeleteTextures(1, &m_buffer_tex);
5153 		glDeleteProgram(m_store_program);
5154 		glDeleteProgram(m_draw_program);
5155 		glDeleteVertexArrays(1, &m_attribless_vao);
5156 		return NO_ERROR;
5157 	}
5158 };
5159 //-----------------------------------------------------------------------------
5160 // 2.1.2 AdvancedSyncVertexArray
5161 //-----------------------------------------------------------------------------
5162 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5163 {
5164 	GLuint m_position_buffer;
5165 	GLuint m_color_buffer;
5166 	GLuint m_element_buffer;
5167 	GLuint m_position_buffer_tex;
5168 	GLuint m_color_buffer_tex;
5169 	GLuint m_element_buffer_tex;
5170 	GLuint m_store_program;
5171 	GLuint m_draw_program;
5172 	GLuint m_attribless_vao;
5173 	GLuint m_draw_vao;
5174 
Setup()5175 	virtual long Setup()
5176 	{
5177 		m_position_buffer	 = 0;
5178 		m_color_buffer		  = 0;
5179 		m_element_buffer	  = 0;
5180 		m_position_buffer_tex = 0;
5181 		m_color_buffer_tex	= 0;
5182 		m_element_buffer_tex  = 0;
5183 		m_store_program		  = 0;
5184 		m_draw_program		  = 0;
5185 		m_attribless_vao	  = 0;
5186 		m_draw_vao			  = 0;
5187 		return NO_ERROR;
5188 	}
5189 
Run()5190 	virtual long Run()
5191 	{
5192 		if (!SupportedInVS(3))
5193 			return NOT_SUPPORTED;
5194 		const char* const glsl_store_vs =
5195 			"#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5196 			"layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5197 			"layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5198 			"void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5199 			"  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5200 			"  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5201 			"  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5202 		const char* const glsl_draw_vs =
5203 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5204 			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5205 			"  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5206 		const char* const glsl_draw_fs =
5207 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5208 			"  o_color = vs_color;" NL "}";
5209 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5210 		glUseProgram(m_store_program);
5211 		glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5212 		glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5213 		glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5214 		glUseProgram(0);
5215 
5216 		m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5217 
5218 		glGenBuffers(1, &m_position_buffer);
5219 		glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5220 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5221 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5222 
5223 		glGenBuffers(1, &m_color_buffer);
5224 		glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5225 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5226 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5227 
5228 		glGenBuffers(1, &m_element_buffer);
5229 		glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5230 		glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5231 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5232 
5233 		glGenTextures(1, &m_position_buffer_tex);
5234 		glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5235 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5236 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5237 
5238 		glGenTextures(1, &m_color_buffer_tex);
5239 		glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5240 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5241 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5242 
5243 		glGenTextures(1, &m_element_buffer_tex);
5244 		glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5245 		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5246 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5247 
5248 		glGenVertexArrays(1, &m_attribless_vao);
5249 
5250 		glGenVertexArrays(1, &m_draw_vao);
5251 		glBindVertexArray(m_draw_vao);
5252 		glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5253 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5254 		glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5255 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5256 		glBindBuffer(GL_ARRAY_BUFFER, 0);
5257 		glEnableVertexAttribArray(0);
5258 		glEnableVertexAttribArray(1);
5259 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5260 		glBindVertexArray(0);
5261 
5262 		glEnable(GL_RASTERIZER_DISCARD);
5263 		glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5264 		glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5265 		glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5266 		glUseProgram(m_store_program);
5267 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5268 		glBindVertexArray(m_attribless_vao);
5269 		glDrawArrays(GL_POINTS, 0, 4);
5270 
5271 		glDisable(GL_RASTERIZER_DISCARD);
5272 		glClear(GL_COLOR_BUFFER_BIT);
5273 		glUseProgram(m_draw_program);
5274 		glBindVertexArray(m_draw_vao);
5275 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5276 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5277 
5278 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5279 		{
5280 			return ERROR;
5281 		}
5282 
5283 		glEnable(GL_RASTERIZER_DISCARD);
5284 		glUseProgram(m_store_program);
5285 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5286 		glBindVertexArray(m_attribless_vao);
5287 		glDrawArrays(GL_POINTS, 0, 4);
5288 
5289 		glDisable(GL_RASTERIZER_DISCARD);
5290 		glClear(GL_COLOR_BUFFER_BIT);
5291 		glUseProgram(m_draw_program);
5292 		glBindVertexArray(m_draw_vao);
5293 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5294 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5295 
5296 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5297 		{
5298 			return ERROR;
5299 		}
5300 		return NO_ERROR;
5301 	}
5302 
Cleanup()5303 	virtual long Cleanup()
5304 	{
5305 		glDisable(GL_RASTERIZER_DISCARD);
5306 		glUseProgram(0);
5307 		glDeleteBuffers(1, &m_position_buffer);
5308 		glDeleteBuffers(1, &m_color_buffer);
5309 		glDeleteBuffers(1, &m_element_buffer);
5310 		glDeleteTextures(1, &m_position_buffer_tex);
5311 		glDeleteTextures(1, &m_color_buffer_tex);
5312 		glDeleteTextures(1, &m_element_buffer_tex);
5313 		glDeleteProgram(m_store_program);
5314 		glDeleteProgram(m_draw_program);
5315 		glDeleteVertexArrays(1, &m_attribless_vao);
5316 		glDeleteVertexArrays(1, &m_draw_vao);
5317 		return NO_ERROR;
5318 	}
5319 };
5320 
5321 //-----------------------------------------------------------------------------
5322 // 2.1.4 AdvancedSyncDrawIndirect
5323 //-----------------------------------------------------------------------------
5324 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5325 {
5326 	GLuint m_draw_command_buffer;
5327 	GLuint m_draw_command_buffer_tex;
5328 	GLuint m_store_program;
5329 	GLuint m_draw_program;
5330 	GLuint m_attribless_vao;
5331 	GLuint m_draw_vao;
5332 	GLuint m_draw_vbo;
5333 
Setup()5334 	virtual long Setup()
5335 	{
5336 		m_draw_command_buffer	 = 0;
5337 		m_draw_command_buffer_tex = 0;
5338 		m_store_program			  = 0;
5339 		m_draw_program			  = 0;
5340 		m_attribless_vao		  = 0;
5341 		m_draw_vao				  = 0;
5342 		m_draw_vbo				  = 0;
5343 		return NO_ERROR;
5344 	}
5345 
Run()5346 	virtual long Run()
5347 	{
5348 		if (!SupportedInVS(1))
5349 			return NOT_SUPPORTED;
5350 		const char* const glsl_store_vs =
5351 			"#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5352 			"  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5353 		const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5354 										 "void main() {" NL "  gl_Position = i_position;" NL "}";
5355 		const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5356 										 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5357 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5358 		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5359 
5360 		glGenBuffers(1, &m_draw_command_buffer);
5361 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5362 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5363 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5364 
5365 		glGenTextures(1, &m_draw_command_buffer_tex);
5366 		glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5367 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5368 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5369 
5370 		glGenVertexArrays(1, &m_attribless_vao);
5371 		CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5372 
5373 		glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5374 
5375 		glEnable(GL_RASTERIZER_DISCARD);
5376 		glUseProgram(m_store_program);
5377 		glBindVertexArray(m_attribless_vao);
5378 		glDrawArrays(GL_POINTS, 0, 1);
5379 
5380 		glDisable(GL_RASTERIZER_DISCARD);
5381 		glClear(GL_COLOR_BUFFER_BIT);
5382 		glUseProgram(m_draw_program);
5383 		glBindVertexArray(m_draw_vao);
5384 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5385 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5386 		glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5387 
5388 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5389 		{
5390 			return ERROR;
5391 		}
5392 		return NO_ERROR;
5393 	}
5394 
Cleanup()5395 	virtual long Cleanup()
5396 	{
5397 		glUseProgram(0);
5398 		glDeleteBuffers(1, &m_draw_command_buffer);
5399 		glDeleteTextures(1, &m_draw_command_buffer_tex);
5400 		glDeleteProgram(m_store_program);
5401 		glDeleteProgram(m_draw_program);
5402 		glDeleteVertexArrays(1, &m_attribless_vao);
5403 		glDeleteVertexArrays(1, &m_draw_vao);
5404 		glDeleteBuffers(1, &m_draw_vbo);
5405 		return NO_ERROR;
5406 	}
5407 };
5408 //-----------------------------------------------------------------------------
5409 // 2.1.5 AdvancedSyncTextureUpdate
5410 //-----------------------------------------------------------------------------
5411 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5412 {
5413 	GLuint m_texture;
5414 	GLuint m_store_program;
5415 	GLuint m_draw_program;
5416 	GLuint m_vao;
5417 	GLuint m_vbo;
5418 	GLuint m_pbo;
5419 
Setup()5420 	virtual long Setup()
5421 	{
5422 		m_texture		= 0;
5423 		m_store_program = 0;
5424 		m_draw_program  = 0;
5425 		m_vao			= 0;
5426 		m_vbo			= 0;
5427 		m_pbo			= 0;
5428 		return NO_ERROR;
5429 	}
5430 
Run()5431 	virtual long Run()
5432 	{
5433 		const char* const glsl_vs =
5434 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5435 			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5436 		const char* const glsl_store_fs =
5437 			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5438 			"  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5439 		const char* const glsl_draw_fs =
5440 			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5441 			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5442 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5443 		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5444 
5445 		std::vector<vec4> data(16 * 16, vec4(1.0f));
5446 		glGenBuffers(1, &m_pbo);
5447 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5448 		glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5449 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5450 
5451 		glGenTextures(1, &m_texture);
5452 		glBindTexture(GL_TEXTURE_2D, m_texture);
5453 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5454 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5455 		glBindTexture(GL_TEXTURE_2D, 0);
5456 
5457 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5458 
5459 		glViewport(0, 0, 16, 16);
5460 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5461 		glUseProgram(m_store_program);
5462 		glBindVertexArray(m_vao);
5463 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5464 
5465 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5466 		glBindTexture(GL_TEXTURE_2D, m_texture);
5467 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5468 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5469 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5470 
5471 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5472 		glClear(GL_COLOR_BUFFER_BIT);
5473 		glUseProgram(m_draw_program);
5474 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5475 
5476 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5477 		{
5478 			return ERROR;
5479 		}
5480 		return NO_ERROR;
5481 	}
5482 
Cleanup()5483 	virtual long Cleanup()
5484 	{
5485 		glUseProgram(0);
5486 		glDeleteBuffers(1, &m_vbo);
5487 		glDeleteBuffers(1, &m_pbo);
5488 		glDeleteTextures(1, &m_texture);
5489 		glDeleteProgram(m_store_program);
5490 		glDeleteProgram(m_draw_program);
5491 		glDeleteVertexArrays(1, &m_vao);
5492 		return NO_ERROR;
5493 	}
5494 };
5495 //-----------------------------------------------------------------------------
5496 // 2.1.6 AdvancedSyncImageAccess2
5497 //-----------------------------------------------------------------------------
5498 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5499 {
5500 	GLuint m_texture;
5501 	GLuint m_store_program;
5502 	GLuint m_draw_program;
5503 	GLuint m_vao;
5504 	GLuint m_vbo;
5505 
Setup()5506 	virtual long Setup()
5507 	{
5508 		m_texture		= 0;
5509 		m_store_program = 0;
5510 		m_draw_program  = 0;
5511 		m_vao			= 0;
5512 		m_vbo			= 0;
5513 		return NO_ERROR;
5514 	}
5515 
Run()5516 	virtual long Run()
5517 	{
5518 		const char* const glsl_vs =
5519 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5520 			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5521 		const char* const glsl_store_fs =
5522 			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5523 			"  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5524 		const char* const glsl_draw_fs =
5525 			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5526 			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5527 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5528 		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5529 
5530 		int width  = getWindowWidth();
5531 		int height = getWindowHeight();
5532 		scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5533 
5534 		glGenTextures(1, &m_texture);
5535 		glBindTexture(GL_TEXTURE_2D, m_texture);
5536 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5537 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5538 		glBindTexture(GL_TEXTURE_2D, 0);
5539 
5540 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5541 
5542 		glViewport(0, 0, width, height);
5543 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5544 		glUseProgram(m_store_program);
5545 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5546 		glBindVertexArray(m_vao);
5547 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5548 
5549 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5550 
5551 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5552 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5553 
5554 		glClear(GL_COLOR_BUFFER_BIT);
5555 		glBindTexture(GL_TEXTURE_2D, m_texture);
5556 		glUseProgram(m_draw_program);
5557 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5558 
5559 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5560 		{
5561 			return ERROR;
5562 		}
5563 		return NO_ERROR;
5564 	}
5565 
Cleanup()5566 	virtual long Cleanup()
5567 	{
5568 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5569 		glUseProgram(0);
5570 		glDeleteBuffers(1, &m_vbo);
5571 		glDeleteTextures(1, &m_texture);
5572 		glDeleteProgram(m_store_program);
5573 		glDeleteProgram(m_draw_program);
5574 		glDeleteVertexArrays(1, &m_vao);
5575 		return NO_ERROR;
5576 	}
5577 };
5578 //-----------------------------------------------------------------------------
5579 // 2.1.7 AdvancedSyncBufferUpdate
5580 //-----------------------------------------------------------------------------
5581 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5582 {
5583 	GLuint m_buffer;
5584 	GLuint m_buffer_tex;
5585 	GLuint m_store_program;
5586 	GLuint m_attribless_vao;
5587 
Setup()5588 	virtual long Setup()
5589 	{
5590 		m_buffer		 = 0;
5591 		m_buffer_tex	 = 0;
5592 		m_store_program  = 0;
5593 		m_attribless_vao = 0;
5594 		return NO_ERROR;
5595 	}
5596 
Run()5597 	virtual long Run()
5598 	{
5599 		if (!SupportedInVS(1))
5600 			return NOT_SUPPORTED;
5601 		const char* const glsl_store_vs =
5602 			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5603 			"  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5604 		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5605 
5606 		glGenVertexArrays(1, &m_attribless_vao);
5607 		glBindVertexArray(m_attribless_vao);
5608 
5609 		glGenBuffers(1, &m_buffer);
5610 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5611 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5612 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5613 
5614 		glGenTextures(1, &m_buffer_tex);
5615 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5616 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5617 
5618 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5619 
5620 		glEnable(GL_RASTERIZER_DISCARD);
5621 		glUseProgram(m_store_program);
5622 		glDrawArrays(GL_POINTS, 0, 1000);
5623 
5624 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5625 
5626 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5627 		vec4* ptr =
5628 			reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5629 		for (int i = 0; i < 1000; ++i)
5630 		{
5631 			if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5632 			{
5633 				m_context.getTestContext().getLog()
5634 					<< tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5635 				return ERROR;
5636 			}
5637 		}
5638 		return NO_ERROR;
5639 	}
5640 
Cleanup()5641 	virtual long Cleanup()
5642 	{
5643 		glDisable(GL_RASTERIZER_DISCARD);
5644 		glUseProgram(0);
5645 		glDeleteBuffers(1, &m_buffer);
5646 		glDeleteTextures(1, &m_buffer_tex);
5647 		glDeleteProgram(m_store_program);
5648 		glDeleteVertexArrays(1, &m_attribless_vao);
5649 		return NO_ERROR;
5650 	}
5651 };
5652 //-----------------------------------------------------------------------------
5653 // 2.2.1 AdvancedAllStagesOneImage
5654 //-----------------------------------------------------------------------------
5655 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5656 {
5657 	GLuint m_program;
5658 	GLuint m_vao;
5659 	GLuint m_vbo;
5660 	GLuint m_ebo;
5661 	GLuint m_buffer;
5662 	GLuint m_buffer_tex;
5663 	GLuint m_texture;
5664 
Setup()5665 	virtual long Setup()
5666 	{
5667 		m_program	= 0;
5668 		m_vao		 = 0;
5669 		m_vbo		 = 0;
5670 		m_ebo		 = 0;
5671 		m_buffer	 = 0;
5672 		m_buffer_tex = 0;
5673 		m_texture	= 0;
5674 		return NO_ERROR;
5675 	}
5676 
Run()5677 	virtual long Run()
5678 	{
5679 		if (!SupportedInGeomStages(2))
5680 			return NOT_SUPPORTED;
5681 		const char* const glsl_vs =
5682 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5683 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5684 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5685 			"  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5686 			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5687 		const char* const glsl_tcs =
5688 			"#version 420 core" NL "layout(vertices = 1) out;" NL
5689 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5690 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5691 			"  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5692 			"  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5693 			"  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5694 			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5695 		const char* const glsl_tes =
5696 			"#version 420 core" NL "layout(triangles, point_mode) in;" NL
5697 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5698 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5699 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5700 			"  gl_Position = gl_in[0].gl_Position;" NL "}";
5701 		const char* const glsl_gs =
5702 			"#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5703 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5704 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5705 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5706 			"  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5707 		const char* const glsl_fs =
5708 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5709 			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5710 			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5711 			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5712 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5713 		m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5714 		glUseProgram(m_program);
5715 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5716 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5717 
5718 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5719 
5720 		GLint i32 = 0;
5721 		glGenBuffers(1, &m_buffer);
5722 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5723 		glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5724 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5725 
5726 		glGenTextures(1, &m_buffer_tex);
5727 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5728 		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5729 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5730 
5731 		GLuint ui32 = 0;
5732 		glGenTextures(1, &m_texture);
5733 		glBindTexture(GL_TEXTURE_2D, m_texture);
5734 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5735 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5736 		glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5737 		glBindTexture(GL_TEXTURE_2D, 0);
5738 
5739 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5740 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5741 
5742 		glBindVertexArray(m_vao);
5743 		glPatchParameteri(GL_PATCH_VERTICES, 1);
5744 
5745 		glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5746 		glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5747 
5748 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5749 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5750 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5751 		if (i32 < 20 || i32 > 50)
5752 		{
5753 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5754 												<< " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5755 			return ERROR;
5756 		}
5757 
5758 		glBindTexture(GL_TEXTURE_2D, m_texture);
5759 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5760 		if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5761 		{
5762 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5763 												<< (2 * i32) << tcu::TestLog::EndMessage;
5764 			return ERROR;
5765 		}
5766 
5767 		return NO_ERROR;
5768 	}
5769 
Cleanup()5770 	virtual long Cleanup()
5771 	{
5772 		glPatchParameteri(GL_PATCH_VERTICES, 3);
5773 		glUseProgram(0);
5774 		glDeleteBuffers(1, &m_buffer);
5775 		glDeleteBuffers(1, &m_vbo);
5776 		glDeleteBuffers(1, &m_ebo);
5777 		glDeleteTextures(1, &m_buffer_tex);
5778 		glDeleteTextures(1, &m_texture);
5779 		glDeleteProgram(m_program);
5780 		glDeleteVertexArrays(1, &m_vao);
5781 		return NO_ERROR;
5782 	}
5783 };
5784 //-----------------------------------------------------------------------------
5785 // 2.3.1 AdvancedMemoryDependentInvocation
5786 //-----------------------------------------------------------------------------
5787 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5788 {
5789 	GLuint m_buffer;
5790 	GLuint m_buffer_tex;
5791 	GLuint m_texture;
5792 	GLuint m_program;
5793 	GLuint m_vao;
5794 	GLuint m_vbo;
5795 
Setup()5796 	virtual long Setup()
5797 	{
5798 		m_buffer	 = 0;
5799 		m_buffer_tex = 0;
5800 		m_texture	= 0;
5801 		m_program	= 0;
5802 		m_vao		 = 0;
5803 		m_vbo		 = 0;
5804 		return NO_ERROR;
5805 	}
5806 
Run()5807 	virtual long Run()
5808 	{
5809 		if (!SupportedInVS(2))
5810 			return NOT_SUPPORTED;
5811 		const char* const glsl_vs =
5812 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5813 			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5814 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5815 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5816 			"  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5817 			"  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5818 		const char* const glsl_fs =
5819 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5820 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5821 			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5822 			"  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5823 			"  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5824 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5825 		glUseProgram(m_program);
5826 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5827 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5828 
5829 		vec4 zero(0);
5830 		glGenBuffers(1, &m_buffer);
5831 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5832 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5833 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5834 
5835 		glGenTextures(1, &m_buffer_tex);
5836 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5837 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5838 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5839 
5840 		glGenTextures(1, &m_texture);
5841 		glBindTexture(GL_TEXTURE_2D, m_texture);
5842 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5843 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5844 		glBindTexture(GL_TEXTURE_2D, 0);
5845 
5846 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5847 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5848 
5849 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5850 
5851 		glClear(GL_COLOR_BUFFER_BIT);
5852 		glBindVertexArray(m_vao);
5853 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5854 
5855 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5856 		{
5857 			return ERROR;
5858 		}
5859 		return NO_ERROR;
5860 	}
5861 
Cleanup()5862 	virtual long Cleanup()
5863 	{
5864 		glUseProgram(0);
5865 		glDeleteBuffers(1, &m_vbo);
5866 		glDeleteBuffers(1, &m_buffer);
5867 		glDeleteTextures(1, &m_texture);
5868 		glDeleteTextures(1, &m_buffer_tex);
5869 		glDeleteProgram(m_program);
5870 		glDeleteVertexArrays(1, &m_vao);
5871 		return NO_ERROR;
5872 	}
5873 };
5874 //-----------------------------------------------------------------------------
5875 // 2.3.2 AdvancedMemoryOrder
5876 //-----------------------------------------------------------------------------
5877 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5878 {
5879 	GLuint m_buffer;
5880 	GLuint m_buffer_tex;
5881 	GLuint m_texture;
5882 	GLuint m_program;
5883 	GLuint m_vao;
5884 	GLuint m_vbo;
5885 
Setup()5886 	virtual long Setup()
5887 	{
5888 		m_buffer	 = 0;
5889 		m_buffer_tex = 0;
5890 		m_texture	= 0;
5891 		m_program	= 0;
5892 		m_vao		 = 0;
5893 		m_vbo		 = 0;
5894 		return NO_ERROR;
5895 	}
5896 
Run()5897 	virtual long Run()
5898 	{
5899 		if (!SupportedInVS(1))
5900 			return NOT_SUPPORTED;
5901 		const char* const glsl_vs =
5902 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5903 			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5904 			"  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5905 			"  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5906 			"  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5907 			"  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5908 		const char* const glsl_fs =
5909 			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5910 			"layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5911 			"  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5912 			"    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5913 			"    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5914 			"}";
5915 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5916 		glUseProgram(m_program);
5917 		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5918 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5919 
5920 		glGenBuffers(1, &m_buffer);
5921 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5922 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5923 		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5924 
5925 		glGenTextures(1, &m_buffer_tex);
5926 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5927 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5928 		glBindTexture(GL_TEXTURE_BUFFER, 0);
5929 
5930 		int width  = getWindowWidth();
5931 		int height = getWindowHeight();
5932 		scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5933 
5934 		std::vector<vec4> data(width * height);
5935 		glGenTextures(1, &m_texture);
5936 		glBindTexture(GL_TEXTURE_2D, m_texture);
5937 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5938 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5939 		glBindTexture(GL_TEXTURE_2D, 0);
5940 
5941 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5942 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5943 
5944 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5945 
5946 		glClear(GL_COLOR_BUFFER_BIT);
5947 		glViewport(0, 0, width, height);
5948 		glBindVertexArray(m_vao);
5949 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5950 
5951 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5952 		{
5953 			return ERROR;
5954 		}
5955 		return NO_ERROR;
5956 	}
5957 
Cleanup()5958 	virtual long Cleanup()
5959 	{
5960 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5961 		glUseProgram(0);
5962 		glDeleteBuffers(1, &m_vbo);
5963 		glDeleteBuffers(1, &m_buffer);
5964 		glDeleteTextures(1, &m_texture);
5965 		glDeleteTextures(1, &m_buffer_tex);
5966 		glDeleteProgram(m_program);
5967 		glDeleteVertexArrays(1, &m_vao);
5968 		return NO_ERROR;
5969 	}
5970 };
5971 //-----------------------------------------------------------------------------
5972 // 2.4.1 AdvancedSSOSimple
5973 //-----------------------------------------------------------------------------
5974 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5975 {
5976 	GLuint m_texture;
5977 	GLuint m_pipeline[2];
5978 	GLuint m_vsp, m_fsp0, m_fsp1;
5979 	GLuint m_vao, m_vbo;
5980 
Setup()5981 	virtual long Setup()
5982 	{
5983 		glGenTextures(1, &m_texture);
5984 		glGenProgramPipelines(2, m_pipeline);
5985 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5986 
5987 		const char* const glsl_vs =
5988 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5989 			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5990 		const char* const glsl_fs0 =
5991 			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5992 			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5993 			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
5994 		const char* const glsl_fs1 =
5995 			"#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5996 			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5997 			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
5998 		m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5999 		m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6000 		m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6001 
6002 		return NO_ERROR;
6003 	}
6004 
Run()6005 	virtual long Run()
6006 	{
6007 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6008 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6009 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6010 		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6011 
6012 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6013 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6014 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6015 		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6016 
6017 		glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6018 		glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6019 
6020 		glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6021 		glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6022 
6023 		int width  = getWindowWidth();
6024 		int height = getWindowHeight();
6025 		scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6026 
6027 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6028 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6029 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6030 
6031 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6032 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6033 		glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6034 		glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6035 		glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6036 		glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6037 		glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6038 		glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6039 
6040 		glBindVertexArray(m_vao);
6041 
6042 		glViewport(0, 0, width, height);
6043 		glBindProgramPipeline(m_pipeline[0]);
6044 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6045 
6046 		glBindProgramPipeline(m_pipeline[1]);
6047 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6048 
6049 		std::vector<vec4> data(width * height * 8);
6050 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6051 
6052 		for (int layer = 0; layer < 8; ++layer)
6053 		{
6054 			for (int h = 0; h < height; ++h)
6055 			{
6056 				for (int w = 0; w < width; ++w)
6057 				{
6058 					const vec4 c = data[layer * width * height + h * width + w];
6059 					if (layer % 2)
6060 					{
6061 						if (!IsEqual(c, vec4(2.0f)))
6062 						{
6063 							return ERROR;
6064 						}
6065 					}
6066 					else
6067 					{
6068 						if (!IsEqual(c, vec4(1.0f)))
6069 						{
6070 							return ERROR;
6071 						}
6072 					}
6073 				}
6074 			}
6075 		}
6076 		return NO_ERROR;
6077 	}
6078 
Cleanup()6079 	virtual long Cleanup()
6080 	{
6081 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6082 		glDeleteBuffers(1, &m_vbo);
6083 		glDeleteTextures(1, &m_texture);
6084 		glDeleteProgram(m_vsp);
6085 		glDeleteProgram(m_fsp0);
6086 		glDeleteProgram(m_fsp1);
6087 		glDeleteVertexArrays(1, &m_vao);
6088 		glDeleteProgramPipelines(2, m_pipeline);
6089 		return NO_ERROR;
6090 	}
6091 };
6092 //-----------------------------------------------------------------------------
6093 // 2.4.2 AdvancedSSOAtomicCounters
6094 //-----------------------------------------------------------------------------
6095 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6096 {
6097 	GLuint m_buffer, m_buffer_tex;
6098 	GLuint m_counter_buffer;
6099 	GLuint m_transform_buffer;
6100 	GLuint m_pipeline;
6101 	GLuint m_vao, m_vbo;
6102 	GLuint m_vsp, m_fsp;
6103 
Setup()6104 	virtual long Setup()
6105 	{
6106 		m_vao = 0;
6107 		m_vbo = 0;
6108 		m_vsp = 0;
6109 		m_fsp = 0;
6110 		glGenBuffers(1, &m_buffer);
6111 		glGenTextures(1, &m_buffer_tex);
6112 		glGenBuffers(1, &m_counter_buffer);
6113 		glGenBuffers(1, &m_transform_buffer);
6114 		glGenProgramPipelines(1, &m_pipeline);
6115 		return NO_ERROR;
6116 	}
6117 
Run()6118 	virtual long Run()
6119 	{
6120 		if (!SupportedInVS(1))
6121 			return NOT_SUPPORTED;
6122 
6123 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6124 		const char* const glsl_vs =
6125 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6126 			"layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6127 			"out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6128 			"  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6129 			"layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6130 			"  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6131 			"  const uint index = atomicCounterIncrement(g_counter);" NL
6132 			"  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6133 		const char* const glsl_fs =
6134 			"#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6135 			"layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6136 		m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6137 		m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6138 
6139 		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6140 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6141 
6142 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6143 		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6144 
6145 		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6146 		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6147 
6148 		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6149 		vec4 zero(0);
6150 		glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6151 
6152 		glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6153 		mat4 identity(1);
6154 		glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6155 
6156 		glClear(GL_COLOR_BUFFER_BIT);
6157 		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6158 		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6159 		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6160 		glBindVertexArray(m_vao);
6161 		glBindProgramPipeline(m_pipeline);
6162 		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6163 
6164 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6165 		{
6166 			return ERROR;
6167 		}
6168 
6169 		std::vector<vec4> data(4);
6170 		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6171 		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6172 
6173 		for (int i = 0; i < 4; ++i)
6174 		{
6175 			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)) &&
6176 				!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 			{
6178 				return ERROR;
6179 			}
6180 		}
6181 
6182 		return NO_ERROR;
6183 	}
6184 
Cleanup()6185 	virtual long Cleanup()
6186 	{
6187 		glDeleteBuffers(1, &m_buffer);
6188 		glDeleteBuffers(1, &m_vbo);
6189 		glDeleteBuffers(1, &m_counter_buffer);
6190 		glDeleteBuffers(1, &m_transform_buffer);
6191 		glDeleteTextures(1, &m_buffer_tex);
6192 		glDeleteProgram(m_vsp);
6193 		glDeleteProgram(m_fsp);
6194 		glDeleteVertexArrays(1, &m_vao);
6195 		glDeleteProgramPipelines(1, &m_pipeline);
6196 		return NO_ERROR;
6197 	}
6198 };
6199 //-----------------------------------------------------------------------------
6200 // 2.4.3 AdvancedSSOSubroutine
6201 //-----------------------------------------------------------------------------
6202 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6203 {
6204 	GLuint m_texture;
6205 	GLuint m_attribless_vao;
6206 	GLuint m_program;
6207 	GLint  m_draw_buffer;
6208 
Setup()6209 	virtual long Setup()
6210 	{
6211 		glGenTextures(1, &m_texture);
6212 		glGenVertexArrays(1, &m_attribless_vao);
6213 
6214 		const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6215 									"const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6216 									"void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6217 		const char* const glsl_fs =
6218 			"#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6219 			"writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6220 			"subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6221 			"  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6222 			"  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6223 			"  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6224 			"subroutine(Brush) void Brush1(ivec2 coord) {" NL
6225 			"  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6226 			"  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6227 			"  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6228 			"  g_brush(ivec2(gl_FragCoord));" NL "}";
6229 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6230 
6231 		return NO_ERROR;
6232 	}
6233 
Run()6234 	virtual long Run()
6235 	{
6236 		int width  = getWindowWidth();
6237 		int height = getWindowHeight();
6238 		scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6239 
6240 		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6241 		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6242 
6243 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6244 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6245 		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6246 
6247 		glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6248 
6249 		glDrawBuffer(GL_NONE);
6250 		glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6251 		glUseProgram(m_program);
6252 		glBindVertexArray(m_attribless_vao);
6253 
6254 		const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6255 									glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6256 
6257 		glViewport(0, 0, width, height);
6258 		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6259 		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6260 
6261 		std::vector<vec4> data(width * height * 3);
6262 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6263 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6264 
6265 		for (int layer = 0; layer < 3; ++layer)
6266 		{
6267 			for (int h = 0; h < height; ++h)
6268 			{
6269 				for (int w = 0; w < width; ++w)
6270 				{
6271 					const vec4 c = data[layer * width * height + h * width + w];
6272 					if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6273 					{
6274 						m_context.getTestContext().getLog()
6275 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6276 							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6277 						return ERROR;
6278 					}
6279 					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6280 					{
6281 						m_context.getTestContext().getLog()
6282 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6283 							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6284 						return ERROR;
6285 					}
6286 					else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6287 					{
6288 						m_context.getTestContext().getLog()
6289 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6290 							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6291 						return ERROR;
6292 					}
6293 				}
6294 			}
6295 		}
6296 
6297 		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6298 		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6299 
6300 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6301 		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6302 
6303 		for (int layer = 0; layer < 3; ++layer)
6304 		{
6305 			for (int h = 0; h < height; ++h)
6306 			{
6307 				for (int w = 0; w < width; ++w)
6308 				{
6309 					const vec4 c = data[layer * width * height + h * width + w];
6310 					if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6311 					{
6312 						m_context.getTestContext().getLog()
6313 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6314 							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6315 						return ERROR;
6316 					}
6317 					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6318 					{
6319 						m_context.getTestContext().getLog()
6320 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6321 							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6322 						return ERROR;
6323 					}
6324 					else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6325 					{
6326 						m_context.getTestContext().getLog()
6327 							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6328 							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6329 						return ERROR;
6330 					}
6331 				}
6332 			}
6333 		}
6334 		return NO_ERROR;
6335 	}
6336 
Cleanup()6337 	virtual long Cleanup()
6338 	{
6339 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6340 		glDrawBuffer(m_draw_buffer);
6341 		glDeleteTextures(1, &m_texture);
6342 		glUseProgram(0);
6343 		glDeleteProgram(m_program);
6344 		glDeleteVertexArrays(1, &m_attribless_vao);
6345 		return NO_ERROR;
6346 	}
6347 };
6348 //-----------------------------------------------------------------------------
6349 // 2.4.4 AdvancedSSOPerSample
6350 //-----------------------------------------------------------------------------
6351 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6352 {
6353 	GLuint m_texture;
6354 	GLuint m_pipeline;
6355 	GLuint m_vao, m_vbo, m_ebo;
6356 	GLuint m_vsp, m_store_fsp, m_load_fsp;
6357 
Setup()6358 	virtual long Setup()
6359 	{
6360 		m_vao		= 0;
6361 		m_vbo		= 0;
6362 		m_ebo		= 0;
6363 		m_vsp		= 0;
6364 		m_store_fsp = 0;
6365 		m_load_fsp  = 0;
6366 		glGenTextures(1, &m_texture);
6367 		glGenProgramPipelines(1, &m_pipeline);
6368 
6369 		return NO_ERROR;
6370 	}
6371 
Run()6372 	virtual long Run()
6373 	{
6374 		if (!SupportedSamples(4))
6375 			return NOT_SUPPORTED;
6376 
6377 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6378 
6379 		const char* const glsl_vs =
6380 			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6381 			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6382 		const char* const glsl_store_fs =
6383 			"#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6384 			"  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6385 		const char* const glsl_load_fs =
6386 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6387 			"layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6388 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6389 			"vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6390 		m_vsp		= BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6391 		m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6392 		m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6393 
6394 		int width  = getWindowWidth();
6395 		int height = getWindowHeight();
6396 		scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6397 
6398 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6399 		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6400 		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6401 
6402 		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6403 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6404 
6405 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6406 
6407 		glClear(GL_COLOR_BUFFER_BIT);
6408 		glViewport(0, 0, width, height);
6409 		glBindVertexArray(m_vao);
6410 		glBindProgramPipeline(m_pipeline);
6411 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6412 
6413 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6414 
6415 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6416 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6417 
6418 		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6419 		{
6420 			return ERROR;
6421 		}
6422 		return NO_ERROR;
6423 	}
6424 
Cleanup()6425 	virtual long Cleanup()
6426 	{
6427 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6428 		glDeleteBuffers(1, &m_vbo);
6429 		glDeleteBuffers(1, &m_ebo);
6430 		glDeleteTextures(1, &m_texture);
6431 		glDeleteProgram(m_vsp);
6432 		glDeleteProgram(m_store_fsp);
6433 		glDeleteProgram(m_load_fsp);
6434 		glDeleteVertexArrays(1, &m_vao);
6435 		glDeleteProgramPipelines(1, &m_pipeline);
6436 		return NO_ERROR;
6437 	}
6438 };
6439 
6440 //-----------------------------------------------------------------------------
6441 // 2.5 AdvancedCopyImage
6442 //-----------------------------------------------------------------------------
6443 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6444 {
6445 	GLuint m_texture[2];
6446 	GLuint m_program;
6447 	GLuint m_vao, m_vbo, m_ebo;
6448 
Setup()6449 	virtual long Setup()
6450 	{
6451 		glGenTextures(2, m_texture);
6452 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6453 
6454 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6455 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6456 		const char* const glsl_fs =
6457 			"#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6458 			"layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6459 			"  ivec2 coord = ivec2(gl_FragCoord);" NL
6460 			"  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6461 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6462 
6463 		return NO_ERROR;
6464 	}
6465 
Run()6466 	virtual long Run()
6467 	{
6468 		int width  = getWindowWidth();
6469 		int height = getWindowHeight();
6470 		scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6471 
6472 		glUseProgram(m_program);
6473 		glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6474 		glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6475 
6476 		std::vector<vec4> data(width * height, vec4(7.0f));
6477 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6478 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6479 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6480 
6481 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6482 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6483 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6484 
6485 		glBindTexture(GL_TEXTURE_2D, 0);
6486 
6487 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6488 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6489 
6490 		glClear(GL_COLOR_BUFFER_BIT);
6491 		glViewport(0, 0, width, height);
6492 		glBindVertexArray(m_vao);
6493 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6494 
6495 		std::vector<vec4> rdata(width * height);
6496 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6497 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6498 
6499 		for (int h = 0; h < height; ++h)
6500 		{
6501 			for (int w = 0; w < width; ++w)
6502 			{
6503 				if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6504 				{
6505 					return ERROR;
6506 				}
6507 			}
6508 		}
6509 		return NO_ERROR;
6510 	}
6511 
Cleanup()6512 	virtual long Cleanup()
6513 	{
6514 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6515 		glUseProgram(0);
6516 		glDeleteBuffers(1, &m_vbo);
6517 		glDeleteBuffers(1, &m_ebo);
6518 		glDeleteTextures(2, m_texture);
6519 		glDeleteProgram(m_program);
6520 		glDeleteVertexArrays(1, &m_vao);
6521 		return NO_ERROR;
6522 	}
6523 };
6524 //-----------------------------------------------------------------------------
6525 // 2.6 AdvancedAllMips
6526 //-----------------------------------------------------------------------------
6527 class AdvancedAllMips : public ShaderImageLoadStoreBase
6528 {
6529 	GLuint m_texture;
6530 	GLuint m_store_program, m_load_program;
6531 	GLuint m_vao, m_vbo, m_ebo;
6532 
Setup()6533 	virtual long Setup()
6534 	{
6535 		glGenTextures(1, &m_texture);
6536 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6537 
6538 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6539 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6540 		const char* const glsl_store_fs =
6541 			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6542 			"  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6543 			"  discard;" NL "}";
6544 		const char* const glsl_load_fs =
6545 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6546 			"layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6547 			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6548 			"    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6549 			"    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6550 		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6551 		m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6552 
6553 		return NO_ERROR;
6554 	}
6555 
Run()6556 	virtual long Run()
6557 	{
6558 		glUseProgram(m_store_program);
6559 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6560 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6561 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6562 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6563 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6564 		glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6565 		glUseProgram(0);
6566 
6567 		glUseProgram(m_load_program);
6568 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6569 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6570 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6571 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6572 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6573 		glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6574 		glUseProgram(0);
6575 
6576 		glBindTexture(GL_TEXTURE_2D, m_texture);
6577 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6578 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6579 		glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6580 		glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6581 		glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6582 		glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6583 		glBindTexture(GL_TEXTURE_2D, 0);
6584 
6585 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6586 		glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587 		glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588 		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589 		glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590 		glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6591 
6592 		glViewport(0, 0, 32, 32);
6593 		glBindVertexArray(m_vao);
6594 
6595 		glClear(GL_COLOR_BUFFER_BIT);
6596 		glUseProgram(m_store_program);
6597 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6598 
6599 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6600 
6601 		glUseProgram(m_load_program);
6602 		glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6603 
6604 		if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6605 		{
6606 			return ERROR;
6607 		}
6608 		return NO_ERROR;
6609 	}
6610 
Cleanup()6611 	virtual long Cleanup()
6612 	{
6613 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6614 		glUseProgram(0);
6615 		glDeleteBuffers(1, &m_vbo);
6616 		glDeleteBuffers(1, &m_ebo);
6617 		glDeleteTextures(1, &m_texture);
6618 		glDeleteProgram(m_store_program);
6619 		glDeleteProgram(m_load_program);
6620 		glDeleteVertexArrays(1, &m_vao);
6621 		return NO_ERROR;
6622 	}
6623 };
6624 //-----------------------------------------------------------------------------
6625 // 2.7 AdvancedCast
6626 //-----------------------------------------------------------------------------
6627 class AdvancedCast : public ShaderImageLoadStoreBase
6628 {
6629 	GLuint m_texture[2];
6630 	GLuint m_program;
6631 	GLuint m_vao, m_vbo, m_ebo;
6632 
Setup()6633 	virtual long Setup()
6634 	{
6635 		glGenTextures(2, m_texture);
6636 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6637 
6638 		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6639 									"void main() {" NL "  gl_Position = i_position;" NL "}";
6640 		const char* const glsl_fs =
6641 			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6642 			"layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6643 			"void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6644 			"  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6645 			"  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6646 			"  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6647 			"  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6648 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6649 
6650 		return NO_ERROR;
6651 	}
6652 
Run()6653 	virtual long Run()
6654 	{
6655 		glUseProgram(m_program);
6656 		glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6657 		glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6658 
6659 		{
6660 			std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6661 			glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6662 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6663 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6664 						 &data[0]);
6665 
6666 			glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6667 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6668 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6669 						 &data[0]);
6670 
6671 			glBindTexture(GL_TEXTURE_2D, 0);
6672 		}
6673 
6674 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6675 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6676 
6677 		glClear(GL_COLOR_BUFFER_BIT);
6678 		glBindVertexArray(m_vao);
6679 		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6680 
6681 		std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6682 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6683 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6684 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6685 
6686 		for (int h = 0; h < getWindowHeight(); ++h)
6687 		{
6688 			for (int w = 0; w < getWindowWidth(); ++w)
6689 			{
6690 				const GLubyte c[4] = {
6691 					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6692 					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6693 				};
6694 				if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6695 				{
6696 					m_context.getTestContext().getLog()
6697 						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6698 						<< ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6699 					return ERROR;
6700 				}
6701 			}
6702 		}
6703 
6704 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6705 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6706 
6707 		for (int h = 0; h < getWindowHeight(); ++h)
6708 		{
6709 			for (int w = 0; w < getWindowWidth(); ++w)
6710 			{
6711 				const GLubyte c[4] = {
6712 					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6713 					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6714 				};
6715 				if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6716 				{
6717 					m_context.getTestContext().getLog()
6718 						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6719 						<< ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6720 					return ERROR;
6721 				}
6722 			}
6723 		}
6724 
6725 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6726 		{
6727 			return ERROR;
6728 		}
6729 		return NO_ERROR;
6730 	}
6731 
Cleanup()6732 	virtual long Cleanup()
6733 	{
6734 		glUseProgram(0);
6735 		glDeleteBuffers(1, &m_vbo);
6736 		glDeleteBuffers(1, &m_ebo);
6737 		glDeleteTextures(2, m_texture);
6738 		glDeleteProgram(m_program);
6739 		glDeleteVertexArrays(1, &m_vao);
6740 		return NO_ERROR;
6741 	}
6742 };
6743 
6744 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6745  *
6746  *  Steps:
6747  *  - create two textures: "source" and "destination". Fill "source"
6748  *  texture with unique values. Fill "destination" texture with zeros,
6749  *  - prepare a program object that will read texel from "source" image at given
6750  *  coordinates and write its value to "destination" image at same
6751  *  coordinates,
6752  *  - bind "source" and "destination" textures as "source" and "destination"
6753  *  image uniforms,
6754  *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6755  *  corner at 1,1),
6756  *  - verify that texel values in "destination" texture match those in
6757  *  "source" texture (use glGetTexImage).
6758  *
6759  *  Test with 2D R8UI textures with following dimensions:
6760  *  - 16x16,
6761  *  - 16x17,
6762  *  - 17x16,
6763  *  - 17x17,
6764  *  - 16x18,
6765  *  - 18x16,
6766  *  - 18x18,
6767  *  - 19x16,
6768  *  - 16x19,
6769  *  - 19x19.
6770  *
6771  *  Note that default data alignment should cause problems with packing/
6772  *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6773  *  of pixel storage mode have to be changed to one byte alignment.
6774  *
6775  *  Program should consist of vertex and fragment shader. Vertex shader should
6776  *  pass vertex position through. Fragment shader should do imageLoad() and
6777  *  imageStore() operations at coordinates gl_FragCoord.
6778  **/
6779 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6780 {
6781 private:
6782 	/* Structures */
6783 	struct TextureDimensions
6784 	{
6785 		GLuint m_width;
6786 		GLuint m_height;
6787 
TextureDimensionsgl4cts::__anonb14d91fe0111::ImageLoadStoreDataAlignmentTest::TextureDimensions6788 		TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6789 		{
6790 		}
6791 	};
6792 
6793 	/* Typedefs */
6794 	typedef std::deque<TextureDimensions> TextureDimensionsList;
6795 
6796 	/* Fields */
6797 	GLuint				  m_destination_texture_id;
6798 	GLuint				  m_program_id;
6799 	TextureDimensionsList m_texture_dimensions;
6800 	GLuint				  m_source_texture_id;
6801 	GLuint				  m_vertex_array_object_id;
6802 	GLuint				  m_vertex_buffer_id;
6803 
6804 public:
6805 	/* Constructor */
ImageLoadStoreDataAlignmentTest()6806 	ImageLoadStoreDataAlignmentTest()
6807 		: m_destination_texture_id(0)
6808 		, m_program_id(0)
6809 		, m_source_texture_id(0)
6810 		, m_vertex_array_object_id(0)
6811 		, m_vertex_buffer_id(0)
6812 	{
6813 		/* Nothing to be done here */
6814 	}
6815 
6816 	/* Methods inherited from SubcaseBase */
Setup()6817 	virtual long Setup()
6818 	{
6819 		/* Shaders code */
6820 		const char* const vertex_shader_code = "#version 400 core\n"
6821 											   "#extension GL_ARB_shader_image_load_store : require\n"
6822 											   "\n"
6823 											   "precision highp float;\n"
6824 											   "\n"
6825 											   "in vec4 vs_in_position;\n"
6826 											   "\n"
6827 											   "void main()\n"
6828 											   "{\n"
6829 											   "    gl_Position = vs_in_position;\n"
6830 											   "}\n";
6831 
6832 		const char* const fragment_shader_code =
6833 			"#version 400 core\n"
6834 			"#extension GL_ARB_shader_image_load_store : require\n"
6835 			"\n"
6836 			"precision highp float;\n"
6837 			"\n"
6838 			"layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6839 			"layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6840 			"\n"
6841 			"void main()\n"
6842 			"{\n"
6843 			"    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6844 			"                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6845 			"\n"
6846 			"    discard;\n"
6847 			"}\n";
6848 
6849 		/* Vertex postions for "full screen" quad, made with triangle strip */
6850 		static const GLfloat m_vertex_buffer_data[] = {
6851 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6852 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6853 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6854 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6855 		};
6856 
6857 		/* Result of BuildProgram operation */
6858 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6859 
6860 		/* Add all tested texture dimensions */
6861 		m_texture_dimensions.push_back(TextureDimensions(16, 16));
6862 		m_texture_dimensions.push_back(TextureDimensions(16, 17));
6863 		m_texture_dimensions.push_back(TextureDimensions(17, 16));
6864 		m_texture_dimensions.push_back(TextureDimensions(17, 17));
6865 		m_texture_dimensions.push_back(TextureDimensions(16, 18));
6866 		m_texture_dimensions.push_back(TextureDimensions(18, 16));
6867 		m_texture_dimensions.push_back(TextureDimensions(18, 18));
6868 		m_texture_dimensions.push_back(TextureDimensions(16, 19));
6869 		m_texture_dimensions.push_back(TextureDimensions(19, 16));
6870 		m_texture_dimensions.push_back(TextureDimensions(19, 19));
6871 
6872 		/* Clean previous error */
6873 		glGetError();
6874 
6875 		/* Set single-byte data alignment */
6876 		glPixelStorei(GL_PACK_ALIGNMENT, 1);
6877 		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6878 		GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6879 
6880 		/* Prepare buffer with vertex positions of "full screen" quad" */
6881 		glGenBuffers(1, &m_vertex_buffer_id);
6882 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6883 
6884 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6885 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6886 
6887 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6888 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6889 
6890 		/* Generate vertex array object */
6891 		glGenVertexArrays(1, &m_vertex_array_object_id);
6892 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6893 
6894 		/* Prepare program object */
6895 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6896 									fragment_shader_code, &is_program_correct);
6897 		if (false == is_program_correct)
6898 		{
6899 			return ERROR;
6900 		}
6901 
6902 		/* Done */
6903 		return NO_ERROR;
6904 	}
6905 
Cleanup()6906 	virtual long Cleanup()
6907 	{
6908 		/* Reset OpenGL state */
6909 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6910 		glBindTexture(GL_TEXTURE_2D, 0);
6911 		glBindVertexArray(0);
6912 		glUseProgram(0);
6913 
6914 		/* Delete program */
6915 		if (0 != m_program_id)
6916 		{
6917 			glDeleteProgram(m_program_id);
6918 			m_program_id = 0;
6919 		}
6920 
6921 		/* Delete textures */
6922 		if (0 != m_destination_texture_id)
6923 		{
6924 			glDeleteTextures(1, &m_destination_texture_id);
6925 			m_destination_texture_id = 0;
6926 		}
6927 
6928 		if (0 != m_source_texture_id)
6929 		{
6930 			glDeleteTextures(1, &m_source_texture_id);
6931 			m_source_texture_id = 0;
6932 		}
6933 
6934 		/* Delete vertex array object */
6935 		if (0 != m_vertex_array_object_id)
6936 		{
6937 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
6938 			m_vertex_array_object_id = 0;
6939 		}
6940 
6941 		/* Delete buffer */
6942 		if (0 != m_vertex_buffer_id)
6943 		{
6944 			glDeleteBuffers(1, &m_vertex_buffer_id);
6945 			m_vertex_buffer_id = 0;
6946 		}
6947 
6948 		/* Done */
6949 		return NO_ERROR;
6950 	}
6951 
Run()6952 	virtual long Run()
6953 	{
6954 		bool result = true;
6955 
6956 		/* For each dimension */
6957 		for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6958 			 ++it)
6959 		{
6960 			/* Prepare "source" and "destination" textures */
6961 			GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6962 								"Create2DR8UIDestinationTexture");
6963 			GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6964 								"Create2DR8UISourceTexture");
6965 
6966 			/* Copy texture data with imageLoad() and imageStore() operations */
6967 			Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6968 
6969 			/* Compare "source" and "destination" textures */
6970 			if (false ==
6971 				Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6972 			{
6973 				m_context.getTestContext().getLog()
6974 					<< tcu::TestLog::Message
6975 					<< "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6976 					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6977 
6978 				result = false;
6979 			}
6980 
6981 			/* Destroy "source" and "destination" textures */
6982 			glDeleteTextures(1, &m_destination_texture_id);
6983 			glDeleteTextures(1, &m_source_texture_id);
6984 
6985 			m_destination_texture_id = 0;
6986 			m_source_texture_id		 = 0;
6987 		}
6988 
6989 		if (false == result)
6990 		{
6991 			return ERROR;
6992 		}
6993 
6994 		/* Done */
6995 		return NO_ERROR;
6996 	}
6997 
6998 private:
6999 	/* Private methods */
7000 
7001 	/** Binds a texture to user-specified image unit and updates relevant sampler uniform
7002 	 *
7003 	 * @param program_id   Program object id
7004 	 * @param texture_id   Texture id
7005 	 * @param image_unit   Index of image unit
7006 	 * @param uniform_name Name of image uniform
7007 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7008 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7009 	{
7010 		/* Uniform location and invalid value */
7011 		static const GLint invalid_uniform_location = -1;
7012 		GLint			   image_uniform_location   = 0;
7013 
7014 		/* Get uniform location */
7015 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7016 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7017 		if (invalid_uniform_location == image_uniform_location)
7018 		{
7019 			throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7020 		}
7021 
7022 		/* Bind texture to image unit */
7023 		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7024 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7025 
7026 		/* Set uniform to image unit */
7027 		glUniform1i(image_uniform_location, image_unit);
7028 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7029 	}
7030 
7031 	/** Compare two 2D R8UI textures
7032 	 *
7033 	 * @param left_texture_id  Id of "left" texture object
7034 	 * @param right_texture_id Id of "right" texture object
7035 	 * @param width            Width of the textures
7036 	 * @param height           Height of the textures
7037 	 *
7038 	 * @return true when texture data is identical, false otherwise
7039 	 **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7040 	bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7041 	{
7042 		/* Size of textures */
7043 		const GLuint texture_data_size = width * height;
7044 
7045 		/* Storage for texture data */
7046 		std::vector<GLubyte> left_texture_data;
7047 		std::vector<GLubyte> right_texture_data;
7048 
7049 		/* Alocate memory for texture data */
7050 		left_texture_data.resize(texture_data_size);
7051 		right_texture_data.resize(texture_data_size);
7052 
7053 		/* Get "left" texture data */
7054 		glBindTexture(GL_TEXTURE_2D, left_texture_id);
7055 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7056 
7057 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7058 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7059 
7060 		/* Get "right" texture data */
7061 		glBindTexture(GL_TEXTURE_2D, right_texture_id);
7062 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7063 
7064 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7065 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7066 
7067 		/* Compare texels */
7068 		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7069 	}
7070 
7071 	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7072 	 *
7073 	 * @param destination_texture_id Id of "destination" texture object
7074 	 * @param source_texture_id      Id of "source" texture object
7075 	 **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7076 	void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7077 	{
7078 		/* Uniform names */
7079 		static const char* const destination_image_uniform_name = "u_destination_image";
7080 		static const char* const source_image_uniform_name		= "u_source_image";
7081 
7082 		/* Attribute name */
7083 		static const char* const position_attribute_name = "vs_in_position";
7084 
7085 		/* Attribute location and invalid value */
7086 		static const GLint invalid_attribute_location  = -1;
7087 		GLint			   position_attribute_location = 0;
7088 
7089 		/* Set current program */
7090 		glUseProgram(m_program_id);
7091 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7092 
7093 		/* Bind vertex array object */
7094 		glBindVertexArray(m_vertex_array_object_id);
7095 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7096 
7097 		/* Bind buffer with quad vertex positions */
7098 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7099 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7100 
7101 		/* Set up position attribute */
7102 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7103 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7104 		if (invalid_attribute_location == position_attribute_location)
7105 		{
7106 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7107 									 __LINE__);
7108 		}
7109 
7110 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7111 							  0 /* stride */, 0);
7112 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7113 
7114 		glEnableVertexAttribArray(position_attribute_location);
7115 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7116 
7117 		/* Set up textures as source and destination images */
7118 		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7119 		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7120 
7121 		/* Execute draw */
7122 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7123 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7124 	}
7125 
7126 	/** Create 2D R8UI texture and fills it with zeros
7127 	 *
7128 	 * @param width          Width of created texture
7129 	 * @param height         Height of created texture
7130 	 * @param out_texture_id Id of created texture, not modified if operation fails
7131 	 *
7132 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7133 	 **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7134 	GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7135 	{
7136 		/* Texture size */
7137 		const GLuint texture_size = width * height;
7138 
7139 		/* Prepare storage for texture data */
7140 		std::vector<GLubyte> texture_data;
7141 		texture_data.resize(texture_size);
7142 
7143 		/* Set all texels */
7144 		for (GLuint i = 0; i < texture_size; ++i)
7145 		{
7146 			texture_data[i] = 0;
7147 		}
7148 
7149 		/* Create texture */
7150 		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7151 	}
7152 
7153 	/** Create 2D R8UI texture and fills it with increasing values, starting from 0
7154 	 *
7155 	 * @param width          Width of created texture
7156 	 * @param height         Height of created texture
7157 	 * @param out_texture_id Id of created texture, not modified if operation fails
7158 	 *
7159 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7160 	 **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7161 	GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7162 	{
7163 		/* Texture size */
7164 		const GLuint texture_size = width * height;
7165 
7166 		/* Value of texel */
7167 		GLubyte texel_value = 0;
7168 
7169 		/* Prepare storage for texture data */
7170 		std::vector<GLubyte> texture_data;
7171 		texture_data.resize(texture_size);
7172 
7173 		/* Set all texels */
7174 		for (GLuint i = 0; i < texture_size; ++i)
7175 		{
7176 			texture_data[i] = texel_value++;
7177 		}
7178 
7179 		/* Create texture */
7180 		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7181 	}
7182 
7183 	/** Create 2D R8UI texture and fills it with user-provided data
7184 	 *
7185 	 * @param width          Width of created texture
7186 	 * @param height         Height of created texture
7187 	 * @param texture_data   Texture data
7188 	 * @param out_texture_id Id of created texture, not modified if operation fails
7189 	 *
7190 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7191 	 **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7192 	GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7193 							   GLuint& out_texture_id)
7194 	{
7195 		GLenum err		  = 0;
7196 		GLuint texture_id = 0;
7197 
7198 		/* Generate texture */
7199 		glGenTextures(1, &texture_id);
7200 		err = glGetError();
7201 		if (GL_NO_ERROR != err)
7202 		{
7203 			return err;
7204 		}
7205 
7206 		/* Bind texture */
7207 		glBindTexture(GL_TEXTURE_2D, texture_id);
7208 		err = glGetError();
7209 		if (GL_NO_ERROR != err)
7210 		{
7211 			glDeleteTextures(1, &texture_id);
7212 			return err;
7213 		}
7214 
7215 		/* Allocate storage and fill texture */
7216 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7217 					 GL_UNSIGNED_BYTE, &texture_data[0]);
7218 		err = glGetError();
7219 		if (GL_NO_ERROR != err)
7220 		{
7221 			glDeleteTextures(1, &texture_id);
7222 			return err;
7223 		}
7224 
7225 		/* Make texture complete */
7226 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7227 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7228 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7229 		err = glGetError();
7230 		if (GL_NO_ERROR != err)
7231 		{
7232 			glDeleteTextures(1, &texture_id);
7233 			return err;
7234 		}
7235 
7236 		/* Set out_texture_id */
7237 		out_texture_id = texture_id;
7238 
7239 		/* Done */
7240 		return GL_NO_ERROR;
7241 	}
7242 };
7243 
7244 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7245  *
7246  *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7247  *
7248  *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7249  *  | Type           | Dimensions |
7250  *  | 2D_ARRAY       | 64x64x6    |
7251  *  | 3D             | 64x64x6    |
7252  *  | CUBE_MAP       | 64         |
7253  *  | CUBE_MAP_ARRAY | 64x3       |
7254  *
7255  *  Use RGBA8 format. All layers shall be tested.
7256  *
7257  *  Program should consist of vertex and fragment shader. Vertex shader should
7258  *  pass vertex position through. Fragment shader should do imageLoad() and
7259  *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7260  *  use image2D as image type.
7261  **/
7262 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7263 {
7264 private:
7265 	/* Structures */
7266 	struct TextureShapeDefinition
7267 	{
7268 		GLuint m_edge;
7269 		GLuint m_n_elements;
7270 		GLenum m_type;
7271 
TextureShapeDefinitiongl4cts::__anonb14d91fe0111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7272 		TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7273 			: m_edge(edge), m_n_elements(n_elements), m_type(type)
7274 		{
7275 		}
7276 	};
7277 
7278 	/* Typedefs */
7279 	typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7280 
7281 	/* Fields */
7282 	GLuint					   m_destination_texture_id;
7283 	GLuint					   m_program_id;
7284 	TextureShapeDefinitionList m_texture_shape_definitions;
7285 	GLuint					   m_source_texture_id;
7286 	GLuint					   m_vertex_array_object_id;
7287 	GLuint					   m_vertex_buffer_id;
7288 
7289 public:
7290 	/* Constructor */
ImageLoadStoreNonLayeredBindingTest()7291 	ImageLoadStoreNonLayeredBindingTest()
7292 		: m_destination_texture_id(0)
7293 		, m_program_id(0)
7294 		, m_source_texture_id(0)
7295 		, m_vertex_array_object_id(0)
7296 		, m_vertex_buffer_id(0)
7297 	{
7298 		/* Nothing to be done here */
7299 	}
7300 
7301 	/* Methods inherited from SubcaseBase */
Setup()7302 	virtual long Setup()
7303 	{
7304 		/* Shaders code */
7305 		const char* const vertex_shader_code = "#version 400 core\n"
7306 											   "#extension GL_ARB_shader_image_load_store : require\n"
7307 											   "\n"
7308 											   "precision highp float;\n"
7309 											   "\n"
7310 											   "in vec4 vs_in_position;\n"
7311 											   "\n"
7312 											   "void main()\n"
7313 											   "{\n"
7314 											   "    gl_Position = vs_in_position;\n"
7315 											   "}\n";
7316 
7317 		const char* const fragment_shader_code =
7318 			"#version 400 core\n"
7319 			"#extension GL_ARB_shader_image_load_store : require\n"
7320 			"\n"
7321 			"precision highp float;\n"
7322 			"\n"
7323 			"layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7324 			"layout(rgba8) readonly  uniform image2D u_source_image;\n"
7325 			"\n"
7326 			"void main()\n"
7327 			"{\n"
7328 			"    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7329 			"                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7330 			"\n"
7331 			"    discard;\n"
7332 			"}\n";
7333 
7334 		/* Vertex postions for "full screen" quad, defined as a triangle strip */
7335 		static const GLfloat m_vertex_buffer_data[] = {
7336 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7337 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7338 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7339 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7340 		};
7341 
7342 		/* Result of BuildProgram operation */
7343 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7344 
7345 		/* Add all tested texture shapes */
7346 		int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7347 		m_texture_shape_definitions.push_back(
7348 			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7349 		m_texture_shape_definitions.push_back(
7350 			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7351 		m_texture_shape_definitions.push_back(
7352 			TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7353 		m_texture_shape_definitions.push_back(
7354 			TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7355 
7356 		/* Prepare buffer with vertex positions of "full screen" quad" */
7357 		glGenBuffers(1, &m_vertex_buffer_id);
7358 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7359 
7360 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7361 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7362 
7363 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7364 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7365 
7366 		/* Generate vertex array object */
7367 		glGenVertexArrays(1, &m_vertex_array_object_id);
7368 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7369 
7370 		/* Prepare program object */
7371 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7372 									fragment_shader_code, &is_program_correct);
7373 		if (false == is_program_correct)
7374 		{
7375 			return ERROR;
7376 		}
7377 
7378 		/* Done */
7379 		return NO_ERROR;
7380 	}
7381 
Cleanup()7382 	virtual long Cleanup()
7383 	{
7384 		/* Reset OpenGL state */
7385 		glBindBuffer(GL_ARRAY_BUFFER, 0);
7386 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7387 		glBindTexture(GL_TEXTURE_3D, 0);
7388 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7389 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7390 		glBindVertexArray(0);
7391 		glUseProgram(0);
7392 
7393 		/* Delete program */
7394 		if (0 != m_program_id)
7395 		{
7396 			glDeleteProgram(m_program_id);
7397 			m_program_id = 0;
7398 		}
7399 
7400 		/* Delete textures */
7401 		if (0 != m_destination_texture_id)
7402 		{
7403 			glDeleteTextures(1, &m_destination_texture_id);
7404 			m_destination_texture_id = 0;
7405 		}
7406 
7407 		if (0 != m_source_texture_id)
7408 		{
7409 			glDeleteTextures(1, &m_source_texture_id);
7410 			m_source_texture_id = 0;
7411 		}
7412 
7413 		/* Delete vertex array object */
7414 		if (0 != m_vertex_array_object_id)
7415 		{
7416 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
7417 			m_vertex_array_object_id = 0;
7418 		}
7419 
7420 		/* Delete buffer */
7421 		if (0 != m_vertex_buffer_id)
7422 		{
7423 			glDeleteBuffers(1, &m_vertex_buffer_id);
7424 			m_vertex_buffer_id = 0;
7425 		}
7426 
7427 		/* Done */
7428 		return NO_ERROR;
7429 	}
7430 
Run()7431 	virtual long Run()
7432 	{
7433 		bool result = true;
7434 
7435 		/* For each shape */
7436 		for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7437 			 m_texture_shape_definitions.end() != it; ++it)
7438 		{
7439 			const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7440 
7441 			/* Prepare "source" and "destination" textures */
7442 			GLU_EXPECT_NO_ERROR(
7443 				CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7444 				"Create2DR8UIDestinationTexture");
7445 			GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7446 								"Create2DR8UISourceTexture");
7447 
7448 			/* Copy texture data with imageLoad() and imageStore() operations */
7449 			CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7450 
7451 			/* Compare "source" and "destination" textures */
7452 			if (false ==
7453 				CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7454 			{
7455 				const char* texture_type = "";
7456 				switch (it->m_type)
7457 				{
7458 				case GL_TEXTURE_2D_ARRAY:
7459 					texture_type = "2d array";
7460 					break;
7461 				case GL_TEXTURE_3D:
7462 					texture_type = "3d";
7463 					break;
7464 				case GL_TEXTURE_CUBE_MAP:
7465 					texture_type = "Cube map";
7466 					break;
7467 				case GL_TEXTURE_CUBE_MAP_ARRAY:
7468 					texture_type = "Cube map array";
7469 					break;
7470 				}
7471 
7472 				m_context.getTestContext().getLog()
7473 					<< tcu::TestLog::Message
7474 					<< "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7475 					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7476 
7477 				result = false;
7478 			}
7479 
7480 			/* Destroy "source" and "destination" textures */
7481 			glDeleteTextures(1, &m_destination_texture_id);
7482 			glDeleteTextures(1, &m_source_texture_id);
7483 
7484 			m_destination_texture_id = 0;
7485 			m_source_texture_id		 = 0;
7486 		}
7487 
7488 		if (false == result)
7489 		{
7490 			return ERROR;
7491 		}
7492 
7493 		/* Done */
7494 		return NO_ERROR;
7495 	}
7496 
7497 private:
7498 	/* Private methods */
7499 
7500 	/** Binds a texture to user-specified image unit and update relevant sampler uniform
7501 	 *
7502 	 * @param program_id   Program object id
7503 	 * @param texture_id   Texture id
7504 	 * @param image_unit   Index of image unit
7505 	 * @param layer        Index of layer bound to unit
7506 	 * @param uniform_name Name of image uniform
7507 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7508 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7509 							const char* uniform_name)
7510 	{
7511 		static const GLint invalid_uniform_location = -1;
7512 		GLint			   image_uniform_location   = 0;
7513 
7514 		/* Get uniform location */
7515 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7516 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7517 		if (invalid_uniform_location == image_uniform_location)
7518 		{
7519 			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7520 		}
7521 
7522 		/* Bind texture to image unit */
7523 		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7524 						   GL_RGBA8);
7525 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7526 
7527 		/* Set uniform to image unit */
7528 		glUniform1i(image_uniform_location, image_unit);
7529 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7530 	}
7531 
7532 	/** Compare two 2D R8UI textures
7533 	 *
7534 	 * @param left_texture_id  Id of "left" texture object
7535 	 * @param right_texture_id Id of "right" texture object
7536 	 * @param edge             Length of texture edge
7537 	 * @param n_layers         Number of layers to compare
7538 	 * @param type             Type of texture
7539 	 *
7540 	 * @return true when texture data is found identical, false otherwise
7541 	 **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7542 	bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7543 							  GLenum type)
7544 	{
7545 		static const GLuint n_components	  = 4; /* RGBA */
7546 		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7547 
7548 		/* Storage for texture data */
7549 		std::vector<GLubyte> left_texture_data;
7550 		std::vector<GLubyte> right_texture_data;
7551 
7552 		ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7553 		ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7554 
7555 		/* Compare texels */
7556 		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7557 	}
7558 
7559 	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7560 	 *
7561 	 * @param destination_texture_id Id of "destination" texture object
7562 	 * @param source_texture_id      Id of "source" texture object
7563 	 * @param n_layers               Number of layers
7564 	 **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7565 	void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7566 	{
7567 		for (GLuint layer = 0; layer < n_layers; ++layer)
7568 		{
7569 			CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7570 		}
7571 	}
7572 
7573 	/** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7574 	 *
7575 	 * @param destination_texture_id Id of "destination" texture object
7576 	 * @param source_texture_id      Id of "source" texture object
7577 	 * @param layer                  Index of layer
7578 	 **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7579 	void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7580 	{
7581 		/* Uniform names */
7582 		static const char* const destination_image_uniform_name = "u_destination_image";
7583 		static const char* const source_image_uniform_name		= "u_source_image";
7584 
7585 		/* Attribute name */
7586 		static const char* const position_attribute_name = "vs_in_position";
7587 
7588 		/* Attribute location and invalid value */
7589 		static const GLint invalid_attribute_location  = -1;
7590 		GLint			   position_attribute_location = 0;
7591 
7592 		/* Set current program */
7593 		glUseProgram(m_program_id);
7594 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7595 
7596 		/* Bind vertex array object */
7597 		glBindVertexArray(m_vertex_array_object_id);
7598 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7599 
7600 		/* Bind buffer with quad vertex positions */
7601 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7602 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7603 
7604 		/* Set up vertex attribute array for position attribute */
7605 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7606 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7607 		if (invalid_attribute_location == position_attribute_location)
7608 		{
7609 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7610 									 __LINE__);
7611 		}
7612 
7613 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7614 							  0 /* stride */, 0 /* pointer */);
7615 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7616 
7617 		glEnableVertexAttribArray(position_attribute_location);
7618 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7619 
7620 		/* Set up textures as source and destination image samplers */
7621 		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7622 						   destination_image_uniform_name);
7623 		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7624 
7625 		/* Execute draw */
7626 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7627 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7628 	}
7629 
7630 	/** Creates RGBA8 texture of given type and fills it with zeros
7631 	 *
7632 	 * @param edge           Edge of created texture
7633 	 * @param n_elements     Number of elements in texture array
7634 	 * @param target         Target of created texture
7635 	 * @param out_texture_id Id of created texture, not modified if operation fails
7636 	 *
7637 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7638 	 **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7639 	GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7640 	{
7641 		/* Constasts to calculate texture size */
7642 		static const GLuint n_components = 4; /* RGBA */
7643 		const GLuint		layer_size   = edge * edge * n_components;
7644 		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7645 		const GLuint		texture_size = layer_size * n_layers;
7646 
7647 		/* Prepare storage for texture data */
7648 		std::vector<GLubyte> texture_data;
7649 		texture_data.resize(texture_size);
7650 
7651 		/* Set all texels */
7652 		for (GLuint i = 0; i < texture_size; ++i)
7653 		{
7654 			texture_data[i] = 0;
7655 		}
7656 
7657 		/* Create texture */
7658 		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7659 	}
7660 
7661 	/** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7662 	 *
7663 	 * @param edge           Edge of created texture
7664 	 * @param n_elements     Number of elements in texture array
7665 	 * @param target         Target of created texture
7666 	 * @param out_texture_id Id of created texture, not modified if operation fails
7667 	 *
7668 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7669 	 **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7670 	GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7671 	{
7672 		/* Constants to calculate texture size */
7673 		static const GLuint n_components = 4; /* RGBA */
7674 		const GLuint		layer_size   = edge * edge * n_components;
7675 		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7676 		const GLuint		texture_size = layer_size * n_layers;
7677 
7678 		/* Value of texel */
7679 		GLubyte texel[4] = { 0, 0, 0, 0xaa };
7680 
7681 		/* Prepare storage for texture data */
7682 		std::vector<GLubyte> texture_data;
7683 		texture_data.resize(texture_size);
7684 
7685 		/* Set all texels */
7686 		for (GLuint layer = 0; layer < n_layers; ++layer)
7687 		{
7688 			const GLuint layer_offset = layer_size * layer;
7689 
7690 			texel[2] = static_cast<GLubyte>(layer);
7691 
7692 			for (GLuint y = 0; y < edge; ++y)
7693 			{
7694 				const GLuint line_offset = y * edge * n_components + layer_offset;
7695 
7696 				texel[1] = static_cast<GLubyte>(y);
7697 
7698 				for (GLuint x = 0; x < edge; ++x)
7699 				{
7700 					const GLuint texel_offset = x * n_components + line_offset;
7701 					texel[0]				  = static_cast<GLubyte>(x);
7702 
7703 					for (GLuint component = 0; component < n_components; ++component)
7704 					{
7705 						texture_data[texel_offset + component] = texel[component];
7706 					}
7707 				}
7708 			}
7709 		}
7710 
7711 		/* Create texture */
7712 		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7713 	}
7714 
7715 	/** Creates RGBA8 texture of given type and fills it provided data
7716 	 *
7717 	 * @param edge           Edge of created texture
7718 	 * @param n_elements     Number of elements in texture array
7719 	 * @param target         Target of created texture
7720 	 * @param texture_data   Texture data
7721 	 * @param out_texture_id Id of created texture, not modified if operation fails
7722 	 *
7723 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7724 	 **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7725 	GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7726 							  GLuint& out_texture_id)
7727 	{
7728 		GLenum err		  = 0;
7729 		GLuint texture_id = 0;
7730 
7731 		/* Generate texture */
7732 		glGenTextures(1, &texture_id);
7733 		err = glGetError();
7734 		if (GL_NO_ERROR != err)
7735 		{
7736 			return err;
7737 		}
7738 
7739 		/* Bind texture */
7740 		glBindTexture(target, texture_id);
7741 		err = glGetError();
7742 		if (GL_NO_ERROR != err)
7743 		{
7744 			glDeleteTextures(1, &texture_id);
7745 			return err;
7746 		}
7747 
7748 		/* Allocate storage and fill texture */
7749 		if (GL_TEXTURE_CUBE_MAP != target)
7750 		{
7751 			glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7752 						 GL_UNSIGNED_BYTE, &texture_data[0]);
7753 		}
7754 		else
7755 		{
7756 			const GLuint n_components = 4;
7757 			const GLuint layer_size   = edge * edge * n_components;
7758 
7759 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7760 						 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7761 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7762 						 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7763 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7764 						 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7765 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7766 						 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7767 			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7768 						 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7769 			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7770 						 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7771 		}
7772 		err = glGetError();
7773 		if (GL_NO_ERROR != err)
7774 		{
7775 			glDeleteTextures(1, &texture_id);
7776 			return err;
7777 		}
7778 
7779 		/* Make texture complete */
7780 		glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7781 		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7782 		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7783 		err = glGetError();
7784 		if (GL_NO_ERROR != err)
7785 		{
7786 			glDeleteTextures(1, &texture_id);
7787 			return err;
7788 		}
7789 
7790 		/* Set out_texture_id */
7791 		out_texture_id = texture_id;
7792 
7793 		/* Done */
7794 		return GL_NO_ERROR;
7795 	}
7796 
7797 	/** Extracts texture data
7798 	 *
7799 	 * @param texture_id   Id of texture object
7800 	 * @param edge         Length of texture edge
7801 	 * @param n_layers     Number of layers
7802 	 * @param target       Target of texture
7803 	 * @param texture_data Extracted texture data
7804 	 **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7805 	void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7806 							std::vector<GLubyte>& texture_data)
7807 	{
7808 		static const GLuint n_components	  = 4; /* RGBA */
7809 		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7810 
7811 		/* Alocate memory for texture data */
7812 		texture_data.resize(texture_data_size);
7813 
7814 		/* Bind texture */
7815 		glBindTexture(target, texture_id);
7816 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7817 
7818 		/* Get data */
7819 		if (GL_TEXTURE_CUBE_MAP != target)
7820 		{
7821 			glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7822 		}
7823 		else
7824 		{
7825 			const GLuint layer_size = edge * edge * n_components;
7826 
7827 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7828 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7829 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7830 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7831 			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7832 			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7833 		}
7834 
7835 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7836 	}
7837 
7838 	/** Get number of layers per single element for given type of texture
7839 	 *
7840 	 * @param target Target of texture
7841 	 *
7842 	 * @return Number of layers
7843 	 **/
GetLayersPerElement(GLenum target)7844 	GLuint GetLayersPerElement(GLenum target)
7845 	{
7846 		switch (target)
7847 		{
7848 		case GL_TEXTURE_2D_ARRAY:
7849 		case GL_TEXTURE_3D:
7850 			return 1;
7851 		case GL_TEXTURE_CUBE_MAP:
7852 		case GL_TEXTURE_CUBE_MAP_ARRAY:
7853 			return 6;
7854 		default:
7855 			throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7856 		}
7857 	}
7858 
7859 	/** Get total number of layers in texture of given type and number of array elements
7860 	 *
7861 	 * @param n_elements Number of elements in texture array
7862 	 * @param target     Target of texture
7863 	 *
7864 	 * @return Number of layers
7865 	 **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7866 	GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7867 	{
7868 		return GetLayersPerElement(target) * n_elements;
7869 	}
7870 };
7871 
7872 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7873  *
7874  *  Load from incomplete textures should return 0.
7875  *  Store to incomplete textures should be ignored.
7876  *
7877  *  Steps:
7878  *  - create two incomplete textures: "incomplete_source" and
7879  *  "incomplete_destination",
7880  *  - create two complete textures: "complete_source" and
7881  *  "complete_destination",
7882  *  - fill all textures with unique values,
7883  *  - prepare program that will:
7884  *      * load texel from "incomplete_source" and store its value to
7885  *      "complete_destination",
7886  *      * load texel from "complete_source" and store its value to
7887  *      "incomplete_destination".
7888  *  - bind textures to corresponding image uniforms
7889  *  - execute program for all texels,
7890  *  - verify that "incomplete_destination" was not modified and
7891  *  "complete_destination" is filled with zeros.
7892  *
7893  *  Texture is considered incomplete when it has enabled mipmaping (see below)
7894  *  and does not have all mipmap levels defined.  But for the case of Image
7895  *  accessing, it is considered invalid if it is mipmap-incomplete and the
7896  *  level is different to the base level (base-incomplete).
7897  *
7898  *  Creation of incomplete texture:
7899  *  - generate and bind texture object id,
7900  *  - call TexImage2D with <level>: 0,
7901  *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7902  *  sure, it should be initial value),
7903  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7904  *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7905  *  height)).
7906  *
7907  *  Creation of complete texture:
7908  *  - generate and bind texture object id,
7909  *  - call TexImage2D with <level>: 0,
7910  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7911  *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7912  *
7913  *  Binding:
7914  *  - Set level == base_level for complete destinations.
7915  *  - Set level != base_level for incomplete destinations that are using
7916  *    mipmap-incomplete textures.
7917  *
7918  *  Test with 2D 64x64 RGBA8 textures.
7919  *
7920  *  Program should consist of vertex and fragment shader. Vertex shader should
7921  *  pass vertex position through. Fragment shader should do imageLoad() and
7922  *  imageStore() operations at coordinates gl_FragCoord.
7923  **/
7924 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7925 {
7926 private:
7927 	/* Constants */
7928 	/* Magic numbers that will identify textures, which will be used as their
7929 	 * texel value.
7930 	 */
7931 	static const GLubyte m_complete_destination_magic_number   = 0x11;
7932 	static const GLubyte m_complete_source_magic_number		   = 0x22;
7933 	static const GLubyte m_incomplete_destination_magic_number = 0x33;
7934 	static const GLubyte m_incomplete_source_magic_number	  = 0x44;
7935 
7936 	/* Texture edge */
7937 	GLuint m_texture_edge;
7938 
7939 	/* Fields */
7940 	GLuint m_complete_destination_texture_id;
7941 	GLuint m_complete_source_texture_id;
7942 	GLuint m_incomplete_destination_texture_id;
7943 	GLuint m_incomplete_source_texture_id;
7944 	GLuint m_program_id;
7945 	GLuint m_vertex_array_object_id;
7946 	GLuint m_vertex_buffer_id;
7947 
7948 public:
7949 	/* Constructor */
ImageLoadStoreIncompleteTexturesTest()7950 	ImageLoadStoreIncompleteTexturesTest()
7951 		: m_texture_edge(0)
7952 		, m_complete_destination_texture_id(0)
7953 		, m_complete_source_texture_id(0)
7954 		, m_incomplete_destination_texture_id(0)
7955 		, m_incomplete_source_texture_id(0)
7956 		, m_program_id(0)
7957 		, m_vertex_array_object_id(0)
7958 		, m_vertex_buffer_id(0)
7959 	{
7960 		/* Nothing to be done here */
7961 	}
7962 
7963 	/* Methods inherited from SubcaseBase */
Setup()7964 	virtual long Setup()
7965 	{
7966 		/* Shaders code */
7967 		const char* const vertex_shader_code = "#version 400 core\n"
7968 											   "#extension GL_ARB_shader_image_load_store : require\n"
7969 											   "\n"
7970 											   "precision highp float;\n"
7971 											   "\n"
7972 											   "in vec4 vs_in_position;\n"
7973 											   "\n"
7974 											   "void main()\n"
7975 											   "{\n"
7976 											   "    gl_Position = vs_in_position;\n"
7977 											   "}\n";
7978 
7979 		const char* const fragment_shader_code =
7980 			"#version 400 core\n"
7981 			"#extension GL_ARB_shader_image_load_store : require\n"
7982 			"\n"
7983 			"precision highp float;\n"
7984 			"\n"
7985 			"layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7986 			"layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
7987 			"layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7988 			"layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
7989 			"\n"
7990 			"void main()\n"
7991 			"{\n"
7992 			"    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
7993 			"    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7994 
7995 			"    imageStore(u_complete_destination_image,\n"
7996 			"               ivec2(gl_FragCoord),\n"
7997 			"               incomplete_loaded_color);\n"
7998 			"    imageStore(u_incomplete_destination_image,\n"
7999 			"               ivec2(gl_FragCoord),\n"
8000 			"               complete_loaded_color);\n"
8001 			"\n"
8002 			"    discard;\n"
8003 			"}\n";
8004 
8005 		/* Vertex postions for "full screen" quad, made with triangle strip */
8006 		static const GLfloat m_vertex_buffer_data[] = {
8007 			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8008 			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
8009 			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
8010 			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
8011 		};
8012 
8013 		/* Result of BuildProgram operation */
8014 		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8015 
8016 		/* Clean previous error */
8017 		glGetError();
8018 
8019 		m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8020 
8021 		/* Prepare textures */
8022 		GLU_EXPECT_NO_ERROR(
8023 			Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8024 			"Create2DRGBA8CompleteTexture");
8025 		GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8026 							"Create2DRGBA8CompleteTexture");
8027 		GLU_EXPECT_NO_ERROR(
8028 			Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8029 			"Create2DRGBA8IncompleteTexture");
8030 		GLU_EXPECT_NO_ERROR(
8031 			Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8032 			"Create2DRGBA8IncompleteTexture");
8033 
8034 		/* Prepare buffer with vertex positions of "full screen" quad" */
8035 		glGenBuffers(1, &m_vertex_buffer_id);
8036 		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8037 
8038 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8039 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8040 
8041 		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8042 		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8043 
8044 		/* Generate vertex array object */
8045 		glGenVertexArrays(1, &m_vertex_array_object_id);
8046 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8047 
8048 		/* Prepare program object */
8049 		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8050 									fragment_shader_code, &is_program_correct);
8051 
8052 		if (false == is_program_correct)
8053 		{
8054 			return ERROR;
8055 		}
8056 
8057 		/* Done */
8058 		return NO_ERROR;
8059 	}
8060 
Cleanup()8061 	virtual long Cleanup()
8062 	{
8063 		/* Reset OpenGL state */
8064 		glBindBuffer(GL_ARRAY_BUFFER, 0);
8065 		glBindTexture(GL_TEXTURE_2D, 0);
8066 		glBindVertexArray(0);
8067 		glUseProgram(0);
8068 
8069 		/* Delete program */
8070 		if (0 != m_program_id)
8071 		{
8072 			glDeleteProgram(m_program_id);
8073 			m_program_id = 0;
8074 		}
8075 
8076 		/* Delete textures */
8077 		if (0 != m_complete_destination_texture_id)
8078 		{
8079 			glDeleteTextures(1, &m_complete_destination_texture_id);
8080 			m_complete_destination_texture_id = 0;
8081 		}
8082 
8083 		if (0 != m_complete_source_texture_id)
8084 		{
8085 			glDeleteTextures(1, &m_complete_source_texture_id);
8086 			m_complete_source_texture_id = 0;
8087 		}
8088 
8089 		if (0 != m_incomplete_destination_texture_id)
8090 		{
8091 			glDeleteTextures(1, &m_incomplete_destination_texture_id);
8092 			m_incomplete_destination_texture_id = 0;
8093 		}
8094 
8095 		if (0 != m_incomplete_source_texture_id)
8096 		{
8097 			glDeleteTextures(1, &m_incomplete_source_texture_id);
8098 			m_incomplete_source_texture_id = 0;
8099 		}
8100 
8101 		/* Delete vertex array object */
8102 		if (0 != m_vertex_array_object_id)
8103 		{
8104 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8105 			m_vertex_array_object_id = 0;
8106 		}
8107 
8108 		/* Delete buffer */
8109 		if (0 != m_vertex_buffer_id)
8110 		{
8111 			glDeleteBuffers(1, &m_vertex_buffer_id);
8112 			m_vertex_buffer_id = 0;
8113 		}
8114 
8115 		/* Done */
8116 		return NO_ERROR;
8117 	}
8118 
Run()8119 	virtual long Run()
8120 	{
8121 		bool result = true;
8122 
8123 		/* Copy textures data with imageLoad() and imageStore() operations */
8124 		Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8125 							m_complete_source_texture_id, m_incomplete_source_texture_id);
8126 
8127 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
8128 
8129 		/* Verify that store to "incomplete destination" was ignored */
8130 		if (true ==
8131 			CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8132 		{
8133 			m_context.getTestContext().getLog()
8134 				<< tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8135 				<< tcu::TestLog::EndMessage;
8136 
8137 			result = false;
8138 		}
8139 
8140 		/* Verify that load from "incomplete source" returned 0 */
8141 		if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8142 		{
8143 			m_context.getTestContext().getLog()
8144 				<< tcu::TestLog::Message
8145 				<< "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8146 				<< tcu::TestLog::EndMessage;
8147 
8148 			result = false;
8149 		}
8150 
8151 		if (false == result)
8152 		{
8153 			return ERROR;
8154 		}
8155 
8156 		/* Done */
8157 		return NO_ERROR;
8158 	}
8159 
8160 private:
8161 	/* Private methods */
8162 
8163 	/** Bind texture to image unit and sets image uniform to that unit
8164 	 *
8165 	 * @param program_id   Program object id
8166 	 * @param texture_id   Texture id
8167 	 * @param level        Texture level
8168 	 * @param image_unit   Index of image unit
8169 	 * @param uniform_name Name of image uniform
8170 	 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8171 	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8172 	{
8173 		/* Uniform location and invalid value */
8174 		static const GLint invalid_uniform_location = -1;
8175 		GLint			   image_uniform_location   = 0;
8176 
8177 		/* Get uniform location */
8178 		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8179 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8180 		if (invalid_uniform_location == image_uniform_location)
8181 		{
8182 			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8183 		}
8184 
8185 		/* Bind texture to image unit */
8186 		glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8187 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8188 
8189 		/* Set uniform to image unit */
8190 		glUniform1i(image_uniform_location, image_unit);
8191 		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8192 	}
8193 
8194 	/** Check if texture is filled with black color, zeros
8195 	 *
8196 	 * @param texture_id Id of texture object
8197 	 *
8198 	 * @return true when texture is fully black, false otherwise
8199 	 **/
CheckIfTextureIsBlack(GLuint texture_id)8200 	bool CheckIfTextureIsBlack(GLuint texture_id)
8201 	{
8202 		/* Constants to calculate size of texture */
8203 		static const GLuint n_components	  = 4; /* RGBA */
8204 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8205 
8206 		/* Storage for texture data */
8207 		std::vector<GLubyte> black_texture_data;
8208 		std::vector<GLubyte> texture_data;
8209 
8210 		/* Allocate memory */
8211 		black_texture_data.resize(texture_data_size);
8212 		texture_data.resize(texture_data_size);
8213 
8214 		/* Set all texels to black */
8215 		for (GLuint i = 0; i < texture_data_size; ++i)
8216 		{
8217 			black_texture_data[i] = 0;
8218 		}
8219 
8220 		/* Bind texture */
8221 		glBindTexture(GL_TEXTURE_2D, texture_id);
8222 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8223 
8224 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8225 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8226 
8227 		/* Compare texels */
8228 		return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8229 	}
8230 
8231 	/** Check if texture was modified
8232 	 *
8233 	 * @param texture_id   Id of texture object
8234 	 * @param nagic_number Magic number that was to create texture
8235 	 *
8236 	 * @return true if texture contents match expected values, false otherwise
8237 	 **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8238 	bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8239 	{
8240 		/* Constants to calculate size of texture */
8241 		static const GLuint n_components	  = 4; /* RGBA */
8242 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8243 
8244 		/* Storage for texture data */
8245 		std::vector<GLubyte> expected_texture_data;
8246 		std::vector<GLubyte> texture_data;
8247 
8248 		/* Allocate memory */
8249 		expected_texture_data.resize(texture_data_size);
8250 		texture_data.resize(texture_data_size);
8251 
8252 		/* Prepare expected texels */
8253 		for (GLuint y = 0; y < m_texture_edge; ++y)
8254 		{
8255 			const GLuint line_offset = y * m_texture_edge * n_components;
8256 
8257 			for (GLuint x = 0; x < m_texture_edge; ++x)
8258 			{
8259 				const GLuint texel_offset = x * n_components + line_offset;
8260 
8261 				SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8262 						 magic_number);
8263 			}
8264 		}
8265 
8266 		/* Bind texture */
8267 		glBindTexture(GL_TEXTURE_2D, texture_id);
8268 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8269 
8270 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8271 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8272 
8273 		/* Compare texels, true when textures are different */
8274 		return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8275 	}
8276 
8277 	/** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8278 	 *
8279 	 * @param complete_destination_texture_id   Id of "complete destination" texture object
8280 	 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8281 	 * @param complete_source_texture_id        Id of "complete source" texture object
8282 	 * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8283 	 **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8284 	void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8285 							 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8286 	{
8287 		/* Uniform names */
8288 		static const char* const complete_destination_image_uniform_name   = "u_complete_destination_image";
8289 		static const char* const complete_source_image_uniform_name		   = "u_complete_source_image";
8290 		static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8291 		static const char* const incomplete_source_image_uniform_name	  = "u_incomplete_source_image";
8292 
8293 		/* Attribute name */
8294 		static const char* const position_attribute_name = "vs_in_position";
8295 
8296 		/* Attribute location and invalid value */
8297 		static const GLint invalid_attribute_location  = -1;
8298 		GLint			   position_attribute_location = 0;
8299 
8300 		/* Set current program */
8301 		glUseProgram(m_program_id);
8302 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8303 
8304 		/* Bind vertex array object */
8305 		glBindVertexArray(m_vertex_array_object_id);
8306 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8307 
8308 		/* Bind buffer with quad vertex positions */
8309 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8310 		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8311 
8312 		/* Setup position attribute */
8313 		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8314 		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8315 		if (invalid_attribute_location == position_attribute_location)
8316 		{
8317 			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8318 									 __LINE__);
8319 		}
8320 
8321 		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8322 		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8323 
8324 		glEnableVertexAttribArray(position_attribute_location);
8325 		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8326 
8327 		/* Setup textures as source and destination images */
8328 		BindTextureToImage(m_program_id, complete_destination_texture_id,
8329 						   0 /* texture level */, 0 /* image_unit */,
8330 						   complete_destination_image_uniform_name);
8331 		BindTextureToImage(m_program_id, complete_source_texture_id,
8332 						   0 /* texture level */, 1 /* image_unit */,
8333 						   complete_source_image_uniform_name);
8334 		BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8335 						   2 /* texture level */, 2 /* image_unit */,
8336 						   incomplete_destination_image_uniform_name);
8337 		BindTextureToImage(m_program_id, incomplete_source_texture_id,
8338 						   2 /* texture level */, 3 /* image_unit */,
8339 						   incomplete_source_image_uniform_name);
8340 
8341 		/* Execute draw */
8342 		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8343 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8344 	}
8345 
8346 	/** Create complete 2D RGBA8 texture.
8347 	 *
8348 	 * @param magic_number   Magic number of texture
8349 	 * @param out_texture_id Id of created texture, not modified if operation fails
8350 	 *
8351 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8352 	 **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8353 	GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8354 	{
8355 		/* Constants to calculate size of texture */
8356 		static const GLuint n_components	  = 4; /* RGBA */
8357 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8358 
8359 		/* Error code */
8360 		GLenum err = 0;
8361 
8362 		/* Texture id */
8363 		GLuint texture_id = 0;
8364 
8365 		/* Prepare storage for texture data */
8366 		std::vector<GLubyte> texture_data;
8367 		texture_data.resize(texture_data_size);
8368 
8369 		/* Prepare texture data */
8370 		for (GLuint y = 0; y < m_texture_edge; ++y)
8371 		{
8372 			const GLuint line_offset = y * m_texture_edge * n_components;
8373 
8374 			for (GLuint x = 0; x < m_texture_edge; ++x)
8375 			{
8376 				const GLuint texel_offset = x * n_components + line_offset;
8377 
8378 				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8379 			}
8380 		}
8381 
8382 		/* Generate texture */
8383 		glGenTextures(1, &texture_id);
8384 		err = glGetError();
8385 		if (GL_NO_ERROR != err)
8386 		{
8387 			return err;
8388 		}
8389 
8390 		/* Bind texture */
8391 		glBindTexture(GL_TEXTURE_2D, texture_id);
8392 		err = glGetError();
8393 		if (GL_NO_ERROR != err)
8394 		{
8395 			glDeleteTextures(1, &texture_id);
8396 			return err;
8397 		}
8398 
8399 		/* Allocate storage and fill texture */
8400 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8401 					 GL_UNSIGNED_BYTE, &texture_data[0]);
8402 		err = glGetError();
8403 		if (GL_NO_ERROR != err)
8404 		{
8405 			glDeleteTextures(1, &texture_id);
8406 			return err;
8407 		}
8408 
8409 		/* Make texture complete */
8410 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8411 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8412 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8413 		err = glGetError();
8414 		if (GL_NO_ERROR != err)
8415 		{
8416 			glDeleteTextures(1, &texture_id);
8417 			return err;
8418 		}
8419 
8420 		/* Set out_texture_id */
8421 		out_texture_id = texture_id;
8422 
8423 		/* Done */
8424 		return GL_NO_ERROR;
8425 	}
8426 
8427 	/** Create incomplete 2D RGBA8 texture
8428 	 *
8429 	 * @param magic_number   Magic number of texture
8430 	 * @param out_texture_id Id of created texture, not modified if operation fails
8431 	 *
8432 	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8433 	 **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8434 	GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8435 	{
8436 		/* Constants to calculate size of texture */
8437 		static const GLuint n_components	  = 4; /* RGBA */
8438 		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8439 
8440 		/* Error code */
8441 		GLenum err = 0;
8442 
8443 		/* Texture id */
8444 		GLuint texture_id = 0;
8445 
8446 		/* Prepare storage for texture data */
8447 		std::vector<GLubyte> texture_data;
8448 		texture_data.resize(texture_data_size);
8449 
8450 		/* Prepare texture data */
8451 		for (GLuint y = 0; y < m_texture_edge; ++y)
8452 		{
8453 			const GLuint line_offset = y * m_texture_edge * n_components;
8454 
8455 			for (GLuint x = 0; x < m_texture_edge; ++x)
8456 			{
8457 				const GLuint texel_offset = x * n_components + line_offset;
8458 
8459 				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8460 			}
8461 		}
8462 
8463 		/* Generate texture */
8464 		glGenTextures(1, &texture_id);
8465 		err = glGetError();
8466 		if (GL_NO_ERROR != err)
8467 		{
8468 			return err;
8469 		}
8470 
8471 		/* Bind texture */
8472 		glBindTexture(GL_TEXTURE_2D, texture_id);
8473 		err = glGetError();
8474 		if (GL_NO_ERROR != err)
8475 		{
8476 			glDeleteTextures(1, &texture_id);
8477 			return err;
8478 		}
8479 
8480 		/* Allocate storage and fill texture */
8481 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8482 					 GL_UNSIGNED_BYTE, &texture_data[0]);
8483 		err = glGetError();
8484 		if (GL_NO_ERROR != err)
8485 		{
8486 			glDeleteTextures(1, &texture_id);
8487 			return err;
8488 		}
8489 
8490 		/* Make texture incomplete */
8491 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8492 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8493 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8494 		err = glGetError();
8495 		if (GL_NO_ERROR != err)
8496 		{
8497 			glDeleteTextures(1, &texture_id);
8498 			return err;
8499 		}
8500 
8501 		/* Set out_texture_id */
8502 		out_texture_id = texture_id;
8503 
8504 		/* Done */
8505 		return GL_NO_ERROR;
8506 	}
8507 
8508 	/** Prepare "unique" texels.
8509 	 *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8510 	 *
8511 	 * @param texel        Storage of texel
8512 	 * @param x_coordinate X coordiante of texel
8513 	 * @param y_coordinate Y coordinate of texel
8514 	 * @param magic_number Magic number of texture
8515 	 **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8516 	void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8517 	{
8518 		texel[0] = x_coordinate;
8519 		texel[1] = y_coordinate;
8520 		texel[2] = magic_number;
8521 		texel[3] = 0xcc;
8522 	}
8523 };
8524 
8525 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8526  *
8527  * Steps:
8528  * - prepare program object, see details below,
8529  * - prepare 2D R32I texture, width should be equal to the number of image
8530  * uniforms used by program object, height should be 2, fill first row with
8531  * unique values, fill second row with zeros,
8532  * - bind texture to first image unit,
8533  * - set all image uniforms to first image unit,
8534  * - execute program for a single vertex,
8535  * - verify that:
8536  *     - values in first row were negated,
8537  *     - values from first row were copied to second row,
8538  *
8539  * Repeat steps to test all shader stages that support at least 2 image
8540  * uniforms.
8541  *
8542  * Program has to contain all necessary shader stages. Use boilerplate shaders
8543  * for shader stages that are not important for the test.
8544  *
8545  * Tested shader stage should:
8546  * - Use as many different image formats as possible, image formats compatible
8547  * with R32I:
8548  *     * rg16f
8549  *     * r11f_g11f_b10f
8550  *     * r32f
8551  *     * rgb10_a2ui
8552  *     * rgba8ui
8553  *     * rg16ui
8554  *     * r32ui
8555  *     * rgba8i
8556  *     * rg16i
8557  *     * r32i
8558  *     * rgb10_a2
8559  *     * rgba8
8560  *     * rg16
8561  *     * rgba8_snorm
8562  *     * rg16_snorm.
8563  * - Declare maximum allowed number of image uniforms,
8564  *
8565  *     layout(format) uniform gimage2D u_image;
8566  *
8567  * where <format> is selected image format, <gimage2D> is type of 2D image
8568  * compatible with <format> and <u_image> is unique name of uniform.
8569  * Note that image uniforms cannot be declared as array, due to different image
8570  * formats. Therefore separate uniforms have to be used.
8571  * - Include following code snippet:
8572  * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8573  * {
8574  *     vec row_1_coord(i,0);
8575  *     vec row_2_coord(i,1);
8576  *
8577  *     row_1_value = imageLoad(u_image[i], row_1_coord);
8578  *     imageStore(u_image[i], row_1_coord, -row_1_value);
8579  *     imageStore(u_image[i], row_2_coord, row_1_value);
8580  * }
8581  * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8582  * stage.
8583  **/
8584 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8585 {
8586 private:
8587 	/* Types */
8588 	/** Details of image format
8589 	 *
8590 	 **/
8591 	struct imageFormatDetails
8592 	{
8593 		typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8594 
8595 		const char*			m_image_format;
8596 		const char*			m_image_type;
8597 		const char*			m_color_type;
8598 		GLenum				m_image_unit_format;
8599 		verificationRoutine m_verification_routine;
8600 	};
8601 
8602 	template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8603 	struct Masks
8604 	{
8605 		/** Get mask of bits used to store in bit-field
8606 		 *
8607 		 * @return Mask
8608 		 **/
RawMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8609 		static inline T RawMask()
8610 		{
8611 			static const T mask = ValueMask() << OFFSET;
8612 
8613 			return mask;
8614 		}
8615 
8616 		/** Get mask of bits used to store value.
8617 		 *
8618 		 * @return Mask
8619 		 **/
ValueMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8620 		static inline T ValueMask()
8621 		{
8622 			static const T mask = (1 << SIZE) - 1;
8623 
8624 			return mask;
8625 		}
8626 
8627 		/** Get offset.
8628 		 *
8629 		 * @return offset
8630 		 **/
Offsetgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8631 		static inline T Offset()
8632 		{
8633 			return OFFSET;
8634 		}
8635 	};
8636 
8637 	template <typename T, GLuint SIZE, GLuint OFFSET>
8638 	struct Masks<T, SIZE, OFFSET, false>
8639 	{
8640 		/** Get mask of bits used to store in bit-field
8641 		 *
8642 		 * @return Mask
8643 		 **/
RawMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8644 		static inline T RawMask()
8645 		{
8646 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8647 			return 0;
8648 		}
8649 
8650 		/** Get mask of bits used to store value.
8651 		 *
8652 		 * @return Mask
8653 		 **/
ValueMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8654 		static inline T ValueMask()
8655 		{
8656 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8657 			return 0;
8658 		}
8659 
8660 		/** Get offset.
8661 		 *
8662 		 * @return offset
8663 		 **/
Offsetgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8664 		static inline T Offset()
8665 		{
8666 			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8667 			return 0;
8668 		}
8669 	};
8670 
8671 	/** Template class for accessing integer values stored in bit-fields
8672 	 *
8673 	 **/
8674 	template <typename T, GLuint SIZE, GLuint OFFSET>
8675 	class Integer
8676 	{
8677 	public:
8678 		/** Constructor
8679 		 *
8680 		 **/
Integer(T raw)8681 		Integer(T raw) : m_raw(raw)
8682 		{
8683 		}
8684 
8685 		/** Extract value from bit-field
8686 		 *
8687 		 * @return Value
8688 		 **/
Get() const8689 		T Get() const
8690 		{
8691 			const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8692 
8693 			const T bits   = m_raw & mask;
8694 			const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8695 
8696 			return result;
8697 		}
8698 
8699 		/** Extract value from bit-field and negate it
8700 		 *
8701 		 * @return Negated value
8702 		 **/
GetNegated() const8703 		T GetNegated() const
8704 		{
8705 			const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8706 			const T value = Get();
8707 
8708 			return Clamp((~value) + 1) & mask;
8709 		}
8710 
Clamp(T n) const8711 		T Clamp(T n) const
8712 		{
8713 			const bool isUnsigned = (T(0) < T(-1));
8714 			const T	min		  = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8715 			const T	max		  = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8716 			const T	x		  = n > max ? max : n;
8717 			return x < min ? min : x;
8718 		}
8719 
8720 	private:
8721 		T m_raw;
8722 	};
8723 
8724 	/* Enums */
8725 	/** Shader stage identification
8726 	 *
8727 	 **/
8728 	enum shaderStage
8729 	{
8730 		fragmentShaderStage				 = 2,
8731 		geometryShaderStage				 = 4,
8732 		tesselationControlShaderStage	= 8,
8733 		tesselationEvalutaionShaderStage = 16,
8734 		vertexShaderStage				 = 32,
8735 	};
8736 
8737 	/** Test result
8738 	 *
8739 	 **/
8740 	enum testResult
8741 	{
8742 		testFailed		 = -1,
8743 		testNotSupported = 1,
8744 		testPassed		 = 0
8745 	};
8746 
8747 	/* Constants */
8748 	static const GLint m_min_required_image_uniforms = 2;
8749 
8750 	/* Fields */
8751 	GLuint m_program_to_test_fs_stage_id;
8752 	GLuint m_program_to_test_gs_stage_id;
8753 	GLuint m_program_to_test_tcs_stage_id;
8754 	GLuint m_program_to_test_tes_stage_id;
8755 	GLuint m_program_to_test_vs_stage_id;
8756 	GLuint m_texture_to_test_fs_stage_id;
8757 	GLuint m_texture_to_test_gs_stage_id;
8758 	GLuint m_texture_to_test_tcs_stage_id;
8759 	GLuint m_texture_to_test_tes_stage_id;
8760 	GLuint m_texture_to_test_vs_stage_id;
8761 	GLuint m_vertex_array_object_id;
8762 
8763 public:
8764 	/* Constructor */
ImageLoadStoreMultipleUniformsTest()8765 	ImageLoadStoreMultipleUniformsTest()
8766 		: m_program_to_test_fs_stage_id(0)
8767 		, m_program_to_test_gs_stage_id(0)
8768 		, m_program_to_test_tcs_stage_id(0)
8769 		, m_program_to_test_tes_stage_id(0)
8770 		, m_program_to_test_vs_stage_id(0)
8771 		, m_texture_to_test_fs_stage_id(0)
8772 		, m_texture_to_test_gs_stage_id(0)
8773 		, m_texture_to_test_tcs_stage_id(0)
8774 		, m_texture_to_test_tes_stage_id(0)
8775 		, m_texture_to_test_vs_stage_id(0)
8776 		, m_vertex_array_object_id(0)
8777 	{
8778 		/* Nothing to be done here */
8779 	}
8780 
8781 	/* Methods inherited from SubcaseBase */
Setup()8782 	virtual long Setup()
8783 	{
8784 		/* Prepare programs */
8785 		m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8786 		m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8787 		m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8788 		m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8789 		m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8790 
8791 		/* Prepare textures */
8792 		m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8793 		m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8794 		m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8795 		m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8796 		m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8797 
8798 		/* Generate vertex array object */
8799 		glGenVertexArrays(1, &m_vertex_array_object_id);
8800 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8801 
8802 		/* Bind vertex array object */
8803 		glBindVertexArray(m_vertex_array_object_id);
8804 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8805 
8806 		/* Set vertices number for patches */
8807 		glPatchParameteri(GL_PATCH_VERTICES, 1);
8808 
8809 		/* Done */
8810 		return NO_ERROR;
8811 	}
8812 
Cleanup()8813 	virtual long Cleanup()
8814 	{
8815 		glUseProgram(0);
8816 
8817 		/* Delete programs */
8818 		if (0 != m_program_to_test_fs_stage_id)
8819 		{
8820 			glDeleteProgram(m_program_to_test_fs_stage_id);
8821 			m_program_to_test_fs_stage_id = 0;
8822 		}
8823 
8824 		if (0 != m_program_to_test_gs_stage_id)
8825 		{
8826 			glDeleteProgram(m_program_to_test_gs_stage_id);
8827 			m_program_to_test_gs_stage_id = 0;
8828 		}
8829 
8830 		if (0 != m_program_to_test_tcs_stage_id)
8831 		{
8832 			glDeleteProgram(m_program_to_test_tcs_stage_id);
8833 			m_program_to_test_tcs_stage_id = 0;
8834 		}
8835 
8836 		if (0 != m_program_to_test_tes_stage_id)
8837 		{
8838 			glDeleteProgram(m_program_to_test_tes_stage_id);
8839 			m_program_to_test_tes_stage_id = 0;
8840 		}
8841 
8842 		if (0 != m_program_to_test_vs_stage_id)
8843 		{
8844 			glDeleteProgram(m_program_to_test_vs_stage_id);
8845 			m_program_to_test_vs_stage_id = 0;
8846 		}
8847 
8848 		/* Delete textures */
8849 		if (0 != m_texture_to_test_fs_stage_id)
8850 		{
8851 			glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8852 			m_texture_to_test_fs_stage_id = 0;
8853 		}
8854 
8855 		if (0 != m_texture_to_test_gs_stage_id)
8856 		{
8857 			glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8858 			m_texture_to_test_gs_stage_id = 0;
8859 		}
8860 
8861 		if (0 != m_texture_to_test_tcs_stage_id)
8862 		{
8863 			glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8864 			m_texture_to_test_tcs_stage_id = 0;
8865 		}
8866 
8867 		if (0 != m_texture_to_test_tes_stage_id)
8868 		{
8869 			glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8870 			m_texture_to_test_tes_stage_id = 0;
8871 		}
8872 
8873 		if (0 != m_texture_to_test_vs_stage_id)
8874 		{
8875 			glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8876 			m_texture_to_test_vs_stage_id = 0;
8877 		}
8878 
8879 		/* Delete vertex array object id */
8880 		if (0 != m_vertex_array_object_id)
8881 		{
8882 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8883 			m_vertex_array_object_id = 0;
8884 		}
8885 
8886 		/* Done */
8887 		return NO_ERROR;
8888 	}
8889 
Run()8890 	virtual long Run()
8891 	{
8892 		bool result = true;
8893 
8894 		if (testFailed == testShaderStage(fragmentShaderStage))
8895 		{
8896 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8897 												<< tcu::TestLog::EndMessage;
8898 
8899 			result = false;
8900 		}
8901 
8902 		if (testFailed == testShaderStage(geometryShaderStage))
8903 		{
8904 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8905 												<< tcu::TestLog::EndMessage;
8906 
8907 			result = false;
8908 		}
8909 
8910 		if (testFailed == testShaderStage(tesselationControlShaderStage))
8911 		{
8912 			m_context.getTestContext().getLog() << tcu::TestLog::Message
8913 												<< "Problems with tesselation control shader stage!"
8914 												<< tcu::TestLog::EndMessage;
8915 
8916 			result = false;
8917 		}
8918 
8919 		if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8920 		{
8921 			m_context.getTestContext().getLog() << tcu::TestLog::Message
8922 												<< "Problems with tesselation evaluation shader stage!"
8923 												<< tcu::TestLog::EndMessage;
8924 
8925 			result = false;
8926 		}
8927 
8928 		if (testFailed == testShaderStage(vertexShaderStage))
8929 		{
8930 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8931 												<< tcu::TestLog::EndMessage;
8932 
8933 			result = false;
8934 		}
8935 
8936 		if (false == result)
8937 		{
8938 			return ERROR;
8939 		}
8940 
8941 		/* Done */
8942 		return NO_ERROR;
8943 	}
8944 
8945 private:
8946 	/* Static routines */
8947 	/** Provide image format details for given index
8948 	 *
8949 	 * @param index       Index
8950 	 * @param out_details Image format detail instance
8951 	 **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8952 	static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8953 	{
8954 		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8955 			"r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8956 		};
8957 
8958 		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8959 			{ "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8960 			{ "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8961 			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8962 			{ "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8963 			{ "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8964 			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8965 			{ "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966 			{ "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8967 			{ "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8968 			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8969 			{ "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8970 			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8971 			{ "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8972 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8973 			{ "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8974 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8975 			{ "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8976 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8977 			{ "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8978 			{ "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8979 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8980 			{ "rg16i", "iimage2D", "ivec4", GL_RG16I,
8981 			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8982 		};
8983 
8984 		static const GLuint n_imageUniformFormatDetails =
8985 			sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8986 
8987 		if (n_imageUniformFormatDetails <= index)
8988 		{
8989 			out_details = default_format_details;
8990 		}
8991 		else
8992 		{
8993 			out_details = format_details[index];
8994 		}
8995 	}
8996 
8997 	/** Write name of image uniform at given index to output stream
8998 	 *
8999 	 * @param stream Output stream
9000 	 * @param index  Index
9001 	 **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9002 	static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9003 	{
9004 		/* u_image_0 */
9005 		stream << "u_image_" << index;
9006 	}
9007 
9008 	/** Write name of variable used to store value loaded from image at given index to output stream
9009 	 *
9010 	 * @param stream Output stream
9011 	 * @param index  Index
9012 	 **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9013 	static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9014 	{
9015 		/* loaded_value_0 */
9016 		stream << "loaded_value_" << index;
9017 	}
9018 
9019 	/** Write name of variable used to store coordinate of texel at given row to output stream
9020 	 *
9021 	 * @param stream Output stream
9022 	 * @param index  Index of image uniform
9023 	 * @param row    Row of image
9024 	 **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9025 	static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9026 	{
9027 		/* row_0_coordinates_0 */
9028 		stream << "row_" << row << "_coordinates_" << index;
9029 	}
9030 
9031 	struct imageUniformDeclaration
9032 	{
imageUniformDeclarationgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9033 		imageUniformDeclaration(GLuint index) : m_index(index)
9034 		{
9035 		}
9036 
9037 		GLuint m_index;
9038 	};
9039 
9040 	/** Write declaration of image uniform at given index to output stream
9041 	 *
9042 	 * @param stream                   Output stream
9043 	 * @param imageUniformDeclaration  Declaration details
9044 	 *
9045 	 * @return stream
9046 	 **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9047 	friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9048 	{
9049 		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9050 		getImageUniformDeclarationDetails(declaration.m_index, format_details);
9051 
9052 		/* layout(r32f) uniform image2D u_image_0; */
9053 		stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9054 
9055 		ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9056 
9057 		stream << ";";
9058 
9059 		return stream;
9060 	}
9061 
9062 	struct imageLoadCall
9063 	{
imageLoadCallgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9064 		imageLoadCall(GLuint index) : m_index(index)
9065 		{
9066 		}
9067 
9068 		GLuint m_index;
9069 	};
9070 
9071 	/* Stream operators */
9072 	/** Write code that execute imageLoad routine for image at given index to output stream
9073 	 *
9074 	 * @param stream Output stream
9075 	 * @param load   imageLoad call details
9076 	 *
9077 	 * @return stream
9078 	 **/
operator <<(std::ostream & stream,const imageLoadCall & load)9079 	friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9080 	{
9081 		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9082 		getImageUniformDeclarationDetails(load.m_index, format_details);
9083 
9084 		/* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9085 		stream << format_details.m_color_type << " ";
9086 
9087 		writeLoadedValueVariableNameToStream(stream, load.m_index);
9088 
9089 		stream << " = imageLoad(";
9090 
9091 		writeImageUniformNameToStream(stream, load.m_index);
9092 
9093 		stream << ", ";
9094 
9095 		writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9096 
9097 		stream << ");";
9098 
9099 		return stream;
9100 	}
9101 
9102 	struct imageStoreCall
9103 	{
imageStoreCallgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9104 		imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9105 		{
9106 		}
9107 
9108 		GLuint m_index;
9109 		GLuint m_row;
9110 	};
9111 
9112 	/** Write code that execute imageStore to image at given index to output stream
9113 	 *
9114 	 * @param stream Output stream
9115 	 * @param store  imageStore call details
9116 	 *
9117 	 * @return stream
9118 	 **/
operator <<(std::ostream & stream,const imageStoreCall & store)9119 	friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9120 	{
9121 		/* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9122 		stream << "imageStore(";
9123 
9124 		writeImageUniformNameToStream(stream, store.m_index);
9125 
9126 		stream << ", ";
9127 
9128 		writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9129 
9130 		if (0 == store.m_row)
9131 		{
9132 			stream << ", -";
9133 		}
9134 		else
9135 		{
9136 			stream << ", ";
9137 		}
9138 
9139 		writeLoadedValueVariableNameToStream(stream, store.m_index);
9140 		stream << ");";
9141 
9142 		return stream;
9143 	}
9144 
9145 	struct coordinatesVariableDeclaration
9146 	{
coordinatesVariableDeclarationgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9147 		coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9148 		{
9149 		}
9150 		GLuint m_index;
9151 		GLuint m_row;
9152 	};
9153 
9154 	/** Write declaration of variable for coordinate at given row to output stream
9155 	 *
9156 	 * @param stream      Output stream
9157 	 * @param declaration Declaration details
9158 	 *
9159 	 * @return stream
9160 	 **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9161 	friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9162 	{
9163 		stream << "const ivec2 ";
9164 
9165 		writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9166 
9167 		stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9168 
9169 		return stream;
9170 	}
9171 
9172 	/* Methods */
9173 	/** Build program to test specified shader stage
9174 	 *
9175 	 * Throws exception in case of any failure
9176 	 *
9177 	 * @param stage Stage id
9178 	 *
9179 	 * @return Program id
9180 	 **/
buildProgramToTestShaderStage(shaderStage stage)9181 	GLuint buildProgramToTestShaderStage(shaderStage stage)
9182 	{
9183 		static const char* const boilerplate_fragment_shader_code =
9184 			"#version 400 core\n"
9185 			"#extension GL_ARB_shader_image_load_store : require\n"
9186 			"\n"
9187 			"precision highp float;\n"
9188 			"\n"
9189 			"void main()\n"
9190 			"{\n"
9191 			"    discard;\n"
9192 			"}\n";
9193 
9194 		static const char* const boilerplate_tesselation_evaluation_shader_code =
9195 			"#version 400 core\n"
9196 			"#extension GL_ARB_shader_image_load_store : require\n"
9197 			"\n"
9198 			"precision highp float;\n"
9199 			"\n"
9200 			"layout(quads, equal_spacing, ccw) in;\n"
9201 			"\n"
9202 			"void main()\n"
9203 			"{\n"
9204 			"\n"
9205 			"}\n";
9206 
9207 		static const char* const boilerplate_vertex_shader_code =
9208 			"#version 400 core\n"
9209 			"#extension GL_ARB_shader_image_load_store : require\n"
9210 			"\n"
9211 			"precision highp float;\n"
9212 			"\n"
9213 			"layout(location = 0) in vec4 i_position;\n"
9214 			"\n"
9215 			"void main()\n"
9216 			"{\n"
9217 			"  gl_Position = i_position;\n"
9218 			"}\n";
9219 
9220 		const char* fragment_shader_code			   = boilerplate_fragment_shader_code;
9221 		const char* geometry_shader_code			   = 0;
9222 		bool		is_program_built				   = true;
9223 		GLuint		program_object_id				   = 0;
9224 		const char* tesselation_control_shader_code	= 0;
9225 		const char* tesselation_evaluation_shader_code = 0;
9226 		std::string tested_shader_stage_code;
9227 		const char* vertex_shader_code = boilerplate_vertex_shader_code;
9228 
9229 		/* Get source code for tested shader stage */
9230 		prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9231 
9232 		if (true == tested_shader_stage_code.empty())
9233 		{
9234 			return 0;
9235 		}
9236 
9237 		/* Set up source code for all required stages */
9238 		switch (stage)
9239 		{
9240 		case fragmentShaderStage:
9241 			fragment_shader_code = tested_shader_stage_code.c_str();
9242 			break;
9243 
9244 		case geometryShaderStage:
9245 			geometry_shader_code = tested_shader_stage_code.c_str();
9246 			break;
9247 
9248 		case tesselationControlShaderStage:
9249 			tesselation_control_shader_code	= tested_shader_stage_code.c_str();
9250 			tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9251 			break;
9252 
9253 		case tesselationEvalutaionShaderStage:
9254 			tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9255 			break;
9256 
9257 		case vertexShaderStage:
9258 			vertex_shader_code = tested_shader_stage_code.c_str();
9259 			break;
9260 
9261 		default:
9262 			TCU_FAIL("Invalid shader stage");
9263 		}
9264 
9265 		/* Build program */
9266 		program_object_id =
9267 			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9268 						 geometry_shader_code, fragment_shader_code, &is_program_built);
9269 
9270 		/* Check if program was built */
9271 		if (false == is_program_built)
9272 		{
9273 			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9274 		}
9275 
9276 		/* Done */
9277 		return program_object_id;
9278 	}
9279 
9280 	/** Create texture to test given shader stage
9281 	 *
9282 	 * Throws exception in case of any failure
9283 	 *
9284 	 * @param stage Stage id
9285 	 *
9286 	 * @return Texture id
9287 	 **/
createTextureToTestShaderStage(shaderStage stage)9288 	GLuint createTextureToTestShaderStage(shaderStage stage)
9289 	{
9290 		GLenum			   error			  = glGetError();
9291 		const GLint		   max_image_uniforms = getMaximumImageUniformsForStage(stage);
9292 		GLuint			   texture_id		  = 0;
9293 		std::vector<GLint> texture_data;
9294 
9295 		const GLsizei height = 2;
9296 		const GLsizei width  = max_image_uniforms;
9297 
9298 		if (m_min_required_image_uniforms > max_image_uniforms)
9299 		{
9300 			return 0;
9301 		}
9302 
9303 		/* Generate texture id */
9304 		glGenTextures(1, &texture_id);
9305 		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9306 
9307 		/* Bind texture */
9308 		glBindTexture(GL_TEXTURE_2D, texture_id);
9309 		error = glGetError();
9310 		if (GL_NO_ERROR != error)
9311 		{
9312 			glDeleteTextures(1, &texture_id);
9313 			GLU_EXPECT_NO_ERROR(error, "BindTexture");
9314 		}
9315 
9316 		/* Prepare storage for texture data */
9317 		texture_data.resize(width * height);
9318 		for (GLint i = 0; i < max_image_uniforms; ++i)
9319 		{
9320 			texture_data[i]			= getExpectedValue(i);
9321 			texture_data[i + width] = 0;
9322 		}
9323 
9324 		/* Create first level of texture */
9325 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9326 					 &texture_data[0]);
9327 		error = glGetError();
9328 		if (GL_NO_ERROR != error)
9329 		{
9330 			glDeleteTextures(1, &texture_id);
9331 			GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9332 		}
9333 
9334 		/* Make texture complete */
9335 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9336 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9337 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9338 		error = glGetError();
9339 		if (GL_NO_ERROR != error)
9340 		{
9341 			glDeleteTextures(1, &texture_id);
9342 			GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9343 		}
9344 
9345 		/* Done */
9346 		return texture_id;
9347 	}
9348 
9349 	/** Get value of texel for image at given index
9350 	 *
9351 	 * @param index Index of image uniform
9352 	 *
9353 	 * @return Value of texel
9354 	 **/
getExpectedValue(GLint index)9355 	GLint getExpectedValue(GLint index)
9356 	{
9357 		// To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9358 		// we set one bit in the exponent of each component of those pixel format
9359 		return 0x40104200 + index;
9360 	}
9361 
9362 	/** Get name of uniform at given index
9363 	 *
9364 	 * @param index    Index of uniform
9365 	 * @param out_name Name of uniform
9366 	 **/
getImageUniformName(GLuint index,std::string & out_name)9367 	void getImageUniformName(GLuint index, std::string& out_name)
9368 	{
9369 		std::stringstream stream;
9370 
9371 		writeImageUniformNameToStream(stream, index);
9372 
9373 		out_name = stream.str();
9374 	}
9375 
9376 	/** Get maximum number of image uniforms allowed for given shader stage
9377 	 *
9378 	 * @param stage Stage id
9379 	 *
9380 	 * @return Maximum allowed image uniforms
9381 	 **/
getMaximumImageUniformsForStage(shaderStage stage)9382 	GLint getMaximumImageUniformsForStage(shaderStage stage)
9383 	{
9384 		GLint  max_image_uniforms = 0;
9385 		GLenum pname			  = 0;
9386 
9387 		switch (stage)
9388 		{
9389 		case fragmentShaderStage:
9390 			pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9391 			break;
9392 
9393 		case geometryShaderStage:
9394 			pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9395 			break;
9396 
9397 		case tesselationControlShaderStage:
9398 			pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9399 			break;
9400 
9401 		case tesselationEvalutaionShaderStage:
9402 			pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9403 			break;
9404 
9405 		case vertexShaderStage:
9406 			pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9407 			break;
9408 
9409 		default:
9410 			TCU_FAIL("Invalid shader stage");
9411 		}
9412 
9413 		glGetIntegerv(pname, &max_image_uniforms);
9414 		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9415 
9416 		return max_image_uniforms;
9417 	}
9418 
9419 	/** Prepare source for tested shader stage
9420 	 *
9421 	 * @param stage    Stage id
9422 	 * @param out_code Source code
9423 	 **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9424 	void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9425 	{
9426 		GLint			  max_image_uniforms	= getMaximumImageUniformsForStage(stage);
9427 		const char*		  stage_specific_layout = "";
9428 		const char*		  stage_specific_predicate = "true";
9429 		std::stringstream stream;
9430 
9431 		if (m_min_required_image_uniforms > max_image_uniforms)
9432 		{
9433 			return;
9434 		}
9435 
9436 		/* Expected result follows
9437 		 *
9438 		 * #version 400 core
9439 		 * #extension GL_ARB_shader_image_load_store : require
9440 		 *
9441 		 * precision highp float;
9442 		 *
9443 		 * stage_specific_layout goes here
9444 		 *
9445 		 * Uniform declarations go here
9446 		 *
9447 		 * void main()
9448 		 * {
9449 		 *     const ivec2 row_0_coordinates(0, 0);
9450 		 *     const ivec2 row_1_coordinates(0, 1);
9451 		 *
9452 		 *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9453 		 *
9454 		 *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9455 		 *
9456 		 *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9457 		 *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9458 		 * }
9459 		 */
9460 
9461 		/* Get piece of code specific for stage */
9462 		switch (stage)
9463 		{
9464 		case fragmentShaderStage:
9465 			break;
9466 
9467 		case geometryShaderStage:
9468 			stage_specific_layout = "layout(points) in;\n"
9469 									"layout(points, max_vertices = 1) out;\n"
9470 									"\n";
9471 			break;
9472 
9473 		case tesselationControlShaderStage:
9474 			stage_specific_layout = "layout(vertices = 4) out;\n"
9475 									"\n";
9476 			stage_specific_predicate = "gl_InvocationID == 0";
9477 			break;
9478 
9479 		case tesselationEvalutaionShaderStage:
9480 			stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9481 									"\n";
9482 			break;
9483 
9484 		case vertexShaderStage:
9485 			break;
9486 
9487 		default:
9488 			TCU_FAIL("Invalid shader stage");
9489 		}
9490 
9491 		/* Preamble */
9492 		stream << "#version 400 core\n"
9493 				  "#extension GL_ARB_shader_image_load_store : require\n"
9494 				  "\n"
9495 				  "precision highp float;\n"
9496 				  "\n"
9497 			   << stage_specific_layout;
9498 
9499 		/* Image uniforms declarations */
9500 		for (GLint i = 0; i < max_image_uniforms; ++i)
9501 		{
9502 			stream << imageUniformDeclaration(i) << "\n";
9503 		}
9504 
9505 		/* Main opening */
9506 		stream << "\n"
9507 				  "void main()\n"
9508 				  "{\n";
9509 
9510 		stream << "    if (" << stage_specific_predicate << ")\n";
9511 		stream << "    {\n";
9512 
9513 		/* imageLoad and imageStores for each uniform */
9514 		for (GLint i = 0; i < max_image_uniforms; ++i)
9515 		{
9516 			stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9517 				   << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9518 				   << "\n"
9519 				   << "        " << imageLoadCall(i) << "\n"
9520 				   << "\n"
9521 				   << "        " << imageStoreCall(i, 0) << "\n"
9522 				   << "        " << imageStoreCall(i, 1) << "\n";
9523 
9524 			if (max_image_uniforms > i + 1)
9525 			{
9526 				stream << "\n";
9527 			}
9528 		}
9529 
9530 		stream << "    }\n";
9531 
9532 		/* Main closing */
9533 		stream << "}\n\n";
9534 
9535 		/* Done */
9536 		out_code = stream.str();
9537 	}
9538 
9539 	/** Test given shader stage
9540 	 *
9541 	 * @param stage Stage id
9542 	 *
9543 	 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9544 	 *         testFailed when test result is negative;
9545 	 *         m_test_passed when test result is positive;
9546 	 **/
testShaderStage(shaderStage stage)9547 	testResult testShaderStage(shaderStage stage)
9548 	{
9549 		std::string		   image_uniform_name;
9550 		static const GLint invalid_uniform_location = -1;
9551 		const GLint		   max_image_uniforms		= getMaximumImageUniformsForStage(stage);
9552 		GLenum			   primitive_mode			= GL_POINTS;
9553 		GLuint			   program_id				= 0;
9554 		testResult		   result					= testPassed;
9555 		std::vector<GLint> texture_data;
9556 		GLuint			   texture_id = 0;
9557 
9558 		static const GLuint height = 2;
9559 		const GLuint		width  = max_image_uniforms;
9560 
9561 		const GLuint		positive_value_index = width;
9562 		static const GLuint negated_value_index  = 0;
9563 
9564 		if (m_min_required_image_uniforms > max_image_uniforms)
9565 		{
9566 			return testNotSupported;
9567 		}
9568 
9569 		/* Select program and texture ids for given stage */
9570 		switch (stage)
9571 		{
9572 		case fragmentShaderStage:
9573 			program_id = m_program_to_test_fs_stage_id;
9574 			texture_id = m_texture_to_test_fs_stage_id;
9575 			break;
9576 
9577 		case geometryShaderStage:
9578 			program_id = m_program_to_test_gs_stage_id;
9579 			texture_id = m_texture_to_test_gs_stage_id;
9580 			break;
9581 
9582 		case tesselationControlShaderStage:
9583 			primitive_mode = GL_PATCHES;
9584 			program_id	 = m_program_to_test_tcs_stage_id;
9585 			texture_id	 = m_texture_to_test_tcs_stage_id;
9586 			break;
9587 
9588 		case tesselationEvalutaionShaderStage:
9589 			primitive_mode = GL_PATCHES;
9590 			program_id	 = m_program_to_test_tes_stage_id;
9591 			texture_id	 = m_texture_to_test_tes_stage_id;
9592 			break;
9593 
9594 		case vertexShaderStage:
9595 			program_id = m_program_to_test_vs_stage_id;
9596 			texture_id = m_texture_to_test_vs_stage_id;
9597 			break;
9598 
9599 		default:
9600 			TCU_FAIL("Invalid shader stage");
9601 		}
9602 
9603 		/* Set program */
9604 		glUseProgram(program_id);
9605 		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9606 
9607 		/* Bind texture to image units */
9608 		for (GLint i = 0; i < max_image_uniforms; ++i)
9609 		{
9610 			imageFormatDetails format_details;
9611 			getImageUniformDeclarationDetails(i, format_details);
9612 
9613 			glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9614 							   GL_READ_WRITE, format_details.m_image_unit_format);
9615 			GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9616 		}
9617 
9618 		/* Set all image uniforms to corresponding image units */
9619 		for (GLint i = 0; i < max_image_uniforms; ++i)
9620 		{
9621 			/* Get name */
9622 			getImageUniformName(i, image_uniform_name);
9623 
9624 			/* Get location */
9625 			GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9626 			GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9627 
9628 			if (invalid_uniform_location == image_uniform_location)
9629 			{
9630 				throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9631 										 __LINE__);
9632 			}
9633 
9634 			/* Set uniform value */
9635 			glUniform1i(image_uniform_location, i /* image_unit */);
9636 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9637 		}
9638 
9639 		/* Execute draw */
9640 		glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9641 		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9642 
9643 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
9644 
9645 		texture_data.resize(width * height);
9646 
9647 		/* Get texture data */
9648 		glBindTexture(GL_TEXTURE_2D, texture_id);
9649 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9650 
9651 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9652 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9653 
9654 		/* Verify each image uniform */
9655 		for (GLint i = 0; i < max_image_uniforms; ++i)
9656 		{
9657 			imageFormatDetails format_details;
9658 			getImageUniformDeclarationDetails(i, format_details);
9659 
9660 			if (false ==
9661 				format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9662 													  texture_data[negated_value_index + i]))
9663 			{
9664 				m_context.getTestContext().getLog()
9665 					<< tcu::TestLog::Message << "Invalid result!"
9666 					<< " Image format: " << format_details.m_image_format << " Original value: "
9667 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9668 					<< " Copied value: "
9669 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9670 					<< texture_data[positive_value_index + i] << " Negated value: "
9671 					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9672 					<< texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9673 
9674 				result = testFailed;
9675 			}
9676 		}
9677 
9678 		/* Done */
9679 		return result;
9680 	}
9681 
9682 	/** Verifies if original_value, positive_value and negated_value match
9683 	 *
9684 	 * @tparam T Type used during verification process, it should match float values by size
9685 	 *
9686 	 * @param original_value Original value of texel, used when creating a texture
9687 	 * @param positive_value Value stored by shader as read
9688 	 * @param negated_value  Value stored by shader after negation
9689 	 *
9690 	 * @return true if values match, false otherwise
9691 	 **/
9692 	template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9693 	static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9694 	{
9695 		if (original_value != positive_value)
9696 		{
9697 			return false;
9698 		}
9699 
9700 		static const GLuint n_elements		  = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9701 		static const GLuint sign_bit_index	= sizeof(T) * 8 - 1;		   /* 7, 15, 31 */
9702 		static const T		sign_bit_mask	 = 1 << sign_bit_index;	   /* 0x80.. */
9703 		static const T		sign_bit_inv_mask = (T)~sign_bit_mask;		   /* 0x7f.. */
9704 
9705 		const T* positive_elements = (T*)&positive_value;
9706 		const T* negated_elements  = (T*)&negated_value;
9707 
9708 		for (GLuint i = 0; i < n_elements; ++i)
9709 		{
9710 			const T positive_element = positive_elements[i];
9711 			const T negated_element  = negated_elements[i];
9712 
9713 			const T positive_sign_bit = positive_element & sign_bit_mask;
9714 			const T negated_sign_bit  = negated_element & sign_bit_mask;
9715 
9716 			const T positive_data = positive_element & sign_bit_inv_mask;
9717 			const T negated_data  = negated_element & sign_bit_inv_mask;
9718 
9719 			/* Compare data bits */
9720 			if (positive_data != negated_data)
9721 			{
9722 				return false;
9723 			}
9724 
9725 			/* Verify that sign bit is inverted */
9726 			if (positive_sign_bit == negated_sign_bit)
9727 			{
9728 				return false;
9729 			}
9730 		}
9731 
9732 		return true;
9733 	}
9734 
9735 	/** Verifies if original_value, positive_value and negated_value match
9736 	 *
9737 	 * @tparam T Type used during verification process, it should match float values by size
9738 	 *
9739 	 * @param original_value Original value of texel, used when creating a texture
9740 	 * @param positive_value Value stored by shader as read
9741 	 * @param negated_value  Value stored by shader after negation
9742 	 *
9743 	 * @return true if values match, false otherwise
9744 	 **/
9745 	template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9746 	static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9747 	{
9748 		if (original_value != positive_value)
9749 		{
9750 			return false;
9751 		}
9752 
9753 		static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9754 
9755 		const T* positive_elements = (T*)&positive_value;
9756 		const T* negated_elements  = (T*)&negated_value;
9757 
9758 		for (GLuint i = 0; i < n_elements; ++i)
9759 		{
9760 			const T positive_element = positive_elements[i];
9761 			const T negated_element  = negated_elements[i];
9762 
9763 			/* Compare data bits */
9764 			if (positive_element != -negated_element)
9765 			{
9766 				return false;
9767 			}
9768 		}
9769 
9770 		return true;
9771 	}
9772 
9773 	/** Verifies if original_value, positive_value and negated_value match
9774 	 *
9775 	 * @tparam R Number of bits for red channel
9776 	 * @tparam G Number of bits for green channel
9777 	 * @tparam B Number of bits for blue channel
9778 	 * @tparam A Number of bits for alpha channel
9779 	 *
9780 	 * @param original_value Original value of texel, used when creating a texture
9781 	 * @param positive_value Value stored by shader as read
9782 	 * @param negated_value  Value stored by shader after negation
9783 	 *
9784 	 * @return true if values match, false otherwise
9785 	 **/
9786 	template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9787 	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9788 	{
9789 		if (original_value != positive_value)
9790 		{
9791 			return false;
9792 		}
9793 
9794 		Integer<T, R, 0> positive_red(positive_value);
9795 		Integer<T, R, 0> negated_red(negated_value);
9796 
9797 		Integer<T, G, R> positive_green(positive_value);
9798 		Integer<T, G, R> negated_green(negated_value);
9799 
9800 		Integer<T, B, R + G> positive_blue(positive_value);
9801 		Integer<T, B, R + G> negated_blue(negated_value);
9802 
9803 		Integer<T, A, R + G + B> positive_alpha(positive_value);
9804 		Integer<T, A, R + G + B> negated_alpha(negated_value);
9805 
9806 		if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9807 			((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9808 			((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9809 			((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9810 		{
9811 			return false;
9812 		}
9813 
9814 		return true;
9815 	}
9816 
9817 	/** Verifies if original_value, positive_value and negated_value match
9818 	 *
9819 	 * @param original_value Original value of texel, used when creating a texture
9820 	 * @param positive_value Value stored by shader as read
9821 	 * @param negated_value  Value stored by shader after negation
9822 	 *
9823 	 * @return true if values match, false otherwise
9824 	 **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9825 	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9826 	{
9827 		if (original_value != positive_value)
9828 		{
9829 			return false;
9830 		}
9831 
9832 		if (positive_value != -negated_value)
9833 		{
9834 			return false;
9835 		}
9836 
9837 		return true;
9838 	}
9839 
9840 	/** Verifies if original_value, positive_value and negated_value match
9841 	 *
9842 	 * @param original_value Original value of texel, used when creating a texture
9843 	 * @param positive_value Value stored by shader as read
9844 	 * @param negated_value  Value stored by shader after negation
9845 	 *
9846 	 * @return true if values match, false otherwise
9847 	 **/
9848 	template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9849 	static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9850 	{
9851 		if (original_value != positive_value)
9852 		{
9853 			return false;
9854 		}
9855 
9856 		if (0 != negated_value)
9857 		{
9858 			return false;
9859 		}
9860 
9861 		return true;
9862 	}
9863 };
9864 
9865 /** Test "Early fragment tests" description follows.
9866  *
9867  *  BasicGLSLEarlyFragTests verifies that:
9868  *  - early z test is applied when enabled,
9869  *  - early z test is not applied when disabled.
9870  *
9871  *  Proposed modifications:
9872  *  - verify that early z test does not discard all fragments when enabled,
9873  *  - verify that early stencil test is applied when enabled,
9874  *  - verify that early stencil test does not discard all fragments when
9875  *  enabled,
9876  *  - verify that early stencil test is not applied when disabled.
9877  *
9878  *  Steps:
9879  *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9880  *  shader stage:
9881  *      a) one program should enable early fragment tests
9882  *      ("layout(early_fragment_tests) in;"),
9883  *      b) second program should disable early fragment tests,
9884  *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9885  *  depth-stencil attachments,
9886  *  - prepare 2D texture 64x64 R32F,
9887  *  - enable depth test,
9888  *  - verify that early z test is applied when enabled:
9889  *      - use program enabling early fragment tests,
9890  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9891  *      - fill texture with zeros,
9892  *      - bind texture to image uniform,
9893  *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9894  *      corner at 1,1) at z: 0.75
9895  *      - verify that texture is still filled with zeros,
9896  *  - verify that early z test does not discard all fragments:
9897  *      - use program enabling early fragment tests,
9898  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9899  *      - fill texture with zeros,
9900  *      - bind texture to image uniform,
9901  *      - draw "full screen" quad at z: 0.25
9902  *      - verify that texture is now filled with 1.0,
9903  *  -verify that early z test is not applied when disabled:
9904  *      - use program disabling early fragment tests,
9905  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9906  *      - fill texture with zeros,
9907  *      - bind texture to image uniform,
9908  *      - draw "full screen" quad at z: 0.75
9909  *      - verify that texture is now filled with 1.0.
9910  *  - disable depth test
9911  *  - enable stencil test
9912  *  - verify that early stencil test is applied when enabled:
9913  *      - use program enabling early fragment tests,
9914  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9915  *      - fill texture with zeros,
9916  *      - set stencil test to:
9917  *          - <func> to GL_LESS,
9918  *          - <ref> to 128,
9919  *          - <mask> 0xffffffff,
9920  *      - bind texture to image uniform,
9921  *      - draw "full screen" quad at z: 0,
9922  *      - verify that texture is still filled with zeros,
9923  *  - verify that early stencil test does not discard all fragments:
9924  *      - use program enabling early fragment tests,
9925  *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9926  *      - fill texture with zeros,
9927  *      - set stencil test to:
9928  *          - <func> to GL_LESS,
9929  *          - <ref> to 0,
9930  *          - <mask> 0xffffffff,
9931  *      - bind texture to image uniform,
9932  *      - draw "full screen" quad at z: 0,
9933  *      - verify that texture is now filled with 1.0,
9934  *  - verify that early stencil test is not applied when disabled:
9935  *      - use program disabling early fragment tests,
9936  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9937  *      - fill texture with zeros,
9938  *      - set stencil test to:
9939  *          - <func> to GL_LESS,
9940  *          - <ref> to 128,
9941  *          - <mask> 0xffffffff,
9942  *      - bind texture to image uniform,
9943  *      - draw "full screen" quad at z: 0,
9944  *      - verify that texture is now filled with 1.0
9945  **/
9946 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9947 {
9948 private:
9949 	/* Constants */
9950 	GLuint			   m_image_edge;
9951 	static const GLint m_invalid_uniform_location = -1;
9952 
9953 	/* Types */
9954 	/** Store id and uniform locations for a single program object
9955 	 *
9956 	 **/
9957 	struct programDetails
9958 	{
9959 		GLint  m_depth_uniform_location;
9960 		GLint  m_image_uniform_location;
9961 		GLuint m_program_id;
9962 
programDetailsgl4cts::__anonb14d91fe0111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9963 		programDetails()
9964 			: m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9965 			, m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9966 			, m_program_id(0)
9967 		{
9968 			/* Nothing to be done here */
9969 		}
9970 	};
9971 
9972 	/* Fileds */
9973 	/* Storage for texture data */
9974 	std::vector<GLfloat> m_clean_texture_data;
9975 	std::vector<GLfloat> m_extracted_texture_data;
9976 
9977 	/* Program details */
9978 	programDetails m_disabled_early_tests;
9979 	programDetails m_enabled_early_tests;
9980 
9981 	/* Ids of GL objects */
9982 	GLuint m_color_renderbuffer_id;
9983 	GLuint m_depth_stencil_renderbuffer_id;
9984 	GLuint m_framebuffer_id;
9985 	GLuint m_texture_id;
9986 	GLuint m_vertex_array_object_id;
9987 
9988 public:
9989 	/* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()9990 	ImageLoadStoreEarlyFragmentTestsTest()
9991 		: m_image_edge(0)
9992 		, m_color_renderbuffer_id(0)
9993 		, m_depth_stencil_renderbuffer_id(0)
9994 		, m_framebuffer_id(0)
9995 		, m_texture_id(0)
9996 		, m_vertex_array_object_id(0)
9997 	{
9998 		/* Nothing to be done here */
9999 	}
10000 
10001 	/* Methods inherited from SubcaseBase */
Cleanup()10002 	virtual long Cleanup()
10003 	{
10004 		/* Restore defaults */
10005 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10006 		glBindRenderbuffer(GL_RENDERBUFFER, 0);
10007 		glBindTexture(GL_TEXTURE_2D, 0);
10008 		glBindVertexArray(0);
10009 		glDisable(GL_DEPTH_TEST);
10010 		glDisable(GL_STENCIL_TEST);
10011 		glUseProgram(0);
10012 
10013 		/* Delete objects */
10014 		if (0 != m_disabled_early_tests.m_program_id)
10015 		{
10016 			glDeleteProgram(m_disabled_early_tests.m_program_id);
10017 			m_disabled_early_tests.m_program_id = 0;
10018 		}
10019 
10020 		if (0 != m_enabled_early_tests.m_program_id)
10021 		{
10022 			glDeleteProgram(m_enabled_early_tests.m_program_id);
10023 			m_enabled_early_tests.m_program_id = 0;
10024 		}
10025 
10026 		if (0 != m_color_renderbuffer_id)
10027 		{
10028 			glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10029 			m_color_renderbuffer_id = 0;
10030 		}
10031 
10032 		if (0 != m_depth_stencil_renderbuffer_id)
10033 		{
10034 			glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10035 			m_depth_stencil_renderbuffer_id = 0;
10036 		}
10037 
10038 		if (0 != m_framebuffer_id)
10039 		{
10040 			glDeleteFramebuffers(1, &m_framebuffer_id);
10041 			m_framebuffer_id = 0;
10042 		}
10043 
10044 		if (0 != m_texture_id)
10045 		{
10046 			glDeleteTextures(1, &m_texture_id);
10047 			m_texture_id = 0;
10048 		}
10049 
10050 		if (0 != m_vertex_array_object_id)
10051 		{
10052 			glDeleteVertexArrays(1, &m_vertex_array_object_id);
10053 			m_vertex_array_object_id = 0;
10054 		}
10055 
10056 		/* Done */
10057 		return NO_ERROR;
10058 	}
10059 
Run()10060 	virtual long Run()
10061 	{
10062 		bool result = true;
10063 
10064 		/* Bind texture to first image unit */
10065 		glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10066 						   GL_READ_WRITE, GL_R32F);
10067 		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10068 
10069 		/* Run tests for depth test */
10070 		if (false == testEarlyZ())
10071 		{
10072 			result = false;
10073 		}
10074 
10075 		/* Run tests for stencil test */
10076 		if (false == testEarlyStencil())
10077 		{
10078 			result = false;
10079 		}
10080 
10081 		/* Return ERROR if any problem was found */
10082 		if (false == result)
10083 		{
10084 			return ERROR;
10085 		}
10086 
10087 		/* Done */
10088 		return NO_ERROR;
10089 	}
10090 
Setup()10091 	virtual long Setup()
10092 	{
10093 		m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10094 
10095 		/* Prepare storage for texture data */
10096 		m_clean_texture_data.resize(m_image_edge * m_image_edge);
10097 		m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10098 
10099 		/* Prepare programs, framebuffer and texture */
10100 		buildPrograms();
10101 		createFramebuffer();
10102 		createTexture();
10103 
10104 		/* Generate vertex array object */
10105 		glGenVertexArrays(1, &m_vertex_array_object_id);
10106 		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10107 
10108 		/* Bind vertex array object */
10109 		glBindVertexArray(m_vertex_array_object_id);
10110 		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10111 
10112 		/* Set clear color */
10113 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10114 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10115 
10116 		/* Done */
10117 		return NO_ERROR;
10118 	}
10119 
10120 private:
10121 	/** Build two programs: with enabled and disabled early fragment tests
10122 	 *
10123 	 **/
buildPrograms()10124 	void buildPrograms()
10125 	{
10126 		static const char* const fragment_shader_with_disabled_early_tests =
10127 			"#version 400 core\n"
10128 			"#extension GL_ARB_shader_image_load_store : require\n"
10129 			"\n"
10130 			"precision highp float;\n"
10131 			"\n"
10132 			"layout(r32f) uniform image2D u_image;\n"
10133 			"\n"
10134 			"void main()\n"
10135 			"{\n"
10136 			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10137 			"\n"
10138 			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10139 			"\n"
10140 			"    discard;\n"
10141 			"}\n\n";
10142 
10143 		static const char* const fragment_shader_with_enabled_early_tests =
10144 			"#version 400 core\n"
10145 			"#extension GL_ARB_shader_image_load_store : require\n"
10146 			"\n"
10147 			"precision highp float;\n"
10148 			"\n"
10149 			"layout(early_fragment_tests) in;\n"
10150 			"\n"
10151 			"layout(r32f) uniform image2D u_image;\n"
10152 			"\n"
10153 			"void main()\n"
10154 			"{\n"
10155 			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10156 			"\n"
10157 			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10158 			"\n"
10159 			"    discard;\n"
10160 			"}\n\n";
10161 
10162 		static const char* const geometry_shader_code = "#version 400 core\n"
10163 														"#extension GL_ARB_shader_image_load_store : require\n"
10164 														"\n"
10165 														"precision highp float;\n"
10166 														"\n"
10167 														"layout(points)                           in;\n"
10168 														"layout(triangle_strip, max_vertices = 4) out;\n"
10169 														"\n"
10170 														"uniform float u_depth;\n"
10171 														"\n"
10172 														"void main()\n"
10173 														"{\n"
10174 														"    // Left-bottom\n"
10175 														"    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10176 														"    EmitVertex();\n"
10177 														"\n"
10178 														"    // Left-top\n"
10179 														"    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10180 														"    EmitVertex();\n"
10181 														"\n"
10182 														"    // Right-bottom\n"
10183 														"    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10184 														"    EmitVertex();\n"
10185 														"\n"
10186 														"    // Right-top\n"
10187 														"    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10188 														"    EmitVertex();\n"
10189 														"}\n\n";
10190 
10191 		static const char* const vertex_shader_code = "#version 400 core\n"
10192 													  "#extension GL_ARB_shader_image_load_store : require\n"
10193 													  "\n"
10194 													  "precision highp float;\n"
10195 													  "\n"
10196 													  "void main()\n"
10197 													  "{\n"
10198 													  "}\n\n";
10199 
10200 		prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10201 							  m_disabled_early_tests);
10202 
10203 		prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10204 							  m_enabled_early_tests);
10205 	}
10206 
10207 	/** Fill texture with zeros
10208 	 *
10209 	 **/
cleanTexture()10210 	void cleanTexture()
10211 	{
10212 		glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10213 						GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10214 		GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10215 	}
10216 
10217 	/** Create and bind (draw) framebuffer with color and depth-stencil attachments
10218 	 *
10219 	 **/
createFramebuffer()10220 	void createFramebuffer()
10221 	{
10222 		/* Generate render buffers */
10223 		glGenRenderbuffers(1, &m_color_renderbuffer_id);
10224 		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10225 
10226 		glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10227 		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10228 
10229 		/* Generate and bind framebuffer object */
10230 		glGenFramebuffers(1, &m_framebuffer_id);
10231 		GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10232 
10233 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10234 		GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10235 
10236 		/* Prepare color render buffer */
10237 		glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10238 		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10239 
10240 		glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10241 		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10242 
10243 		/* Set up color attachment */
10244 		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10245 		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10246 
10247 		/* Prepare depth-stencil render buffer */
10248 		glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10249 		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10250 
10251 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10252 		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10253 
10254 		/* Set up depth-stencil attachment */
10255 		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10256 								  m_depth_stencil_renderbuffer_id);
10257 		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10258 	}
10259 
10260 	/** Create 2D R32F texture
10261 	 *
10262 	 **/
createTexture()10263 	void createTexture()
10264 	{
10265 		glGenTextures(1, &m_texture_id);
10266 		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10267 
10268 		glBindTexture(GL_TEXTURE_2D, m_texture_id);
10269 		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10270 
10271 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10272 		GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10273 	}
10274 
10275 	/** Extracts red channel from texture and verify if all texels are set to specified value
10276 	 *
10277 	 * @param value Expected value
10278 	 *
10279 	 * @return true if all texel match expected value, false otherwise
10280 	 **/
isTextureFilledWithValue(GLfloat value)10281 	bool isTextureFilledWithValue(GLfloat value)
10282 	{
10283 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10284 		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10285 
10286 		for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10287 		{
10288 			if (value != m_extracted_texture_data[i])
10289 			{
10290 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10291 													<< " has invalid value: " << m_extracted_texture_data[i]
10292 													<< " expected: " << value << tcu::TestLog::EndMessage;
10293 
10294 				return false;
10295 			}
10296 		}
10297 
10298 		return true;
10299 	}
10300 
10301 	/** Build program, extract location of uniforms and store results in programDetails instance
10302 	 *
10303 	 * Throws tcu::InternalError if uniforms are inactive
10304 	 *
10305 	 * @param fragment_shader_code Source of fragment shader
10306 	 * @param geometry_shader_code Source of geometry shader
10307 	 * @param vertex_shader_code   Source of vertex shader
10308 	 * @param out_program_details  Instance of programDetails
10309 	 **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10310 	void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10311 							   const char* vertex_shader_code, programDetails& out_program_details)
10312 	{
10313 		static const char* const depth_uniform_name = "u_depth";
10314 		static const char* const image_uniform_name = "u_image";
10315 		bool					 is_program_built   = true;
10316 
10317 		GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10318 										 fragment_shader_code, &is_program_built);
10319 
10320 		if (false == is_program_built)
10321 		{
10322 			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10323 		}
10324 
10325 		/* Get depth uniform location */
10326 		GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10327 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10328 
10329 		if (m_invalid_uniform_location == depth_uniform_location)
10330 		{
10331 			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10332 		}
10333 
10334 		/* Get image uniform location */
10335 		GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10336 		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10337 
10338 		if (m_invalid_uniform_location == image_uniform_location)
10339 		{
10340 			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10341 		}
10342 
10343 		/* Store results */
10344 		out_program_details.m_depth_uniform_location = depth_uniform_location;
10345 		out_program_details.m_image_uniform_location = image_uniform_location;
10346 		out_program_details.m_program_id			 = program_id;
10347 	}
10348 
10349 	/** Test if early fragment stencil test works as expected.
10350 	 *
10351 	 * @return true if successful, false otherwise
10352 	 **/
testEarlyStencil()10353 	bool testEarlyStencil()
10354 	{
10355 		bool result = true;
10356 
10357 		glEnable(GL_STENCIL_TEST);
10358 		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10359 
10360 		glClearDepthf(1.0f);
10361 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10362 
10363 		/* verify that early stencil test is applied when enabled */
10364 		{
10365 			glUseProgram(m_enabled_early_tests.m_program_id);
10366 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10367 
10368 			glClearStencil(0);
10369 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10370 
10371 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10372 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10373 
10374 			cleanTexture();
10375 
10376 			glStencilFunc(GL_LESS, 128, 0xffffffff);
10377 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10378 
10379 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10380 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10381 
10382 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10383 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10384 
10385 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10386 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10387 
10388 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10389 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10390 
10391 			if (false == isTextureFilledWithValue(0.0f))
10392 			{
10393 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10394 													<< "Problem with early stencil test. It is not applied"
10395 													<< tcu::TestLog::EndMessage;
10396 
10397 				result = false;
10398 			}
10399 		}
10400 
10401 		/* verify that early stencil test does not discard all fragments */
10402 		{
10403 			glClearStencil(128);
10404 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10405 
10406 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10407 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10408 
10409 			cleanTexture();
10410 
10411 			glStencilFunc(GL_LESS, 0, 0xffffffff);
10412 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10413 
10414 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10415 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10416 
10417 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10418 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10419 
10420 			if (false == isTextureFilledWithValue(1.0f))
10421 			{
10422 				m_context.getTestContext().getLog()
10423 					<< tcu::TestLog::Message
10424 					<< "Problem with early stencil test. It discards fragments, that shall be drawn"
10425 					<< tcu::TestLog::EndMessage;
10426 
10427 				result = false;
10428 			}
10429 		}
10430 
10431 		/* verify that early stencil test is not applied when disabled */
10432 		{
10433 			glUseProgram(m_disabled_early_tests.m_program_id);
10434 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10435 
10436 			glClearStencil(0);
10437 			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10438 
10439 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10440 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10441 
10442 			cleanTexture();
10443 
10444 			glStencilFunc(GL_LESS, 128, 0xffffffff);
10445 			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10446 
10447 			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10448 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10449 
10450 			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10451 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10452 
10453 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10454 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10455 
10456 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10457 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10458 
10459 			if (false == isTextureFilledWithValue(1.0f))
10460 			{
10461 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10462 													<< "Problem with early stencil test. It is applied when disabled"
10463 													<< tcu::TestLog::EndMessage;
10464 
10465 				result = false;
10466 			}
10467 		}
10468 
10469 		glDisable(GL_STENCIL_TEST);
10470 		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10471 
10472 		/* Done */
10473 		return result;
10474 	}
10475 
10476 	/** Test if early fragment depth test works as expected.
10477 	 *
10478 	 * @return true if successful, false otherwise
10479 	 **/
testEarlyZ()10480 	bool testEarlyZ()
10481 	{
10482 		bool result = true;
10483 
10484 		glEnable(GL_DEPTH_TEST);
10485 		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10486 
10487 		glClearDepthf(0.5f);
10488 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10489 
10490 		glClearStencil(0);
10491 		GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10492 
10493 		/* verify that early z test is applied when enabled */
10494 		{
10495 			glUseProgram(m_enabled_early_tests.m_program_id);
10496 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10497 
10498 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10499 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10500 
10501 			cleanTexture();
10502 
10503 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10504 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10505 
10506 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10507 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10508 
10509 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10510 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10511 
10512 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10513 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10514 
10515 			if (false == isTextureFilledWithValue(0.0f))
10516 			{
10517 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10518 													<< "Problem with early z test. It is not applied"
10519 													<< tcu::TestLog::EndMessage;
10520 
10521 				result = false;
10522 			}
10523 		}
10524 
10525 		/* verify that early z test does not discard all fragments */
10526 		{
10527 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10528 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10529 
10530 			cleanTexture();
10531 
10532 			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10533 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10534 
10535 			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10536 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10537 
10538 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10539 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10540 
10541 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10542 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10543 
10544 			if (false == isTextureFilledWithValue(1.0f))
10545 			{
10546 				m_context.getTestContext().getLog()
10547 					<< tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10548 					<< tcu::TestLog::EndMessage;
10549 
10550 				result = false;
10551 			}
10552 		}
10553 
10554 		/* verify that early z test is not applied when disabled */
10555 		{
10556 			glUseProgram(m_disabled_early_tests.m_program_id);
10557 			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10558 
10559 			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10560 			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10561 
10562 			cleanTexture();
10563 
10564 			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10565 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10566 
10567 			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10568 			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10569 
10570 			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10571 			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10572 
10573 			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10574 			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10575 
10576 			if (false == isTextureFilledWithValue(1.0f))
10577 			{
10578 				m_context.getTestContext().getLog() << tcu::TestLog::Message
10579 													<< "Problem with early z test. It is applied when disabled"
10580 													<< tcu::TestLog::EndMessage;
10581 
10582 				result = false;
10583 			}
10584 		}
10585 
10586 		glDisable(GL_DEPTH_TEST);
10587 		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10588 
10589 		/* Done */
10590 		return result;
10591 	}
10592 };
10593 
10594 //-----------------------------------------------------------------------------
10595 // 4.1 NegativeUniform
10596 //-----------------------------------------------------------------------------
10597 class NegativeUniform : public ShaderImageLoadStoreBase
10598 {
10599 	GLuint m_program;
10600 
Setup()10601 	virtual long Setup()
10602 	{
10603 		m_program = 0;
10604 		return NO_ERROR;
10605 	}
10606 
Run()10607 	virtual long Run()
10608 	{
10609 		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10610 							  "  gl_Position = i_position;" NL "}";
10611 		const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10612 							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10613 							  "  discard;" NL "}";
10614 		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10615 
10616 		GLint max_image_units;
10617 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10618 		glUseProgram(m_program);
10619 
10620 		glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10621 		if (glGetError() != GL_INVALID_VALUE)
10622 		{
10623 			m_context.getTestContext().getLog()
10624 				<< tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10625 				<< tcu::TestLog::EndMessage;
10626 			return ERROR;
10627 		}
10628 		glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10629 		if (glGetError() != GL_INVALID_VALUE)
10630 		{
10631 			m_context.getTestContext().getLog()
10632 				<< tcu::TestLog::Message
10633 				<< "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10634 				<< "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10635 			return ERROR;
10636 		}
10637 
10638 		GLint i = -3;
10639 		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10640 		if (glGetError() != GL_INVALID_VALUE)
10641 		{
10642 			m_context.getTestContext().getLog()
10643 				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10644 				<< tcu::TestLog::EndMessage;
10645 			return ERROR;
10646 		}
10647 		i = max_image_units + 1;
10648 		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10649 		if (glGetError() != GL_INVALID_VALUE)
10650 		{
10651 			m_context.getTestContext().getLog()
10652 				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10653 											"than or equal to the value of MAX_IMAGE_UNITS."
10654 				<< tcu::TestLog::EndMessage;
10655 			return ERROR;
10656 		}
10657 
10658 		glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10659 		if (glGetError() != GL_INVALID_OPERATION)
10660 		{
10661 			m_context.getTestContext().getLog()
10662 				<< tcu::TestLog::Message
10663 				<< "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10664 				<< tcu::TestLog::EndMessage;
10665 			return ERROR;
10666 		}
10667 		glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10668 		if (glGetError() != GL_INVALID_OPERATION)
10669 		{
10670 			m_context.getTestContext().getLog()
10671 				<< tcu::TestLog::Message
10672 				<< "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10673 				<< tcu::TestLog::EndMessage;
10674 			return ERROR;
10675 		}
10676 
10677 		{
10678 			glUseProgram(0);
10679 
10680 			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10681 			if (glGetError() != GL_INVALID_VALUE)
10682 			{
10683 				m_context.getTestContext().getLog()
10684 					<< tcu::TestLog::Message
10685 					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10686 					<< tcu::TestLog::EndMessage;
10687 				return ERROR;
10688 			}
10689 			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10690 			if (glGetError() != GL_INVALID_VALUE)
10691 			{
10692 				m_context.getTestContext().getLog()
10693 					<< tcu::TestLog::Message
10694 					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10695 					   "value of MAX_IMAGE_UNITS."
10696 					<< tcu::TestLog::EndMessage;
10697 				return ERROR;
10698 			}
10699 
10700 			GLint ii = -3;
10701 			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10702 			if (glGetError() != GL_INVALID_VALUE)
10703 			{
10704 				m_context.getTestContext().getLog()
10705 					<< tcu::TestLog::Message
10706 					<< "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10707 					<< tcu::TestLog::EndMessage;
10708 				return ERROR;
10709 			}
10710 			ii = max_image_units + 1;
10711 			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10712 			if (glGetError() != GL_INVALID_VALUE)
10713 			{
10714 				m_context.getTestContext().getLog()
10715 					<< tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10716 												"is greater than or equal to the value of MAX_IMAGE_UNITS."
10717 					<< tcu::TestLog::EndMessage;
10718 				return ERROR;
10719 			}
10720 
10721 			glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10722 			if (glGetError() != GL_INVALID_OPERATION)
10723 			{
10724 				m_context.getTestContext().getLog()
10725 					<< tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10726 												"location refers to an image variable."
10727 					<< tcu::TestLog::EndMessage;
10728 				return ERROR;
10729 			}
10730 			glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10731 			if (glGetError() != GL_INVALID_OPERATION)
10732 			{
10733 				m_context.getTestContext().getLog()
10734 					<< tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10735 												"location refers to an image variable."
10736 					<< tcu::TestLog::EndMessage;
10737 				return ERROR;
10738 			}
10739 		}
10740 
10741 		return NO_ERROR;
10742 	}
10743 
Cleanup()10744 	virtual long Cleanup()
10745 	{
10746 		glUseProgram(0);
10747 		glDeleteProgram(m_program);
10748 		return NO_ERROR;
10749 	}
10750 };
10751 //-----------------------------------------------------------------------------
10752 // 4.2 NegativeBind
10753 //-----------------------------------------------------------------------------
10754 class NegativeBind : public ShaderImageLoadStoreBase
10755 {
Setup()10756 	virtual long Setup()
10757 	{
10758 		return NO_ERROR;
10759 	}
10760 
Run()10761 	virtual long Run()
10762 	{
10763 		glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10764 		if (glGetError() != GL_INVALID_VALUE)
10765 		{
10766 			m_context.getTestContext().getLog()
10767 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10768 											"greater than or equal to the value of MAX_IMAGE_UNITS."
10769 				<< tcu::TestLog::EndMessage;
10770 			return ERROR;
10771 		}
10772 
10773 		glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10774 		if (glGetError() != GL_INVALID_VALUE)
10775 		{
10776 			m_context.getTestContext().getLog()
10777 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10778 											"the name of an existing texture object."
10779 				<< tcu::TestLog::EndMessage;
10780 			return ERROR;
10781 		}
10782 
10783 		glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10784 		if (glGetError() != GL_INVALID_VALUE)
10785 		{
10786 			m_context.getTestContext().getLog()
10787 				<< tcu::TestLog::Message
10788 				<< "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10789 				<< tcu::TestLog::EndMessage;
10790 			return ERROR;
10791 		}
10792 		return NO_ERROR;
10793 	}
10794 
Cleanup()10795 	virtual long Cleanup()
10796 	{
10797 		return NO_ERROR;
10798 	}
10799 };
10800 //-----------------------------------------------------------------------------
10801 // 4.3 NegativeCompileErrors
10802 //-----------------------------------------------------------------------------
10803 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10804 {
Run()10805 	virtual long Run()
10806 	{
10807 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10808 					 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10809 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10810 			return ERROR;
10811 
10812 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10813 					 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10814 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10815 			return ERROR;
10816 
10817 		if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10818 					 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10819 					 "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10820 			return ERROR;
10821 
10822 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10823 					 "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10824 			return ERROR;
10825 
10826 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10827 					 "readonly uniform image2D g_image;" NL "void main() {" NL
10828 					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10829 			return ERROR;
10830 
10831 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10832 					 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10833 			return ERROR;
10834 
10835 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10836 					 "layout(rg16) uniform iimage2D 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(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10841 					 "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10842 			return ERROR;
10843 
10844 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10845 					 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10846 					 "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10847 			return ERROR;
10848 
10849 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10850 					 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10851 					 "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10852 			return ERROR;
10853 
10854 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10855 					 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10856 					 "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10857 			return ERROR;
10858 
10859 		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10860 					 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10861 					 "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10862 					 "}"))
10863 			return ERROR;
10864 
10865 		return NO_ERROR;
10866 	}
10867 
Compile(const std::string & source)10868 	bool Compile(const std::string& source)
10869 	{
10870 		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10871 
10872 		const char* const src = source.c_str();
10873 		glShaderSource(sh, 1, &src, NULL);
10874 		glCompileShader(sh);
10875 
10876 		GLchar log[1024];
10877 		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10878 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10879 											<< log << tcu::TestLog::EndMessage;
10880 
10881 		GLint status;
10882 		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10883 		glDeleteShader(sh);
10884 
10885 		if (status == GL_TRUE)
10886 		{
10887 			m_context.getTestContext().getLog()
10888 				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10889 			return false;
10890 		}
10891 
10892 		return true;
10893 	}
10894 };
10895 //-----------------------------------------------------------------------------
10896 // 4.4 NegativeLinkErrors
10897 //-----------------------------------------------------------------------------
10898 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10899 {
Run()10900 	virtual long Run()
10901 	{
10902 		if (!SupportedInVS(1))
10903 			return NOT_SUPPORTED;
10904 
10905 		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10906 				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10907 				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10908 				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10909 				  "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10910 				  "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10911 			return ERROR;
10912 
10913 		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10914 				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10915 				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10916 				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10917 				  "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10918 				  "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10919 			return ERROR;
10920 
10921 		return NO_ERROR;
10922 	}
10923 
Link(const std::string & vs,const std::string & fs)10924 	bool Link(const std::string& vs, const std::string& fs)
10925 	{
10926 		const GLuint p = glCreateProgram();
10927 
10928 		const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10929 		glAttachShader(p, vsh);
10930 		glDeleteShader(vsh);
10931 		const char* const vssrc = vs.c_str();
10932 		glShaderSource(vsh, 1, &vssrc, NULL);
10933 		glCompileShader(vsh);
10934 
10935 		const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10936 		glAttachShader(p, fsh);
10937 		glDeleteShader(fsh);
10938 		const char* const fssrc = fs.c_str();
10939 		glShaderSource(fsh, 1, &fssrc, NULL);
10940 		glCompileShader(fsh);
10941 
10942 		GLint status;
10943 		glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10944 		if (status == GL_FALSE)
10945 		{
10946 			glDeleteProgram(p);
10947 			m_context.getTestContext().getLog()
10948 				<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10949 			return false;
10950 		}
10951 		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10952 		if (status == GL_FALSE)
10953 		{
10954 			glDeleteProgram(p);
10955 			m_context.getTestContext().getLog()
10956 				<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10957 			return false;
10958 		}
10959 
10960 		glLinkProgram(p);
10961 
10962 		GLchar log[1024];
10963 		glGetProgramInfoLog(p, sizeof(log), NULL, log);
10964 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10965 											<< log << tcu::TestLog::EndMessage;
10966 
10967 		glGetProgramiv(p, GL_LINK_STATUS, &status);
10968 		glDeleteProgram(p);
10969 
10970 		if (status == GL_TRUE)
10971 		{
10972 			m_context.getTestContext().getLog()
10973 				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10974 			return false;
10975 		}
10976 
10977 		return true;
10978 	}
10979 };
10980 
10981 /** Negative Test "Active image uniform limits", description follows.
10982  *
10983  *  Program that exceeds resource limits should not compile and/or link.
10984  *
10985  *  Steps:
10986  *  - try to compile and link a program that uses too many image uniforms in
10987  *  fragment shader stage,
10988  *  - try to compile and link a program that uses too many image uniforms in
10989  *  vertex shader stage,
10990  *  - try to compile and link a program that uses too many image uniforms in
10991  *  tessellation control shader stage,
10992  *  - try to compile and link a program that uses too many image uniforms in
10993  *  tessellation evaluation shader stage,
10994  *  - try to compile and link a program that uses too many image uniforms in
10995  *  geometry shader stage,
10996  *  - try to compile and link a program that uses too many image uniforms in all
10997  *  shader stages combined, any single stage should not exceed its limits, this
10998  *  step might be impossible to fulfill.
10999  *
11000  *  Test should use the following declaration of image uniforms:
11001  *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11002  *
11003  *  For cases where limit for single stage is tested, N_UNIFORMS should be
11004  *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11005  *  corresponding to tested shader stage.
11006  *
11007  *  For case where limit for combined stages is tested:
11008  *  - u_image name should be appended with the name of shader stage, like
11009  *  u_image_vertex,
11010  *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11011  *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11012  *  - compilation and linking shall succeed, when sum of all
11013  *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11014  *  gl_MaxCombinedImageUniforms.
11015  *
11016  *  All defined image uniforms have to be active. Each shader stage that declare
11017  *  image uniforms should include following code snippet:
11018  *  value = 1;
11019  *  for (int i = 0; i < N_UNIFORMS; ++i)
11020  *  {
11021  *      value = imageAtomicAdd(u_image[i], coord, value);
11022  *  }
11023  **/
11024 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11025 {
11026 private:
11027 	/* Fields */
11028 	/* Results */
11029 	bool m_result_for_combined;
11030 	bool m_result_for_fragment_shader;
11031 	bool m_result_for_geometry_shader;
11032 	bool m_result_for_tesselation_control_shader;
11033 	bool m_result_for_tesselatioon_evaluation_shader;
11034 	bool m_result_for_vertex_shader;
11035 
11036 public:
11037 	/* Constructor */
ImageLoadStoreUniformLimitsTest()11038 	ImageLoadStoreUniformLimitsTest()
11039 		: m_result_for_combined(false)
11040 		, m_result_for_fragment_shader(false)
11041 		, m_result_for_geometry_shader(false)
11042 		, m_result_for_tesselation_control_shader(false)
11043 		, m_result_for_tesselatioon_evaluation_shader(false)
11044 		, m_result_for_vertex_shader(false)
11045 	{
11046 		/* Nothing to be done */
11047 	}
11048 
11049 	/* Methods inherited from SubcaseBase */
Cleanup()11050 	virtual long Cleanup()
11051 	{
11052 		/* Done */
11053 		return NO_ERROR;
11054 	}
11055 
Run()11056 	virtual long Run()
11057 	{
11058 		m_context.getTestContext().getLog() << tcu::TestLog::Message
11059 											<< "This test tries to build invalid programs, expect error messages about "
11060 											   "exceeded number of active image uniforms"
11061 											<< tcu::TestLog::EndMessage;
11062 
11063 		testFragmentShaderStage();
11064 		testGeometryShaderStage();
11065 		testTesselationControlShaderStage();
11066 		testTesselationEvaluationShaderStage();
11067 		testVertexShaderStage();
11068 		testCombinedShaderStages();
11069 
11070 		/* Return error if any stage failed */
11071 		if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11072 			(false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11073 			(false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11074 		{
11075 			return ERROR;
11076 		}
11077 
11078 		/* Done */
11079 		return NO_ERROR;
11080 	}
11081 
Setup()11082 	virtual long Setup()
11083 	{
11084 		/* Done */
11085 		return NO_ERROR;
11086 	}
11087 
11088 private:
11089 	/** Test fragment shader stage
11090 	 *
11091 	 **/
testFragmentShaderStage()11092 	void testFragmentShaderStage()
11093 	{
11094 		static const char* const fragment_shader_code =
11095 			"#version 400 core\n"
11096 			"#extension GL_ARB_shader_image_load_store : require\n"
11097 			"\n"
11098 			"precision highp float;\n"
11099 			"\n"
11100 			"#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11101 			"\n"
11102 			"flat in ivec2 vs_fs_coord;\n"
11103 			"\n"
11104 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11105 			"\n"
11106 			"void main()\n"
11107 			"{\n"
11108 			"    int value = 1;\n"
11109 			"\n"
11110 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11111 			"    {\n"
11112 			"        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11113 			"    }\n"
11114 			"\n"
11115 			"    discard;\n"
11116 			"}\n\n";
11117 
11118 		static const char* const vertex_shader_code = "#version 400 core\n"
11119 													  "#extension GL_ARB_shader_image_load_store : require\n"
11120 													  "\n"
11121 													  "precision highp float;\n"
11122 													  "\n"
11123 													  "     in  ivec2 vs_in_coord;\n"
11124 													  "flat out ivec2 vs_fs_coord;\n"
11125 													  "\n"
11126 													  "void main()\n"
11127 													  "{\n"
11128 													  "    vs_fs_coord = vs_in_coord;\n"
11129 													  "}\n\n";
11130 
11131 		m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11132 														0 /* tesselation_control_shader_code */,
11133 														0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11134 
11135 		if (false == m_result_for_fragment_shader)
11136 		{
11137 			m_context.getTestContext().getLog()
11138 				<< tcu::TestLog::Message
11139 				<< "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11140 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11141 				<< fragment_shader_code << tcu::TestLog::EndMessage;
11142 		}
11143 	}
11144 
11145 	/** Test geometry shader stage
11146 	 *
11147 	 **/
testGeometryShaderStage()11148 	void testGeometryShaderStage()
11149 	{
11150 		static const char* const fragment_shader_code = "#version 400 core\n"
11151 														"#extension GL_ARB_shader_image_load_store : require\n"
11152 														"\n"
11153 														"precision highp float;\n"
11154 														"\n"
11155 														"void main()\n"
11156 														"{\n"
11157 														"    discard;\n"
11158 														"}\n\n";
11159 
11160 		static const char* const geometry_shader_code =
11161 			"#version 400 core\n"
11162 			"#extension GL_ARB_shader_image_load_store : require\n"
11163 			"\n"
11164 			"precision highp float;\n"
11165 			"\n"
11166 			"layout(points)                   in;\n"
11167 			"layout(points, max_vertices = 1) out;\n"
11168 			"\n"
11169 			"#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11170 			"\n"
11171 			"in ivec2 vs_gs_coord[];\n"
11172 			"\n"
11173 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11174 			"\n"
11175 			"void main()\n"
11176 			"{\n"
11177 			"    int value = 1;\n"
11178 			"\n"
11179 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11180 			"    {\n"
11181 			"        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11182 			"    }\n"
11183 			"}\n\n";
11184 
11185 		static const char* const vertex_shader_code = "#version 400 core\n"
11186 													  "#extension GL_ARB_shader_image_load_store : require\n"
11187 													  "\n"
11188 													  "precision highp float;\n"
11189 													  "\n"
11190 													  "in  ivec2 vs_in_coord;\n"
11191 													  "out ivec2 vs_gs_coord;\n"
11192 													  "\n"
11193 													  "void main()\n"
11194 													  "{\n"
11195 													  "    vs_gs_coord = vs_in_coord;\n"
11196 													  "}\n\n";
11197 
11198 		m_result_for_geometry_shader =
11199 			!doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11200 							 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11201 
11202 		if (false == m_result_for_geometry_shader)
11203 		{
11204 			m_context.getTestContext().getLog()
11205 				<< tcu::TestLog::Message
11206 				<< "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11207 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11208 				<< geometry_shader_code << tcu::TestLog::EndMessage;
11209 		}
11210 	}
11211 
11212 	/** Test tesselation control shader stage
11213 	 *
11214 	 **/
testTesselationControlShaderStage()11215 	void testTesselationControlShaderStage()
11216 	{
11217 		static const char* const fragment_shader_code = "#version 400 core\n"
11218 														"#extension GL_ARB_shader_image_load_store : require\n"
11219 														"\n"
11220 														"precision highp float;\n"
11221 														"\n"
11222 														"void main()\n"
11223 														"{\n"
11224 														"    discard;\n"
11225 														"}\n\n";
11226 
11227 		static const char* const tesselation_control_shader_code =
11228 			"#version 400 core\n"
11229 			"#extension GL_ARB_shader_image_load_store : require\n"
11230 			"\n"
11231 			"precision highp float;\n"
11232 			"\n"
11233 			"layout(vertices = 4) out;\n"
11234 			"\n"
11235 			"#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11236 			"\n"
11237 			"in ivec2 vs_tcs_coord[];\n"
11238 			"\n"
11239 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11240 			"\n"
11241 			"void main()\n"
11242 			"{\n"
11243 			"    int value = 1;\n"
11244 			"\n"
11245 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11246 			"    {\n"
11247 			"        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11248 			"    }\n"
11249 			"}\n\n";
11250 
11251 		static const char* const tesselation_evaluation_shader_code =
11252 			"#version 400 core\n"
11253 			"#extension GL_ARB_shader_image_load_store : require\n"
11254 			"\n"
11255 			"precision highp float;\n"
11256 			"\n"
11257 			"layout(quads, equal_spacing, ccw) in;\n"
11258 			"\n"
11259 			"void main()\n"
11260 			"{\n"
11261 			"}\n";
11262 
11263 		static const char* const vertex_shader_code = "#version 400 core\n"
11264 													  "#extension GL_ARB_shader_image_load_store : require\n"
11265 													  "\n"
11266 													  "precision highp float;\n"
11267 													  "\n"
11268 													  "in  ivec2 vs_in_coord;\n"
11269 													  "out ivec2 vs_tcs_coord;\n"
11270 													  "\n"
11271 													  "void main()\n"
11272 													  "{\n"
11273 													  "    vs_tcs_coord = vs_in_coord;\n"
11274 													  "}\n\n";
11275 
11276 		m_result_for_tesselation_control_shader =
11277 			!doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11278 							 tesselation_evaluation_shader_code, vertex_shader_code);
11279 
11280 		if (false == m_result_for_tesselation_control_shader)
11281 		{
11282 			m_context.getTestContext().getLog()
11283 				<< tcu::TestLog::Message
11284 				<< "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11285 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11286 				<< tesselation_control_shader_code << tcu::TestLog::EndMessage;
11287 		}
11288 	}
11289 
11290 	/** Test teselation evaluation shader stage
11291 	 *
11292 	 **/
testTesselationEvaluationShaderStage()11293 	void testTesselationEvaluationShaderStage()
11294 	{
11295 		static const char* const fragment_shader_code = "#version 400 core\n"
11296 														"#extension GL_ARB_shader_image_load_store : require\n"
11297 														"\n"
11298 														"precision highp float;\n"
11299 														"\n"
11300 														"void main()\n"
11301 														"{\n"
11302 														"    discard;\n"
11303 														"}\n\n";
11304 
11305 		static const char* const tesselation_evaluation_shader_code =
11306 			"#version 400 core\n"
11307 			"#extension GL_ARB_shader_image_load_store : require\n"
11308 			"\n"
11309 			"precision highp float;\n"
11310 			"\n"
11311 			"layout(quads, equal_spacing, ccw) in;\n"
11312 			"\n"
11313 			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11314 			"\n"
11315 			"in ivec2 vs_tes_coord[];\n"
11316 			"\n"
11317 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11318 			"\n"
11319 			"void main()\n"
11320 			"{\n"
11321 			"    int value = 1;\n"
11322 			"\n"
11323 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11324 			"    {\n"
11325 			"        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11326 			"    }\n"
11327 			"}\n\n";
11328 
11329 		static const char* const vertex_shader_code = "#version 400 core\n"
11330 													  "#extension GL_ARB_shader_image_load_store : require\n"
11331 													  "\n"
11332 													  "precision highp float;\n"
11333 													  "\n"
11334 													  "in  ivec2 vs_in_coord;\n"
11335 													  "out ivec2 vs_tes_coord;\n"
11336 													  "\n"
11337 													  "void main()\n"
11338 													  "{\n"
11339 													  "    vs_tes_coord = vs_in_coord;\n"
11340 													  "}\n\n";
11341 
11342 		m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11343 			fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11344 			tesselation_evaluation_shader_code, vertex_shader_code);
11345 
11346 		if (false == m_result_for_tesselatioon_evaluation_shader)
11347 		{
11348 			m_context.getTestContext().getLog()
11349 				<< tcu::TestLog::Message
11350 				<< "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11351 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11352 				<< tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11353 		}
11354 	}
11355 
11356 	/** Test vertex shader stage
11357 	 *
11358 	 **/
testVertexShaderStage()11359 	void testVertexShaderStage()
11360 	{
11361 		static const char* const fragment_shader_code = "#version 400 core\n"
11362 														"#extension GL_ARB_shader_image_load_store : require\n"
11363 														"\n"
11364 														"precision highp float;\n"
11365 														"\n"
11366 														"void main()\n"
11367 														"{\n"
11368 														"    discard;\n"
11369 														"}\n\n";
11370 
11371 		static const char* const vertex_shader_code =
11372 			"#version 400 core\n"
11373 			"#extension GL_ARB_shader_image_load_store : require\n"
11374 			"\n"
11375 			"precision highp float;\n"
11376 			"\n"
11377 			"in ivec2 vs_in_coord;\n"
11378 			"\n"
11379 			"#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11380 			"\n"
11381 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11382 			"\n"
11383 			"void main()\n"
11384 			"{\n"
11385 			"    int value = 1;\n"
11386 			"\n"
11387 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11388 			"    {\n"
11389 			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11390 			"    }\n"
11391 			"}\n\n";
11392 
11393 		m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11394 													  0 /* tesselation_control_shader_code */,
11395 													  0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11396 
11397 		if (false == m_result_for_vertex_shader)
11398 		{
11399 			m_context.getTestContext().getLog()
11400 				<< tcu::TestLog::Message
11401 				<< "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11402 				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11403 				<< vertex_shader_code << tcu::TestLog::EndMessage;
11404 		}
11405 	}
11406 
11407 	/** Test combined shader stages
11408 	 *
11409 	 **/
testCombinedShaderStages()11410 	void testCombinedShaderStages()
11411 	{
11412 		std::string fragment_shader_code =
11413 			"#version 400 core\n"
11414 			"#extension GL_ARB_shader_image_load_store : require\n"
11415 			"\n"
11416 			"precision highp float;\n"
11417 			"\n"
11418 			"#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11419 			"\n"
11420 			"flat in ivec2 gs_fs_coord;\n"
11421 			"\n"
11422 			"layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11423 			"\n"
11424 			"void main()\n"
11425 			"{\n"
11426 			"    int value = 1;\n"
11427 			"\n"
11428 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11429 			"    {\n"
11430 			"        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11431 			"    }\n"
11432 			"\n"
11433 			"    discard;\n"
11434 			"}\n\n";
11435 
11436 		std::string geometry_shader_code =
11437 			"#version 400 core\n"
11438 			"#extension GL_ARB_shader_image_load_store : require\n"
11439 			"\n"
11440 			"precision highp float;\n"
11441 			"\n"
11442 			"layout(points)                   in;\n"
11443 			"layout(points, max_vertices = 1) out;\n"
11444 			"\n"
11445 			"#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11446 			"\n"
11447 			"flat in  ivec2 tes_gs_coord[];\n"
11448 			"flat out ivec2 gs_fs_coord;\n"
11449 			"\n"
11450 			"#ifdef IMAGES\n"
11451 			"layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11452 			"#endif\n"
11453 			"\n"
11454 			"void main()\n"
11455 			"{\n"
11456 			"#ifdef IMAGES\n"
11457 			"    int value = 1;\n"
11458 			"\n"
11459 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11460 			"    {\n"
11461 			"        value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11462 			"    }\n"
11463 			"\n"
11464 			"#endif\n"
11465 			"    gs_fs_coord = tes_gs_coord[0];\n"
11466 			"    EmitVertex();\n"
11467 			"}\n\n";
11468 
11469 		std::string tesselation_control_shader_code =
11470 			"#version 400 core\n"
11471 			"#extension GL_ARB_shader_image_load_store : require\n"
11472 			"\n"
11473 			"precision highp float;\n"
11474 			"\n"
11475 			"layout(vertices = 4) out;\n"
11476 			"\n"
11477 			"#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11478 			"\n"
11479 			"flat in  ivec2 vs_tcs_coord[];\n"
11480 			"flat out ivec2 tcs_tes_coord[];\n"
11481 			"\n"
11482 			"#ifdef IMAGES\n"
11483 			"layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11484 			"#endif\n"
11485 			"\n"
11486 			"void main()\n"
11487 			"{\n"
11488 			"#ifdef IMAGES\n"
11489 			"    int value = 1;\n"
11490 			"\n"
11491 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11492 			"    {\n"
11493 			"        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11494 			"    }\n"
11495 			"\n"
11496 			"#endif\n"
11497 			"    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11498 			"}\n\n";
11499 
11500 		std::string tesselation_evaluation_shader_code =
11501 			"#version 400 core\n"
11502 			"#extension GL_ARB_shader_image_load_store : require\n"
11503 			"\n"
11504 			"precision highp float;\n"
11505 			"\n"
11506 			"layout(quads, equal_spacing, ccw) in;\n"
11507 			"\n"
11508 			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11509 			"\n"
11510 			"flat in  ivec2 tcs_tes_coord[];\n"
11511 			"flat out ivec2 tes_gs_coord;\n"
11512 			"\n"
11513 			"#ifdef IMAGES\n"
11514 			"layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11515 			"#endif\n"
11516 			"\n"
11517 			"void main()\n"
11518 			"{\n"
11519 			"#ifdef IMAGES\n"
11520 			"    int value = 1;\n"
11521 			"\n"
11522 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11523 			"    {\n"
11524 			"        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11525 			"    }\n"
11526 			"\n"
11527 			"#endif\n"
11528 			"    tes_gs_coord = tcs_tes_coord[0];\n"
11529 			"}\n\n";
11530 
11531 		std::string vertex_shader_code =
11532 			"#version 400 core\n"
11533 			"#extension GL_ARB_shader_image_load_store : require\n"
11534 			"\n"
11535 			"precision highp float;\n"
11536 			"\n"
11537 			"     in  ivec2 vs_in_coord;\n"
11538 			"flat out ivec2 vs_tcs_coord;\n"
11539 			"\n"
11540 			"#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11541 			"\n"
11542 			"#ifdef IMAGES\n"
11543 			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11544 			"#endif\n"
11545 			"\n"
11546 			"void main()\n"
11547 			"{\n"
11548 			"#ifdef IMAGES\n"
11549 			"    int value = 1;\n"
11550 			"\n"
11551 			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11552 			"    {\n"
11553 			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11554 			"    }\n"
11555 			"\n"
11556 			"#endif\n"
11557 			"    vs_tcs_coord = vs_tcs_coord;\n"
11558 			"}\n\n";
11559 
11560 		/* Active image uniform limits */
11561 		GLint max_combined_image_uniforms				= 0;
11562 		GLint max_fragment_image_uniforms				= 0;
11563 		GLint max_geometry_image_uniforms				= 0;
11564 		GLint max_tesselation_control_image_uniforms	= 0;
11565 		GLint max_tesselation_evaluation_image_uniforms = 0;
11566 		GLint max_vertex_image_uniforms					= 0;
11567 
11568 		/* Get limit values */
11569 		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11570 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11571 		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11572 		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11573 		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11574 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11575 		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11576 
11577 		if (max_vertex_image_uniforms)
11578 			vertex_shader_code.insert(18, "#define IMAGES\n");
11579 		if (max_geometry_image_uniforms)
11580 			geometry_shader_code.insert(18, "#define IMAGES\n");
11581 		if (max_tesselation_control_image_uniforms)
11582 			tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11583 		if (max_tesselation_evaluation_image_uniforms)
11584 			tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11585 
11586 		/* Check if program builds */
11587 		m_result_for_combined =
11588 			!doesProgramLink(fragment_shader_code.c_str(),
11589 							 geometry_shader_code.c_str(),
11590 							 tesselation_control_shader_code.c_str(),
11591 							 tesselation_evaluation_shader_code.c_str(),
11592 							 vertex_shader_code.c_str());
11593 
11594 		/* Result depends on the limit values */
11595 		if (max_combined_image_uniforms >=
11596 			(max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11597 			 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11598 		{
11599 			/* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11600 			m_result_for_combined = !m_result_for_combined;
11601 
11602 			if (false == m_result_for_combined)
11603 			{
11604 				m_context.getTestContext().getLog()
11605 					<< tcu::TestLog::Message << "There was an error while building a program."
11606 					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11607 					<< vertex_shader_code << "\nTesselation control shader code:\n"
11608 					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11609 					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11610 					<< geometry_shader_code << "\nFragment shader code:\n"
11611 					<< fragment_shader_code << tcu::TestLog::EndMessage;
11612 			}
11613 		}
11614 		else
11615 		{
11616 			/* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11617 			if (false == m_result_for_combined)
11618 			{
11619 				m_context.getTestContext().getLog()
11620 					<< tcu::TestLog::Message
11621 					<< "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11622 					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11623 					<< vertex_shader_code << "\nTesselation control shader code:\n"
11624 					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11625 					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11626 					<< geometry_shader_code << "\nFragment shader code:\n"
11627 					<< fragment_shader_code << tcu::TestLog::EndMessage;
11628 			}
11629 		}
11630 	}
11631 
11632 	/** Check if program builds successfully
11633 	 *
11634 	 * @param fragment_shader_code               Source code for fragment shader stage
11635 	 * @param geometry_shader_code               Source code for geometry shader stage
11636 	 * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11637 	 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11638 	 * @param vertex_shader_code                 Source code for vertex shader stage
11639 	 *
11640 	 * @return true if program was built without errors, false otherwise
11641 	 **/
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)11642 	bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11643 						 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11644 						 const char* vertex_shader_code)
11645 	{
11646 		bool   is_program_built = true;
11647 		GLuint program_id		= 0;
11648 
11649 		program_id =
11650 			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11651 						 geometry_shader_code, fragment_shader_code, &is_program_built);
11652 
11653 		if (0 != program_id)
11654 		{
11655 			glDeleteProgram(program_id);
11656 		}
11657 
11658 		return is_program_built;
11659 	}
11660 };
11661 }
11662 
ShaderImageLoadStoreTests(deqp::Context & context)11663 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11664 	: TestCaseGroup(context, "shader_image_load_store", "")
11665 {
11666 }
11667 
~ShaderImageLoadStoreTests(void)11668 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11669 {
11670 }
11671 
init()11672 void ShaderImageLoadStoreTests::init()
11673 {
11674 	using namespace deqp;
11675 	addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11676 	addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11677 	addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11678 	addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11679 	addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11680 	addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11681 	addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11682 							 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11683 	addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11684 							 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11685 	addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11686 							 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11687 	addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11688 	addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11689 	addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11690 	addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11691 	addChild(
11692 		new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11693 	addChild(
11694 		new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11695 	addChild(
11696 		new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11697 	addChild(
11698 		new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11699 	addChild(
11700 		new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11701 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11702 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11703 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11704 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11705 	addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11706 	addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11707 	addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11708 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11709 	addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11710 	addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11711 	addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11712 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11713 	addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11714 	addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11715 	addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11716 							 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11717 	addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11718 	addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11719 	addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11720 	addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11721 	addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11722 	addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11723 	addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11724 	addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11725 	addChild(
11726 		new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11727 	addChild(
11728 		new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11729 	addChild(
11730 		new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11731 	addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11732 	addChild(
11733 		new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11734 	addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11735 	addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11736 	addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11737 	addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11738 	addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11739 }
11740 }
11741