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