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