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