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 "gl4cES31CompatibilityTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include <assert.h>
31 #include <cstdarg>
32 #include <map>
33
34 namespace gl4cts
35 {
36 namespace es31compatibility
37 {
38 using namespace glw;
39 namespace
40 {
41 typedef tcu::Vec2 vec2;
42 typedef tcu::Vec4 vec4;
43 typedef tcu::IVec4 ivec4;
44 typedef tcu::UVec4 uvec4;
45 typedef tcu::Mat4 mat4;
46
47 enum Target
48 {
49 T2D = 0,
50 T3D,
51 TCM,
52 T2DA
53 };
54
55 const char *const kGLSLVer = "#version 310 es";
56 const char *const kGLSLSIA = NL "#extension GL_OES_shader_image_atomic : require";
57 const char *const kGLSLPrec =
58 NL "precision highp float;" NL "precision highp int;" NL "precision highp sampler2D;" NL
59 "precision highp sampler3D;" NL "precision highp samplerCube;" NL "precision highp sampler2DArray;" NL
60 "precision highp isampler2D;" NL "precision highp isampler3D;" NL "precision highp isamplerCube;" NL
61 "precision highp isampler2DArray;" NL "precision highp usampler2D;" NL "precision highp usampler3D;" NL
62 "precision highp usamplerCube;" NL "precision highp usampler2DArray;" NL "precision highp image2D;" NL
63 "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL
64 "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL
65 "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL
66 "precision highp uimageCube;" NL "precision highp uimage2DArray;";
67
68 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
69 {
70 public:
Title()71 virtual std::string Title()
72 {
73 return "";
74 }
75
Purpose()76 virtual std::string Purpose()
77 {
78 return "";
79 }
80
Method()81 virtual std::string Method()
82 {
83 return "";
84 }
85
PassCriteria()86 virtual std::string PassCriteria()
87 {
88 return "";
89 }
90
IsVSFSAvailable(int requiredVS,int requiredFS)91 bool IsVSFSAvailable(int requiredVS, int requiredFS)
92 {
93 GLint imagesVS, imagesFS;
94 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
95 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS);
96 if (imagesVS >= requiredVS && imagesFS >= requiredFS)
97 return true;
98 else
99 {
100 std::ostringstream reason;
101 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
102 << std::endl
103 << "Required " << requiredFS << " FS image uniforms but only " << imagesFS << " available."
104 << std::endl;
105 OutputNotSupported(reason.str());
106 return false;
107 }
108 }
IsSSBInVSFSAvailable(int required)109 bool IsSSBInVSFSAvailable(int required)
110 {
111 GLint blocksVS, blocksFS;
112 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
113 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
114 if (blocksVS >= required && blocksFS >= required)
115 return true;
116 else
117 {
118 std::ostringstream reason;
119 reason << "Required " << required << " VS storage blocks but only " << blocksVS << " available."
120 << std::endl
121 << "Required " << required << " FS storage blocks but only " << blocksFS << " available."
122 << std::endl;
123 OutputNotSupported(reason.str());
124 return false;
125 }
126 }
127
IsImageAtomicSupported()128 bool IsImageAtomicSupported()
129 {
130 bool is_at_least_gl_45 =
131 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
132 bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility");
133 if (!(is_at_least_gl_45 || is_arb_es31_compatibility))
134 {
135 std::ostringstream reason;
136 reason << "Required GL_OES_shader_image_atomic is not available." << std::endl;
137 OutputNotSupported(reason.str());
138 return false;
139 }
140 return true;
141 }
142
AreOutputsAvailable(int required)143 bool AreOutputsAvailable(int required)
144 {
145 GLint outputs;
146 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &outputs);
147 if (outputs < required)
148 {
149 std::ostringstream reason;
150 reason << "Required " << required << " shader output resources but only " << outputs << " available."
151 << std::endl;
152 OutputNotSupported(reason.str());
153 return false;
154 }
155 return true;
156 }
157
getWindowWidth()158 int getWindowWidth()
159 {
160 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
161 return renderTarget.getWidth();
162 }
163
getWindowHeight()164 int getWindowHeight()
165 {
166 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
167 return renderTarget.getHeight();
168 }
169
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)170 inline bool ColorEqual(const vec4 &c0, const vec4 &c1, const vec4 &epsilon)
171 {
172 if (fabs(c0[0] - c1[0]) > epsilon[0])
173 return false;
174 if (fabs(c0[1] - c1[1]) > epsilon[1])
175 return false;
176 if (fabs(c0[2] - c1[2]) > epsilon[2])
177 return false;
178 if (fabs(c0[3] - c1[3]) > epsilon[3])
179 return false;
180 return true;
181 }
182
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)183 bool Equal(const vec4 &v0, const vec4 &v1, GLenum internalformat)
184 {
185 if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RGBA8)
186 {
187 return ColorEqual(v0, v1, vec4(0.01f));
188 }
189 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
190 }
Equal(const ivec4 & a,const ivec4 & b,GLenum)191 bool Equal(const ivec4 &a, const ivec4 &b, GLenum)
192 {
193 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
194 }
Equal(const uvec4 & a,const uvec4 & b,GLenum)195 bool Equal(const uvec4 &a, const uvec4 &b, GLenum)
196 {
197 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
198 }
199
200 template <class T>
ToString(T v)201 std::string ToString(T v)
202 {
203 std::ostringstream s;
204 s << "[";
205 for (int i = 0; i < 4; ++i)
206 s << v[i] << (i == 3 ? "" : ",");
207 s << "]";
208 return s.str();
209 }
210
211 template <typename T>
CompareValues(T * map_data,int kSize,const T & expected_value,GLenum internalformat=0,int layers=1)212 bool CompareValues(T *map_data, int kSize, const T &expected_value, GLenum internalformat = 0, int layers = 1)
213 {
214 for (int i = 0; i < kSize * kSize * layers; ++i)
215 {
216 if (!Equal(map_data[i], expected_value, internalformat))
217 {
218 m_context.getTestContext().getLog()
219 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
220 << ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage;
221 return false;
222 }
223 }
224 return true;
225 }
226 template <typename T>
CompareValues(bool always,T * map_data,int kSize,const T & expected_value,GLenum internalformat=0,int layers=1)227 bool CompareValues(bool always, T *map_data, int kSize, const T &expected_value, GLenum internalformat = 0,
228 int layers = 1)
229 {
230 (void)internalformat;
231 for (int i = 0; i < kSize * kSize * layers; ++i)
232 {
233 if (always)
234 {
235 m_context.getTestContext().getLog()
236 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
237 << ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage;
238 }
239 }
240 return true;
241 }
242
CheckFB(vec4 expected)243 bool CheckFB(vec4 expected)
244 {
245 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
246 const tcu::PixelFormat &pixelFormat = renderTarget.getPixelFormat();
247 vec4 g_color_eps = vec4(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
248 1.f / (float)(1 << pixelFormat.blueBits), 1.f);
249 vec4 g_color_max = vec4(255);
250 std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4);
251 int fb_w = getWindowWidth();
252 int fb_h = getWindowHeight();
253 glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
254 for (GLint i = 0, y = 0; y < fb_h; ++y)
255 for (GLint x = 0; x < fb_w; ++x, i += 4)
256 {
257 if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] ||
258 fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] ||
259 fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2])
260 {
261 m_context.getTestContext().getLog()
262 << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << ", " << y
263 << "). Color is (" << fb[i + 0] / g_color_max[0] << ", " << fb[i + 1] / g_color_max[1] << ", "
264 << fb[i + 2] / g_color_max[2] << "). Color should be (" << expected[0] << ", " << expected[1]
265 << ", " << expected[2] << ")." << tcu::TestLog::EndMessage;
266 return false;
267 }
268 }
269 return true;
270 }
271
CompileShader(GLuint shader)272 bool CompileShader(GLuint shader)
273 {
274 glCompileShader(shader);
275
276 GLint status;
277 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
278 if (status == GL_FALSE)
279 {
280 GLsizei length;
281 GLchar log[1024];
282 glGetShaderInfoLog(shader, sizeof(log), &length, log);
283 if (length > 1)
284 {
285 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
286 << log << tcu::TestLog::EndMessage;
287 }
288 return false;
289 }
290 return true;
291 }
292
LinkProgram(GLuint program)293 bool LinkProgram(GLuint program)
294 {
295 glLinkProgram(program);
296
297 GLint status;
298 glGetProgramiv(program, GL_LINK_STATUS, &status);
299 if (status == GL_FALSE)
300 {
301 GLsizei length;
302 GLchar log[1024];
303 glGetProgramInfoLog(program, sizeof(log), &length, log);
304 if (length > 1)
305 {
306 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
307 << log << tcu::TestLog::EndMessage;
308 }
309 return false;
310 }
311 return true;
312 }
313
BuildProgram(const char * src_vs,const char * src_fs,bool SIAvs=false,bool SIAfs=false)314 GLuint BuildProgram(const char *src_vs, const char *src_fs, bool SIAvs = false, bool SIAfs = false)
315 {
316 std::ostringstream osvs, osfs;
317 osvs << kGLSLVer << (SIAvs ? kGLSLSIA : "\n") << kGLSLPrec;
318 osfs << kGLSLVer << (SIAfs ? kGLSLSIA : "\n") << kGLSLPrec;
319 std::string hvs = osvs.str();
320 std::string hfs = osfs.str();
321
322 const GLuint p = glCreateProgram();
323
324 if (src_vs)
325 {
326 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
327 glAttachShader(p, sh);
328 glDeleteShader(sh);
329 const char *const src[2] = {hvs.c_str(), src_vs};
330 glShaderSource(sh, 2, src, NULL);
331 if (!CompileShader(sh))
332 {
333 m_context.getTestContext().getLog()
334 << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
335 return p;
336 }
337 }
338 if (src_fs)
339 {
340 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
341 glAttachShader(p, sh);
342 glDeleteShader(sh);
343 const char *const src[2] = {hfs.c_str(), src_fs};
344 glShaderSource(sh, 2, src, NULL);
345 if (!CompileShader(sh))
346 {
347 m_context.getTestContext().getLog()
348 << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
349 return p;
350 }
351 }
352 if (!LinkProgram(p))
353 {
354 if (src_vs)
355 m_context.getTestContext().getLog()
356 << tcu::TestLog::Message << hvs.c_str() << src_vs << tcu::TestLog::EndMessage;
357 if (src_fs)
358 m_context.getTestContext().getLog()
359 << tcu::TestLog::Message << hfs.c_str() << src_fs << tcu::TestLog::EndMessage;
360 return p;
361 }
362
363 return p;
364 }
365
CreateComputeProgram(const std::string & cs,bool SIA=false)366 GLuint CreateComputeProgram(const std::string &cs, bool SIA = false)
367 {
368 std::ostringstream oscs;
369 oscs << kGLSLVer << (SIA ? kGLSLSIA : "\n") << kGLSLPrec;
370 std::string hcs = oscs.str();
371 const GLuint p = glCreateProgram();
372
373 if (!cs.empty())
374 {
375 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
376 glAttachShader(p, sh);
377 glDeleteShader(sh);
378 const char *const src[2] = {hcs.c_str(), cs.c_str()};
379 glShaderSource(sh, 2, src, NULL);
380 if (!CompileShader(sh))
381 {
382 m_context.getTestContext().getLog()
383 << tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
384 return p;
385 }
386 }
387 if (!LinkProgram(p))
388 {
389 if (!cs.empty())
390 m_context.getTestContext().getLog()
391 << tcu::TestLog::Message << hcs.c_str() << cs.c_str() << tcu::TestLog::EndMessage;
392 return p;
393 }
394
395 return p;
396 }
397
BuildShaderProgram(GLenum type,const char * src)398 GLuint BuildShaderProgram(GLenum type, const char *src)
399 {
400 const char *const src3[3] = {kGLSLVer, kGLSLPrec, src};
401 const GLuint p = glCreateShaderProgramv(type, 3, src3);
402 GLint status;
403 glGetProgramiv(p, GL_LINK_STATUS, &status);
404 if (status == GL_FALSE)
405 {
406 GLchar log[1024];
407 glGetProgramInfoLog(p, sizeof(log), NULL, log);
408 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
409 << log << "\n"
410 << src3[0] << "\n"
411 << src3[1] << "\n"
412 << src3[2] << tcu::TestLog::EndMessage;
413 }
414 return p;
415 }
416
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)417 void CreateFullViewportQuad(GLuint *vao, GLuint *vbo, GLuint *ebo)
418 {
419 assert(vao && vbo);
420
421 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
422 const float v[] = {
423 -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,
424 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,
425 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,
426 };
427 glGenBuffers(1, vbo);
428 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
429 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
430 glBindBuffer(GL_ARRAY_BUFFER, 0);
431
432 if (ebo)
433 {
434 std::vector<GLushort> index_data(4);
435 for (int i = 0; i < 4; ++i)
436 {
437 index_data[i] = static_cast<GLushort>(i);
438 }
439 glGenBuffers(1, ebo);
440 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
441 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
442 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
443 }
444
445 glGenVertexArrays(1, vao);
446 glBindVertexArray(*vao);
447 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
448 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
449
450 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
451 reinterpret_cast<void *>(sizeof(float) * 2));
452
453 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
454
455 reinterpret_cast<void *>(sizeof(float) * 5));
456
457 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
458 reinterpret_cast<void *>(sizeof(float) * 8));
459
460 glBindBuffer(GL_ARRAY_BUFFER, 0);
461 glEnableVertexAttribArray(0);
462 glEnableVertexAttribArray(1);
463 glEnableVertexAttribArray(2);
464 glEnableVertexAttribArray(3);
465 if (ebo)
466 {
467 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
468 }
469 glBindVertexArray(0);
470 }
471
FormatEnumToString(GLenum e)472 std::string FormatEnumToString(GLenum e)
473 {
474 switch (e)
475 {
476 case GL_RGBA32F:
477 return "rgba32f";
478 case GL_RGBA16F:
479 return "rgba16f";
480 case GL_R32F:
481 return "r32f";
482
483 case GL_RGBA32UI:
484 return "rgba32ui";
485 case GL_RGBA16UI:
486 return "rgba16ui";
487 case GL_RGBA8UI:
488 return "rgba8ui";
489 case GL_R32UI:
490 return "r32ui";
491
492 case GL_RGBA32I:
493 return "rgba32i";
494 case GL_RGBA16I:
495 return "rgba16i";
496 case GL_RGBA8I:
497 return "rgba8i";
498 case GL_R32I:
499 return "r32i";
500
501 case GL_RGBA8:
502 return "rgba8";
503
504 case GL_RGBA8_SNORM:
505 return "rgba8_snorm";
506 }
507
508 assert(0);
509 return "";
510 }
511
512 template <typename T>
513 GLenum Format();
514
515 template <typename T>
516 GLenum Type();
517
518 template <typename T>
519 std::string TypePrefix();
520
521 template <typename T>
522 GLenum ImageType(GLenum target);
523
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)524 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4 &color)
525 {
526 glClearBufferfv(buffer, drawbuffer, &color[0]);
527 }
528
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)529 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4 &color)
530 {
531 glClearBufferiv(buffer, drawbuffer, &color[0]);
532 }
533
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)534 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4 &color)
535 {
536 glClearBufferuiv(buffer, drawbuffer, &color[0]);
537 }
538
CheckMax(GLenum pname,GLint min_value)539 bool CheckMax(GLenum pname, GLint min_value)
540 {
541 GLboolean b;
542 GLint i;
543 GLfloat f;
544 GLint64 i64;
545
546 glGetIntegerv(pname, &i);
547 if (i < min_value)
548 return false;
549
550 glGetBooleanv(pname, &b);
551 if (b != (i ? GL_TRUE : GL_FALSE))
552 return false;
553
554 glGetFloatv(pname, &f);
555 if (static_cast<GLint>(f) < min_value)
556 return false;
557
558 glGetInteger64v(pname, &i64);
559 if (static_cast<GLint>(i64) < min_value)
560 return false;
561
562 return true;
563 }
564
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)565 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
566 GLenum format)
567 {
568 GLint i;
569 GLboolean b;
570
571 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
572 if (static_cast<GLuint>(i) != texture)
573 {
574 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
575 << " should be " << texture << "." << tcu::TestLog::EndMessage;
576 return false;
577 }
578
579 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
580 if (i != level)
581 {
582 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
583 << " should be " << level << "." << tcu::TestLog::EndMessage;
584 return false;
585 }
586
587 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
588 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
589 if (i != layered || b != layered)
590 {
591 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
592 << " should be " << layered << "." << tcu::TestLog::EndMessage;
593 return false;
594 }
595
596 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
597 if (i != layer)
598 {
599 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
600 << " should be " << layer << "." << tcu::TestLog::EndMessage;
601 return false;
602 }
603
604 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
605 if (static_cast<GLenum>(i) != access)
606 {
607 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
608 << " should be " << access << "." << tcu::TestLog::EndMessage;
609 return false;
610 }
611
612 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
613 if (static_cast<GLenum>(i) != format)
614 {
615 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
616 << " should be " << format << "." << tcu::TestLog::EndMessage;
617 return false;
618 }
619
620 return true;
621 }
EnumToString(GLenum e)622 const char *EnumToString(GLenum e)
623 {
624 switch (e)
625 {
626 case GL_TEXTURE_2D:
627 return "GL_TEXTURE_2D";
628 case GL_TEXTURE_3D:
629 return "GL_TEXTURE_3D";
630 case GL_TEXTURE_CUBE_MAP:
631 return "GL_TEXTURE_CUBE_MAP";
632 case GL_TEXTURE_2D_ARRAY:
633 return "GL_TEXTURE_2D_ARRAY";
634
635 default:
636 assert(0);
637 break;
638 }
639 return NULL;
640 }
641 };
642
643 template <>
Format()644 GLenum ShaderImageLoadStoreBase::Format<vec4>()
645 {
646 return GL_RGBA;
647 }
648
649 template <>
Format()650 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
651 {
652 return GL_RGBA_INTEGER;
653 }
654
655 template <>
Format()656 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
657 {
658 return GL_RGBA_INTEGER;
659 }
660
661 template <>
Format()662 GLenum ShaderImageLoadStoreBase::Format<GLint>()
663 {
664 return GL_RED_INTEGER;
665 }
666
667 template <>
Format()668 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
669 {
670 return GL_RED_INTEGER;
671 }
672
673 template <>
Type()674 GLenum ShaderImageLoadStoreBase::Type<vec4>()
675 {
676 return GL_FLOAT;
677 }
678
679 template <>
Type()680 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
681 {
682 return GL_INT;
683 }
684
685 template <>
Type()686 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
687 {
688 return GL_UNSIGNED_INT;
689 }
690
691 template <>
Type()692 GLenum ShaderImageLoadStoreBase::Type<GLint>()
693 {
694 return GL_INT;
695 }
696
697 template <>
Type()698 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
699 {
700 return GL_UNSIGNED_INT;
701 }
702
703 template <>
TypePrefix()704 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
705 {
706 return "";
707 }
708
709 template <>
710
TypePrefix()711 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
712 {
713 return "i";
714 }
715
716 template <>
TypePrefix()717 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
718 {
719 return "u";
720 }
721
722 template <>
723
TypePrefix()724 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
725 {
726 return "i";
727 }
728
729 template <>
TypePrefix()730 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
731 {
732 return "u";
733 }
734
735 template <>
ImageType(GLenum target)736 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
737 {
738 switch (target)
739 {
740 case GL_TEXTURE_2D:
741 return GL_IMAGE_2D;
742 case GL_TEXTURE_3D:
743 return GL_IMAGE_3D;
744 case GL_TEXTURE_CUBE_MAP:
745 return GL_IMAGE_CUBE;
746 case GL_TEXTURE_2D_ARRAY:
747 return GL_IMAGE_2D_ARRAY;
748 }
749 assert(0);
750 return 0;
751 }
752
753 template <>
ImageType(GLenum target)754 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
755 {
756 switch (target)
757 {
758 case GL_TEXTURE_2D:
759 return GL_INT_IMAGE_2D;
760 case GL_TEXTURE_3D:
761 return GL_INT_IMAGE_3D;
762 case GL_TEXTURE_CUBE_MAP:
763 return GL_INT_IMAGE_CUBE;
764 case GL_TEXTURE_2D_ARRAY:
765 return GL_INT_IMAGE_2D_ARRAY;
766 }
767 assert(0);
768 return 0;
769 }
770
771 template <>
ImageType(GLenum target)772 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
773 {
774 switch (target)
775 {
776 case GL_TEXTURE_2D:
777 return GL_UNSIGNED_INT_IMAGE_2D;
778 case GL_TEXTURE_3D:
779 return GL_UNSIGNED_INT_IMAGE_3D;
780 case GL_TEXTURE_CUBE_MAP:
781 return GL_UNSIGNED_INT_IMAGE_CUBE;
782 case GL_TEXTURE_2D_ARRAY:
783 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
784 }
785 assert(0);
786 return 0;
787 }
788
Components(GLenum e)789 int Components(GLenum e)
790 {
791 return (e == GL_RED || e == GL_RED_INTEGER) ? 1 : 4;
792 }
793
Shorts(GLenum e)794 bool Shorts(GLenum e)
795 {
796 return (e == GL_RGBA16I || e == GL_RGBA16UI);
797 }
798
Bytes(GLenum e)799 bool Bytes(GLenum e)
800 {
801 return (e == GL_RGBA8I || e == GL_RGBA8UI || e == GL_RGBA8 || e == GL_RGBA8_SNORM);
802 }
803
804 template <typename T>
805 class ShortByteData
806 {
807 public:
808 std::vector<T> data;
809 std::vector<GLshort> datas;
810 std::vector<GLbyte> datab;
811
ShortByteData(int size,const T & value,GLenum internalformat,GLenum format)812 ShortByteData(int size, const T &value, GLenum internalformat, GLenum format)
813 : data(size * size, value)
814 , datas(size * size * 4)
815 , datab(size * size * 4)
816 {
817 if (Components(format) == 1)
818 for (unsigned i = 0; i < data.size() / 4; ++i)
819 {
820 data[i][0] = data[i * 4][0];
821 data[i][1] = data[i * 4 + 1][0];
822 data[i][2] = data[i * 4 + 2][0];
823 data[i][3] = data[i * 4 + 3][0];
824 }
825 if (Shorts(internalformat))
826 {
827 for (unsigned i = 0; i < datas.size(); i += 4)
828 {
829 datas[i] = static_cast<GLshort>(data[i / 4][0]);
830 datas[i + 1] = static_cast<GLshort>(data[i / 4][1]);
831 datas[i + 2] = static_cast<GLshort>(data[i / 4][2]);
832 datas[i + 3] = static_cast<GLshort>(data[i / 4][3]);
833 }
834 }
835 if (Bytes(internalformat))
836 {
837 for (unsigned i = 0; i < datas.size(); i += 4)
838 {
839 if (internalformat == GL_RGBA8I || internalformat == GL_RGBA8UI)
840 {
841 datab[i] = static_cast<GLbyte>(data[i / 4][0]);
842 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1]);
843 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2]);
844 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3]);
845 }
846 else if (internalformat == GL_RGBA8)
847 {
848 datab[i] = static_cast<GLbyte>(data[i / 4][0] * 255);
849 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 255);
850 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 255);
851 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 255);
852 }
853 else
854 { // GL_RGBA8_SNORM
855 datab[i] = static_cast<GLbyte>(data[i / 4][0] * 127);
856 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 127);
857 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 127);
858 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 127);
859 }
860 }
861 }
862 }
863 };
864
865 //-----------------------------------------------------------------------------
866 // 1.1.1 BasicAPIGet
867 //-----------------------------------------------------------------------------
868 class BasicAPIGet : public ShaderImageLoadStoreBase
869 {
Run()870 virtual long Run()
871 {
872 if (!CheckMax(GL_MAX_IMAGE_UNITS, 4))
873 {
874 m_context.getTestContext().getLog()
875 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
876 return ERROR;
877 }
878 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4))
879 {
880 m_context.getTestContext().getLog()
881 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
882 << tcu::TestLog::EndMessage;
883 return ERROR;
884 }
885 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
886 {
887 m_context.getTestContext().getLog()
888 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
889 << tcu::TestLog::EndMessage;
890 return ERROR;
891 }
892 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 0))
893 {
894 m_context.getTestContext().getLog()
895 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
896 << tcu::TestLog::EndMessage;
897 return ERROR;
898 }
899 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 4))
900 {
901 m_context.getTestContext().getLog()
902 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
903 << tcu::TestLog::EndMessage;
904 return ERROR;
905 }
906 if (!CheckMax(GL_MAX_COMPUTE_IMAGE_UNIFORMS, 4))
907 {
908 m_context.getTestContext().getLog()
909 << tcu::TestLog::Message << "GL_MAX_COMPUTE_IMAGE_UNIFORMS value is invalid."
910 << tcu::TestLog::EndMessage;
911 return ERROR;
912 }
913 return NO_ERROR;
914 }
915 };
916
917 //-----------------------------------------------------------------------------
918 // 1.1.2 BasicAPIBind
919 //-----------------------------------------------------------------------------
920 class BasicAPIBind : public ShaderImageLoadStoreBase
921 {
922 GLuint m_texture;
923
Setup()924 virtual long Setup()
925 {
926 m_texture = 0;
927 return NO_ERROR;
928 }
929
Run()930 virtual long Run()
931 {
932 bool status = true;
933 for (GLuint index = 0; index < 4; ++index)
934 {
935 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI))
936 {
937 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
938 << " has invalid default state." << tcu::TestLog::EndMessage;
939 status = false;
940 }
941 }
942
943 glGenTextures(1, &m_texture);
944 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
945 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RG32F, 16, 16, 4);
946 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
947
948 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
949 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
950 status = false;
951
952 glBindImageTexture(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
953 if (!CheckBinding(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
954 status = false;
955
956 glBindImageTexture(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI);
957 if (!CheckBinding(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI))
958 status = false;
959
960 glBindImageTexture(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
961 if (!CheckBinding(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
962 status = false;
963
964 glDeleteTextures(1, &m_texture);
965 m_texture = 0;
966
967 for (GLuint index = 0; index < 4; ++index)
968 {
969 GLint name;
970 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
971 if (name != 0)
972 {
973 m_context.getTestContext().getLog()
974 << tcu::TestLog::Message << "Binding point " << index
975 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
976 status = false;
977 }
978 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI))
979 status = false;
980 }
981
982 return status ? NO_ERROR : ERROR;
983 }
984
Cleanup()985 virtual long Cleanup()
986 {
987 glDeleteTextures(1, &m_texture);
988 return NO_ERROR;
989 }
990 };
991 //-----------------------------------------------------------------------------
992 // 1.1.3 BasicAPIBarrier
993 //-----------------------------------------------------------------------------
994 class BasicAPIBarrier : public ShaderImageLoadStoreBase
995 {
Run()996 virtual long Run()
997 {
998 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
999 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1000 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1001 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1002 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1003 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1004 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1005 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1006 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1007 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1008 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1009 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1010 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
1011
1012 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1013 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1014 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1015 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT |
1016 GL_SHADER_STORAGE_BARRIER_BIT);
1017
1018 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1019
1020 return NO_ERROR;
1021 }
1022 };
1023
1024 class BasicAPIBarrierByRegion : public ShaderImageLoadStoreBase
1025 {
Run()1026 virtual long Run()
1027 {
1028 glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT);
1029 glMemoryBarrierByRegion(GL_TEXTURE_FETCH_BARRIER_BIT);
1030 glMemoryBarrierByRegion(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1031 glMemoryBarrierByRegion(GL_FRAMEBUFFER_BARRIER_BIT);
1032 glMemoryBarrierByRegion(GL_ATOMIC_COUNTER_BARRIER_BIT);
1033 glMemoryBarrierByRegion(GL_SHADER_STORAGE_BARRIER_BIT);
1034
1035 glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT |
1036 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1037 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
1038
1039 glMemoryBarrierByRegion(GL_ALL_BARRIER_BITS);
1040 return NO_ERROR;
1041 }
1042 };
1043 //-----------------------------------------------------------------------------
1044 // 1.1.4 BasicAPITexParam
1045 //-----------------------------------------------------------------------------
1046 class BasicAPITexParam : public ShaderImageLoadStoreBase
1047 {
1048 GLuint m_texture;
1049
Setup()1050 virtual long Setup()
1051 {
1052 m_texture = 0;
1053 return NO_ERROR;
1054 }
1055
Run()1056 virtual long Run()
1057 {
1058 glGenTextures(1, &m_texture);
1059 glBindTexture(GL_TEXTURE_2D, m_texture);
1060 glTexStorage2D(GL_TEXTURE_2D, 5, GL_RG32F, 16, 16);
1061
1062 GLint i;
1063 GLfloat f;
1064
1065 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1066 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1067 {
1068 m_context.getTestContext().getLog()
1069 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1070 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1071 << tcu::TestLog::EndMessage;
1072 return ERROR;
1073 }
1074 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1075 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1076 {
1077 m_context.getTestContext().getLog()
1078 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1079 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1080 << tcu::TestLog::EndMessage;
1081 return ERROR;
1082 }
1083
1084 return NO_ERROR;
1085 }
1086
Cleanup()1087 virtual long Cleanup()
1088 {
1089 glDeleteTextures(1, &m_texture);
1090 return NO_ERROR;
1091 }
1092 };
1093 //-----------------------------------------------------------------------------
1094 // 1.2.1 BasicAllFormatsStore
1095 //-----------------------------------------------------------------------------
1096 class BasicAllFormatsStoreFS : public ShaderImageLoadStoreBase
1097 {
1098 GLuint m_vao, m_vbo;
1099
Setup()1100 virtual long Setup()
1101 {
1102 m_vao = 0;
1103 m_vbo = 0;
1104 return NO_ERROR;
1105 }
1106
Run()1107 virtual long Run()
1108 {
1109 if (!IsVSFSAvailable(0, 1))
1110 return NOT_SUPPORTED;
1111
1112 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1113
1114 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1115 return ERROR;
1116 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1117 return ERROR;
1118 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1119 return ERROR;
1120
1121 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1122 return ERROR;
1123 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1124 return ERROR;
1125 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1126 return ERROR;
1127 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1128 return ERROR;
1129
1130 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1131 return ERROR;
1132 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1133 return ERROR;
1134 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1135 return ERROR;
1136 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1137 return ERROR;
1138
1139 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1140 return ERROR;
1141
1142 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1143 return ERROR;
1144
1145 return NO_ERROR;
1146 }
1147
1148 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1149 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
1150 {
1151 const char *src_vs =
1152 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
1153 GLuint program = BuildProgram(src_vs, GenFS(internalformat, write_value).c_str());
1154 const int kSize = 11;
1155 std::vector<T> data(kSize * kSize);
1156 GLuint texture;
1157 glGenTextures(1, &texture);
1158 glUseProgram(program);
1159
1160 GLuint unit = 2;
1161 glBindTexture(GL_TEXTURE_2D, texture);
1162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1164 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1165 glBindTexture(GL_TEXTURE_2D, 0);
1166
1167 glViewport(0, 0, kSize, kSize);
1168 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1169 glBindVertexArray(m_vao);
1170 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1171
1172 glBindTexture(GL_TEXTURE_2D, texture);
1173 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1174
1175 GLuint c_program = CreateComputeProgram(GenC(write_value));
1176 std::vector<T> out_data(kSize * kSize);
1177 GLuint m_buffer;
1178 glGenBuffers(1, &m_buffer);
1179 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1180 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1181
1182 glUseProgram(c_program);
1183 glDispatchCompute(1, 1, 1);
1184 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1185 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1186 for (int i = 0; i < kSize * kSize; ++i)
1187 {
1188 if (!Equal(map_data[i], expected_value, internalformat))
1189 {
1190 m_context.getTestContext().getLog()
1191 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1192 << ". Value should be: " << ToString(expected_value).c_str()
1193 << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1194 << tcu::TestLog::EndMessage;
1195 glDeleteTextures(1, &texture);
1196 glUseProgram(0);
1197 glDeleteProgram(program);
1198 glDeleteProgram(c_program);
1199 glDeleteBuffers(1, &m_buffer);
1200 return false;
1201 }
1202 }
1203 glDeleteTextures(1, &texture);
1204 glUseProgram(0);
1205 glDeleteProgram(program);
1206 glDeleteProgram(c_program);
1207 glDeleteBuffers(1, &m_buffer);
1208 return true;
1209 }
1210
Cleanup()1211 virtual long Cleanup()
1212 {
1213 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1214 glDeleteVertexArrays(1, &m_vao);
1215 glDeleteBuffers(1, &m_vbo);
1216 return NO_ERROR;
1217 }
1218
1219 template <typename T>
GenFS(GLenum internalformat,const T & value)1220 std::string GenFS(GLenum internalformat, const T &value)
1221 {
1222 std::ostringstream os;
1223 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
1224 << TypePrefix<T>()
1225 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1226 " imageStore(g_image, coord, "
1227 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1228 return os.str();
1229 }
1230
1231 template <typename T>
GenC(const T & value)1232 std::string GenC(const T &value)
1233 {
1234 std::ostringstream os;
1235 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1236 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " "
1237 << TypePrefix<T>()
1238 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1239 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1240 " //data[gl_LocalInvocationIndex] = "
1241 << value << ";" NL "}";
1242 return os.str();
1243 }
1244 };
1245
1246 class BasicAllFormatsStoreCS : public ShaderImageLoadStoreBase
1247 {
Setup()1248 virtual long Setup()
1249 {
1250 return NO_ERROR;
1251 }
1252
1253 template <typename T>
GenCS(GLenum internalformat,const T & value)1254 std::string GenCS(GLenum internalformat, const T &value)
1255 {
1256 std::ostringstream os;
1257 os << NL "#define KSIZE 4" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1258 << TypePrefix<T>()
1259 << "image2D g_image;" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "void main() {" NL
1260 " ivec2 thread_xy = ivec2(gl_LocalInvocationID);" NL " imageStore(g_image, thread_xy, "
1261 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1262 return os.str();
1263 }
1264
1265 template <typename T>
GenC(const T & value)1266 std::string GenC(const T &value)
1267 {
1268 std::ostringstream os;
1269 os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1270 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " "
1271 << TypePrefix<T>()
1272 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1273 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1274 " //data[gl_LocalInvocationIndex] = "
1275 << TypePrefix<T>() << "vec4" << value << ";" NL "}";
1276 return os.str();
1277 }
1278
1279 template <typename T>
WriteCS(GLenum internalformat,const T & write_value,const T & expected_value)1280 bool WriteCS(GLenum internalformat, const T &write_value, const T &expected_value)
1281 {
1282 const int kSize = 4;
1283 GLuint program = CreateComputeProgram(GenCS(internalformat, write_value));
1284
1285 std::vector<T> data(kSize * kSize);
1286 GLuint texture;
1287 glGenTextures(1, &texture);
1288
1289 GLuint unit = 0;
1290 glBindTexture(GL_TEXTURE_2D, texture);
1291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1292 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1293 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1294 glBindTexture(GL_TEXTURE_2D, 0);
1295 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1296 glUseProgram(program);
1297 glDispatchCompute(1, 1, 1);
1298
1299 glBindTexture(GL_TEXTURE_2D, texture);
1300 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1301
1302 GLuint c_program = CreateComputeProgram(GenC(expected_value));
1303 std::vector<T> out_data(kSize * kSize);
1304 GLuint m_buffer;
1305 glGenBuffers(1, &m_buffer);
1306 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1307 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1308
1309 glUseProgram(c_program);
1310 glDispatchCompute(1, 1, 1);
1311 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1312 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1313 for (int i = 0; i < kSize * kSize; ++i)
1314 {
1315 if (!Equal(map_data[i], expected_value, internalformat))
1316 {
1317 m_context.getTestContext().getLog()
1318 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1319 << ". Value should be: " << ToString(expected_value).c_str()
1320 << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1321 << tcu::TestLog::EndMessage;
1322 glDeleteTextures(1, &texture);
1323 glUseProgram(0);
1324 glDeleteProgram(program);
1325 glDeleteProgram(c_program);
1326 glDeleteBuffers(1, &m_buffer);
1327 return false;
1328 }
1329 }
1330 glDeleteTextures(1, &texture);
1331 glUseProgram(0);
1332 glDeleteProgram(program);
1333 glDeleteProgram(c_program);
1334 glDeleteBuffers(1, &m_buffer);
1335
1336 return true;
1337 }
1338
Run()1339 virtual long Run()
1340 {
1341
1342 if (!WriteCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1343 return ERROR;
1344 if (!WriteCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1345 return ERROR;
1346 if (!WriteCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1347 return ERROR;
1348
1349 if (!WriteCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1350 return ERROR;
1351 if (!WriteCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1352 return ERROR;
1353 if (!WriteCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1354 return ERROR;
1355 if (!WriteCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1356 return ERROR;
1357
1358 if (!WriteCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1359 return ERROR;
1360 if (!WriteCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1361 return ERROR;
1362 if (!WriteCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1363 return ERROR;
1364 if (!WriteCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1365 return ERROR;
1366
1367 if (!WriteCS(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1368 return ERROR;
1369
1370 if (!WriteCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1371 return ERROR;
1372
1373 return NO_ERROR;
1374 }
1375
Cleanup()1376 virtual long Cleanup()
1377 {
1378 return NO_ERROR;
1379 }
1380 };
1381 //-----------------------------------------------------------------------------
1382 // 1.2.2 BasicAllFormatsLoad
1383 //-----------------------------------------------------------------------------
1384 class BasicAllFormatsLoadFS : public ShaderImageLoadStoreBase
1385 {
1386 GLuint m_vao, m_vbo;
1387
Setup()1388 virtual long Setup()
1389 {
1390 m_vao = 0;
1391 m_vbo = 0;
1392 return NO_ERROR;
1393 }
1394
Run()1395 virtual long Run()
1396 {
1397 if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1))
1398 return NOT_SUPPORTED;
1399
1400 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1401
1402 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1403 return ERROR;
1404 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1405 return ERROR;
1406 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1407 return ERROR;
1408
1409 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT))
1410 return ERROR;
1411 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1412 return ERROR;
1413 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT))
1414 return ERROR;
1415 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE))
1416 return ERROR;
1417
1418 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1419 return ERROR;
1420 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1421 return ERROR;
1422 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1423 return ERROR;
1424 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1425 return ERROR;
1426
1427 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1428 return ERROR;
1429
1430 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1431 return ERROR;
1432
1433 return NO_ERROR;
1434 }
1435
1436 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1437 bool Read(GLenum internalformat, const T &value, const T &expected_value, GLenum format, GLenum type)
1438 {
1439 const char *src_vs =
1440 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
1441 GLuint program = BuildProgram(src_vs, GenFS(internalformat, expected_value).c_str());
1442 const int kSize = 11;
1443 ShortByteData<T> d(kSize, value, internalformat, format);
1444 GLuint texture;
1445 glGenTextures(1, &texture);
1446 GLuint unit = 1;
1447 glBindTexture(GL_TEXTURE_2D, texture);
1448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1450 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1451 if (Shorts(internalformat))
1452 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1453 else if (Bytes(internalformat))
1454 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1455 else
1456 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1457 glBindTexture(GL_TEXTURE_2D, 0);
1458
1459 glViewport(0, 0, kSize, kSize);
1460 glClear(GL_COLOR_BUFFER_BIT);
1461 glUseProgram(program);
1462 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1463 glBindVertexArray(m_vao);
1464
1465 std::vector<T> out_data(kSize * kSize);
1466 GLuint m_buffer;
1467 glGenBuffers(1, &m_buffer);
1468 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1469 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1470
1471 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1472 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1473 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1474 for (int i = 0; i < kSize * kSize; ++i)
1475 {
1476 if (!Equal(map_data[i], expected_value, internalformat))
1477 {
1478 m_context.getTestContext().getLog()
1479 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1480 << ". Value should be: " << ToString(expected_value).c_str()
1481 << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1482 << tcu::TestLog::EndMessage;
1483 glUseProgram(0);
1484 glDeleteProgram(program);
1485 glDeleteTextures(1, &texture);
1486 glDeleteBuffers(1, &m_buffer);
1487 return false;
1488 }
1489 }
1490 glUseProgram(0);
1491 glDeleteProgram(program);
1492 glDeleteTextures(1, &texture);
1493 glDeleteBuffers(1, &m_buffer);
1494 return true;
1495 }
1496
Cleanup()1497 virtual long Cleanup()
1498 {
1499 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1500 glDeleteVertexArrays(1, &m_vao);
1501 glDeleteBuffers(1, &m_vbo);
1502 return NO_ERROR;
1503 }
1504
1505 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1506 std::string GenFS(GLenum internalformat, const T &expected_value)
1507 {
1508 std::ostringstream os;
1509 os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat)
1510 << ", binding = 1) readonly uniform " << TypePrefix<T>()
1511 << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>()
1512 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1513 << TypePrefix<T>()
1514 << "vec4 v = imageLoad(g_image, coord);" NL " data[coord.y * KSIZE + coord.x] = v;" NL
1515 " //data[coord.y * KSIZE + coord.x] = "
1516 << TypePrefix<T>() << "vec4" << expected_value << ";" NL " discard;" NL "}";
1517 return os.str();
1518 }
1519 };
1520
1521 class BasicAllFormatsLoadCS : public ShaderImageLoadStoreBase
1522 {
Setup()1523 virtual long Setup()
1524 {
1525 return NO_ERROR;
1526 }
1527
1528 template <typename T>
GenCS(GLenum internalformat,const T & expected_value)1529 std::string GenCS(GLenum internalformat, const T &expected_value)
1530 {
1531 std::ostringstream os;
1532 os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout("
1533 << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>()
1534 << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>()
1535 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
1536 " "
1537 << TypePrefix<T>()
1538 << "vec4 v = imageLoad(g_image, coord);" NL " data[gl_LocalInvocationIndex] = v;" NL
1539 " //data[gl_LocalInvocationIndex] = "
1540 << TypePrefix<T>() << "vec4" << expected_value << ";" NL "}";
1541 return os.str();
1542 }
1543
Run()1544 virtual long Run()
1545 {
1546 if (!ReadCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1547 return ERROR;
1548 if (!ReadCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1549 return ERROR;
1550 if (!ReadCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1551 return ERROR;
1552
1553 if (!ReadCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT))
1554 return ERROR;
1555 if (!ReadCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1556 return ERROR;
1557 if (!ReadCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT))
1558 return ERROR;
1559 if (!ReadCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE))
1560 return ERROR;
1561
1562 if (!ReadCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1563 return ERROR;
1564 if (!ReadCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1565 return ERROR;
1566 if (!ReadCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1567 return ERROR;
1568 if (!ReadCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1569 return ERROR;
1570
1571 if (!ReadCS(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1572 return ERROR;
1573
1574 if (!ReadCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1575 return ERROR;
1576
1577 return NO_ERROR;
1578 }
1579
1580 template <typename T>
ReadCS(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1581 bool ReadCS(GLenum internalformat, const T &value, const T &expected_value, GLenum format, GLenum type)
1582 {
1583 GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value));
1584 const int kSize = 4;
1585 ShortByteData<T> d(kSize, value, internalformat, format);
1586 GLuint texture;
1587 glGenTextures(1, &texture);
1588
1589 GLuint unit = 1;
1590 glBindTexture(GL_TEXTURE_2D, texture);
1591 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1592 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1593 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1594 if (Shorts(internalformat))
1595 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1596 else if (Bytes(internalformat))
1597 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1598 else
1599 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1600 glBindTexture(GL_TEXTURE_2D, 0);
1601
1602 glUseProgram(program);
1603 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1604
1605 std::vector<T> out_data(kSize * kSize);
1606 GLuint m_buffer;
1607 glGenBuffers(1, &m_buffer);
1608 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1609 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1610
1611 glDispatchCompute(1, 1, 1);
1612 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1613 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1614 for (int i = 0; i < kSize * kSize; ++i)
1615 {
1616 if (!Equal(map_data[i], expected_value, internalformat))
1617 {
1618 m_context.getTestContext().getLog()
1619 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1620 << ". Value should be: " << ToString(expected_value).c_str()
1621 << ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1622 << tcu::TestLog::EndMessage;
1623 glUseProgram(0);
1624 glDeleteProgram(program);
1625 glDeleteTextures(1, &texture);
1626 glDeleteBuffers(1, &m_buffer);
1627 return false;
1628 }
1629 }
1630 glUseProgram(0);
1631 glDeleteProgram(program);
1632 glDeleteTextures(1, &texture);
1633 glDeleteBuffers(1, &m_buffer);
1634 return true;
1635 }
1636
Cleanup()1637 virtual long Cleanup()
1638 {
1639 return NO_ERROR;
1640 }
1641 };
1642
1643 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
1644 {
Run()1645 virtual long Run()
1646 {
1647
1648 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT))
1649 return ERROR;
1650 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1651 return ERROR;
1652 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT))
1653 return ERROR;
1654
1655 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_INT))
1656 return ERROR;
1657 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(2, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1658 return ERROR;
1659 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_SHORT))
1660 return ERROR;
1661 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_BYTE))
1662 return ERROR;
1663
1664 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1665 return ERROR;
1666 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(14, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1667 return ERROR;
1668 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1669 return ERROR;
1670 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1671 return ERROR;
1672
1673 if (!Read(GL_RGBA8, vec4(0.5f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1674 return ERROR;
1675 if (!Read(GL_RGBA8_SNORM, vec4(0.5f, 0.0f, 0.5f, -0.5f), vec4(1.0f, 0.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1676 return ERROR;
1677
1678 return NO_ERROR;
1679 }
1680
1681 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1682 bool Read(GLenum internalformat, const T &value, const T &expected_value, GLenum format, GLenum type)
1683 {
1684 GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value));
1685
1686 const int kSize = 8;
1687 ShortByteData<T> d(kSize, value, internalformat, format);
1688 GLuint texture[2];
1689 glGenTextures(2, texture);
1690
1691 /* read texture */
1692 {
1693 glBindTexture(GL_TEXTURE_2D, texture[0]);
1694 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1696 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1697 if (Shorts(internalformat))
1698 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1699 else if (Bytes(internalformat))
1700 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1701 else
1702 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1703 }
1704 /* write texture */
1705 {
1706 glBindTexture(GL_TEXTURE_2D, texture[1]);
1707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1709 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1710 }
1711 glBindTexture(GL_TEXTURE_2D, 0);
1712
1713 glUseProgram(program);
1714
1715 glBindImageTexture(2, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
1716 glBindImageTexture(3, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1717
1718 glDispatchCompute(1, 1, 1);
1719
1720 glBindTexture(GL_TEXTURE_2D, texture[1]);
1721 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1722
1723 GLuint c_program = CreateComputeProgram(GenC(expected_value));
1724 std::vector<T> out_data(kSize * kSize);
1725 GLuint m_buffer;
1726 glGenBuffers(1, &m_buffer);
1727 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1728 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1729
1730 glUseProgram(c_program);
1731 glDispatchCompute(1, 1, 1);
1732 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1733 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1734 for (int i = 0; i < kSize * kSize; ++i)
1735 {
1736 if (!Equal(map_data[i], expected_value, internalformat))
1737 {
1738 m_context.getTestContext().getLog()
1739 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1740 << ". Value should be: " << ToString(expected_value).c_str()
1741 << ". Format is: " << FormatEnumToString(internalformat).c_str() << "." << tcu::TestLog::EndMessage;
1742 glDeleteTextures(2, texture);
1743 glUseProgram(0);
1744 glDeleteProgram(program);
1745 glDeleteProgram(c_program);
1746 glDeleteBuffers(1, &m_buffer);
1747 return false;
1748 }
1749 }
1750 glDeleteTextures(2, texture);
1751 glUseProgram(0);
1752 glDeleteProgram(program);
1753 glDeleteProgram(c_program);
1754 glDeleteBuffers(1, &m_buffer);
1755
1756 return true;
1757 }
1758
1759 template <typename T>
GenCS(GLenum internalformat,const T & expected_value)1760 std::string GenCS(GLenum internalformat, const T &expected_value)
1761 {
1762 std::ostringstream os;
1763 os << NL "#define KSIZE 8" NL "layout(local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout("
1764 << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " << TypePrefix<T>()
1765 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat)
1766 << ", binding = 3) writeonly uniform " << TypePrefix<T>()
1767 << "image2D g_image_write;" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " "
1768 << TypePrefix<T>()
1769 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v+v);" NL
1770 " //imageStore(g_image_write, coord, "
1771 << TypePrefix<T>() << "vec4" << expected_value << ");" NL "}";
1772 return os.str();
1773 }
1774
1775 template <typename T>
GenC(const T & value)1776 std::string GenC(const T &value)
1777 {
1778 std::ostringstream os;
1779 os << NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1780 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " "
1781 << TypePrefix<T>()
1782 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1783 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1784 " //data[gl_LocalInvocationIndex] = "
1785 << TypePrefix<T>() << "vec4" << value << ";" NL "}";
1786 return os.str();
1787 }
1788 };
1789 //-----------------------------------------------------------------------------
1790 // 1.3.1 BasicAllTargetsStore
1791 //-----------------------------------------------------------------------------
1792 class BasicAllTargetsStoreFS : public ShaderImageLoadStoreBase
1793 {
1794 GLuint m_vao;
1795 GLuint m_vbo;
1796
Setup()1797 virtual long Setup()
1798 {
1799 m_vao = 0;
1800 m_vbo = 0;
1801 return NO_ERROR;
1802 }
1803
Run()1804 virtual long Run()
1805 {
1806 if (!IsVSFSAvailable(0, 4))
1807 return NOT_SUPPORTED;
1808 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1809
1810 if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1811 return ERROR;
1812 if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1813 return ERROR;
1814 if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1815 return ERROR;
1816 if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1817 return ERROR;
1818 if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1819 return ERROR;
1820 if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1821 return ERROR;
1822 if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1823 return ERROR;
1824 if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1825 return ERROR;
1826 if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1827 return ERROR;
1828 if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1829 return ERROR;
1830 if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1831 return ERROR;
1832 if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1833 return ERROR;
1834
1835 return NO_ERROR;
1836 }
1837
Cleanup()1838 virtual long Cleanup()
1839 {
1840 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1841 glDeleteVertexArrays(1, &m_vao);
1842 glDeleteBuffers(1, &m_vbo);
1843 glActiveTexture(GL_TEXTURE0);
1844 return NO_ERROR;
1845 }
1846
1847 template <typename T>
Write(int target,GLenum internalformat,const T & write_value,const T & expected_value)1848 bool Write(int target, GLenum internalformat, const T &write_value, const T &expected_value)
1849 {
1850 const char *src_vs =
1851 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
1852 const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, write_value).c_str());
1853 GLuint textures[8];
1854 glGenTextures(8, textures);
1855
1856 const int kSize = 11;
1857 std::vector<T> data(kSize * kSize * 2);
1858
1859 glBindTexture(GL_TEXTURE_2D, textures[1]);
1860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1862 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1863 glBindTexture(GL_TEXTURE_2D, 0);
1864
1865 glBindTexture(GL_TEXTURE_3D, textures[2]);
1866 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1867 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1868 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
1869 glBindTexture(GL_TEXTURE_3D, 0);
1870
1871 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
1872 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1873 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1874 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
1875 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1876
1877 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
1878 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1879 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1880 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
1881 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1882
1883 glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
1884 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D
1885 glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube
1886 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray
1887
1888 glUseProgram(program);
1889 glBindVertexArray(m_vao);
1890 glViewport(0, 0, kSize, kSize);
1891 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1892
1893 glActiveTexture(GL_TEXTURE1);
1894 glBindTexture(GL_TEXTURE_2D, textures[1]);
1895 glActiveTexture(GL_TEXTURE2);
1896 glBindTexture(GL_TEXTURE_3D, textures[2]);
1897 glActiveTexture(GL_TEXTURE3);
1898 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
1899 glActiveTexture(GL_TEXTURE4);
1900 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
1901 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1902
1903 GLuint c_program = CreateComputeProgram(GenC(write_value));
1904 std::vector<T> out_data2D(kSize * kSize * 6);
1905 std::vector<T> out_data3D(kSize * kSize * 6);
1906 std::vector<T> out_dataCube(kSize * kSize * 6);
1907 std::vector<T> out_data2DArray(kSize * kSize * 6);
1908 GLuint m_buffer[4];
1909 glGenBuffers(4, m_buffer);
1910 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]);
1911 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1912 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
1913 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1914 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]);
1915 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1916 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
1917 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1918
1919 glUseProgram(c_program);
1920 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1);
1921 glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2);
1922 glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3);
1923 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4);
1924 glDispatchCompute(1, 1, 1);
1925 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1926
1927 bool status = true;
1928 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
1929 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1930 int layers = 2;
1931 if (target == T2D)
1932 layers = 1;
1933 if (target == TCM)
1934 layers = 6;
1935 status = CompareValues(map_data, kSize, expected_value, internalformat, layers);
1936 if (!status)
1937 m_context.getTestContext().getLog()
1938 << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
1939 << " format failed." << tcu::TestLog::EndMessage;
1940 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1941
1942 glDeleteTextures(8, textures);
1943 glUseProgram(0);
1944 glDeleteProgram(program);
1945 glDeleteProgram(c_program);
1946 glDeleteBuffers(4, m_buffer);
1947
1948 return status;
1949 }
1950
1951 template <typename T>
GenFS(int target,GLenum internalformat,const T & write_value)1952 std::string GenFS(int target, GLenum internalformat, const T &write_value)
1953 {
1954 std::ostringstream os;
1955 switch (target)
1956 {
1957 case T2D:
1958 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform "
1959 << TypePrefix<T>() << "image2D g_image_2d;";
1960 break;
1961 case T3D:
1962 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
1963 << TypePrefix<T>() << "image3D g_image_3d;";
1964 break;
1965 case TCM:
1966 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
1967 << TypePrefix<T>() << "imageCube g_image_cube;";
1968 break;
1969 case T2DA:
1970 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform "
1971 << TypePrefix<T>() << "image2DArray g_image_2darray;";
1972 break;
1973 }
1974 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);";
1975
1976 switch (target)
1977 {
1978 case T2D:
1979 os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");";
1980 break;
1981 case T3D:
1982 os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1983 << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1984 << ");";
1985 break;
1986 case TCM:
1987 os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1988 << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1989 << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value
1990 << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value
1991 << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value
1992 << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value
1993 << ");";
1994 break;
1995 case T2DA:
1996 os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1997 << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1998 << ");";
1999 break;
2000 }
2001 os << NL " discard;" NL "}";
2002 return os.str();
2003 }
2004
2005 template <typename T>
GenC(const T & write_value)2006 std::string GenC(const T &write_value)
2007 {
2008 std::ostringstream os;
2009 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
2010 << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>()
2011 << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform "
2012 << TypePrefix<T>()
2013 << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL " "
2014 << TypePrefix<T>()
2015 << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL "layout(std430, binding = 0) buffer OutputBuffer3D {" NL
2016 " "
2017 << TypePrefix<T>()
2018 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL
2019 "layout(std430, binding = 3) buffer OutputBufferCube {" NL " "
2020 << TypePrefix<T>()
2021 << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL
2022 "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL " "
2023 << TypePrefix<T>()
2024 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL
2025 " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL
2026 " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL
2027 " uint layer = uint(KSIZE * KSIZE);" NL
2028 " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL
2029 " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), "
2030 "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, "
2031 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = "
2032 "texelFetch(g_sampler_2darray, "
2033 "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL
2034 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, "
2035 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = "
2036 "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL
2037 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, "
2038 "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = "
2039 "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL
2040 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, "
2041 "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = "
2042 "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL
2043 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, "
2044 "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = "
2045 << write_value << ";" NL "}";
2046 return os.str();
2047 }
2048 };
2049
2050 class BasicAllTargetsStoreCS : public ShaderImageLoadStoreBase
2051 {
Setup()2052 virtual long Setup()
2053 {
2054 return NO_ERROR;
2055 }
2056
Run()2057 virtual long Run()
2058 {
2059
2060 if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2061 return ERROR;
2062 if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2063 return ERROR;
2064 if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2065 return ERROR;
2066 if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2067 return ERROR;
2068 if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2069 return ERROR;
2070 if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2071 return ERROR;
2072 if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2073 return ERROR;
2074 if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2075 return ERROR;
2076 if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2077 return ERROR;
2078 if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2079 return ERROR;
2080 if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2081 return ERROR;
2082 if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2083 return ERROR;
2084
2085 return NO_ERROR;
2086 }
2087
Cleanup()2088 virtual long Cleanup()
2089 {
2090 glActiveTexture(GL_TEXTURE0);
2091 return NO_ERROR;
2092 }
2093
2094 template <typename T>
Write(int target,GLenum internalformat,const T & write_value,const T & expected_value)2095 bool Write(int target, GLenum internalformat, const T &write_value, const T &expected_value)
2096 {
2097 const GLuint program = CreateComputeProgram(GenCS(target, internalformat, write_value));
2098 GLuint textures[8];
2099 glGenTextures(8, textures);
2100
2101 const int kSize = 11;
2102 std::vector<T> data(kSize * kSize * 2);
2103
2104 glBindTexture(GL_TEXTURE_2D, textures[1]);
2105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2107 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2108 glBindTexture(GL_TEXTURE_2D, 0);
2109
2110 glBindTexture(GL_TEXTURE_3D, textures[2]);
2111 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2112 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2113 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2114 glBindTexture(GL_TEXTURE_3D, 0);
2115
2116 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2117 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2118 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2119 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2120 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2121
2122 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2123 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2124 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2125 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2126 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2127
2128 glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
2129 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D
2130 glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube
2131 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray
2132
2133 glUseProgram(program);
2134 glDispatchCompute(1, 1, 1);
2135
2136 glActiveTexture(GL_TEXTURE1);
2137 glBindTexture(GL_TEXTURE_2D, textures[1]);
2138 glActiveTexture(GL_TEXTURE2);
2139 glBindTexture(GL_TEXTURE_3D, textures[2]);
2140 glActiveTexture(GL_TEXTURE3);
2141 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2142 glActiveTexture(GL_TEXTURE4);
2143 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2144 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
2145
2146 GLuint c_program = CreateComputeProgram(GenC(write_value));
2147 std::vector<T> out_data2D(kSize * kSize * 6);
2148 std::vector<T> out_data3D(kSize * kSize * 6);
2149 std::vector<T> out_dataCube(kSize * kSize * 6);
2150 std::vector<T> out_data2DArray(kSize * kSize * 6);
2151 GLuint m_buffer[4];
2152 glGenBuffers(4, m_buffer);
2153 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
2154 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2155 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
2156 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2157 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]);
2158 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2159 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]);
2160 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2161
2162 glUseProgram(c_program);
2163 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1);
2164 glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2);
2165 glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3);
2166 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4);
2167
2168 glDispatchCompute(1, 1, 1);
2169 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2170
2171 bool status = true;
2172
2173 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2174 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2175 int layers = 2;
2176 if (target == T2D)
2177 layers = 1;
2178 if (target == TCM)
2179 layers = 6;
2180 status = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2181 if (!status)
2182 m_context.getTestContext().getLog()
2183 << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2184 << " format failed." << tcu::TestLog::EndMessage;
2185 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2186
2187 glDeleteTextures(8, textures);
2188 glUseProgram(0);
2189 glDeleteProgram(program);
2190 glDeleteProgram(c_program);
2191 glDeleteBuffers(4, m_buffer);
2192
2193 return status;
2194 }
2195
2196 template <typename T>
GenCS(int target,GLenum internalformat,const T & write_value)2197 std::string GenCS(int target, GLenum internalformat, const T &write_value)
2198 {
2199 std::ostringstream os;
2200 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;";
2201 switch (target)
2202 {
2203 case T2D:
2204 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform "
2205 << TypePrefix<T>() << "image2D g_image_2d;";
2206 break;
2207 case T3D:
2208 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
2209 << TypePrefix<T>() << "image3D g_image_3d;";
2210 break;
2211 case TCM:
2212 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
2213 << TypePrefix<T>() << "imageCube g_image_cube;";
2214 break;
2215 case T2DA:
2216 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform "
2217 << TypePrefix<T>() << "image2DArray g_image_2darray;";
2218 break;
2219 }
2220 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);";
2221 switch (target)
2222 {
2223 case T2D:
2224 os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");";
2225 break;
2226 case T3D:
2227 os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2228 << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2229 << ");";
2230 break;
2231 case TCM:
2232 os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2233 << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2234 << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value
2235 << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value
2236 << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value
2237 << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value
2238 << ");";
2239 break;
2240 case T2DA:
2241 os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2242 << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2243 << ");";
2244 break;
2245 }
2246 os << NL "}";
2247 return os.str();
2248 }
2249
2250 template <typename T>
GenC(const T & write_value)2251 std::string GenC(const T &write_value)
2252 {
2253 std::ostringstream os;
2254 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
2255 << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>()
2256 << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform "
2257 << TypePrefix<T>()
2258 << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL " "
2259 << TypePrefix<T>()
2260 << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL "layout(std430, binding = 1) buffer OutputBuffer3D {" NL
2261 " "
2262 << TypePrefix<T>()
2263 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL
2264 "layout(std430, binding = 2) buffer OutputBufferCube {" NL " "
2265 << TypePrefix<T>()
2266 << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL
2267 "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL " "
2268 << TypePrefix<T>()
2269 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL
2270 " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL
2271 " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL
2272 " uint layer = uint(KSIZE * KSIZE);" NL
2273 " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL
2274 " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), "
2275 "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, "
2276 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = "
2277 "texelFetch(g_sampler_2darray, "
2278 "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL
2279 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, "
2280 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = "
2281 "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL
2282 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, "
2283 "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = "
2284 "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL
2285 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, "
2286 "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = "
2287 "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL
2288 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, "
2289 "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = "
2290 << write_value << ";" NL "}";
2291 return os.str();
2292 }
2293 };
2294 //-----------------------------------------------------------------------------
2295 // 1.3.2.1 BasicAllTargetsLoad
2296 //-----------------------------------------------------------------------------
2297 class BasicAllTargetsLoadFS : public ShaderImageLoadStoreBase
2298 {
2299 GLuint m_vao;
2300 GLuint m_vbo;
2301
Setup()2302 virtual long Setup()
2303 {
2304 m_vao = 0;
2305 m_vbo = 0;
2306 return NO_ERROR;
2307 }
2308
Run()2309 virtual long Run()
2310 {
2311 if (!IsVSFSAvailable(0, 4) || !IsSSBInVSFSAvailable(4))
2312 return NOT_SUPPORTED;
2313 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2314
2315 if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2316 GL_FLOAT))
2317 return ERROR;
2318 if (!Read(T2D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2319 return ERROR;
2320 if (!Read(T2D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2321 return ERROR;
2322 if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2323 GL_FLOAT))
2324 return ERROR;
2325 if (!Read(T3D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2326 return ERROR;
2327 if (!Read(T3D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2328 return ERROR;
2329 if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2330 GL_FLOAT))
2331 return ERROR;
2332 if (!Read(TCM, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2333 return ERROR;
2334 if (!Read(TCM, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2335 return ERROR;
2336 if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2337 GL_FLOAT))
2338 return ERROR;
2339 if (!Read(T2DA, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2340 return ERROR;
2341 if (!Read(T2DA, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER,
2342 GL_UNSIGNED_INT))
2343 return ERROR;
2344
2345 return NO_ERROR;
2346 }
2347
Cleanup()2348 virtual long Cleanup()
2349 {
2350 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2351 glDeleteVertexArrays(1, &m_vao);
2352 glDeleteBuffers(1, &m_vbo);
2353 return NO_ERROR;
2354 }
2355
2356 template <typename T>
Read(int target,GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)2357 bool Read(int target, GLenum internalformat, const T &value, const T &expected_value, GLenum format, GLenum type)
2358 {
2359 const char *src_vs =
2360 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
2361 const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, expected_value).c_str());
2362 GLuint textures[8];
2363 glGenTextures(8, textures);
2364
2365 const int kSize = 11;
2366 std::vector<T> data(kSize * kSize * 2, value);
2367
2368 glBindTexture(GL_TEXTURE_2D, textures[1]);
2369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2371 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2372 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2373 glBindTexture(GL_TEXTURE_2D, 0);
2374
2375 glBindTexture(GL_TEXTURE_3D, textures[2]);
2376 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2377 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2378 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2379 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2380 glBindTexture(GL_TEXTURE_3D, 0);
2381
2382 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2383 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2384 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2385 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2386 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2387 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2388 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2389 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2390 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2391 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2392 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2393
2394 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2395 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2396 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2397 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2398 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2399 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2400
2401 glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
2402 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D
2403 glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube
2404 glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray
2405
2406 std::vector<T> out_data2D(kSize * kSize * 6);
2407 std::vector<T> out_data3D(kSize * kSize * 6);
2408 std::vector<T> out_dataCube(kSize * kSize * 6);
2409 std::vector<T> out_data2DArray(kSize * kSize * 6);
2410 GLuint m_buffer[4];
2411 glGenBuffers(4, m_buffer);
2412 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]);
2413 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2414 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
2415 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2416 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]);
2417 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2418 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
2419 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2420
2421 glUseProgram(program);
2422 glClear(GL_COLOR_BUFFER_BIT);
2423 glBindVertexArray(m_vao);
2424 glViewport(0, 0, kSize, kSize);
2425 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2426 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2427
2428 bool status = true;
2429 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2430 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2431 int layers = 2;
2432 if (target == T2D)
2433 layers = 1;
2434 if (target == TCM)
2435 layers = 6;
2436 status = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2437 if (!status)
2438 m_context.getTestContext().getLog()
2439 << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2440 << " format failed." << tcu::TestLog::EndMessage;
2441 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2442
2443 glUseProgram(0);
2444 glDeleteProgram(program);
2445 glDeleteTextures(8, textures);
2446 glDeleteBuffers(4, m_buffer);
2447
2448 return status;
2449 }
2450
2451 template <typename T>
GenFS(int target,GLenum internalformat,const T & expected_value)2452 std::string GenFS(int target, GLenum internalformat, const T &expected_value)
2453 {
2454 std::ostringstream os;
2455 os << NL "#define KSIZE 11";
2456 switch (target)
2457 {
2458 case T2D:
2459 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform "
2460 << TypePrefix<T>()
2461 << "image2D g_image_2d;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL " "
2462 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;";
2463 break;
2464 case T3D:
2465 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform "
2466 << TypePrefix<T>()
2467 << "image3D g_image_3d;" NL "layout(std430, binding = 0) buffer OutputBuffer3D {" NL " "
2468 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;";
2469 break;
2470 case TCM:
2471 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
2472 << TypePrefix<T>()
2473 << "imageCube g_image_cube;" NL "layout(std430, binding = 3) buffer OutputBufferCube {" NL " "
2474 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;";
2475 break;
2476 case T2DA:
2477 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform "
2478 << TypePrefix<T>()
2479 << "image2DArray g_image_2darray;" NL "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL " "
2480 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;";
2481 break;
2482 }
2483 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2484 " int coordIndex = coord.x + KSIZE * coord.y;" NL " int layer = int(KSIZE * KSIZE);" NL " "
2485 << TypePrefix<T>() << "vec4 v;";
2486
2487 switch (target)
2488 {
2489 case T2D:
2490 os << NL " v = imageLoad(g_image_2d, coord);" NL " g_buff_2d.data[coordIndex] = v;";
2491 break;
2492 case T3D:
2493 os << NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL " g_buff_3d.data[coordIndex] = v;" NL
2494 " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL " g_buff_3d.data[coordIndex + layer] = v;";
2495 break;
2496 case TCM:
2497 os << NL
2498 " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " g_buff_cube.data[coordIndex] = v;" NL
2499 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " g_buff_cube.data[coordIndex + layer] = v;" NL
2500 " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
2501 " g_buff_cube.data[coordIndex + 2 * layer] = v;" NL
2502 " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
2503 " g_buff_cube.data[coordIndex + 3 * layer] = v;" NL
2504 " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
2505 " g_buff_cube.data[coordIndex + 4 * layer] = v;" NL
2506 " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL " g_buff_cube.data[coordIndex + 5 * layer] = v;";
2507 break;
2508 case T2DA:
2509 os << NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL " g_buff_2darray.data[coordIndex] = v;" NL
2510 " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
2511 " g_buff_2darray.data[coordIndex + layer] = v;";
2512 break;
2513 }
2514 os << NL " //g_buff_2d.data[coordIndex] = " << expected_value << ";" NL "}";
2515 return os.str();
2516 }
2517 };
2518
2519 class BasicAllTargetsLoadCS : public ShaderImageLoadStoreBase
2520 {
Setup()2521 virtual long Setup()
2522 {
2523 return NO_ERROR;
2524 }
2525
Run()2526 virtual long Run()
2527 {
2528 if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2529 GL_FLOAT))
2530 return ERROR;
2531 if (!Read(T2D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2532 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2533 return ERROR;
2534 if (!Read(T2D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2535 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2536 return ERROR;
2537 if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2538 GL_FLOAT))
2539 return ERROR;
2540 if (!Read(T3D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2541 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2542 return ERROR;
2543 if (!Read(T3D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2544 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2545 return ERROR;
2546 if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2547 GL_FLOAT))
2548 return ERROR;
2549 if (!Read(TCM, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2550 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2551 return ERROR;
2552 if (!Read(TCM, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2553 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2554 return ERROR;
2555 if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2556 GL_FLOAT))
2557 return ERROR;
2558 if (!Read(T2DA, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2559 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2560 return ERROR;
2561 if (!Read(T2DA, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2562 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2563 return ERROR;
2564
2565 return NO_ERROR;
2566 }
2567
Cleanup()2568 virtual long Cleanup()
2569 {
2570 return NO_ERROR;
2571 }
2572
2573 template <typename T>
Read(int target,GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)2574 bool Read(int target, GLenum internalformat, const T &value, const T &expected_value, GLenum format, GLenum type)
2575 {
2576 const GLuint program = CreateComputeProgram(GenCS(target, internalformat, expected_value));
2577 GLuint textures[8];
2578 glGenTextures(8, textures);
2579
2580 const int kSize = 11;
2581 std::vector<T> data(kSize * kSize * 2, value);
2582
2583 glBindTexture(GL_TEXTURE_2D, textures[1]);
2584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2586 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2587 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2588 glBindTexture(GL_TEXTURE_2D, 0);
2589
2590 glBindTexture(GL_TEXTURE_3D, textures[2]);
2591 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2592 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2593 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2594 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2595 glBindTexture(GL_TEXTURE_3D, 0);
2596
2597 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2598 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2599 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2600 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2601 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2602 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2603 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2604 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2605 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2606 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2607 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2608
2609 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2610 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2611 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2612 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2613 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2614 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2615
2616 glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
2617 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D
2618 glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube
2619 glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray
2620
2621 std::vector<T> out_data2D(kSize * kSize * 6);
2622 std::vector<T> out_data3D(kSize * kSize * 6);
2623 std::vector<T> out_dataCube(kSize * kSize * 6);
2624 std::vector<T> out_data2DArray(kSize * kSize * 6);
2625 GLuint m_buffer[4];
2626 glGenBuffers(4, m_buffer);
2627 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
2628 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2629 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
2630 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2631 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]);
2632 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2633 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]);
2634 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2635
2636 glUseProgram(program);
2637 glDispatchCompute(1, 1, 1);
2638 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2639
2640 bool status = true;
2641
2642 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2643 T *map_data = (T *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2644 int layers = 2;
2645 if (target == T2D)
2646 layers = 1;
2647 if (target == TCM)
2648 layers = 6;
2649 status = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2650 if (!status)
2651 m_context.getTestContext().getLog()
2652 << tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2653 << " format failed." << tcu::TestLog::EndMessage;
2654 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2655
2656 glUseProgram(0);
2657 glDeleteProgram(program);
2658 glDeleteTextures(8, textures);
2659 glDeleteBuffers(4, m_buffer);
2660
2661 return status;
2662 }
2663
2664 template <typename T>
GenCS(int target,GLenum internalformat,const T & expected_value)2665 std::string GenCS(int target, GLenum internalformat, const T &expected_value)
2666 {
2667 std::ostringstream os;
2668 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;";
2669 switch (target)
2670 {
2671 case T2D:
2672 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform "
2673 << TypePrefix<T>()
2674 << "image2D g_image_2d;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL " "
2675 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;";
2676 break;
2677 case T3D:
2678 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform "
2679 << TypePrefix<T>()
2680 << "image3D g_image_3d;" NL "layout(std430, binding = 1) buffer OutputBuffer3D {" NL " "
2681 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;";
2682 break;
2683 case TCM:
2684 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
2685 << TypePrefix<T>()
2686 << "imageCube g_image_cube;" NL "layout(std430, binding = 2) buffer OutputBufferCube {" NL " "
2687 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;";
2688 break;
2689 case T2DA:
2690 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform "
2691 << TypePrefix<T>()
2692 << "image2DArray g_image_2darray;" NL "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL " "
2693 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;";
2694 break;
2695 }
2696 os << NL "void main() {" NL " ivec3 coord = ivec3(gl_LocalInvocationID.xy, 0);" NL
2697 " uint layer = uint(KSIZE * KSIZE);" NL " "
2698 << TypePrefix<T>() << "vec4 v;";
2699 switch (target)
2700 {
2701 case T2D:
2702 os << NL " v = imageLoad(g_image_2d, coord.xy);" NL " g_buff_2d.data[gl_LocalInvocationIndex] = v;";
2703 break;
2704 case T3D:
2705 os << NL " v = imageLoad(g_image_3d, coord);" NL " g_buff_3d.data[gl_LocalInvocationIndex] = v;" NL
2706 " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
2707 " g_buff_3d.data[gl_LocalInvocationIndex + layer] = v;";
2708 break;
2709 case TCM:
2710 os << NL " v = imageLoad(g_image_cube, coord);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = v;" NL
2711 " v = imageLoad(g_image_cube, ivec3(coord.xy, 1));" NL
2712 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = v;" NL
2713 " v = imageLoad(g_image_cube, ivec3(coord.xy, 2));" NL
2714 " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = v;" NL
2715 " v = imageLoad(g_image_cube, ivec3(coord.xy, 3));" NL
2716 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = v;" NL
2717 " v = imageLoad(g_image_cube, ivec3(coord.xy, 4));" NL
2718 " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = v;" NL
2719 " v = imageLoad(g_image_cube, ivec3(coord.xy, 5));" NL
2720 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = v;";
2721 break;
2722 case T2DA:
2723 os << NL " v = imageLoad(g_image_2darray, coord);" NL
2724 " g_buff_2darray.data[gl_LocalInvocationIndex] = v;" NL
2725 " v = imageLoad(g_image_2darray, ivec3(coord.xy, 1));" NL
2726 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = v;";
2727 break;
2728 }
2729 os << NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " << expected_value << ";" NL "}";
2730 return os.str();
2731 }
2732 };
2733 //-----------------------------------------------------------------------------
2734 // 1.3.3 BasicAllTargetsAtomic
2735 //-----------------------------------------------------------------------------
2736 class BasicAllTargetsAtomicFS : public ShaderImageLoadStoreBase
2737 {
2738 GLuint m_vao;
2739 GLuint m_vbo;
2740
Setup()2741 virtual long Setup()
2742 {
2743 m_vao = 0;
2744 m_vbo = 0;
2745 return NO_ERROR;
2746 }
2747
Run()2748 virtual long Run()
2749 {
2750 if (!IsImageAtomicSupported())
2751 return NOT_SUPPORTED;
2752 if (!IsVSFSAvailable(0, 4))
2753 return NOT_SUPPORTED;
2754 if (!AreOutputsAvailable(5))
2755 return NOT_SUPPORTED;
2756 if (!IsSSBInVSFSAvailable(1))
2757 return NOT_SUPPORTED;
2758 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2759
2760 if (!Atomic<GLint>(GL_R32I))
2761 return ERROR;
2762 if (!Atomic<GLuint>(GL_R32UI))
2763 return ERROR;
2764
2765 return NO_ERROR;
2766 }
2767
Cleanup()2768 virtual long Cleanup()
2769 {
2770 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2771 glDeleteVertexArrays(1, &m_vao);
2772 glDeleteBuffers(1, &m_vbo);
2773 return NO_ERROR;
2774 }
2775
2776 template <typename T>
Atomic(GLenum internalformat)2777 bool Atomic(GLenum internalformat)
2778 {
2779 const char *src_vs =
2780 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
2781 const GLuint program = BuildProgram(src_vs, GenFS<T>(internalformat).c_str(), false, true);
2782 GLuint textures[8];
2783 GLuint buffer;
2784 glGenTextures(8, textures);
2785 glGenBuffers(1, &buffer);
2786
2787 const int kSize = 11;
2788 std::vector<T> data(kSize * kSize * 3);
2789
2790 glBindTexture(GL_TEXTURE_2D, textures[1]);
2791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2793 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2794 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2795 glBindTexture(GL_TEXTURE_2D, 0);
2796
2797 glBindTexture(GL_TEXTURE_3D, textures[2]);
2798 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2799 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2800 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 3);
2801 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]);
2802 glBindTexture(GL_TEXTURE_3D, 0);
2803
2804 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2805 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2806 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2807 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2808 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2809 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2810 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2811 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2812 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2813 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2814 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2815
2816 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2817 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2818 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2819 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 3);
2820 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]);
2821 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2822
2823 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D
2824 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 3D
2825 glBindImageTexture(0, textures[4], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // Cube
2826 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 2DArray
2827
2828 std::vector<ivec4> o_data(kSize * kSize);
2829 GLuint m_buffer;
2830 glGenBuffers(1, &m_buffer);
2831 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
2832 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
2833
2834 glUseProgram(program);
2835 glClear(GL_COLOR_BUFFER_BIT);
2836 glBindVertexArray(m_vao);
2837 glViewport(0, 0, kSize, kSize);
2838 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2839 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2840
2841 bool status = true;
2842
2843 ivec4 *out_data =
2844 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2845 for (int i = 0; i < kSize * kSize; ++i)
2846 {
2847 if (!Equal(out_data[i], ivec4(10, 10, 10, 10), 0))
2848 {
2849 status = false;
2850 m_context.getTestContext().getLog()
2851 << tcu::TestLog::Message << "[" << i
2852 << "] Atomic operation check failed. (operation/target coded: " << ToString(out_data[i]).c_str()
2853 << ")" << tcu::TestLog::EndMessage;
2854 }
2855 }
2856
2857 glUseProgram(0);
2858 glDeleteProgram(program);
2859 glDeleteTextures(8, textures);
2860 glDeleteBuffers(1, &buffer);
2861 glDeleteBuffers(1, &m_buffer);
2862
2863 return status;
2864 }
2865
2866 template <typename T>
GenFS(GLenum internalformat)2867 std::string GenFS(GLenum internalformat)
2868 {
2869 std::ostringstream os;
2870 os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat)
2871 << ", binding = 1) coherent uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2872 << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform " << TypePrefix<T>()
2873 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
2874 << ", binding = 0) coherent uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2875 << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform " << TypePrefix<T>()
2876 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL
2877 " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
2878 << TypePrefix<T>() << "vec2 t(int i) {" NL " return " << TypePrefix<T>()
2879 << "vec2(i);" NL "}" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2880 " int coordIndex = coord.x + KSIZE * coord.y;" NL " o_color[coordIndex] = ivec4(coordIndex);" NL
2881 " if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color[coordIndex].x = 1;" NL
2882 " else if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color[coordIndex].x = 2;" NL
2883 " else if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color[coordIndex].x = 3;" NL
2884 " else if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color[coordIndex].x = 4;" NL
2885 " else if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color[coordIndex].x = 5;" NL
2886 " else if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color[coordIndex].x = 6;" NL
2887 " else if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color[coordIndex].x = 7;" NL
2888 " else if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color[coordIndex].x = "
2889 "8;" NL " else o_color[coordIndex].x = 10;" NL
2890 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].y = 1;" NL
2891 " else if (imageAtomicMin(g_image_3d, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].y = 2;" NL
2892 " else if (imageAtomicMax(g_image_3d, ivec3(coord, 2), t(4).x) != t(2).x) o_color[coordIndex].y = 3;" NL
2893 " else if (imageAtomicAnd(g_image_3d, ivec3(coord, 2), t(0).x) != t(4).x) o_color[coordIndex].y = 4;" NL
2894 " else if (imageAtomicOr(g_image_3d, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].y = 5;" NL
2895 " else if (imageAtomicXor(g_image_3d, ivec3(coord, 2), t(4).x) != t(7).x) o_color[coordIndex].y = 6;" NL
2896 " else if (imageAtomicExchange(g_image_3d, ivec3(coord, 2), t(1).x) != t(3).x) o_color[coordIndex].y = "
2897 "7;" NL " else if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) "
2898 "o_color[coordIndex].y = 8;" NL " else o_color[coordIndex].y = 10;" NL
2899 " if (imageAtomicAdd(g_image_cube, ivec3(coord, 3), t(2).x) != t(0).x) o_color[coordIndex].z = 1;" NL
2900 " else if (imageAtomicMin(g_image_cube, ivec3(coord, 3), t(3).x) != t(2).x) o_color[coordIndex].z = "
2901 "2;" NL " else if (imageAtomicMax(g_image_cube, ivec3(coord, 3), t(4).x) != t(2).x) "
2902 "o_color[coordIndex].z = 3;" NL " else if (imageAtomicAnd(g_image_cube, ivec3(coord, 3), "
2903 "t(0).x) != t(4).x) o_color[coordIndex].z = 4;" NL
2904 " else if (imageAtomicOr(g_image_cube, ivec3(coord, 3), t(7).x) != t(0).x) o_color[coordIndex].z = 5;" NL
2905 " else if (imageAtomicXor(g_image_cube, ivec3(coord, 3), t(4).x) != t(7).x) o_color[coordIndex].z = "
2906 "6;" NL " else if (imageAtomicExchange(g_image_cube, ivec3(coord, 3), t(1).x) != t(3).x) "
2907 "o_color[coordIndex].z = 7;" NL " else if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 3), "
2908 "t(1).x, t(6).x) != t(1).x) o_color[coordIndex].z = 8;" NL " else o_color[coordIndex].z = 10;" NL
2909 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].w = 1;" NL
2910 " else if (imageAtomicMin(g_image_2darray, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].w = "
2911 "2;" NL " else if (imageAtomicMax(g_image_2darray, ivec3(coord, 2), t(4).x) != t(2).x) "
2912 "o_color[coordIndex].w = 3;" NL " else if (imageAtomicAnd(g_image_2darray, ivec3(coord, 2), "
2913 "t(0).x) != t(4).x) o_color[coordIndex].w = 4;" NL
2914 " else if (imageAtomicOr(g_image_2darray, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].w = "
2915 "5;" NL " else if (imageAtomicXor(g_image_2darray, ivec3(coord, 2), t(4).x) != t(7).x) "
2916 "o_color[coordIndex].w = 6;" NL " else if (imageAtomicExchange(g_image_2darray, ivec3(coord, "
2917 "2), t(1).x) != t(3).x) o_color[coordIndex].w = 7;" NL
2918 " else if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) "
2919 "o_color[coordIndex].w = 8;" NL " else o_color[coordIndex].w = 10;" NL " discard;" NL "}";
2920 return os.str();
2921 }
2922 };
2923 //-----------------------------------------------------------------------------
2924 // LoadStoreMachine
2925 //-----------------------------------------------------------------------------
2926 class LoadStoreMachine : public ShaderImageLoadStoreBase
2927 {
2928 GLuint m_vao;
2929 GLuint m_buffer;
2930 int m_stage;
2931
Setup()2932 virtual long Setup()
2933 {
2934 glEnable(GL_RASTERIZER_DISCARD);
2935 glGenVertexArrays(1, &m_vao);
2936 glGenBuffers(1, &m_buffer);
2937 return NO_ERROR;
2938 }
2939
Cleanup()2940 virtual long Cleanup()
2941 {
2942 glDisable(GL_RASTERIZER_DISCARD);
2943 glDeleteVertexArrays(1, &m_vao);
2944 glDeleteBuffers(1, &m_buffer);
2945 return NO_ERROR;
2946 }
2947
2948 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2949 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
2950 {
2951 const GLenum targets[] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY};
2952 const int kTargets = sizeof(targets) / sizeof(targets[0]);
2953 const int kSize = 100;
2954 GLuint program_store = 0;
2955 GLuint program_load = 0;
2956 if (m_stage == 0)
2957 { // VS
2958 const char *src_fs = NL "void main() {" NL " discard;" NL "}";
2959 program_store = BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), src_fs);
2960 program_load = BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), src_fs);
2961 }
2962 else if (m_stage == 4)
2963 { // CS
2964 program_store = CreateComputeProgram(GenStoreShader(m_stage, internalformat, write_value));
2965 program_load = CreateComputeProgram(GenLoadShader(m_stage, internalformat, expected_value));
2966 }
2967 GLuint textures[kTargets];
2968 glGenTextures(kTargets, textures);
2969
2970 for (int i = 0; i < kTargets; ++i)
2971 {
2972 glBindTexture(targets[i], textures[i]);
2973 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2974 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2975
2976 if (targets[i] == GL_TEXTURE_2D)
2977 {
2978 glTexStorage2D(targets[i], 1, internalformat, kSize, 1);
2979 }
2980 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
2981 {
2982 glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2);
2983 }
2984 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
2985 {
2986 glTexStorage2D(targets[i], 1, internalformat, kSize, kSize);
2987 }
2988 }
2989 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
2990 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D
2991 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube
2992 glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray
2993
2994 std::vector<ivec4> b_data(kSize);
2995 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
2996 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW);
2997
2998 glUseProgram(program_store);
2999 glBindVertexArray(m_vao);
3000 if (m_stage == 4)
3001 { // CS
3002 glDispatchCompute(1, 1, 1);
3003 }
3004 else if (m_stage == 0)
3005 { // VS
3006 glDrawArrays(GL_POINTS, 0, kSize);
3007 }
3008 bool status = true;
3009 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
3010
3011 glBindImageTexture(3, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
3012 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D
3013 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube
3014 glBindImageTexture(0, textures[3], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray
3015
3016 glUseProgram(program_load);
3017 if (m_stage == 0)
3018 { // VS
3019 glDrawArrays(GL_POINTS, 0, kSize);
3020 }
3021 else if (m_stage == 4)
3022 { // CS
3023 glDispatchCompute(1, 1, 1);
3024 }
3025 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3026
3027 ivec4 *out_data = (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT);
3028 for (int i = 0; i < kSize; ++i)
3029 {
3030 if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0))
3031 {
3032 status = false;
3033 m_context.getTestContext().getLog()
3034 << tcu::TestLog::Message << "[" << i << "] load/store operation check failed. ("
3035 << ToString(out_data[i]).c_str() << ")" << tcu::TestLog::EndMessage;
3036 }
3037 }
3038 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3039 glUseProgram(0);
3040 glDeleteProgram(program_store);
3041 glDeleteProgram(program_load);
3042 glDeleteTextures(kTargets, textures);
3043 return status;
3044 }
3045
3046 template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)3047 std::string GenStoreShader(int stage, GLenum internalformat, const T &write_value)
3048 {
3049 std::ostringstream os;
3050 if (stage == 4)
3051 { // CS
3052 os << NL "#define KSIZE 100" NL "layout(local_size_x = KSIZE) in;";
3053 }
3054 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
3055 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3056 << ", binding = 2) writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3057 << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " << TypePrefix<T>()
3058 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
3059 << ", binding = 3) writeonly uniform " << TypePrefix<T>()
3060 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color;" NL "};" NL
3061 "void main() {" NL " "
3062 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color) + " << TypePrefix<T>() << "vec4"
3063 << write_value
3064 << ";" NL " int g_index[6] = int[](o_color.x, o_color.y, o_color.z, o_color.w, o_color.r, o_color.g);";
3065 if (stage == 0)
3066 { // VS
3067 os << NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
3068 }
3069 else if (stage == 4)
3070 { // CS
3071 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
3072 }
3073 os << NL " imageStore(g_image_2d, coord, g_value);" NL
3074 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
3075 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
3076 " for (int i = 0; i < 6; ++i) {" NL
3077 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
3078 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
3079 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL "}";
3080 return os.str();
3081 }
3082
3083 template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)3084 std::string GenLoadShader(int stage, GLenum internalformat, const T &expected_value)
3085 {
3086 std::ostringstream os;
3087 os << NL "#define KSIZE 100";
3088 if (stage == 4)
3089 { // CS
3090 os << NL "layout(local_size_x = KSIZE) in;";
3091 }
3092 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
3093 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3094 << ", binding = 2) readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3095 << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>()
3096 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
3097 << ", binding = 0) readonly uniform " << TypePrefix<T>()
3098 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE];" NL
3099 "};" NL "void main() {";
3100
3101 if (stage == 0)
3102 { // VS
3103 os << NL " " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color[gl_VertexID]) + "
3104 << TypePrefix<T>() << "vec4" << expected_value << ";";
3105 }
3106 else if (stage == 4)
3107 { // CS
3108 os << NL " " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>()
3109 << "vec4(o_color[gl_GlobalInvocationID.x]) + " << TypePrefix<T>() << "vec4" << expected_value << ";";
3110 }
3111
3112 os << NL " int g_index[6] = int[](o_color[0].x, o_color[0].y, o_color[0].z, o_color[0].w, o_color[1].r, "
3113 "o_color[1].g);";
3114 if (stage == 0)
3115 { // VS
3116 os << NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
3117 }
3118 else if (stage == 4)
3119 { // CS
3120 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
3121 }
3122 os << NL " vec4 r = vec4(0.0, 1.0, 0.0, 1.0);" NL " " << TypePrefix<T>()
3123 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
3124 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 2.0);" NL
3125 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
3126 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 3.0);" NL
3127 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
3128 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 6.0);" NL
3129 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
3130 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 23.0);" NL " o_color[coord.x] = ivec4(r);" NL
3131 "}";
3132 return os.str();
3133 }
3134
3135 protected:
RunStage(int stage)3136 long RunStage(int stage)
3137 {
3138 m_stage = stage;
3139 if (!AreOutputsAvailable(5))
3140 return NOT_SUPPORTED;
3141
3142 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
3143 return ERROR;
3144 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
3145 return ERROR;
3146 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
3147 return ERROR;
3148
3149 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3150 return ERROR;
3151 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
3152 return ERROR;
3153 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3154 return ERROR;
3155 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3156 return ERROR;
3157
3158 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3159 return ERROR;
3160 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
3161 return ERROR;
3162 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3163 return ERROR;
3164 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3165 return ERROR;
3166
3167 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
3168 return ERROR;
3169
3170 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
3171 return ERROR;
3172
3173 return NO_ERROR;
3174 }
3175 };
3176
3177 //-----------------------------------------------------------------------------
3178 // AtomicMachine
3179 //-----------------------------------------------------------------------------
3180 class AtomicMachine : public ShaderImageLoadStoreBase
3181 {
3182 GLuint m_vao;
3183 GLuint m_buffer;
3184
Setup()3185 virtual long Setup()
3186 {
3187 glEnable(GL_RASTERIZER_DISCARD);
3188 glGenVertexArrays(1, &m_vao);
3189 glGenBuffers(1, &m_buffer);
3190 return NO_ERROR;
3191 }
3192
Cleanup()3193 virtual long Cleanup()
3194 {
3195 glDisable(GL_RASTERIZER_DISCARD);
3196 glDeleteVertexArrays(1, &m_vao);
3197 glDeleteBuffers(1, &m_buffer);
3198 return NO_ERROR;
3199 }
3200
3201 template <typename T>
Atomic(int target,int stage,GLenum internalformat)3202 bool Atomic(int target, int stage, GLenum internalformat)
3203 {
3204 GLuint program = 0;
3205 if (stage == 0)
3206 { // VS
3207 const char *src_fs = NL "void main() {" NL " discard;" NL "}";
3208 program = BuildProgram(GenShader<T>(target, stage, internalformat).c_str(), src_fs, true, false);
3209 }
3210 else if (stage == 4)
3211 { // CS
3212 program = CreateComputeProgram(GenShader<T>(target, stage, internalformat), true);
3213 }
3214
3215 const GLenum targets[] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY};
3216 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3217 const int kSize = 100;
3218
3219 GLuint textures[kTargets];
3220 glGenTextures(kTargets, textures);
3221
3222 for (int i = 0; i < kTargets; ++i)
3223 {
3224 glBindTexture(targets[i], textures[i]);
3225 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3226 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3227 if (targets[i] == GL_TEXTURE_2D)
3228 {
3229 glTexStorage2D(targets[i], 1, internalformat, kSize, 1);
3230 }
3231 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3232 {
3233 glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2);
3234 }
3235 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3236 {
3237 glTexStorage2D(targets[i], 1, internalformat, kSize, kSize);
3238 }
3239 }
3240 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D
3241 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 3D
3242 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // Cube
3243 glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 2DArray
3244
3245 std::vector<ivec4> b_data(kSize);
3246 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3247 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW);
3248
3249 glUseProgram(program);
3250 glBindVertexArray(m_vao);
3251 if (stage == 0)
3252 { // VS
3253 glDrawArrays(GL_POINTS, 0, kSize);
3254 }
3255 else if (stage == 4)
3256 { // CS
3257 glDispatchCompute(1, 1, 1);
3258 }
3259 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3260
3261 bool status = true;
3262 ivec4 *out_data = (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT);
3263 for (int i = 0; i < kSize; ++i)
3264 {
3265 if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0))
3266 {
3267 status = false;
3268 m_context.getTestContext().getLog()
3269 << tcu::TestLog::Message << "[" << i << "] Atomic operation check failed. ("
3270 << ToString(out_data[i]).c_str() << ")" << tcu::TestLog::EndMessage;
3271 }
3272 }
3273 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3274 glUseProgram(0);
3275 glDeleteProgram(program);
3276 glDeleteTextures(kTargets, textures);
3277 return status;
3278 }
3279
3280 template <typename T>
GenShader(int target,int stage,GLenum internalformat)3281 std::string GenShader(int target, int stage, GLenum internalformat)
3282 {
3283 std::ostringstream os;
3284 os << NL "#define KSIZE 100";
3285 if (stage == 4)
3286 { // CS
3287 os << NL "layout(local_size_x = KSIZE) in;";
3288 }
3289 switch (target)
3290 {
3291 case T2D:
3292 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) coherent uniform "
3293 << TypePrefix<T>() << "image2D g_image_2d;";
3294 break;
3295 case T3D:
3296 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform "
3297 << TypePrefix<T>() << "image3D g_image_3d;";
3298 break;
3299 case TCM:
3300 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) coherent uniform "
3301 << TypePrefix<T>() << "imageCube g_image_cube;";
3302 break;
3303 case T2DA:
3304 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform "
3305 << TypePrefix<T>() << "image2DArray g_image_2darray;";
3306 break;
3307 }
3308 os << NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE];" NL "} r;" NL << TypePrefix<T>()
3309 << "vec2 t(int i) {" NL " return " << TypePrefix<T>()
3310 << "vec2(i);" NL "}" NL "void main() {" NL " int g_value[6] = int[](r.o_color[0].x, r.o_color[0].y+1, "
3311 "r.o_color[0].z+2, r.o_color[0].w+3, r.o_color[1].r+4, "
3312 "r.o_color[1].g+5);";
3313 if (stage == 0)
3314 { // VS
3315 os << NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
3316 }
3317 else if (stage == 4)
3318 { // CS
3319 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
3320 }
3321 os << NL " ivec4 o_color = ivec4(0, 1, 0, 1);";
3322
3323 switch (target)
3324 {
3325 case T2D:
3326 os << NL " ivec4 i = ivec4(1, 0, 0, 2);" NL " imageAtomicExchange(g_image_2d, coord, t(0).x);" NL
3327 " if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color = i;" NL
3328 " if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color = i;" NL
3329 " if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color = i;" NL
3330 " if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color = i;" NL
3331 " if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color = i;" NL
3332 " if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color = i;" NL
3333 " if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color = i;" NL
3334 " if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3335 " if (imageAtomicExchange(g_image_2d, coord, t(0).x) != t(6).x) o_color = i;";
3336 break;
3337 case T3D:
3338 os << NL " ivec4 i = ivec4(1, 0, 0, 3);" NL
3339 " imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x);" NL
3340 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL
3341 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3342 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), t(4).x) != t(2).x) o_color = i;" NL
3343 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3344 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3345 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL
3346 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3347 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3348 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3349 break;
3350 case TCM:
3351 os << NL
3352 " ivec4 i = ivec4(1, 0, 0, 6);" NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x);" NL
3353 " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), t(g_value[2]).x) != t(0).x) o_color = i;" NL
3354 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3355 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL
3356 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3357 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3358 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL
3359 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3360 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), t(1).x, t(6).x) != t(1).x) o_color "
3361 "= i;" NL " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3362 break;
3363 case T2DA:
3364 os << NL
3365 " ivec4 i = ivec4(1, 0, 0, 23);" NL
3366 " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x);" NL
3367 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL
3368 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3369 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL
3370 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3371 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3372 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), t(g_value[4]).x) != t(7).x) o_color = i;" NL
3373 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3374 " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3375 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3376 break;
3377 }
3378 os << NL " r.o_color[coord.x] = o_color;" NL "}";
3379 return os.str();
3380 }
3381
3382 protected:
RunStage(int stage)3383 long RunStage(int stage)
3384 {
3385 if (!IsImageAtomicSupported())
3386 return NOT_SUPPORTED;
3387 if (!Atomic<GLint>(T2D, stage, GL_R32I))
3388 return ERROR;
3389 if (!Atomic<GLuint>(T2D, stage, GL_R32UI))
3390 return ERROR;
3391 if (!Atomic<GLint>(T3D, stage, GL_R32I))
3392 return ERROR;
3393 if (!Atomic<GLuint>(T3D, stage, GL_R32UI))
3394 return ERROR;
3395 if (!Atomic<GLint>(TCM, stage, GL_R32I))
3396 return ERROR;
3397 if (!Atomic<GLuint>(TCM, stage, GL_R32UI))
3398 return ERROR;
3399 if (!Atomic<GLint>(T2DA, stage, GL_R32I))
3400 return ERROR;
3401 if (!Atomic<GLuint>(T2DA, stage, GL_R32UI))
3402 return ERROR;
3403 return NO_ERROR;
3404 }
3405 };
3406
3407 //-----------------------------------------------------------------------------
3408 // 1.3.4 BasicAllTargetsLoadStoreVS
3409 //-----------------------------------------------------------------------------
3410 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
3411 {
Run()3412 virtual long Run()
3413 {
3414 if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1))
3415 return NOT_SUPPORTED;
3416 return RunStage(0);
3417 }
3418 };
3419
3420 //-----------------------------------------------------------------------------
3421 // 1.3.8 BasicAllTargetsLoadStoreCS
3422 //-----------------------------------------------------------------------------
3423 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
3424 {
Run()3425 virtual long Run()
3426 {
3427 return RunStage(4);
3428 }
3429 };
3430
3431 //-----------------------------------------------------------------------------
3432 // 1.3.9 BasicAllTargetsAtomicVS
3433 //-----------------------------------------------------------------------------
3434 class BasicAllTargetsAtomicVS : public AtomicMachine
3435 {
Run()3436 virtual long Run()
3437 {
3438 if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1))
3439 return NOT_SUPPORTED;
3440 return RunStage(0);
3441 }
3442 };
3443
3444 //-----------------------------------------------------------------------------
3445 // 1.3.13 BasicAllTargetsAtomicCS
3446 //-----------------------------------------------------------------------------
3447 class BasicAllTargetsAtomicCS : public AtomicMachine
3448 {
Run()3449 virtual long Run()
3450 {
3451 return RunStage(4);
3452 }
3453 };
3454
3455 //-----------------------------------------------------------------------------
3456 // 1.4.1 BasicGLSLMisc
3457 //-----------------------------------------------------------------------------
3458 class BasicGLSLMiscFS : public ShaderImageLoadStoreBase
3459 {
3460 GLuint m_texture;
3461 GLuint m_program;
3462 GLuint m_vao, m_vbo;
3463 GLuint m_buffer;
3464
Setup()3465 virtual long Setup()
3466 {
3467 m_texture = 0;
3468 m_program = 0;
3469 m_vao = m_vbo = 0;
3470 m_buffer = 0;
3471 return NO_ERROR;
3472 }
3473
Run()3474 virtual long Run()
3475 {
3476 if (!IsVSFSAvailable(0, 2) || !IsSSBInVSFSAvailable(1))
3477 return NOT_SUPPORTED;
3478
3479 const int kSize = 32;
3480 std::vector<float> data(kSize * kSize * 4);
3481
3482 glGenTextures(1, &m_texture);
3483 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
3484 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3485 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3486 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4);
3487 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]);
3488 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3489
3490 const char *src_vs =
3491 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
3492
3493 const char *src_fs =
3494 NL "#define KSIZE 32" NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
3495 "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL
3496 "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
3497 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image_layer0, coord, vec4(1.0));" NL
3498 " memoryBarrier();" NL " imageStore(g_image_layer1, coord, vec4(2.0));" NL " memoryBarrier();" NL
3499 " imageStore(g_image_layer0, coord, vec4(3.0));" NL " memoryBarrier();" NL
3500 " int coordIndex = coord.x + KSIZE * coord.y;" NL
3501 " o_color[coordIndex] = ivec4(imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord));" NL
3502 "}";
3503 m_program = BuildProgram(src_vs, src_fs);
3504
3505 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3506
3507 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
3508 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
3509
3510 glClear(GL_COLOR_BUFFER_BIT);
3511 glViewport(0, 0, kSize, kSize);
3512
3513 std::vector<ivec4> o_data(kSize * kSize);
3514 glGenBuffers(1, &m_buffer);
3515 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3516 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
3517
3518 glUseProgram(m_program);
3519 glBindVertexArray(m_vao);
3520 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3521 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3522
3523 bool status = true;
3524
3525 ivec4 *out_data =
3526 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3527 for (int i = 0; i < kSize * kSize; ++i)
3528 {
3529 if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0))
3530 {
3531 status = false;
3532 m_context.getTestContext().getLog()
3533 << tcu::TestLog::Message << "[" << i
3534 << "] Check failed. Received: " << ToString(out_data[i]).c_str()
3535 << " instead of: " << ToString(ivec4(5, 0, 0, 2)).c_str() << tcu::TestLog::EndMessage;
3536 }
3537 }
3538
3539 if (status)
3540 return NO_ERROR;
3541 else
3542 return ERROR;
3543 }
3544
Cleanup()3545 virtual long Cleanup()
3546 {
3547 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3548 glDeleteTextures(1, &m_texture);
3549 glDeleteVertexArrays(1, &m_vao);
3550 glDeleteBuffers(1, &m_vbo);
3551 glDeleteBuffers(1, &m_buffer);
3552 glUseProgram(0);
3553 glDeleteProgram(m_program);
3554 return NO_ERROR;
3555 }
3556 };
3557
3558 class BasicGLSLMiscCS : public ShaderImageLoadStoreBase
3559 {
3560 GLuint m_texture;
3561 GLuint m_program;
3562 GLuint m_buffer;
3563
Setup()3564 virtual long Setup()
3565 {
3566 m_texture = 0;
3567 m_program = 0;
3568 m_buffer = 0;
3569 return NO_ERROR;
3570 }
3571
Run()3572 virtual long Run()
3573 {
3574 const int kSize = 10;
3575 std::vector<float> data(kSize * kSize * 4);
3576
3577 glGenTextures(1, &m_texture);
3578 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
3579 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3580 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3581 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4);
3582 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]);
3583 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3584
3585 const char *src_cs =
3586 NL "#define KSIZE 10" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
3587 "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
3588 "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL
3589 "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
3590 " ivec2 coord = ivec2(gl_LocalInvocationID.xy);" NL " imageStore(g_image_layer0, coord, vec4(1.0));" NL
3591 " memoryBarrier();" NL " imageStore(g_image_layer1, coord, vec4(2.0));" NL " memoryBarrier();" NL
3592 " imageStore(g_image_layer0, coord, vec4(3.0));" NL " memoryBarrier();" NL
3593 " o_color[gl_LocalInvocationIndex] = ivec4(imageLoad(g_image_layer0, coord) + "
3594 "imageLoad(g_image_layer1, coord));" NL "}";
3595 m_program = CreateComputeProgram(src_cs);
3596
3597 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
3598 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
3599
3600 std::vector<ivec4> o_data(kSize * kSize);
3601 glGenBuffers(1, &m_buffer);
3602 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3603 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
3604
3605 glUseProgram(m_program);
3606 glDispatchCompute(1, 1, 1);
3607 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3608
3609 bool status = true;
3610
3611 ivec4 *out_data =
3612 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3613 for (int i = 0; i < kSize * kSize; ++i)
3614 {
3615 if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0))
3616 {
3617 status = false;
3618 m_context.getTestContext().getLog()
3619 << tcu::TestLog::Message << "[" << i
3620 << "] Check failed. Received: " << ToString(out_data[i]).c_str()
3621 << " instead of: " << ToString(ivec4(5, 0, 0, 2)).c_str() << tcu::TestLog::EndMessage;
3622 }
3623 }
3624
3625 if (status)
3626 return NO_ERROR;
3627 else
3628 return ERROR;
3629 }
3630
Cleanup()3631 virtual long Cleanup()
3632 {
3633 glDeleteTextures(1, &m_texture);
3634 glUseProgram(0);
3635 glDeleteProgram(m_program);
3636 glDeleteBuffers(1, &m_buffer);
3637 return NO_ERROR;
3638 }
3639 };
3640
3641 //-----------------------------------------------------------------------------
3642 // 1.4.2 BasicGLSLEarlyFragTests
3643 //-----------------------------------------------------------------------------
3644 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
3645 {
3646 GLuint m_texture[2];
3647 GLuint m_program[2];
3648 GLuint m_vao, m_vbo;
3649 GLuint c_program;
3650 GLuint m_buffer;
3651
Setup()3652 virtual long Setup()
3653 {
3654 m_texture[0] = m_texture[1] = 0;
3655 m_program[0] = m_program[1] = 0;
3656 m_vao = m_vbo = 0;
3657 m_buffer = 0;
3658 c_program = 0;
3659 return NO_ERROR;
3660 }
3661
Run()3662 virtual long Run()
3663 {
3664 if (!IsVSFSAvailable(0, 1))
3665 return NOT_SUPPORTED;
3666
3667 const int kSize = 8;
3668 std::vector<vec4> data(kSize * kSize);
3669
3670 glGenTextures(2, m_texture);
3671 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
3672 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3673 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3674 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
3675 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
3676 glBindTexture(GL_TEXTURE_2D, 0);
3677
3678 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
3679 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3680 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3681 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
3682 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
3683 glBindTexture(GL_TEXTURE_2D, 0);
3684
3685 const char *glsl_vs =
3686 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
3687 const char *glsl_early_frag_tests_fs =
3688 NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
3689 "layout(rgba32f, binding = 0) writeonly coherent uniform image2D g_image;" NL "void main() {" NL
3690 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(17.0));" NL
3691 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3692 const char *glsl_fs =
3693 NL "layout(location = 0) out vec4 o_color;" NL
3694 "layout(rgba32f, binding = 1) writeonly coherent uniform image2D g_image;" NL "void main() {" NL
3695 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(13.0));" NL
3696 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3697 m_program[0] = BuildProgram(glsl_vs, glsl_early_frag_tests_fs);
3698 m_program[1] = BuildProgram(glsl_vs, glsl_fs);
3699
3700 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3701
3702 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3703 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3704
3705 glViewport(0, 0, kSize, kSize);
3706 glBindVertexArray(m_vao);
3707
3708 glEnable(GL_DEPTH_TEST);
3709 glClearColor(0.0, 1.0f, 0.0, 1.0f);
3710 glClearDepthf(0.0f);
3711
3712 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3713 glUseProgram(m_program[0]);
3714
3715 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3716
3717 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3718 glUseProgram(m_program[1]);
3719 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3720
3721 const char *check_cs =
3722 NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
3723 "uniform sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL
3724 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
3725 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL "}";
3726
3727 c_program = CreateComputeProgram(check_cs);
3728 std::vector<vec4> out_data(kSize * kSize);
3729 glGenBuffers(1, &m_buffer);
3730 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3731 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
3732
3733 glActiveTexture(GL_TEXTURE5);
3734 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
3735 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3736
3737 glUseProgram(c_program);
3738 glUniform1i(glGetUniformLocation(c_program, "g_sampler"), 5);
3739 glDispatchCompute(1, 1, 1);
3740 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3741 vec4 *map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3742
3743 float expectedVal = 0.0f;
3744 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
3745 if (renderTarget.getDepthBits() == 0)
3746 {
3747 expectedVal = 17.0f;
3748 }
3749
3750 if (!CompareValues(map_data, kSize, vec4(expectedVal)))
3751 return ERROR;
3752 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3753
3754 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
3755 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3756
3757 glDispatchCompute(1, 1, 1);
3758 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3759 map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3760
3761 if (!CompareValues(map_data, kSize, vec4(13.0f)))
3762 return ERROR;
3763
3764 return NO_ERROR;
3765 }
3766
Cleanup()3767 virtual long Cleanup()
3768 {
3769 glDisable(GL_DEPTH_TEST);
3770 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3771 glClearDepthf(1.0f);
3772 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3773 glDeleteTextures(2, m_texture);
3774 glDeleteVertexArrays(1, &m_vao);
3775 glDeleteBuffers(1, &m_vbo);
3776 glUseProgram(0);
3777 glDeleteProgram(m_program[0]);
3778 glDeleteProgram(m_program[1]);
3779 glDeleteProgram(c_program);
3780 glDeleteBuffers(1, &m_buffer);
3781 glActiveTexture(GL_TEXTURE0);
3782 return NO_ERROR;
3783 }
3784 };
3785
3786 //-----------------------------------------------------------------------------
3787 // 1.4.3 BasicGLSLConst
3788 //-----------------------------------------------------------------------------
3789 class BasicGLSLConst : public ShaderImageLoadStoreBase
3790 {
3791 GLuint m_program;
3792 GLuint m_buffer;
3793
Setup()3794 virtual long Setup()
3795 {
3796 m_program = 0;
3797 m_buffer = 0;
3798 return NO_ERROR;
3799 }
3800
Run()3801 virtual long Run()
3802 {
3803 const char *src_cs =
3804 NL "layout (local_size_x = 1) in;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color;" NL "};" NL
3805 "uniform int MaxImageUnits;" NL "uniform int MaxCombinedShaderOutputResources;" NL
3806 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxFragmentImageUniforms;" NL
3807 "uniform int MaxComputeImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL "void main() {" NL
3808 " o_color = ivec4(0, 1, 0, 1);" NL
3809 " if (gl_MaxImageUnits != MaxImageUnits) o_color = ivec4(1, 0, 0, 1);" NL
3810 " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = ivec4(1, 0, "
3811 "0, 2);" NL " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = ivec4(1, 0, 0, 4);" NL
3812 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = ivec4(1, 0, 0, 5);" NL
3813 " if (gl_MaxComputeImageUniforms != MaxComputeImageUniforms) o_color = ivec4(1, 0, 0, 6);" NL
3814 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = ivec4(1, 0, 0, 9);" NL "}";
3815 m_program = CreateComputeProgram(src_cs);
3816 glUseProgram(m_program);
3817
3818 GLint i;
3819 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
3820 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
3821
3822 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
3823 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
3824
3825 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
3826 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
3827
3828 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
3829 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
3830
3831 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &i);
3832 glUniform1i(glGetUniformLocation(m_program, "MaxComputeImageUniforms"), i);
3833
3834 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
3835 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
3836
3837 std::vector<ivec4> out_data(1);
3838 glGenBuffers(1, &m_buffer);
3839 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3840 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4, &out_data[0], GL_STATIC_DRAW);
3841
3842 glDispatchCompute(1, 1, 1);
3843
3844 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3845 ivec4 *map_data = (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4, GL_MAP_READ_BIT);
3846
3847 if (!Equal(map_data[0], ivec4(0, 1, 0, 1), 0))
3848 {
3849 m_context.getTestContext().getLog()
3850 << tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[0]).c_str()
3851 << ". Value should be: " << ToString(ivec4(0, 1, 0, 1)).c_str() << tcu::TestLog::EndMessage;
3852 return ERROR;
3853 }
3854 return NO_ERROR;
3855 }
3856
Cleanup()3857 virtual long Cleanup()
3858 {
3859 glUseProgram(0);
3860 glDeleteProgram(m_program);
3861 glDeleteBuffers(1, &m_buffer);
3862 return NO_ERROR;
3863 }
3864 };
3865
3866 //-----------------------------------------------------------------------------
3867 // 2.1.1 AdvancedSyncImageAccess
3868 //-----------------------------------------------------------------------------
3869 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
3870 {
3871 GLuint m_buffer;
3872 GLuint m_texture;
3873 GLuint m_store_program;
3874 GLuint m_draw_program;
3875 GLuint m_attribless_vao;
3876
Setup()3877 virtual long Setup()
3878 {
3879 m_buffer = 0;
3880 m_texture = 0;
3881 m_store_program = 0;
3882 m_draw_program = 0;
3883 m_attribless_vao = 0;
3884 return NO_ERROR;
3885 }
3886
Run()3887 virtual long Run()
3888 {
3889 if (!IsVSFSAvailable(1, 0) || !IsSSBInVSFSAvailable(1))
3890 return NOT_SUPPORTED;
3891
3892 const int kSize = 44;
3893 const char *const glsl_store_vs =
3894 NL "layout(rgba32f) writeonly uniform image2D g_output_data;" NL "void main() {" NL
3895 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
3896 " imageStore(g_output_data, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL
3897 " gl_PointSize = 1.0;" NL "}";
3898 const char *const glsl_store_fs = NL "void main() {" NL " discard;" NL "}";
3899 const char *const glsl_draw_vs =
3900 NL "out vec4 vs_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL
3901 "uniform sampler2D g_sampler;" NL "void main() {" NL
3902 " vec4 pi = imageLoad(g_image, ivec2(gl_VertexID, 0));" NL
3903 " vec4 ps = texelFetch(g_sampler, ivec2(gl_VertexID, 0), 0);" NL
3904 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3905 " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " gl_Position = pi;" NL "}";
3906 const char *const glsl_draw_fs =
3907 NL "#define KSIZE 44" NL "in vec4 vs_color;" NL "layout(std430) buffer OutputBuffer {" NL
3908 " vec4 o_color[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3909 " int coordIndex = coord.x + KSIZE * coord.y;" NL " o_color[coordIndex] = vs_color;" NL "}";
3910 m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs);
3911 m_draw_program = BuildProgram(glsl_draw_vs, glsl_draw_fs);
3912
3913 glGenVertexArrays(1, &m_attribless_vao);
3914 glBindVertexArray(m_attribless_vao);
3915
3916 glGenTextures(1, &m_texture);
3917 glBindTexture(GL_TEXTURE_2D, m_texture);
3918 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3919 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3920 std::vector<ivec4> data(4);
3921 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
3922 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT, &data[0]);
3923
3924 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3925
3926 glUseProgram(m_store_program);
3927 glDrawArrays(GL_POINTS, 0, 4);
3928
3929 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
3930
3931 glViewport(0, 0, kSize, kSize);
3932 glClear(GL_COLOR_BUFFER_BIT);
3933 glUseProgram(m_draw_program);
3934
3935 std::vector<vec4> out_data(kSize * kSize);
3936 glGenBuffers(1, &m_buffer);
3937 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3938 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
3939
3940 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3941 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3942 vec4 *map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3943
3944 if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1)))
3945 return ERROR;
3946
3947 return NO_ERROR;
3948 }
3949
Cleanup()3950 virtual long Cleanup()
3951 {
3952 glUseProgram(0);
3953 glDeleteBuffers(1, &m_buffer);
3954 glDeleteTextures(1, &m_texture);
3955 glDeleteProgram(m_store_program);
3956 glDeleteProgram(m_draw_program);
3957 glDeleteVertexArrays(1, &m_attribless_vao);
3958 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3959 return NO_ERROR;
3960 }
3961 };
3962
3963 //-----------------------------------------------------------------------------
3964 // 2.1.2 AdvancedSyncVertexArray
3965 //-----------------------------------------------------------------------------
3966 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
3967 {
3968 GLuint m_position_buffer;
3969 GLuint m_color_buffer;
3970 GLuint m_element_buffer;
3971 GLuint m_texture[3];
3972 GLuint m_store_program;
3973 GLuint m_copy_program;
3974 GLuint m_draw_program;
3975 GLuint m_attribless_vao;
3976 GLuint m_draw_vao;
3977
Setup()3978 virtual long Setup()
3979 {
3980 m_position_buffer = 0;
3981 m_color_buffer = 0;
3982 m_element_buffer = 0;
3983 m_store_program = 0;
3984 m_draw_program = 0;
3985 m_copy_program = 0;
3986 m_attribless_vao = 0;
3987 m_draw_vao = 0;
3988 return NO_ERROR;
3989 }
3990
Run()3991 virtual long Run()
3992 {
3993 if (!IsVSFSAvailable(3, 0))
3994 return NOT_SUPPORTED;
3995 const char *const glsl_store_vs =
3996 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_position_buffer;" NL
3997 "layout(rgba32f, binding = 1) writeonly uniform image2D g_color_buffer;" NL
3998 "layout(r32ui, binding = 2) writeonly uniform uimage2D g_element_buffer;" NL "uniform vec4 g_color;" NL
3999 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
4000 " imageStore(g_position_buffer, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL
4001 " imageStore(g_color_buffer, ivec2(gl_VertexID,0), g_color);" NL
4002 " imageStore(g_element_buffer, ivec2(gl_VertexID,0), uvec4(gl_VertexID));" NL "}";
4003 const char *const glsl_store_fs = NL "void main() {" NL " discard;" NL "}";
4004 const char *glsl_copy_cs =
4005 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL
4006 "layout(rgba32f, binding = 0) readonly uniform image2D g_position_img;" NL
4007 "layout(rgba32f, binding = 1) readonly uniform image2D g_color_img;" NL
4008 "layout(r32ui, binding = 2) readonly uniform uimage2D g_element_img;" NL
4009 "layout(std430, binding = 1) buffer g_position_buf {" NL " vec2 g_pos[KSIZE];" NL "};" NL
4010 "layout(std430, binding = 2) buffer g_color_buf {" NL " vec4 g_col[KSIZE];" NL "};" NL
4011 "layout(std430, binding = 3) buffer g_element_buf {" NL " uint g_elem[KSIZE];" NL "};" NL
4012 "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID.x, 0);" NL
4013 " g_pos[coord.x] = (imageLoad(g_position_img, coord)).xy;" NL
4014 " g_col[coord.x] = imageLoad(g_color_img, coord);" NL
4015 " g_elem[coord.x] = uint((imageLoad(g_element_img, coord)).x);" NL "}";
4016 const char *const glsl_draw_vs = NL
4017 "layout(location = 0) in vec4 i_position;" NL "layout(location = 1) in vec4 i_color;" NL
4018 "out vec4 vs_color;" NL "void main() {" NL " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
4019 const char *const glsl_draw_fs = NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
4020 "void main() {" NL " o_color = vs_color;" NL "}";
4021 m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs);
4022 m_copy_program = CreateComputeProgram(glsl_copy_cs);
4023 m_draw_program = BuildProgram(glsl_draw_vs, glsl_draw_fs);
4024
4025 glGenTextures(3, m_texture);
4026 std::vector<ivec4> data(4);
4027 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4028 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
4029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4031 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4032 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
4033 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4035 glBindTexture(GL_TEXTURE_2D, m_texture[2]);
4036 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 1);
4037 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4038 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4039
4040 glGenVertexArrays(1, &m_attribless_vao);
4041 glGenVertexArrays(1, &m_draw_vao);
4042 glBindVertexArray(m_draw_vao);
4043 glGenBuffers(1, &m_position_buffer);
4044 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
4045 glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4046 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
4047 glGenBuffers(1, &m_color_buffer);
4048 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
4049 glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4050 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
4051 glBindBuffer(GL_ARRAY_BUFFER, 0);
4052 glEnableVertexAttribArray(0);
4053 glEnableVertexAttribArray(1);
4054 glGenBuffers(1, &m_element_buffer);
4055 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
4056 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4057 glBindVertexArray(0);
4058
4059 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4060 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4061 glBindImageTexture(2, m_texture[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4062 glUseProgram(m_store_program);
4063 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
4064 glBindVertexArray(m_attribless_vao);
4065 glDrawArrays(GL_POINTS, 0, 4);
4066
4067 glUseProgram(m_copy_program);
4068 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_position_buffer);
4069 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_color_buffer);
4070 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_element_buffer);
4071 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4072 glDispatchCompute(1, 1, 1);
4073
4074 glClear(GL_COLOR_BUFFER_BIT);
4075 glUseProgram(m_draw_program);
4076 glBindVertexArray(m_draw_vao);
4077 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
4078 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
4079
4080 if (!CheckFB(vec4(0, 1, 0, 1)))
4081 {
4082 return ERROR;
4083 }
4084
4085 glUseProgram(m_store_program);
4086 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
4087 glBindVertexArray(m_attribless_vao);
4088 glDrawArrays(GL_POINTS, 0, 4);
4089 glUseProgram(m_copy_program);
4090 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4091 glDispatchCompute(1, 1, 1);
4092 glClear(GL_COLOR_BUFFER_BIT);
4093 glUseProgram(m_draw_program);
4094 glBindVertexArray(m_draw_vao);
4095 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
4096 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
4097
4098 if (!CheckFB(vec4(0, 0, 1, 1)))
4099 {
4100 return ERROR;
4101 }
4102 return NO_ERROR;
4103 }
4104
Cleanup()4105 virtual long Cleanup()
4106 {
4107 glDisable(GL_RASTERIZER_DISCARD);
4108 glUseProgram(0);
4109 glDeleteTextures(3, m_texture);
4110 glDeleteBuffers(1, &m_position_buffer);
4111 glDeleteBuffers(1, &m_color_buffer);
4112 glDeleteBuffers(1, &m_element_buffer);
4113 glDeleteProgram(m_store_program);
4114 glDeleteProgram(m_copy_program);
4115 glDeleteProgram(m_draw_program);
4116 glDeleteVertexArrays(1, &m_attribless_vao);
4117 glDeleteVertexArrays(1, &m_draw_vao);
4118 return NO_ERROR;
4119 }
4120 };
4121
4122 //-----------------------------------------------------------------------------
4123 // 2.1.6 AdvancedSyncImageAccess2
4124 //-----------------------------------------------------------------------------
4125 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
4126 {
4127 GLuint m_texture;
4128 GLuint m_store_program;
4129 GLuint m_draw_program;
4130 GLuint m_vao;
4131 GLuint m_vbo;
4132 GLuint m_buffer;
4133
Setup()4134 virtual long Setup()
4135 {
4136 m_texture = 0;
4137 m_store_program = 0;
4138 m_draw_program = 0;
4139 m_vao = 0;
4140 m_vbo = 0;
4141 m_buffer = 0;
4142 return NO_ERROR;
4143 }
4144
Run()4145 virtual long Run()
4146 {
4147 const int kSize = 32;
4148 if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1))
4149 return NOT_SUPPORTED;
4150 const char *const glsl_vs =
4151 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
4152 const char *const glsl_store_fs =
4153 NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
4154 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
4155 const char *const glsl_draw_fs =
4156 NL "layout(location = 0) out vec4 o_color;" NL "uniform sampler2D g_sampler;" NL
4157 "layout(std430) buffer OutputBuffer {" NL " uvec4 counter;" NL " vec4 data[];" NL "};" NL
4158 "void main() {" NL " uint idx = atomicAdd(counter[0], 1u);" NL
4159 " data[idx] = texelFetch(g_sampler, ivec2(gl_FragCoord.xy), 0);" NL "}";
4160 m_store_program = BuildProgram(glsl_vs, glsl_store_fs);
4161 m_draw_program = BuildProgram(glsl_vs, glsl_draw_fs);
4162
4163 glGenTextures(1, &m_texture);
4164 glBindTexture(GL_TEXTURE_2D, m_texture);
4165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4167 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight());
4168 glBindTexture(GL_TEXTURE_2D, 0);
4169
4170 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4171
4172 glViewport(0, 0, kSize, kSize);
4173 std::vector<vec4> data_b(kSize * kSize + 1);
4174 glGenBuffers(1, &m_buffer);
4175 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4176 glBufferData(GL_SHADER_STORAGE_BUFFER, (kSize * kSize + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4177
4178 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4179 glUseProgram(m_store_program);
4180 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
4181 glBindVertexArray(m_vao);
4182 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4183
4184 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4185
4186 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
4187 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4188
4189 glBindTexture(GL_TEXTURE_2D, m_texture);
4190 glUseProgram(m_draw_program);
4191 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
4192 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4193
4194 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4195 vec4 *map_data =
4196 (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4197
4198 if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1)))
4199 return ERROR;
4200 return NO_ERROR;
4201 }
4202
Cleanup()4203 virtual long Cleanup()
4204 {
4205 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4206 glUseProgram(0);
4207 glDeleteBuffers(1, &m_vbo);
4208 glDeleteTextures(1, &m_texture);
4209 glDeleteProgram(m_store_program);
4210 glDeleteProgram(m_draw_program);
4211 glDeleteVertexArrays(1, &m_vao);
4212 glDeleteBuffers(1, &m_buffer);
4213 return NO_ERROR;
4214 }
4215 };
4216
4217 //-----------------------------------------------------------------------------
4218 // 2.2.1 AdvancedAllStagesOneImage
4219 //-----------------------------------------------------------------------------
4220 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
4221 {
4222 GLuint m_program;
4223 GLuint c_program;
4224 GLuint m_vao;
4225 GLuint m_vbo;
4226 GLuint m_buffer;
4227 GLuint m_texture;
4228
Setup()4229 virtual long Setup()
4230 {
4231 m_program = 0;
4232 c_program = 0;
4233 m_vao = 0;
4234 m_vbo = 0;
4235 m_buffer = 0;
4236 m_texture = 0;
4237 return NO_ERROR;
4238 }
4239
Run()4240 virtual long Run()
4241 {
4242 const int kSize = 64;
4243 if (!IsVSFSAvailable(1, 1) || !IsImageAtomicSupported())
4244 return NOT_SUPPORTED;
4245 const char *const glsl_vs =
4246 NL "layout(location = 0) in vec4 i_position;" NL
4247 "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL "void main() {" NL
4248 " gl_Position = i_position;" NL " imageAtomicAdd(g_image, ivec2(0, gl_VertexID), 100u);" NL "}";
4249 const char *const glsl_fs =
4250 NL "#define KSIZE 64" NL "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL
4251 "void main() {" NL " imageAtomicAdd(g_image, ivec2(0, int(gl_FragCoord.x) & 0x03), 0x1u);" NL "}";
4252 m_program = BuildProgram(glsl_vs, glsl_fs, true, true);
4253 const char *const glsl_cs =
4254 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL
4255 "layout(r32ui, binding = 3) uniform uimage2D g_image;" NL "layout(std430) buffer out_data {" NL
4256 " uvec4 data[KSIZE];" NL "};" NL "void main() {" NL
4257 " uvec4 v = imageLoad(g_image, ivec2(0, gl_LocalInvocationID.x));" NL
4258 " data[gl_LocalInvocationIndex] = v;" NL "}";
4259 c_program = CreateComputeProgram(glsl_cs, true);
4260 glUseProgram(m_program);
4261
4262 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4263
4264 std::vector<uvec4> ui32(16);
4265 glGenTextures(1, &m_texture);
4266 glBindTexture(GL_TEXTURE_2D, m_texture);
4267 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 4);
4268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4270 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32[0]);
4271 glBindTexture(GL_TEXTURE_2D, 0);
4272
4273 glBindImageTexture(3, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4274
4275 glViewport(0, 0, kSize, kSize);
4276 glBindVertexArray(m_vao);
4277 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4278 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4279
4280 std::vector<vec4> data_b(4);
4281 glGenBuffers(1, &m_buffer);
4282 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4283 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4284 glUseProgram(c_program);
4285 glDispatchCompute(1, 1, 1);
4286
4287 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4288 uvec4 *map_data = (uvec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
4289
4290 if (!CompareValues(map_data, 2, uvec4(1024 + 100, 0, 0, 1)))
4291 return ERROR;
4292 return NO_ERROR;
4293 }
4294
Cleanup()4295 virtual long Cleanup()
4296 {
4297 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4298 glUseProgram(0);
4299 glDeleteBuffers(1, &m_buffer);
4300 glDeleteBuffers(1, &m_vbo);
4301 glDeleteTextures(1, &m_texture);
4302 glDeleteProgram(m_program);
4303 glDeleteProgram(c_program);
4304 glDeleteVertexArrays(1, &m_vao);
4305 return NO_ERROR;
4306 }
4307 };
4308
4309 //-----------------------------------------------------------------------------
4310 // 2.3.2 AdvancedMemoryOrder
4311 //-----------------------------------------------------------------------------
4312 class AdvancedMemoryOrderVSFS : public ShaderImageLoadStoreBase
4313 {
4314 GLuint m_buffer;
4315 GLuint m_texture[2];
4316 GLuint m_program;
4317 GLuint m_vao;
4318 GLuint m_vbo;
4319
Setup()4320 virtual long Setup()
4321 {
4322 m_buffer = 0;
4323 m_program = 0;
4324 m_vao = 0;
4325 m_vbo = 0;
4326 return NO_ERROR;
4327 }
4328
Run()4329 virtual long Run()
4330 {
4331 const int kSize = 11;
4332 if (!IsVSFSAvailable(1, 1) || !IsSSBInVSFSAvailable(1))
4333 return NOT_SUPPORTED;
4334 const char *const glsl_vs = NL
4335 "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
4336 "layout(r32f, binding = 0) uniform image2D g_image_vs;" NL "void main() {" NL
4337 " gl_Position = i_position;" NL " vs_color = vec4(41, 42, 43, 44);" NL
4338 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(1.0));" NL
4339 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(2.0));" NL
4340 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(3.0));" NL
4341 " if (imageLoad(g_image_vs, ivec2(gl_VertexID)) != vec4(3,0,0,1)) vs_color = vec4(21, 22, 23, 24);" NL "}";
4342 const char *const glsl_fs =
4343 NL "#define KSIZE 11" NL "in vec4 vs_color;" NL "layout(r32f, binding = 1) uniform image2D g_image;" NL
4344 "layout(std430) buffer out_data {" NL " vec4 data[KSIZE*KSIZE*4];" NL "};" NL "void main() {" NL
4345 " ivec2 coord = ivec2(gl_FragCoord);" NL " int coordIndex = coord.x + KSIZE * coord.y;" NL
4346 " for (int i = 0; i < 4; ++i) {" NL " data[coordIndex + i * KSIZE*KSIZE] = vs_color;" NL " }" NL
4347 " for (int i = 0; i < 4; ++i) {" NL " imageStore(g_image, coord, vec4(i+50));" NL
4348 " vec4 v = imageLoad(g_image, coord);" NL " if (v.x != float(i+50)) {" NL
4349 " data[coordIndex + i * KSIZE*KSIZE] = vec4(v.xyz, i+10);" NL " break;" NL " }" NL " }" NL
4350 "}";
4351 m_program = BuildProgram(glsl_vs, glsl_fs);
4352 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4353
4354 std::vector<float> data(kSize * kSize);
4355 glGenTextures(2, m_texture);
4356 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4357 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4360 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]);
4361 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4362 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4365 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]);
4366 glBindTexture(GL_TEXTURE_2D, 0);
4367
4368 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4369 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4370
4371 std::vector<vec4> data_b(kSize * kSize * 4);
4372 glGenBuffers(1, &m_buffer);
4373 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4374 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4375
4376 glUseProgram(m_program);
4377 glViewport(0, 0, kSize, kSize);
4378 glBindVertexArray(m_vao);
4379 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4380
4381 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4382 vec4 *map_data =
4383 (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4384
4385 if (!CompareValues(map_data, kSize * 2, vec4(41, 42, 43, 44)))
4386 return ERROR;
4387 return NO_ERROR;
4388 }
4389
Cleanup()4390 virtual long Cleanup()
4391 {
4392 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4393 glUseProgram(0);
4394 glDeleteBuffers(1, &m_vbo);
4395 glDeleteBuffers(1, &m_buffer);
4396 glDeleteTextures(2, m_texture);
4397 glDeleteProgram(m_program);
4398 glDeleteVertexArrays(1, &m_vao);
4399 return NO_ERROR;
4400 }
4401 };
4402
4403 //-----------------------------------------------------------------------------
4404 // 2.4.1 AdvancedSSOSimple
4405 //-----------------------------------------------------------------------------
4406 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
4407 {
4408 bool pipeline;
4409 GLuint m_texture;
4410 GLuint m_pipeline[2];
4411 GLuint m_vsp, m_fsp0, m_fsp1;
4412 GLuint m_vao, m_vbo;
4413 GLuint m_program[2];
4414 GLuint c_program;
4415 GLuint m_buffer;
4416
Setup()4417 virtual long Setup()
4418 {
4419 c_program = 0;
4420 m_buffer = 0;
4421 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4422 glGenTextures(1, &m_texture);
4423 const char *const glsl_vs =
4424 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
4425 const char *const glsl_fs0 =
4426 NL "layout(rgba32f, binding = 2) writeonly uniform image2D g_image[2];" NL "void main() {" NL
4427 " int i = g_image.length();" NL " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+98));" NL
4428 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+99));" NL " discard;" NL "}";
4429 const char *const glsl_fs1 =
4430 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[2];" NL "void main() {" NL
4431 " int i = g_image.length();" NL " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+8));" NL
4432 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+9));" NL " discard;" NL "}";
4433 if (pipeline)
4434 {
4435 glGenProgramPipelines(2, m_pipeline);
4436 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
4437 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
4438 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
4439 }
4440 else
4441 {
4442 m_program[0] = BuildProgram(glsl_vs, glsl_fs0);
4443 m_program[1] = BuildProgram(glsl_vs, glsl_fs1);
4444 }
4445 return NO_ERROR;
4446 }
4447
Run()4448 virtual long Run()
4449 {
4450 if (!IsVSFSAvailable(0, 2))
4451 return NOT_SUPPORTED;
4452 const int kSize = 4;
4453
4454 if (pipeline)
4455 {
4456 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
4457 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
4458 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
4459 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
4460 }
4461 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4462 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4463 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4464 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8);
4465
4466 glBindImageTexture(0, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
4467 glBindImageTexture(1, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
4468 glBindImageTexture(2, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
4469 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
4470
4471 glBindVertexArray(m_vao);
4472 if (pipeline)
4473 glBindProgramPipeline(m_pipeline[0]);
4474 else
4475 glUseProgram(m_program[0]);
4476 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4477
4478 if (pipeline)
4479 glBindProgramPipeline(m_pipeline[1]);
4480 else
4481 glUseProgram(m_program[1]);
4482 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4483
4484 const char *const glsl_cs =
4485 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4486 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL
4487 "layout(std430) buffer OutputBuffer {" NL " uvec4 counter;" NL " vec4 data[];" NL "};" NL
4488 "void main() {" NL " uint idx = atomicAdd(counter[0], 1u);" NL
4489 " data[idx][0] = (imageLoad(g_image[0], ivec2(gl_GlobalInvocationID))).z;" NL
4490 " data[idx][1] = (imageLoad(g_image[1], ivec2(gl_GlobalInvocationID))).z;" NL
4491 " data[idx][2] = (imageLoad(g_image[2], ivec2(gl_GlobalInvocationID))).z;" NL
4492 " data[idx][3] = (imageLoad(g_image[3], ivec2(gl_GlobalInvocationID))).z;" NL "}";
4493 c_program = CreateComputeProgram(glsl_cs);
4494 glUseProgram(c_program);
4495 int wsx = (getWindowWidth() / kSize) * kSize;
4496 int wsy = (getWindowHeight() / kSize) * kSize;
4497 int minor = wsx > wsy ? wsy : wsx;
4498
4499 std::vector<vec4> data_b(wsx * wsy + 1);
4500 glGenBuffers(1, &m_buffer);
4501 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4502 glBufferData(GL_SHADER_STORAGE_BUFFER, (wsx * wsy + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4503
4504 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4505 glDispatchCompute(wsx / kSize, wsy / kSize, 1);
4506 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4507 vec4 *map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, wsx * wsy * 4 * 4, GL_MAP_READ_BIT);
4508
4509 if (!CompareValues(map_data, minor, vec4(10, 11, 100, 101)))
4510 return ERROR;
4511 return NO_ERROR;
4512 }
4513
Cleanup()4514 virtual long Cleanup()
4515 {
4516 glUseProgram(0);
4517 glDeleteBuffers(1, &m_vbo);
4518 glDeleteTextures(1, &m_texture);
4519 if (pipeline)
4520 {
4521 glDeleteProgram(m_vsp);
4522 glDeleteProgram(m_fsp0);
4523 glDeleteProgram(m_fsp1);
4524 glDeleteProgramPipelines(2, m_pipeline);
4525 }
4526 else
4527 {
4528 glDeleteProgram(m_program[0]);
4529 glDeleteProgram(m_program[1]);
4530 }
4531 glDeleteProgram(c_program);
4532 glDeleteVertexArrays(1, &m_vao);
4533 glDeleteBuffers(1, &m_buffer);
4534 return NO_ERROR;
4535 }
4536
4537 public:
AdvancedSSOSimple()4538 AdvancedSSOSimple() : pipeline(true)
4539 {
4540 }
4541 };
4542
4543 //-----------------------------------------------------------------------------
4544 // 2.5 AdvancedCopyImage
4545 //-----------------------------------------------------------------------------
4546 class AdvancedCopyImageFS : public ShaderImageLoadStoreBase
4547 {
4548 GLuint m_texture[2];
4549 GLuint m_program;
4550 GLuint c_program;
4551 GLuint m_vao, m_vbo, m_ebo;
4552 GLuint m_buffer;
4553
Setup()4554 virtual long Setup()
4555 {
4556 glGenTextures(2, m_texture);
4557 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4558 glGenBuffers(1, &m_buffer);
4559
4560 const char *const glsl_vs =
4561 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
4562 const char *const glsl_fs =
4563 NL "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL
4564 "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL
4565 " ivec2 coord = ivec2(gl_FragCoord);" NL
4566 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
4567 m_program = BuildProgram(glsl_vs, glsl_fs);
4568 const char *const glsl_cs = NL
4569 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4570 "layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL
4571 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4572 " data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}";
4573 c_program = CreateComputeProgram(glsl_cs);
4574
4575 return NO_ERROR;
4576 }
4577
Run()4578 virtual long Run()
4579 {
4580 const int kSize = 11;
4581 if (!IsVSFSAvailable(0, 2))
4582 return NOT_SUPPORTED;
4583
4584 std::vector<vec4> data(kSize * kSize, vec4(7.0f));
4585 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4586 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4589 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
4590
4591 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4592 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4593 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4594 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4595
4596 glBindTexture(GL_TEXTURE_2D, 0);
4597
4598 glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4599 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4600 glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4601
4602 std::vector<vec4> data_b(kSize * kSize);
4603 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4604 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4605
4606 glUseProgram(m_program);
4607 glBindVertexArray(m_vao);
4608 glViewport(0, 0, kSize, kSize);
4609 glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
4610 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4611
4612 glUseProgram(c_program);
4613 glDispatchCompute(1, 1, 1);
4614 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4615 vec4 *map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4616
4617 if (!CompareValues(map_data, kSize, vec4(7.f)))
4618 return ERROR;
4619 return NO_ERROR;
4620 }
4621
Cleanup()4622 virtual long Cleanup()
4623 {
4624 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4625 glUseProgram(0);
4626 glDeleteBuffers(1, &m_vbo);
4627 glDeleteBuffers(1, &m_ebo);
4628 glDeleteBuffers(1, &m_buffer);
4629 glDeleteTextures(2, m_texture);
4630 glDeleteProgram(m_program);
4631 glDeleteProgram(c_program);
4632 glDeleteVertexArrays(1, &m_vao);
4633 return NO_ERROR;
4634 }
4635 };
4636
4637 class AdvancedCopyImageCS : public ShaderImageLoadStoreBase
4638 {
4639 GLuint m_texture[2];
4640 GLuint m_program;
4641 GLuint c_program;
4642 GLuint m_buffer;
4643
Setup()4644 virtual long Setup()
4645 {
4646 glGenTextures(2, m_texture);
4647 glGenBuffers(1, &m_buffer);
4648
4649 const char *const glsl_cs =
4650 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4651 "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL
4652 "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL
4653 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4654 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "}";
4655 m_program = CreateComputeProgram(glsl_cs);
4656 const char *const glsl_cs_c = NL
4657 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4658 "layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL
4659 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4660 " data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}";
4661 c_program = CreateComputeProgram(glsl_cs_c);
4662
4663 return NO_ERROR;
4664 }
4665
Run()4666 virtual long Run()
4667 {
4668 const int kSize = 11;
4669
4670 std::vector<vec4> data(kSize * kSize, vec4(7.0f));
4671 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4672 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4673 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4674 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4675 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
4676
4677 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4678 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4679 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4680 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4681
4682 glBindTexture(GL_TEXTURE_2D, 0);
4683
4684 glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4685 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4686 glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4687
4688 std::vector<vec4> data_b(kSize * kSize);
4689 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4690 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4691
4692 glUseProgram(m_program);
4693 glDispatchCompute(1, 1, 1);
4694 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4695
4696 glUseProgram(c_program);
4697 glDispatchCompute(1, 1, 1);
4698 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4699 vec4 *map_data = (vec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4700
4701 if (!CompareValues(map_data, kSize, vec4(7.f)))
4702 return ERROR;
4703 return NO_ERROR;
4704 }
4705
Cleanup()4706 virtual long Cleanup()
4707 {
4708 glUseProgram(0);
4709 glDeleteBuffers(1, &m_buffer);
4710 glDeleteTextures(2, m_texture);
4711 glDeleteProgram(m_program);
4712 glDeleteProgram(c_program);
4713 return NO_ERROR;
4714 }
4715 };
4716
4717 //-----------------------------------------------------------------------------
4718 // 2.6 AdvancedAllMips
4719 //-----------------------------------------------------------------------------
4720 class AdvancedAllMipsFS : public ShaderImageLoadStoreBase
4721 {
4722 GLuint m_texture;
4723 GLuint m_store_program, m_load_program;
4724 GLuint m_vao, m_vbo, m_ebo;
4725 GLuint m_buffer;
4726
Setup()4727 virtual long Setup()
4728 {
4729 glGenTextures(1, &m_texture);
4730 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4731 glGenBuffers(1, &m_buffer);
4732
4733 const char *const glsl_vs =
4734 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
4735 const char *const glsl_store_fs =
4736 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL
4737 " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(23));" NL
4738 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(24));" NL
4739 " imageStore(g_image[2], ivec2(gl_FragCoord), vec4(25));" NL
4740 " imageStore(g_image[3], ivec2(gl_FragCoord), vec4(26));" NL " discard;" NL "}";
4741 const char *const glsl_load_cs = NL
4742 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4743 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL
4744 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4745 " data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL " vec4 c0 = imageLoad(g_image[0], coord);" NL
4746 " vec4 c1 = imageLoad(g_image[1], coord);" NL " vec4 c2 = imageLoad(g_image[2], coord);" NL
4747 " vec4 c3 = imageLoad(g_image[3], coord);" NL
4748 " if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && "
4749 "c0.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][0] = int(c0.x);" NL
4750 " if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && "
4751 "c1.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][1] = int(c1.x);" NL
4752 " if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && "
4753 "c2.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][2] = int(c2.x);" NL
4754 " if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && "
4755 "c3.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}";
4756 m_store_program = BuildProgram(glsl_vs, glsl_store_fs);
4757 m_load_program = CreateComputeProgram(glsl_load_cs);
4758
4759 return NO_ERROR;
4760 }
4761
Run()4762 virtual long Run()
4763 {
4764 const int kSize = 11;
4765 if (!IsVSFSAvailable(0, 4))
4766 return NOT_SUPPORTED;
4767 glBindTexture(GL_TEXTURE_2D, m_texture);
4768 glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128);
4769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4771 glBindTexture(GL_TEXTURE_2D, 0);
4772
4773 glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4774 glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4775 glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4776 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4777
4778 std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4779 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4780 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4781
4782 glViewport(0, 0, kSize, kSize);
4783 glBindVertexArray(m_vao);
4784
4785 glUseProgram(m_store_program);
4786 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
4787
4788 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4789
4790 glUseProgram(m_load_program);
4791 glDispatchCompute(1, 1, 1);
4792 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4793 ivec4 *map_data =
4794 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4795
4796 if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5)))
4797 return ERROR;
4798 return NO_ERROR;
4799 }
4800
Cleanup()4801 virtual long Cleanup()
4802 {
4803 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4804 glUseProgram(0);
4805 glDeleteBuffers(1, &m_vbo);
4806 glDeleteBuffers(1, &m_ebo);
4807 glDeleteTextures(1, &m_texture);
4808 glDeleteProgram(m_store_program);
4809 glDeleteProgram(m_load_program);
4810 glDeleteVertexArrays(1, &m_vao);
4811 glDeleteBuffers(1, &m_buffer);
4812 return NO_ERROR;
4813 }
4814 };
4815
4816 class AdvancedAllMipsCS : public ShaderImageLoadStoreBase
4817 {
4818 GLuint m_texture;
4819 GLuint m_store_program, m_load_program;
4820 GLuint m_buffer;
4821
Setup()4822 virtual long Setup()
4823 {
4824 glGenTextures(1, &m_texture);
4825 glGenBuffers(1, &m_buffer);
4826
4827 const char *const glsl_store_cs =
4828 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4829 "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL
4830 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " imageStore(g_image[0], coord, vec4(23));" NL
4831 " imageStore(g_image[1], coord, vec4(24));" NL " imageStore(g_image[2], coord, vec4(25));" NL
4832 " imageStore(g_image[3], coord, vec4(26));" NL "}";
4833 const char *const glsl_load_cs = NL
4834 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4835 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL
4836 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4837 " data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL " vec4 c0 = imageLoad(g_image[0], coord);" NL
4838 " vec4 c1 = imageLoad(g_image[1], coord);" NL " vec4 c2 = imageLoad(g_image[2], coord);" NL
4839 " vec4 c3 = imageLoad(g_image[3], coord);" NL
4840 " if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && "
4841 "c0.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][0] = int(c0.x);" NL
4842 " if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && "
4843 "c1.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][1] = int(c1.x);" NL
4844 " if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && "
4845 "c2.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][2] = int(c2.x);" NL
4846 " if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && "
4847 "c3.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}";
4848 m_store_program = CreateComputeProgram(glsl_store_cs);
4849 m_load_program = CreateComputeProgram(glsl_load_cs);
4850
4851 return NO_ERROR;
4852 }
4853
Run()4854 virtual long Run()
4855 {
4856 const int kSize = 11;
4857 glBindTexture(GL_TEXTURE_2D, m_texture);
4858 glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128);
4859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4861 glBindTexture(GL_TEXTURE_2D, 0);
4862
4863 glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4864 glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4865 glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4866 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4867
4868 std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4869 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4870 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4871
4872 glUseProgram(m_store_program);
4873 glDispatchCompute(1, 1, 1);
4874 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4875
4876 glUseProgram(m_load_program);
4877 glDispatchCompute(1, 1, 1);
4878 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4879 ivec4 *map_data =
4880 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4881
4882 if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5)))
4883 return ERROR;
4884 return NO_ERROR;
4885 }
4886
Cleanup()4887 virtual long Cleanup()
4888 {
4889 glUseProgram(0);
4890 glDeleteTextures(1, &m_texture);
4891 glDeleteProgram(m_store_program);
4892 glDeleteProgram(m_load_program);
4893 glDeleteBuffers(1, &m_buffer);
4894 return NO_ERROR;
4895 }
4896 };
4897
4898 //-----------------------------------------------------------------------------
4899 // 2.7 AdvancedCast
4900 //-----------------------------------------------------------------------------
4901 class AdvancedCastFS : public ShaderImageLoadStoreBase
4902 {
4903 GLuint m_texture[2];
4904 GLuint m_program;
4905 GLuint c_program;
4906 GLuint m_vao, m_vbo, m_ebo;
4907 GLuint m_buffer;
4908
Setup()4909 virtual long Setup()
4910 {
4911 glGenTextures(2, m_texture);
4912 glGenBuffers(1, &m_buffer);
4913 m_program = 0;
4914 c_program = 0;
4915 return NO_ERROR;
4916 }
4917
Run()4918 virtual long Run()
4919 {
4920 if (!IsVSFSAvailable(0, 2) || !IsImageAtomicSupported())
4921 return NOT_SUPPORTED;
4922 const int kSize = 11;
4923 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4924
4925 const char *const glsl_vs =
4926 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
4927 const char *const glsl_fs =
4928 NL "#define KSIZE 11" NL "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL
4929 "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL
4930 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageAtomicAdd(g_image0, coord, 2);" NL
4931 " imageAtomicAdd(g_image0, coord, -1);" NL " imageAtomicAdd(g_image1, coord, 1u);" NL
4932 " imageAtomicAdd(g_image1, coord, 2u);" NL "}";
4933 m_program = BuildProgram(glsl_vs, glsl_fs, false, true);
4934
4935 const char *const glsl_cs = NL
4936 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4937 "layout(r32i, binding = 0) uniform iimage2D gi_image;" NL
4938 "layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL
4939 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4940 " data[gl_LocalInvocationIndex].yx = imageLoad(gi_image, coord).xy;" NL
4941 " data[gl_LocalInvocationIndex].wz = ivec2(imageLoad(gu_image, coord).xz);" NL "}";
4942 c_program = CreateComputeProgram(glsl_cs);
4943
4944 std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4945 glActiveTexture(GL_TEXTURE11);
4946 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4947 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4948 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
4949 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4951 glActiveTexture(GL_TEXTURE15);
4952 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4953 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4954 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
4955 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4957
4958 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
4959 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4960
4961 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4962 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4963
4964 glUseProgram(m_program);
4965 glBindVertexArray(m_vao);
4966 glViewport(0, 0, kSize, kSize);
4967 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
4968 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4969
4970 glUseProgram(c_program);
4971 glDispatchCompute(1, 1, 1);
4972 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4973 ivec4 *map_data =
4974 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4975
4976 if (!CompareValues(map_data, kSize, ivec4(0, 1, 0, 3)))
4977 return ERROR;
4978 return NO_ERROR;
4979 }
4980
Cleanup()4981 virtual long Cleanup()
4982 {
4983 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4984 glUseProgram(0);
4985 glDeleteBuffers(1, &m_vbo);
4986 glDeleteBuffers(1, &m_ebo);
4987 glDeleteBuffers(1, &m_buffer);
4988 glDeleteTextures(2, m_texture);
4989 glDeleteProgram(m_program);
4990 glDeleteProgram(c_program);
4991 glDeleteVertexArrays(1, &m_vao);
4992 glActiveTexture(GL_TEXTURE0);
4993 return NO_ERROR;
4994 }
4995 };
4996
4997 class AdvancedCastCS : public ShaderImageLoadStoreBase
4998 {
4999 GLuint m_texture[2];
5000 GLuint m_program;
5001 GLuint c_program;
5002 GLuint m_buffer;
5003
Setup()5004 virtual long Setup()
5005 {
5006 glGenTextures(2, m_texture);
5007 glGenBuffers(1, &m_buffer);
5008 m_program = 0;
5009 c_program = 0;
5010 return NO_ERROR;
5011 }
5012
Run()5013 virtual long Run()
5014 {
5015 const int kSize = 11;
5016 if (!IsImageAtomicSupported())
5017 return NO_ERROR;
5018
5019 const char *const glsl_cs =
5020 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
5021 "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL
5022 "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL
5023 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " imageAtomicAdd(g_image0, coord, 222);" NL
5024 " imageAtomicAdd(g_image0, coord, -11);" NL " imageAtomicAdd(g_image1, coord, 1u);" NL
5025 " imageAtomicAdd(g_image1, coord, 2u);" NL "}";
5026 m_program = CreateComputeProgram(glsl_cs, true);
5027
5028 const char *const glsl_cs_c = NL
5029 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
5030 "layout(r32i, binding = 0) uniform iimage2D gi_image;" NL
5031 "layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL
5032 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL
5033 " data[gl_LocalInvocationIndex].yz = imageLoad(gi_image, coord).xw;" NL
5034 " data[gl_LocalInvocationIndex].wx = ivec2(imageLoad(gu_image, coord).xy);" NL "}";
5035 c_program = CreateComputeProgram(glsl_cs_c);
5036
5037 std::vector<GLubyte> data(kSize * kSize * 4 * 4);
5038 glActiveTexture(GL_TEXTURE11);
5039 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
5040 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5041 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
5042 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5044 glActiveTexture(GL_TEXTURE15);
5045 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
5046 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5047 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
5048 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5049 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5050
5051 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5052 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5053
5054 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
5055 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
5056
5057 glUseProgram(m_program);
5058 glDispatchCompute(1, 1, 1);
5059 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5060
5061 glUseProgram(c_program);
5062 glDispatchCompute(1, 1, 1);
5063 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5064 ivec4 *map_data =
5065 (ivec4 *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
5066
5067 if (!CompareValues(map_data, kSize, ivec4(0, 211, 1, 3)))
5068 return ERROR;
5069 return NO_ERROR;
5070 }
5071
Cleanup()5072 virtual long Cleanup()
5073 {
5074 glUseProgram(0);
5075 glDeleteBuffers(1, &m_buffer);
5076 glDeleteTextures(2, m_texture);
5077 glDeleteProgram(m_program);
5078 glDeleteProgram(c_program);
5079 glActiveTexture(GL_TEXTURE0);
5080 return NO_ERROR;
5081 }
5082 };
5083 //-----------------------------------------------------------------------------
5084 // 4.1 NegativeUniform
5085 //-----------------------------------------------------------------------------
5086 class NegativeUniform : public ShaderImageLoadStoreBase
5087 {
5088 GLuint m_program;
5089
Setup()5090 virtual long Setup()
5091 {
5092 m_program = 0;
5093 return NO_ERROR;
5094 }
5095
Run()5096 virtual long Run()
5097 {
5098 const char *glsl_vs =
5099 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}";
5100 const char *glsl_fs = NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
5101 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
5102 " imageStore(g_image, coord, vec4(0.0));" NL " discard;" NL "}";
5103 m_program = BuildProgram(glsl_vs, glsl_fs);
5104
5105 GLint max_image_units;
5106 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
5107 glUseProgram(m_program);
5108 bool status = true;
5109 GLint i = 1;
5110 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5111 if (glGetError() != GL_INVALID_OPERATION)
5112 status = false;
5113 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
5114 if (glGetError() != GL_INVALID_OPERATION)
5115 status = false;
5116 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
5117 if (glGetError() != GL_INVALID_OPERATION)
5118 status = false;
5119 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
5120 if (glGetError() != GL_INVALID_OPERATION)
5121 status = false;
5122
5123 if (!status)
5124 {
5125 m_context.getTestContext().getLog()
5126 << tcu::TestLog::Message << "glUniform* should generate INVALID_OPERATION "
5127 << "if the location refers to an image variable." << tcu::TestLog::EndMessage;
5128 return ERROR;
5129 }
5130
5131 glUseProgram(0);
5132 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), 1);
5133 if (glGetError() != GL_INVALID_OPERATION)
5134 status = false;
5135 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &i);
5136 if (glGetError() != GL_INVALID_OPERATION)
5137 status = false;
5138 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
5139 if (glGetError() != GL_INVALID_OPERATION)
5140 status = false;
5141 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
5142 if (glGetError() != GL_INVALID_OPERATION)
5143 status = false;
5144
5145 if (!status)
5146 {
5147 m_context.getTestContext().getLog()
5148 << tcu::TestLog::Message << "glProgramUniform* should generate INVALID_OPERATION "
5149 << "if the location refers to an image variable." << tcu::TestLog::EndMessage;
5150 return ERROR;
5151 }
5152
5153 return NO_ERROR;
5154 }
5155
Cleanup()5156 virtual long Cleanup()
5157 {
5158 glUseProgram(0);
5159 glDeleteProgram(m_program);
5160 return NO_ERROR;
5161 }
5162 };
5163
5164 //-----------------------------------------------------------------------------
5165 // 4.2 NegativeBind
5166 //-----------------------------------------------------------------------------
5167 class NegativeBind : public ShaderImageLoadStoreBase
5168 {
5169 GLuint m_texture, m_texture2;
5170
Setup()5171 virtual long Setup()
5172 {
5173 m_texture = 0;
5174 m_texture2 = 0;
5175 return NO_ERROR;
5176 }
5177
Run()5178 virtual long Run()
5179 {
5180 GLint max_image_units;
5181 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
5182 glGenTextures(1, &m_texture);
5183 glBindTexture(GL_TEXTURE_2D, m_texture);
5184 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 64, 64);
5185
5186 glBindImageTexture(max_image_units, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5187 if (glGetError() != GL_INVALID_VALUE)
5188 {
5189 m_context.getTestContext().getLog()
5190 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> "
5191 << "is greater than or equal to the value of MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
5192 return ERROR;
5193 }
5194
5195 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5196 if (glGetError() != GL_INVALID_VALUE)
5197 {
5198 m_context.getTestContext().getLog()
5199 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> "
5200 << "is not the name of an existing texture object." << tcu::TestLog::EndMessage;
5201 return ERROR;
5202 }
5203
5204 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
5205 if (glGetError() != GL_INVALID_VALUE)
5206 {
5207 m_context.getTestContext().getLog()
5208 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <format> "
5209 << "is not a legal format." << tcu::TestLog::EndMessage;
5210 return ERROR;
5211 }
5212
5213 glBindImageTexture(1, m_texture, -1, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5214 if (glGetError() != GL_INVALID_VALUE)
5215 {
5216 m_context.getTestContext().getLog()
5217 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <level> "
5218 << "is less than zero." << tcu::TestLog::EndMessage;
5219 return ERROR;
5220 }
5221
5222 glBindImageTexture(1, m_texture, 0, GL_FALSE, -1, GL_READ_ONLY, GL_RGBA32F);
5223 if (glGetError() != GL_INVALID_VALUE)
5224 {
5225 m_context.getTestContext().getLog()
5226 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <layer> "
5227 << "is less than zero." << tcu::TestLog::EndMessage;
5228 return ERROR;
5229 }
5230
5231 glGenTextures(1, &m_texture2);
5232 glBindTexture(GL_TEXTURE_2D, m_texture2);
5233 glBindImageTexture(1, m_texture2, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5234 if (glGetError() != GL_INVALID_OPERATION)
5235 {
5236 m_context.getTestContext().getLog()
5237 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> "
5238 << "is a mutable texture object." << tcu::TestLog::EndMessage;
5239 return ERROR;
5240 }
5241
5242 return NO_ERROR;
5243 }
5244
Cleanup()5245 virtual long Cleanup()
5246 {
5247 glDeleteTextures(1, &m_texture);
5248 glDeleteTextures(1, &m_texture2);
5249 return NO_ERROR;
5250 }
5251 };
5252
5253 //-----------------------------------------------------------------------------
5254 // 4.3 NegativeCompileErrors
5255 //-----------------------------------------------------------------------------
5256 class NegativeCompileErrors : public ShaderImageLoadStoreBase
5257 {
Run()5258 virtual long Run()
5259 {
5260 if (!Compile( // writeonly & readonly qualifiers
5261 NL "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
5262 " vec4 o_color;" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5263 return ERROR;
5264
5265 if (!Compile( // writeonly && reading
5266 NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5267 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5268 return ERROR;
5269
5270 if (!Compile( //readonly && writing
5271 NL "uniform vec4 i_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
5272 " vec4 o_color;" NL " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
5273 return ERROR;
5274
5275 if (!Compile( // no format layout && load
5276 NL "uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5277 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5278 return ERROR;
5279
5280 if (!Compile( // no fromat layout && readonly && load
5281 NL "readonly uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5282 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5283 return ERROR;
5284
5285 if (!Compile( // target type image1D not supported
5286 NL "layout(r32i) uniform image1D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5287 " o_color = vec4(1.0);" NL "}"))
5288 return ERROR;
5289
5290 if (!Compile( // format layout not compatible with type
5291 NL "layout(rgba16) writeonly uniform iimage2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5292 " o_color = vec4(1.0);" NL "}"))
5293 return ERROR;
5294
5295 if (!Compile( // imageAtomicAdd doesn't support r32f
5296 NL "#extension GL_OES_shader_image_atomic : require" NL
5297 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5298 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
5299 return ERROR;
5300
5301 if (!Compile( // imageAtomicAdd doesn't support rgba8i
5302 NL "#extension GL_OES_shader_image_atomic : require" NL
5303 "layout(rgba8i) coherent uniform iimage2D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5304 " imageAtomicAdd(g_image, ivec2(1), 1);" NL " o_color = vec4(1.0);" NL "}"))
5305 return ERROR;
5306
5307 if (!Compile( // format layout not compatible with type
5308 NL "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL " vec4 o_color;" NL
5309 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
5310 return ERROR;
5311
5312 if (!Compile( // format layout not compatible with type
5313 NL "layout(r32f) uniform uimage2DArray g_image;" NL "void main() {" NL " vec4 o_color;" NL
5314 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
5315 return ERROR;
5316
5317 if (!Compile( // wrong function argument type
5318 NL "layout(r32f) coherent uniform image2D g_image;" NL "vec4 Load(iimage2D image) {" NL
5319 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " vec4 o_color;" NL
5320 " o_color = Load(g_image);" NL "}"))
5321 return ERROR;
5322
5323 return NO_ERROR;
5324 }
5325
Compile(const std::string & source)5326 bool Compile(const std::string &source)
5327 {
5328 const char *const csVer = "#version 310 es" NL "layout(local_size_x = 1) in;";
5329 const char *const src[3] = {csVer, kGLSLPrec, source.c_str()};
5330 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
5331 glShaderSource(sh, 3, src, NULL);
5332 glCompileShader(sh);
5333
5334 GLchar log[1024];
5335 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
5336 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
5337 << log << tcu::TestLog::EndMessage;
5338
5339 GLint status;
5340 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
5341 glDeleteShader(sh);
5342
5343 if (status == GL_TRUE)
5344 {
5345 m_context.getTestContext().getLog()
5346 << tcu::TestLog::Message << "Compilation should fail [compute shader]." << tcu::TestLog::EndMessage;
5347 return false;
5348 }
5349 const char *const fsVer = "#version 310 es" NL "precision highp float;";
5350 const char *const fsrc[3] = {fsVer, kGLSLPrec, source.c_str()};
5351 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
5352 glShaderSource(fsh, 3, fsrc, NULL);
5353 glCompileShader(fsh);
5354
5355 glGetShaderInfoLog(fsh, sizeof(log), NULL, log);
5356 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
5357 << log << tcu::TestLog::EndMessage;
5358 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
5359 glDeleteShader(fsh);
5360
5361 if (status == GL_TRUE)
5362 {
5363 m_context.getTestContext().getLog()
5364 << tcu::TestLog::Message << "Compilation should fail [fragment shader]." << tcu::TestLog::EndMessage;
5365 return false;
5366 }
5367
5368 return true;
5369 }
5370 };
5371
5372 //-----------------------------------------------------------------------------
5373 // 4.4 NegativeLinkErrors
5374 //-----------------------------------------------------------------------------
5375 class NegativeLinkErrors : public ShaderImageLoadStoreBase
5376 {
Run()5377 virtual long Run()
5378 {
5379 if (!IsVSFSAvailable(1, 1))
5380 return NOT_SUPPORTED;
5381 if (!Link(NL "layout(location = 0) in vec4 i_position;" NL
5382 "layout(rgba32f) writeonly uniform highp image3D g_image;" NL "void main() {" NL
5383 " imageStore(g_image, ivec3(gl_VertexID), vec4(0));" NL " gl_Position = i_position;" NL "}",
5384
5385 NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL
5386 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5387 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
5388 return ERROR;
5389
5390 if (!Link(NL "layout(location = 0) in vec4 i_position;" NL
5391 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5392 " imageStore(g_image, ivec2(gl_VertexID), vec4(0));" NL " gl_Position = i_position;" NL "}",
5393
5394 NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL
5395 "layout(r32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5396 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
5397 return ERROR;
5398
5399 return NO_ERROR;
5400 }
5401
Link(const std::string & vs,const std::string & fs)5402 bool Link(const std::string &vs, const std::string &fs)
5403 {
5404 const char *const sVer = "#version 310 es";
5405 const GLuint p = glCreateProgram();
5406
5407 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
5408 glAttachShader(p, vsh);
5409 glDeleteShader(vsh);
5410 const char *const vssrc[2] = {sVer, vs.c_str()};
5411 glShaderSource(vsh, 2, vssrc, NULL);
5412 glCompileShader(vsh);
5413
5414 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
5415 glAttachShader(p, fsh);
5416 glDeleteShader(fsh);
5417 const char *const fssrc[2] = {sVer, fs.c_str()};
5418 glShaderSource(fsh, 2, fssrc, NULL);
5419 glCompileShader(fsh);
5420
5421 GLint status;
5422 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
5423 if (status == GL_FALSE)
5424 {
5425 glDeleteProgram(p);
5426 m_context.getTestContext().getLog()
5427 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
5428 return false;
5429 }
5430 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
5431 if (status == GL_FALSE)
5432 {
5433 glDeleteProgram(p);
5434 m_context.getTestContext().getLog()
5435 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
5436 return false;
5437 }
5438
5439 glLinkProgram(p);
5440
5441 GLchar log[1024];
5442 glGetProgramInfoLog(p, sizeof(log), NULL, log);
5443 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
5444 << log << tcu::TestLog::EndMessage;
5445
5446 glGetProgramiv(p, GL_LINK_STATUS, &status);
5447 glDeleteProgram(p);
5448
5449 if (status == GL_TRUE)
5450 {
5451 m_context.getTestContext().getLog()
5452 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
5453 return false;
5454 }
5455
5456 return true;
5457 }
5458 };
5459
5460 } // anonymous namespace
5461
ShaderImageLoadStoreTests(deqp::Context & context)5462 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context &context)
5463 : TestCaseGroup(context, "shader_image_load_store", "")
5464 {
5465 }
5466
~ShaderImageLoadStoreTests(void)5467 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
5468 {
5469 }
5470
init()5471 void ShaderImageLoadStoreTests::init()
5472 {
5473 using namespace deqp;
5474 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
5475 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
5476 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
5477 addChild(new TestSubcase(m_context, "basic-api-barrier-byRegion", TestSubcase::Create<BasicAPIBarrierByRegion>));
5478 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
5479 addChild(new TestSubcase(m_context, "basic-allFormats-store-fs", TestSubcase::Create<BasicAllFormatsStoreFS>));
5480 addChild(new TestSubcase(m_context, "basic-allFormats-store-cs", TestSubcase::Create<BasicAllFormatsStoreCS>));
5481 addChild(new TestSubcase(m_context, "basic-allFormats-load-fs", TestSubcase::Create<BasicAllFormatsLoadFS>));
5482 addChild(new TestSubcase(m_context, "basic-allFormats-load-cs", TestSubcase::Create<BasicAllFormatsLoadCS>));
5483 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
5484 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
5485 addChild(new TestSubcase(m_context, "basic-allTargets-store-fs", TestSubcase::Create<BasicAllTargetsStoreFS>));
5486 addChild(new TestSubcase(m_context, "basic-allTargets-store-cs", TestSubcase::Create<BasicAllTargetsStoreCS>));
5487 addChild(new TestSubcase(m_context, "basic-allTargets-load-fs", TestSubcase::Create<BasicAllTargetsLoadFS>));
5488 addChild(new TestSubcase(m_context, "basic-allTargets-load-cs", TestSubcase::Create<BasicAllTargetsLoadCS>));
5489 addChild(new TestSubcase(m_context, "basic-allTargets-atomicFS", TestSubcase::Create<BasicAllTargetsAtomicFS>));
5490 addChild(
5491 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
5492 addChild(
5493 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
5494 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
5495 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
5496 addChild(new TestSubcase(m_context, "basic-glsl-misc-fs", TestSubcase::Create<BasicGLSLMiscFS>));
5497 addChild(new TestSubcase(m_context, "basic-glsl-misc-cs", TestSubcase::Create<BasicGLSLMiscCS>));
5498 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
5499 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
5500 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
5501 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
5502 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
5503 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
5504 addChild(new TestSubcase(m_context, "advanced-memory-order-vsfs", TestSubcase::Create<AdvancedMemoryOrderVSFS>));
5505 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
5506 addChild(new TestSubcase(m_context, "advanced-copyImage-fs", TestSubcase::Create<AdvancedCopyImageFS>));
5507 addChild(new TestSubcase(m_context, "advanced-copyImage-cs", TestSubcase::Create<AdvancedCopyImageCS>));
5508 addChild(new TestSubcase(m_context, "advanced-allMips-fs", TestSubcase::Create<AdvancedAllMipsFS>));
5509 addChild(new TestSubcase(m_context, "advanced-allMips-cs", TestSubcase::Create<AdvancedAllMipsCS>));
5510 addChild(new TestSubcase(m_context, "advanced-cast-fs", TestSubcase::Create<AdvancedCastFS>));
5511 addChild(new TestSubcase(m_context, "advanced-cast-cs", TestSubcase::Create<AdvancedCastCS>));
5512 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
5513 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
5514 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
5515 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
5516 }
5517
5518 } // namespace es31compatibility
5519 } // namespace gl4cts
5520