1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 #include "gl4cShaderImageLoadStoreTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuPlatform.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include <assert.h>
32 #include <climits>
33 #include <cmath>
34 #include <cstdarg>
35 #include <deque>
36 #include <iomanip>
37 #include <map>
38 #include <sstream>
39 #include <tcuFloat.hpp>
40
41 namespace gl4cts
42 {
43 using namespace glw;
44
45 namespace
46 {
47 typedef tcu::Vec2 vec2;
48 typedef tcu::Vec4 vec4;
49 typedef tcu::IVec4 ivec4;
50 typedef tcu::UVec4 uvec4;
51 typedef tcu::Mat4 mat4;
52
53 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
54 {
Title()55 virtual std::string Title()
56 {
57 return "";
58 }
59
Purpose()60 virtual std::string Purpose()
61 {
62 return "";
63 }
64
Method()65 virtual std::string Method()
66 {
67 return "";
68 }
69
PassCriteria()70 virtual std::string PassCriteria()
71 {
72 return "";
73 }
74
75 public:
SupportedInVS(int requiredVS)76 bool SupportedInVS(int requiredVS)
77 {
78 GLint imagesVS;
79 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
80 if (imagesVS >= requiredVS)
81 return true;
82 else
83 {
84 std::ostringstream reason;
85 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
86 << std::endl;
87 OutputNotSupported(reason.str());
88 return false;
89 }
90 }
91
SupportedInTCS(int requiredTCS)92 bool SupportedInTCS(int requiredTCS)
93 {
94 GLint imagesTCS;
95 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
96 if (imagesTCS >= requiredTCS)
97 return true;
98 else
99 {
100 std::ostringstream reason;
101 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
102 << std::endl;
103 OutputNotSupported(reason.str());
104 return false;
105 }
106 }
107
SupportedInTES(int requiredTES)108 bool SupportedInTES(int requiredTES)
109 {
110 GLint imagesTES;
111 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
112 if (imagesTES >= requiredTES)
113 return true;
114 else
115 {
116 std::ostringstream reason;
117 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
118 << std::endl;
119 OutputNotSupported(reason.str());
120 return false;
121 }
122 }
123
SupportedInGS(int requiredGS)124 bool SupportedInGS(int requiredGS)
125 {
126 GLint imagesGS;
127 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
128 if (imagesGS >= requiredGS)
129 return true;
130 else
131 {
132 std::ostringstream reason;
133 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
134 << std::endl;
135 OutputNotSupported(reason.str());
136 return false;
137 }
138 }
139
SupportedInGeomStages(int required)140 bool SupportedInGeomStages(int required)
141 {
142 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
143 SupportedInGS(required);
144 }
145
SupportedInStage(int stage,int required)146 bool SupportedInStage(int stage, int required)
147 {
148 switch (stage)
149 {
150 case 0:
151 return SupportedInVS(required);
152 case 1:
153 return SupportedInTCS(required);
154 case 2:
155 return SupportedInTES(required);
156 case 3:
157 return SupportedInGS(required);
158 default:
159 return true;
160 }
161 }
162
SupportedSamples(int required)163 bool SupportedSamples(int required)
164 {
165 int i;
166 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
167 if (i >= required)
168 return true;
169 else
170 {
171 std::ostringstream reason;
172 reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
173 OutputNotSupported(reason.str());
174 return false;
175 }
176 }
177
getWindowWidth()178 int getWindowWidth()
179 {
180 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
181 return renderTarget.getWidth();
182 }
183
getWindowHeight()184 int getWindowHeight()
185 {
186 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
187 return renderTarget.getHeight();
188 }
189
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)190 void scaleDimensionsToMemory(int &width, int &height, int devLayers, int sysLayers, int devBPP, int sysBPP)
191 {
192 tcu::PlatformMemoryLimits memoryLimits;
193 m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
194 GLsizeiptr sysSpace = memoryLimits.totalSystemMemory;
195 GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory;
196 int devInSysLayers = 0;
197
198 if (devSpace == 0)
199 {
200 devInSysLayers = devLayers;
201 devLayers = 0;
202 }
203
204 // Check if available memory is enough
205 GLsizeiptr pixelsPerLayer = width * height;
206 GLsizeiptr sysRequired = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
207 GLsizeiptr devRequired = pixelsPerLayer * devBPP * devLayers;
208 if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
209 {
210 return;
211 }
212
213 // Scales the width and height such that the overall texture fits into
214 // the available space for both system and device.
215 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
216 if (devSpace != 0)
217 {
218 GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
219 scale = de::min(devScale, scale);
220 }
221 int newWidth = int(width * scale);
222 int newHeight = int(height * scale);
223
224 m_context.getTestContext().getLog()
225 << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
226 << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
227
228 width = newWidth;
229 height = newHeight;
230 }
231
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)232 inline bool ColorEqual(const vec4 &c0, const vec4 &c1, const vec4 &epsilon)
233 {
234 if (fabs(c0[0] - c1[0]) > epsilon[0])
235 return false;
236 if (fabs(c0[1] - c1[1]) > epsilon[1])
237 return false;
238 if (fabs(c0[2] - c1[2]) > epsilon[2])
239 return false;
240 if (fabs(c0[3] - c1[3]) > epsilon[3])
241 return false;
242 return true;
243 }
244
IsEqual(vec4 a,vec4 b)245 bool IsEqual(vec4 a, vec4 b)
246 {
247 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
248 }
249
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)250 bool Equal(const vec4 &v0, const vec4 &v1, GLenum internalformat)
251 {
252 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
253 {
254 return ColorEqual(v0, v1, vec4(0.0001f));
255 }
256 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
257 {
258 return ColorEqual(v0, v1, vec4(0.01f));
259 }
260 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
261 }
262
Equal(const ivec4 & a,const ivec4 & b,GLenum)263 bool Equal(const ivec4 &a, const ivec4 &b, GLenum)
264 {
265 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
266 }
267
Equal(const uvec4 & a,const uvec4 & b,GLenum)268 bool Equal(const uvec4 &a, const uvec4 &b, GLenum)
269 {
270 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
271 }
272
273 template <class T>
ToString(T v)274 std::string ToString(T v)
275 {
276 std::ostringstream s;
277 s << "[";
278 for (int i = 0; i < 4; ++i)
279 s << v[i] << (i == 3 ? "" : ",");
280 s << "]";
281 return s.str();
282 }
283
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)284 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4 &expected)
285 {
286 bool status = true;
287 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
288 const tcu::PixelFormat &pixelFormat = renderTarget.getPixelFormat();
289 vec4 g_color_eps = vec4(
290 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
291 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
292
293 std::vector<vec4> fb(w * h);
294 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
295
296 for (int yy = 0; yy < h; ++yy)
297 {
298 for (int xx = 0; xx < w; ++xx)
299 {
300 const int idx = yy * w + xx;
301 if (!ColorEqual(fb[idx], expected, g_color_eps))
302 {
303 m_context.getTestContext().getLog()
304 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
305 << tcu::TestLog::EndMessage;
306 status = false;
307 return status;
308 }
309 }
310 }
311 return status;
312 }
313
CompileShader(GLuint shader)314 bool CompileShader(GLuint shader)
315 {
316 glCompileShader(shader);
317
318 GLint status;
319 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
320 if (status == GL_FALSE)
321 {
322 GLsizei length;
323 GLchar log[1024];
324 glGetShaderInfoLog(shader, sizeof(log), &length, log);
325 if (length > 1)
326 {
327 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
328 << log << tcu::TestLog::EndMessage;
329 }
330 return false;
331 }
332 return true;
333 }
334
LinkProgram(GLuint program)335 bool LinkProgram(GLuint program)
336 {
337 glLinkProgram(program);
338
339 GLint status;
340 glGetProgramiv(program, GL_LINK_STATUS, &status);
341 if (status == GL_FALSE)
342 {
343 GLsizei length;
344 GLchar log[1024];
345 glGetProgramInfoLog(program, sizeof(log), &length, log);
346 if (length > 1)
347 {
348 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
349 << log << tcu::TestLog::EndMessage;
350 }
351 return false;
352 }
353 return true;
354 }
355
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)356 GLuint BuildProgram(const char *src_vs, const char *src_tcs, const char *src_tes, const char *src_gs,
357 const char *src_fs, bool *result = NULL)
358 {
359 const GLuint p = glCreateProgram();
360
361 if (src_vs)
362 {
363 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
364 glAttachShader(p, sh);
365 glDeleteShader(sh);
366 glShaderSource(sh, 1, &src_vs, NULL);
367 if (!CompileShader(sh))
368 {
369 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
370 if (result)
371 *result = false;
372 return p;
373 }
374 }
375 if (src_tcs)
376 {
377 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
378 glAttachShader(p, sh);
379 glDeleteShader(sh);
380 glShaderSource(sh, 1, &src_tcs, NULL);
381 if (!CompileShader(sh))
382 {
383 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
384 if (result)
385 *result = false;
386 return p;
387 }
388 }
389 if (src_tes)
390 {
391 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
392 glAttachShader(p, sh);
393 glDeleteShader(sh);
394 glShaderSource(sh, 1, &src_tes, NULL);
395 if (!CompileShader(sh))
396 {
397 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
398 if (result)
399 *result = false;
400 return p;
401 }
402 }
403 if (src_gs)
404 {
405 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
406 glAttachShader(p, sh);
407 glDeleteShader(sh);
408 glShaderSource(sh, 1, &src_gs, NULL);
409 if (!CompileShader(sh))
410 {
411 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
412 if (result)
413 *result = false;
414 return p;
415 }
416 }
417 if (src_fs)
418 {
419 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
420 glAttachShader(p, sh);
421 glDeleteShader(sh);
422 glShaderSource(sh, 1, &src_fs, NULL);
423 if (!CompileShader(sh))
424 {
425 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
426 if (result)
427 *result = false;
428 return p;
429 }
430 }
431 if (!LinkProgram(p))
432 {
433 if (src_vs)
434 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
435 if (src_tcs)
436 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
437 if (src_tes)
438 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
439 if (src_gs)
440 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
441 if (src_fs)
442 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
443 if (result)
444 *result = false;
445 return p;
446 }
447
448 return p;
449 }
450
BuildShaderProgram(GLenum type,const char * src)451 GLuint BuildShaderProgram(GLenum type, const char *src)
452 {
453 const GLuint p = glCreateShaderProgramv(type, 1, &src);
454
455 GLint status;
456 glGetProgramiv(p, GL_LINK_STATUS, &status);
457 if (status == GL_FALSE)
458 {
459 GLchar log[1024];
460 glGetProgramInfoLog(p, sizeof(log), NULL, log);
461 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
462 << log << "\n"
463 << src << tcu::TestLog::EndMessage;
464 }
465
466 return p;
467 }
468
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)469 void CreateFullViewportQuad(GLuint *vao, GLuint *vbo, GLuint *ebo)
470 {
471 assert(vao && vbo);
472
473 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
474 const float v[] = {
475 -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
476 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
477 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
478 };
479 glGenBuffers(1, vbo);
480 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
481 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
482 glBindBuffer(GL_ARRAY_BUFFER, 0);
483
484 if (ebo)
485 {
486 std::vector<GLushort> index_data(4);
487 for (int i = 0; i < 4; ++i)
488 {
489 index_data[i] = static_cast<GLushort>(i);
490 }
491 glGenBuffers(1, ebo);
492 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
493 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
494 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
495 }
496
497 glGenVertexArrays(1, vao);
498 glBindVertexArray(*vao);
499 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
500 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
501 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
502 reinterpret_cast<void *>(sizeof(float) * 2));
503 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
504 reinterpret_cast<void *>(sizeof(float) * 5));
505 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
506 reinterpret_cast<void *>(sizeof(float) * 8));
507 glBindBuffer(GL_ARRAY_BUFFER, 0);
508 glEnableVertexAttribArray(0);
509 glEnableVertexAttribArray(1);
510 glEnableVertexAttribArray(2);
511 glEnableVertexAttribArray(3);
512 if (ebo)
513 {
514 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
515 }
516 glBindVertexArray(0);
517 }
518
FormatEnumToString(GLenum e)519 std::string FormatEnumToString(GLenum e)
520 {
521 switch (e)
522 {
523 case GL_RGBA32F:
524 return "rgba32f";
525 case GL_RGBA16F:
526 return "rgba16f";
527 case GL_RG32F:
528 return "rg32f";
529 case GL_RG16F:
530 return "rg16f";
531 case GL_R11F_G11F_B10F:
532 return "r11f_g11f_b10f";
533 case GL_R32F:
534 return "r32f";
535 case GL_R16F:
536 return "r16f";
537
538 case GL_RGBA32UI:
539 return "rgba32ui";
540 case GL_RGBA16UI:
541 return "rgba16ui";
542 case GL_RGB10_A2UI:
543 return "rgb10_a2ui";
544 case GL_RGBA8UI:
545 return "rgba8ui";
546 case GL_RG32UI:
547 return "rg32ui";
548 case GL_RG16UI:
549 return "rg16ui";
550 case GL_RG8UI:
551 return "rg8ui";
552 case GL_R32UI:
553 return "r32ui";
554 case GL_R16UI:
555 return "r16ui";
556 case GL_R8UI:
557 return "r8ui";
558
559 case GL_RGBA32I:
560 return "rgba32i";
561 case GL_RGBA16I:
562 return "rgba16i";
563 case GL_RGBA8I:
564 return "rgba8i";
565 case GL_RG32I:
566 return "rg32i";
567 case GL_RG16I:
568 return "rg16i";
569 case GL_RG8I:
570 return "rg8i";
571 case GL_R32I:
572 return "r32i";
573 case GL_R16I:
574 return "r16i";
575 case GL_R8I:
576 return "r8i";
577
578 case GL_RGBA16:
579 return "rgba16";
580 case GL_RGB10_A2:
581 return "rgb10_a2";
582 case GL_RGBA8:
583 return "rgba8";
584 case GL_RG16:
585 return "rg16";
586 case GL_RG8:
587 return "rg8";
588 case GL_R16:
589 return "r16";
590 case GL_R8:
591 return "r8";
592
593 case GL_RGBA16_SNORM:
594 return "rgba16_snorm";
595 case GL_RGBA8_SNORM:
596 return "rgba8_snorm";
597 case GL_RG16_SNORM:
598 return "rg16_snorm";
599 case GL_RG8_SNORM:
600 return "rg8_snorm";
601 case GL_R16_SNORM:
602 return "r16_snorm";
603 case GL_R8_SNORM:
604 return "r8_snorm";
605 }
606
607 assert(0);
608 return "";
609 }
610
StageName(int stage)611 const char *StageName(int stage)
612 {
613 switch (stage)
614 {
615 case 0:
616 return "Vertex Shader";
617 case 1:
618 return "Tessellation Control Shader";
619 case 2:
620 return "Tessellation Evaluation Shader";
621 case 3:
622 return "Geometry Shader";
623 case 4:
624 return "Compute Shader";
625 }
626 assert(0);
627 return NULL;
628 }
629
630 template <typename T>
631 GLenum Format();
632
633 template <typename T>
634 GLenum Type();
635
636 template <typename T>
637 std::string TypePrefix();
638
639 template <typename T>
640 GLenum ImageType(GLenum target);
641
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)642 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4 &color)
643 {
644 glClearBufferfv(buffer, drawbuffer, &color[0]);
645 }
646
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)647 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4 &color)
648 {
649 glClearBufferiv(buffer, drawbuffer, &color[0]);
650 }
651
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)652 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4 &color)
653 {
654 glClearBufferuiv(buffer, drawbuffer, &color[0]);
655 }
656
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)657 bool CheckUniform(GLuint program, const std::string &name, const std::map<std::string, GLuint> &name_index_map,
658 GLint size, GLenum type)
659 {
660 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
661 assert(iter != name_index_map.end());
662
663 GLchar name_gl[32];
664 GLsizei length_gl;
665 GLint size_gl;
666 GLenum type_gl;
667
668 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
669
670 if (std::string(name_gl) != name)
671 {
672 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
673 << " should be " << name << tcu::TestLog::EndMessage;
674 return false;
675 }
676 if (length_gl != static_cast<GLsizei>(name.length()))
677 {
678 m_context.getTestContext().getLog()
679 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
680 << ")" << tcu::TestLog::EndMessage;
681 return false;
682 }
683 if (size_gl != size)
684 {
685 m_context.getTestContext().getLog()
686 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
687 << ")" << tcu::TestLog::EndMessage;
688 return false;
689 }
690 if (type_gl != type)
691 {
692 m_context.getTestContext().getLog()
693 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
694 << ")" << tcu::TestLog::EndMessage;
695 return false;
696 }
697
698 return true;
699 }
700
CheckMax(GLenum pname,GLint min_value)701 bool CheckMax(GLenum pname, GLint min_value)
702 {
703 GLboolean b;
704 GLint i;
705 GLfloat f;
706 GLdouble d;
707 GLint64 i64;
708
709 glGetIntegerv(pname, &i);
710 if (i < min_value)
711 return false;
712
713 glGetBooleanv(pname, &b);
714 if (b != (i ? GL_TRUE : GL_FALSE))
715 return false;
716
717 glGetFloatv(pname, &f);
718 if (static_cast<GLint>(f) < min_value)
719 return false;
720
721 glGetDoublev(pname, &d);
722 if (static_cast<GLint>(d) < min_value)
723 return false;
724
725 glGetInteger64v(pname, &i64);
726 if (static_cast<GLint>(i64) < min_value)
727 return false;
728
729 return true;
730 }
731
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)732 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
733 GLenum format)
734 {
735 GLint i;
736 GLboolean b;
737
738 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
739 if (static_cast<GLuint>(i) != texture)
740 {
741 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
742 << " should be " << texture << tcu::TestLog::EndMessage;
743 return false;
744 }
745 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
746 if (b != (i ? GL_TRUE : GL_FALSE))
747 {
748 m_context.getTestContext().getLog()
749 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
750 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
751 return false;
752 }
753
754 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
755 if (i != level)
756 {
757 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
758 << " should be " << level << tcu::TestLog::EndMessage;
759 return false;
760 }
761 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
762 if (b != (i ? GL_TRUE : GL_FALSE))
763 {
764 m_context.getTestContext().getLog()
765 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
766 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
767 return false;
768 }
769
770 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
771 if (i != layered)
772 {
773 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
774 << " should be " << layered << tcu::TestLog::EndMessage;
775 return false;
776 }
777 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
778 if (b != (i ? GL_TRUE : GL_FALSE))
779 {
780 m_context.getTestContext().getLog()
781 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
782 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
783 return false;
784 }
785
786 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
787 if (i != layer)
788 {
789 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
790 << " should be " << layer << tcu::TestLog::EndMessage;
791 return false;
792 }
793 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
794 if (b != (i ? GL_TRUE : GL_FALSE))
795 {
796 m_context.getTestContext().getLog()
797 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
798 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
799 return false;
800 }
801
802 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
803 if (static_cast<GLenum>(i) != access)
804 {
805 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
806 << " should be " << access << tcu::TestLog::EndMessage;
807 return false;
808 }
809 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
810 if (b != (i ? GL_TRUE : GL_FALSE))
811 {
812 m_context.getTestContext().getLog()
813 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
814 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
815 return false;
816 }
817
818 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
819 if (static_cast<GLenum>(i) != format)
820 {
821 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
822 << " should be " << format << tcu::TestLog::EndMessage;
823 return false;
824 }
825 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
826 if (b != (i ? GL_TRUE : GL_FALSE))
827 {
828 m_context.getTestContext().getLog()
829 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
830 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
831 return false;
832 }
833
834 return true;
835 }
EnumToString(GLenum e)836 const char *EnumToString(GLenum e)
837 {
838 switch (e)
839 {
840 case GL_TEXTURE_1D:
841 return "GL_TEXTURE_1D";
842 case GL_TEXTURE_2D:
843 return "GL_TEXTURE_2D";
844 case GL_TEXTURE_3D:
845 return "GL_TEXTURE_3D";
846 case GL_TEXTURE_RECTANGLE:
847 return "GL_TEXTURE_RECTANGLE";
848 case GL_TEXTURE_CUBE_MAP:
849 return "GL_TEXTURE_CUBE_MAP";
850 case GL_TEXTURE_1D_ARRAY:
851 return "GL_TEXTURE_1D_ARRAY";
852 case GL_TEXTURE_2D_ARRAY:
853 return "GL_TEXTURE_2D_ARRAY";
854 case GL_TEXTURE_CUBE_MAP_ARRAY:
855 return "GL_TEXTURE_CUBE_MAP_ARRAY";
856
857 default:
858 assert(0);
859 break;
860 }
861 return NULL;
862 }
863 };
864
865 template <>
Format()866 GLenum ShaderImageLoadStoreBase::Format<vec4>()
867 {
868 return GL_RGBA;
869 }
870
871 template <>
Format()872 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
873 {
874 return GL_RGBA_INTEGER;
875 }
876
877 template <>
Format()878 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
879 {
880 return GL_RGBA_INTEGER;
881 }
882
883 template <>
Format()884 GLenum ShaderImageLoadStoreBase::Format<GLint>()
885 {
886 return GL_RED_INTEGER;
887 }
888
889 template <>
Format()890 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
891 {
892 return GL_RED_INTEGER;
893 }
894
895 template <>
Type()896 GLenum ShaderImageLoadStoreBase::Type<vec4>()
897 {
898 return GL_FLOAT;
899 }
900
901 template <>
Type()902 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
903 {
904 return GL_INT;
905 }
906
907 template <>
Type()908 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
909 {
910 return GL_UNSIGNED_INT;
911 }
912
913 template <>
Type()914 GLenum ShaderImageLoadStoreBase::Type<GLint>()
915 {
916 return GL_INT;
917 }
918
919 template <>
Type()920 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
921 {
922 return GL_UNSIGNED_INT;
923 }
924
925 template <>
TypePrefix()926 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
927 {
928 return "";
929 }
930
931 template <>
TypePrefix()932 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
933 {
934 return "i";
935 }
936
937 template <>
TypePrefix()938 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
939 {
940 return "u";
941 }
942
943 template <>
TypePrefix()944 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
945 {
946 return "i";
947 }
948
949 template <>
TypePrefix()950 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
951 {
952 return "u";
953 }
954
955 template <>
ImageType(GLenum target)956 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
957 {
958 switch (target)
959 {
960 case GL_TEXTURE_1D:
961 return GL_IMAGE_1D;
962 case GL_TEXTURE_2D:
963 return GL_IMAGE_2D;
964 case GL_TEXTURE_3D:
965 return GL_IMAGE_3D;
966 case GL_TEXTURE_RECTANGLE:
967 return GL_IMAGE_2D_RECT;
968 case GL_TEXTURE_CUBE_MAP:
969 return GL_IMAGE_CUBE;
970 case GL_TEXTURE_BUFFER:
971 return GL_IMAGE_BUFFER;
972 case GL_TEXTURE_1D_ARRAY:
973 return GL_IMAGE_1D_ARRAY;
974 case GL_TEXTURE_2D_ARRAY:
975 return GL_IMAGE_2D_ARRAY;
976 case GL_TEXTURE_CUBE_MAP_ARRAY:
977 return GL_IMAGE_CUBE_MAP_ARRAY;
978 case GL_TEXTURE_2D_MULTISAMPLE:
979 return GL_IMAGE_2D_MULTISAMPLE;
980 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
981 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
982 }
983 assert(0);
984 return 0;
985 }
986
987 template <>
ImageType(GLenum target)988 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
989 {
990 switch (target)
991 {
992 case GL_TEXTURE_1D:
993 return GL_INT_IMAGE_1D;
994 case GL_TEXTURE_2D:
995 return GL_INT_IMAGE_2D;
996 case GL_TEXTURE_3D:
997 return GL_INT_IMAGE_3D;
998 case GL_TEXTURE_RECTANGLE:
999 return GL_INT_IMAGE_2D_RECT;
1000 case GL_TEXTURE_CUBE_MAP:
1001 return GL_INT_IMAGE_CUBE;
1002 case GL_TEXTURE_BUFFER:
1003 return GL_INT_IMAGE_BUFFER;
1004 case GL_TEXTURE_1D_ARRAY:
1005 return GL_INT_IMAGE_1D_ARRAY;
1006 case GL_TEXTURE_2D_ARRAY:
1007 return GL_INT_IMAGE_2D_ARRAY;
1008 case GL_TEXTURE_CUBE_MAP_ARRAY:
1009 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1010 case GL_TEXTURE_2D_MULTISAMPLE:
1011 return GL_INT_IMAGE_2D_MULTISAMPLE;
1012 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1013 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1014 }
1015 assert(0);
1016 return 0;
1017 }
1018
1019 template <>
ImageType(GLenum target)1020 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1021 {
1022 switch (target)
1023 {
1024 case GL_TEXTURE_1D:
1025 return GL_UNSIGNED_INT_IMAGE_1D;
1026 case GL_TEXTURE_2D:
1027 return GL_UNSIGNED_INT_IMAGE_2D;
1028 case GL_TEXTURE_3D:
1029 return GL_UNSIGNED_INT_IMAGE_3D;
1030 case GL_TEXTURE_RECTANGLE:
1031 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1032 case GL_TEXTURE_CUBE_MAP:
1033 return GL_UNSIGNED_INT_IMAGE_CUBE;
1034 case GL_TEXTURE_BUFFER:
1035 return GL_UNSIGNED_INT_IMAGE_BUFFER;
1036 case GL_TEXTURE_1D_ARRAY:
1037 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1038 case GL_TEXTURE_2D_ARRAY:
1039 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1040 case GL_TEXTURE_CUBE_MAP_ARRAY:
1041 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1042 case GL_TEXTURE_2D_MULTISAMPLE:
1043 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1044 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1045 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1046 }
1047 assert(0);
1048 return 0;
1049 }
1050
1051 //-----------------------------------------------------------------------------
1052 // 1.1.1 BasicAPIGet
1053 //-----------------------------------------------------------------------------
1054 class BasicAPIGet : public ShaderImageLoadStoreBase
1055 {
Run()1056 virtual long Run()
1057 {
1058 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1059 {
1060 m_context.getTestContext().getLog()
1061 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1062 return ERROR;
1063 }
1064 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1065 {
1066 m_context.getTestContext().getLog()
1067 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1068 << tcu::TestLog::EndMessage;
1069 return ERROR;
1070 }
1071 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1072 {
1073 m_context.getTestContext().getLog()
1074 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1075 return ERROR;
1076 }
1077 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1078 {
1079 m_context.getTestContext().getLog()
1080 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1081 << tcu::TestLog::EndMessage;
1082 return ERROR;
1083 }
1084 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1085 {
1086 m_context.getTestContext().getLog()
1087 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1088 << tcu::TestLog::EndMessage;
1089 return ERROR;
1090 }
1091 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1092 {
1093 m_context.getTestContext().getLog()
1094 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1095 << tcu::TestLog::EndMessage;
1096 return ERROR;
1097 }
1098 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1099 {
1100 m_context.getTestContext().getLog()
1101 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1102 << tcu::TestLog::EndMessage;
1103 return ERROR;
1104 }
1105 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1106 {
1107 m_context.getTestContext().getLog()
1108 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1109 << tcu::TestLog::EndMessage;
1110 return ERROR;
1111 }
1112 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1113 {
1114 m_context.getTestContext().getLog()
1115 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1116 << tcu::TestLog::EndMessage;
1117 return ERROR;
1118 }
1119 return NO_ERROR;
1120 }
1121 };
1122 //-----------------------------------------------------------------------------
1123 // 1.1.2 BasicAPIBind
1124 //-----------------------------------------------------------------------------
1125 class BasicAPIBind : public ShaderImageLoadStoreBase
1126 {
1127 GLuint m_texture;
1128
Setup()1129 virtual long Setup()
1130 {
1131 m_texture = 0;
1132 return NO_ERROR;
1133 }
1134
Run()1135 virtual long Run()
1136 {
1137 for (GLuint index = 0; index < 8; ++index)
1138 {
1139 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1140 {
1141 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1142 << " has invalid default state." << tcu::TestLog::EndMessage;
1143 return ERROR;
1144 }
1145 }
1146
1147 glGenTextures(1, &m_texture);
1148 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1149 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1152 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1153 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1154 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1155
1156 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1157 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1158 return ERROR;
1159
1160 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1161 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1162 return ERROR;
1163
1164 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1165 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1166 return ERROR;
1167
1168 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1169 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1170 return ERROR;
1171
1172 glDeleteTextures(1, &m_texture);
1173 m_texture = 0;
1174
1175 for (GLuint index = 0; index < 8; ++index)
1176 {
1177 GLint name;
1178 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1179 if (name != 0)
1180 {
1181 m_context.getTestContext().getLog()
1182 << tcu::TestLog::Message << "Binding point " << index
1183 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1184 return ERROR;
1185 }
1186 }
1187
1188 return NO_ERROR;
1189 }
1190
Cleanup()1191 virtual long Cleanup()
1192 {
1193 glDeleteTextures(1, &m_texture);
1194 return NO_ERROR;
1195 }
1196 };
1197 //-----------------------------------------------------------------------------
1198 // 1.1.3 BasicAPIBarrier
1199 //-----------------------------------------------------------------------------
1200 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1201 {
Run()1202 virtual long Run()
1203 {
1204 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1205 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1206 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1207 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1208 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1209 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1210 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1211 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1212 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1213 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1214 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1215 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1216
1217 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1218 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1219 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1220 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1221
1222 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1223
1224 return NO_ERROR;
1225 }
1226 };
1227 //-----------------------------------------------------------------------------
1228 // 1.1.4 BasicAPITexParam
1229 //-----------------------------------------------------------------------------
1230 class BasicAPITexParam : public ShaderImageLoadStoreBase
1231 {
1232 GLuint m_texture;
1233
Setup()1234 virtual long Setup()
1235 {
1236 m_texture = 0;
1237 return NO_ERROR;
1238 }
1239
Run()1240 virtual long Run()
1241 {
1242 glGenTextures(1, &m_texture);
1243 glBindTexture(GL_TEXTURE_2D, m_texture);
1244 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1245
1246 GLint i;
1247 GLfloat f;
1248 GLuint ui;
1249
1250 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1251 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1252 {
1253 m_context.getTestContext().getLog()
1254 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1255 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1256 << tcu::TestLog::EndMessage;
1257 return ERROR;
1258 }
1259 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1260 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1261 {
1262 m_context.getTestContext().getLog()
1263 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1264 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1265 << tcu::TestLog::EndMessage;
1266 return ERROR;
1267 }
1268 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1269 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1270 {
1271 m_context.getTestContext().getLog()
1272 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1273 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1274 << tcu::TestLog::EndMessage;
1275 return ERROR;
1276 }
1277 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1278 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1279 {
1280 m_context.getTestContext().getLog()
1281 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1282 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1283 << tcu::TestLog::EndMessage;
1284 return ERROR;
1285 }
1286
1287 return NO_ERROR;
1288 }
1289
Cleanup()1290 virtual long Cleanup()
1291 {
1292 glDeleteTextures(1, &m_texture);
1293 return NO_ERROR;
1294 }
1295 };
1296 //-----------------------------------------------------------------------------
1297 // 1.2.1 BasicAllFormatsStore
1298 //-----------------------------------------------------------------------------
1299 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1300 {
1301 GLuint m_vao;
1302 GLuint m_vbo;
1303
Setup()1304 virtual long Setup()
1305 {
1306 m_vao = 0;
1307 m_vbo = 0;
1308 return NO_ERROR;
1309 }
1310
Run()1311 virtual long Run()
1312 {
1313 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1314
1315 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1316 return ERROR;
1317 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1318 return ERROR;
1319 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1320 return ERROR;
1321
1322 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1323 return ERROR;
1324 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1325 return ERROR;
1326 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1327 return ERROR;
1328
1329 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1330 return ERROR;
1331 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1332 return ERROR;
1333 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1334 return ERROR;
1335
1336 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1337 return ERROR;
1338
1339 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1340 return ERROR;
1341 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1342 return ERROR;
1343 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1344 return ERROR;
1345
1346 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1347 return ERROR;
1348 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1349 return ERROR;
1350 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1351 return ERROR;
1352
1353 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354 return ERROR;
1355 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1356 return ERROR;
1357 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1358 return ERROR;
1359 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1360 return ERROR;
1361
1362 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1363 return ERROR;
1364 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1365 return ERROR;
1366 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1367 return ERROR;
1368
1369 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1370 return ERROR;
1371 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1372 return ERROR;
1373 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1374 return ERROR;
1375
1376 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1377 return ERROR;
1378 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1379 return ERROR;
1380 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1381 return ERROR;
1382 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1383 return ERROR;
1384
1385 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1386 return ERROR;
1387 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1388 return ERROR;
1389 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1390 return ERROR;
1391
1392 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1393 return ERROR;
1394 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1395 return ERROR;
1396 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1397 return ERROR;
1398
1399 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1400 return ERROR;
1401 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1402 return ERROR;
1403 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1404 return ERROR;
1405
1406 return NO_ERROR;
1407 }
1408
1409 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1410 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
1411 {
1412 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1413 " gl_Position = i_position;" NL "}";
1414 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1415 const int kSize = 16;
1416 std::vector<T> data(kSize * kSize);
1417 GLuint texture;
1418 glGenTextures(1, &texture);
1419
1420 for (GLuint unit = 0; unit < 8; ++unit)
1421 {
1422 glBindTexture(GL_TEXTURE_2D, texture);
1423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1425 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1426 glBindTexture(GL_TEXTURE_2D, 0);
1427
1428 glViewport(0, 0, kSize, kSize);
1429 glUseProgram(program);
1430 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1431 glBindVertexArray(m_vao);
1432 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1433
1434 glBindTexture(GL_TEXTURE_2D, texture);
1435 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1436 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1437
1438 for (int i = 0; i < kSize * kSize; ++i)
1439 {
1440 if (!Equal(data[i], expected_value, internalformat))
1441 {
1442 glDeleteTextures(1, &texture);
1443 glUseProgram(0);
1444 glDeleteProgram(program);
1445 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1446 << ". Value should be: " << ToString(expected_value)
1447 << ". Format is: " << FormatEnumToString(internalformat)
1448 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1449 return false;
1450 }
1451 }
1452
1453 if (unit < 7)
1454 {
1455 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1456 }
1457 }
1458
1459 glDeleteTextures(1, &texture);
1460 glUseProgram(0);
1461 glDeleteProgram(program);
1462
1463 return true;
1464 }
1465
Cleanup()1466 virtual long Cleanup()
1467 {
1468 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1469 glDeleteVertexArrays(1, &m_vao);
1470 glDeleteBuffers(1, &m_vbo);
1471 return NO_ERROR;
1472 }
1473
1474 template <typename T>
GenFS(GLenum internalformat,const T & value)1475 std::string GenFS(GLenum internalformat, const T &value)
1476 {
1477 std::ostringstream os;
1478 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1479 << TypePrefix<T>()
1480 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1481 " imageStore(g_image, coord, "
1482 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1483 return os.str();
1484 }
1485 };
1486 //-----------------------------------------------------------------------------
1487 // 1.2.2 BasicAllFormatsLoad
1488 //-----------------------------------------------------------------------------
1489 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1490 {
1491 GLuint m_vao;
1492 GLuint m_vbo;
1493
Setup()1494 virtual long Setup()
1495 {
1496 m_vao = 0;
1497 m_vbo = 0;
1498 return NO_ERROR;
1499 }
1500
Run()1501 virtual long Run()
1502 {
1503 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1504
1505 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1506 return ERROR;
1507 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1508 return ERROR;
1509 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1510 return ERROR;
1511
1512 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1513 return ERROR;
1514 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1515 return ERROR;
1516 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1517 return ERROR;
1518
1519 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1520 return ERROR;
1521 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1522 return ERROR;
1523 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1524 return ERROR;
1525
1526 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1527 return ERROR;
1528
1529 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1530 return ERROR;
1531 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1532 return ERROR;
1533 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1534 return ERROR;
1535
1536 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1537 return ERROR;
1538 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1539 return ERROR;
1540 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1541 return ERROR;
1542
1543 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1544 return ERROR;
1545 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1546 return ERROR;
1547 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1548 return ERROR;
1549 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1550 return ERROR;
1551
1552 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1553 return ERROR;
1554 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1555 return ERROR;
1556 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1557 return ERROR;
1558
1559 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1560 return ERROR;
1561 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1562 return ERROR;
1563 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1564 return ERROR;
1565
1566 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1567 return ERROR;
1568 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1569 return ERROR;
1570 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1571 return ERROR;
1572 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1573 return ERROR;
1574
1575 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1576 return ERROR;
1577 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1578 return ERROR;
1579 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1580 return ERROR;
1581
1582 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1583 return ERROR;
1584 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1585 return ERROR;
1586 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1587 return ERROR;
1588
1589 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1590 return ERROR;
1591 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1592 return ERROR;
1593 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1594 return ERROR;
1595
1596 return NO_ERROR;
1597 }
1598
1599 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1600 bool Read(GLenum internalformat, const T &value, const T &expected_value)
1601 {
1602 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1603 " gl_Position = i_position;" NL "}";
1604 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1605 const int kSize = 16;
1606 std::vector<T> data(kSize * kSize, value);
1607 GLuint texture;
1608 glGenTextures(1, &texture);
1609
1610 for (GLuint unit = 0; unit < 8; ++unit)
1611 {
1612 glBindTexture(GL_TEXTURE_2D, texture);
1613 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1614 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1615 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1616 glBindTexture(GL_TEXTURE_2D, 0);
1617
1618 glViewport(0, 0, kSize, kSize);
1619 glClear(GL_COLOR_BUFFER_BIT);
1620 glUseProgram(program);
1621 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1622 glBindVertexArray(m_vao);
1623 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1624
1625 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1626 {
1627 glDeleteTextures(1, &texture);
1628 glUseProgram(0);
1629 glDeleteProgram(program);
1630 m_context.getTestContext().getLog()
1631 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1632 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1633 return false;
1634 }
1635
1636 if (unit < 7)
1637 {
1638 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1639 }
1640 }
1641
1642 glDeleteTextures(1, &texture);
1643 glUseProgram(0);
1644 glDeleteProgram(program);
1645
1646 return true;
1647 }
1648
Cleanup()1649 virtual long Cleanup()
1650 {
1651 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1652 glDeleteVertexArrays(1, &m_vao);
1653 glDeleteBuffers(1, &m_vbo);
1654 return NO_ERROR;
1655 }
1656
1657 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1658 std::string GenFS(GLenum internalformat, const T &expected_value)
1659 {
1660 std::ostringstream os;
1661 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1662 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1663 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1664 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
1665 << expected_value
1666 << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1667 return os.str();
1668 }
1669 };
1670 //-----------------------------------------------------------------------------
1671 // 1.2.3 BasicAllFormatsStoreGeometryStages
1672 //-----------------------------------------------------------------------------
1673 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1674 {
1675 GLuint m_vao;
1676
Setup()1677 virtual long Setup()
1678 {
1679 glGenVertexArrays(1, &m_vao);
1680 return NO_ERROR;
1681 }
1682
Run()1683 virtual long Run()
1684 {
1685 if (!SupportedInGeomStages(1))
1686 return NOT_SUPPORTED;
1687 glEnable(GL_RASTERIZER_DISCARD);
1688
1689 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1690 return ERROR;
1691 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1692 return ERROR;
1693 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1694 return ERROR;
1695
1696 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1697 return ERROR;
1698 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1699 return ERROR;
1700 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1701 return ERROR;
1702
1703 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1704 return ERROR;
1705 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1706 return ERROR;
1707 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1708 return ERROR;
1709
1710 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1711 return ERROR;
1712
1713 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1714 return ERROR;
1715 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1716 return ERROR;
1717 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1718 return ERROR;
1719
1720 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1721 return ERROR;
1722 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1723 return ERROR;
1724 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1725 return ERROR;
1726
1727 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1728 return ERROR;
1729 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1730 return ERROR;
1731 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1732 return ERROR;
1733 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1734 return ERROR;
1735
1736 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1737 return ERROR;
1738 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1739 return ERROR;
1740 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1741 return ERROR;
1742
1743 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1744 return ERROR;
1745 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1746 return ERROR;
1747 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1748 return ERROR;
1749
1750 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1751 return ERROR;
1752 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1753 return ERROR;
1754 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1755 return ERROR;
1756 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1757 return ERROR;
1758
1759 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1760 return ERROR;
1761 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1762 return ERROR;
1763 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1764 return ERROR;
1765
1766 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1767 return ERROR;
1768 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1769 return ERROR;
1770 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1771 return ERROR;
1772
1773 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1774 return ERROR;
1775 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1776 return ERROR;
1777 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1778 return ERROR;
1779
1780 return NO_ERROR;
1781 }
1782
1783 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1784 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
1785 {
1786 const GLuint program =
1787 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1788 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1789 const int kSize = 1;
1790 std::vector<T> data(kSize * kSize);
1791 GLuint texture[4];
1792 glGenTextures(4, texture);
1793
1794 for (int i = 0; i < 4; ++i)
1795 {
1796 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1797 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1798 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1799 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1800 }
1801 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1802
1803 glUseProgram(program);
1804 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1805 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1806 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1807 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1808 for (GLuint i = 0; i < 4; ++i)
1809 {
1810 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1811 }
1812 glBindVertexArray(m_vao);
1813 glPatchParameteri(GL_PATCH_VERTICES, 1);
1814 glDrawArrays(GL_PATCHES, 0, 1);
1815 glPatchParameteri(GL_PATCH_VERTICES, 3);
1816
1817 for (int i = 0; i < 4; ++i)
1818 {
1819 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1820 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1821 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1822
1823 if (!Equal(data[0], expected_value, internalformat))
1824 {
1825 glDeleteTextures(4, texture);
1826 glUseProgram(0);
1827 glDeleteProgram(program);
1828 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1829 << ". Value should be: " << ToString(expected_value)
1830 << ". Format is: " << FormatEnumToString(internalformat)
1831 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1832 return false;
1833 }
1834 }
1835 glDeleteTextures(4, texture);
1836 glUseProgram(0);
1837 glDeleteProgram(program);
1838 return true;
1839 }
1840
Cleanup()1841 virtual long Cleanup()
1842 {
1843 glDisable(GL_RASTERIZER_DISCARD);
1844 glDeleteVertexArrays(1, &m_vao);
1845 return NO_ERROR;
1846 }
1847
1848 template <typename T>
GenVS(GLenum internalformat,const T & value)1849 std::string GenVS(GLenum internalformat, const T &value)
1850 {
1851 std::ostringstream os;
1852 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1853 << TypePrefix<T>()
1854 << "image2DArray g_image0;" NL "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL
1855 " imageStore(g_image0, coord, "
1856 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1857 return os.str();
1858 }
1859
1860 template <typename T>
GenTCS(GLenum internalformat,const T & value)1861 std::string GenTCS(GLenum internalformat, const T &value)
1862 {
1863 std::ostringstream os;
1864 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1865 << ") writeonly uniform " << TypePrefix<T>()
1866 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
1867 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
1868 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
1869 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, "
1870 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1871 return os.str();
1872 }
1873
1874 template <typename T>
GenTES(GLenum internalformat,const T & value)1875 std::string GenTES(GLenum internalformat, const T &value)
1876 {
1877 std::ostringstream os;
1878 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1879 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1880 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1881 " imageStore(g_image2, coord, "
1882 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1883 return os.str();
1884 }
1885
1886 template <typename T>
GenGS(GLenum internalformat,const T & value)1887 std::string GenGS(GLenum internalformat, const T &value)
1888 {
1889 std::ostringstream os;
1890 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1891 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1892 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1893 " imageStore(g_image3, coord, "
1894 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1895 return os.str();
1896 }
1897 };
1898 //-----------------------------------------------------------------------------
1899 // 1.2.4 BasicAllFormatsLoadGeometryStages
1900 //-----------------------------------------------------------------------------
1901 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1902 {
1903 GLuint m_vao;
1904
Setup()1905 virtual long Setup()
1906 {
1907 glGenVertexArrays(1, &m_vao);
1908 return NO_ERROR;
1909 }
1910
Run()1911 virtual long Run()
1912 {
1913 if (!SupportedInGeomStages(2))
1914 return NOT_SUPPORTED;
1915 glEnable(GL_RASTERIZER_DISCARD);
1916
1917 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1918 return ERROR;
1919 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1920 return ERROR;
1921 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1922 return ERROR;
1923
1924 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1925 return ERROR;
1926 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1927 return ERROR;
1928 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1929 return ERROR;
1930
1931 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1932 return ERROR;
1933 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1934 return ERROR;
1935 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1936 return ERROR;
1937
1938 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1939 return ERROR;
1940
1941 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1942 return ERROR;
1943 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1944 return ERROR;
1945 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1946 return ERROR;
1947
1948 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1949 return ERROR;
1950 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1951 return ERROR;
1952 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1953 return ERROR;
1954
1955 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1956 return ERROR;
1957 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1958 return ERROR;
1959 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1960 return ERROR;
1961 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1962 return ERROR;
1963
1964 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1965 return ERROR;
1966 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1967 return ERROR;
1968 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1969 return ERROR;
1970
1971 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1972 return ERROR;
1973 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1974 return ERROR;
1975 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1976 return ERROR;
1977
1978 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1979 return ERROR;
1980 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1981 return ERROR;
1982 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1983 return ERROR;
1984 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1985 return ERROR;
1986
1987 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1988 return ERROR;
1989 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1990 return ERROR;
1991 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1992 return ERROR;
1993
1994 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1995 return ERROR;
1996 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1997 return ERROR;
1998 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1999 return ERROR;
2000
2001 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2002 return ERROR;
2003 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2004 return ERROR;
2005 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2006 return ERROR;
2007
2008 return NO_ERROR;
2009 }
2010
2011 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2012 bool Read(GLenum internalformat, const T &value, const T &expected_value)
2013 {
2014 const GLuint program = BuildProgram(
2015 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2016 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2017 const int kSize = 1;
2018 std::vector<T> data(kSize * kSize, value);
2019 GLuint texture[8];
2020 glGenTextures(8, texture);
2021
2022 for (int i = 0; i < 4; ++i)
2023 {
2024 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2025 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2026 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2027 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2028 }
2029 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2030 vec4 zero(0);
2031 for (int i = 4; i < 8; ++i)
2032 {
2033 glBindTexture(GL_TEXTURE_2D, texture[i]);
2034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2035 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2036 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2037 }
2038 glBindTexture(GL_TEXTURE_2D, 0);
2039
2040 glUseProgram(program);
2041 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2042 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2043 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2044 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2045 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2046 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2047 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2048 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2049
2050 for (GLuint i = 0; i < 4; ++i)
2051 {
2052 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2053 }
2054 for (GLuint i = 4; i < 8; ++i)
2055 {
2056 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2057 }
2058 glBindVertexArray(m_vao);
2059 glPatchParameteri(GL_PATCH_VERTICES, 1);
2060 glDrawArrays(GL_PATCHES, 0, 1);
2061 glPatchParameteri(GL_PATCH_VERTICES, 3);
2062
2063 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
2064 const tcu::PixelFormat &pixelFormat = renderTarget.getPixelFormat();
2065 vec4 g_color_eps = vec4(
2066 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2067 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2068
2069 for (int i = 0; i < 4; ++i)
2070 {
2071 glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2072 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2073 vec4 result;
2074 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2075 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2076 {
2077 glDeleteTextures(8, texture);
2078 glUseProgram(0);
2079 glDeleteProgram(program);
2080 m_context.getTestContext().getLog()
2081 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2082 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2083 return false;
2084 }
2085 }
2086 glDeleteTextures(8, texture);
2087 glUseProgram(0);
2088 glDeleteProgram(program);
2089 return true;
2090 }
2091
Cleanup()2092 virtual long Cleanup()
2093 {
2094 glDisable(GL_RASTERIZER_DISCARD);
2095 glDeleteVertexArrays(1, &m_vao);
2096 return NO_ERROR;
2097 }
2098
2099 template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2100 std::string GenVS(GLenum internalformat, const T &expected_value)
2101 {
2102 std::ostringstream os;
2103 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2104 << TypePrefix<T>()
2105 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2106 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " "
2107 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2108 << expected_value
2109 << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2110 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2111 return os.str();
2112 }
2113
2114 template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2115 std::string GenTCS(GLenum internalformat, const T &expected_value)
2116 {
2117 std::ostringstream os;
2118 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2119 << ") readonly uniform " << TypePrefix<T>()
2120 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2121 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL
2122 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL
2123 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2124 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2125 << expected_value
2126 << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2127 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2128 return os.str();
2129 }
2130
2131 template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2132 std::string GenTES(GLenum internalformat, const T &expected_value)
2133 {
2134 std::ostringstream os;
2135 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2136 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2137 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2138 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2139 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2140 << expected_value
2141 << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2142 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2143 return os.str();
2144 }
2145
2146 template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2147 std::string GenGS(GLenum internalformat, const T &expected_value)
2148 {
2149 std::ostringstream os;
2150 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2151 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2152 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2153 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " "
2154 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2155 << expected_value
2156 << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2157 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2158 return os.str();
2159 }
2160 };
2161 //-----------------------------------------------------------------------------
2162 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2163 //-----------------------------------------------------------------------------
2164 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2165 {
Run()2166 virtual long Run()
2167 {
2168 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2169 {
2170 m_context.getTestContext().getLog()
2171 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2172 << tcu::TestLog::EndMessage;
2173 return NOT_SUPPORTED;
2174 }
2175
2176 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2177 return ERROR;
2178 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2179 return ERROR;
2180 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2181 return ERROR;
2182
2183 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2184 return ERROR;
2185 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2186 return ERROR;
2187 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2188 return ERROR;
2189
2190 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2191 return ERROR;
2192 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2193 return ERROR;
2194 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2195 return ERROR;
2196
2197 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2198 return ERROR;
2199
2200 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2201 return ERROR;
2202 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2203 return ERROR;
2204 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2205 return ERROR;
2206
2207 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2208 return ERROR;
2209 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2210 return ERROR;
2211 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2212 return ERROR;
2213
2214 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2215 return ERROR;
2216 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2217 return ERROR;
2218 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2219 return ERROR;
2220 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2221 return ERROR;
2222
2223 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2224 return ERROR;
2225 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2226 return ERROR;
2227 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2228 return ERROR;
2229
2230 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2231 return ERROR;
2232 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2233 return ERROR;
2234 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2235 return ERROR;
2236
2237 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2238 return ERROR;
2239 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2240 return ERROR;
2241 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2242 return ERROR;
2243 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2244 return ERROR;
2245
2246 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2247 return ERROR;
2248 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2249 return ERROR;
2250 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2251 return ERROR;
2252
2253 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2254 return ERROR;
2255 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2256 return ERROR;
2257 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2258 return ERROR;
2259
2260 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2261 return ERROR;
2262 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2263 return ERROR;
2264 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2265 return ERROR;
2266
2267 return NO_ERROR;
2268 }
2269
2270 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2271 bool Read(GLenum internalformat, const T &value, const T &expected_value)
2272 {
2273 GLuint program;
2274 std::string source = GenCS<T>(internalformat);
2275 const char *const src = source.c_str();
2276 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2277 glShaderSource(sh, 1, &src, NULL);
2278 glCompileShader(sh);
2279 program = glCreateProgram();
2280 glAttachShader(program, sh);
2281 glLinkProgram(program);
2282 glDeleteShader(sh);
2283
2284 const int kSize = 1;
2285 std::vector<T> data(kSize * kSize, value);
2286 GLuint texture[2];
2287 glGenTextures(2, texture);
2288
2289 glBindTexture(GL_TEXTURE_2D, texture[0]);
2290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2292 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2293 glBindTexture(GL_TEXTURE_2D, texture[1]);
2294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2296 vec4 zero(0);
2297 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2298
2299 glBindTexture(GL_TEXTURE_2D, 0);
2300
2301 glUseProgram(program);
2302 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2303 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2304
2305 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2306 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2307
2308 glDispatchCompute(1, 1, 1);
2309
2310 for (int i = 0; i < 2; ++i)
2311 {
2312 glBindTexture(GL_TEXTURE_2D, texture[i]);
2313 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2314 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2315
2316 if (!Equal(data[0], expected_value, internalformat))
2317 {
2318 glDeleteTextures(4, texture);
2319 glUseProgram(0);
2320 glDeleteProgram(program);
2321 m_context.getTestContext().getLog()
2322 << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2323 << ". Value should be: " << ToString(expected_value)
2324 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2325 return false;
2326 }
2327 }
2328 glDeleteTextures(2, texture);
2329 glUseProgram(0);
2330 glDeleteProgram(program);
2331 return true;
2332 }
2333
2334 template <typename T>
GenCS(GLenum internalformat)2335 std::string GenCS(GLenum internalformat)
2336 {
2337 std::ostringstream os;
2338 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2339 "layout("
2340 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2341 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2342 << TypePrefix<T>()
2343 << "image2D g_image_write;" NL "void main() {" NL
2344 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " "
2345 << TypePrefix<T>()
2346 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}";
2347 return os.str();
2348 }
2349 };
2350 //-----------------------------------------------------------------------------
2351 // 1.3.1 BasicAllTargetsStore
2352 //-----------------------------------------------------------------------------
2353 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2354 {
2355 GLuint m_vao;
2356 GLuint m_vbo;
2357
Setup()2358 virtual long Setup()
2359 {
2360 m_vao = 0;
2361 m_vbo = 0;
2362 return NO_ERROR;
2363 }
2364
Run()2365 virtual long Run()
2366 {
2367 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2368
2369 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2370 return ERROR;
2371 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2372 return ERROR;
2373 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2374 return ERROR;
2375
2376 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2377 return ERROR;
2378 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2379 return ERROR;
2380 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2381 return ERROR;
2382
2383 if (SupportedSamples(4))
2384 {
2385 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2386 return ERROR;
2387
2388 GLint isamples;
2389 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2390 if (isamples >= 4)
2391 {
2392 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2393 return ERROR;
2394 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2395 return ERROR;
2396 }
2397 }
2398 return NO_ERROR;
2399 }
2400
Cleanup()2401 virtual long Cleanup()
2402 {
2403 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2404 glDeleteVertexArrays(1, &m_vao);
2405 glDeleteBuffers(1, &m_vbo);
2406 return NO_ERROR;
2407 }
2408
2409 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2410 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
2411 {
2412 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2413 " gl_Position = i_position;" NL "}";
2414 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2415 GLuint textures[8];
2416 GLuint buffer;
2417 glGenTextures(8, textures);
2418 glGenBuffers(1, &buffer);
2419
2420 const int kSize = 16;
2421 std::vector<T> data(kSize * kSize * 2);
2422
2423 glBindTexture(GL_TEXTURE_1D, textures[0]);
2424 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2425 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2426 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2427 glBindTexture(GL_TEXTURE_1D, 0);
2428
2429 glBindTexture(GL_TEXTURE_2D, textures[1]);
2430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2431 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2432 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2433 glBindTexture(GL_TEXTURE_2D, 0);
2434
2435 glBindTexture(GL_TEXTURE_3D, textures[2]);
2436 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2437 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2438 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2439 glBindTexture(GL_TEXTURE_3D, 0);
2440
2441 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2442 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2443 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2444 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2445 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2446
2447 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2448 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2449 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2450 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451 &data[0]);
2452 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2453 &data[0]);
2454 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2455 &data[0]);
2456 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2457 &data[0]);
2458 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2459 &data[0]);
2460 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2461 &data[0]);
2462 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2463
2464 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2465 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2466 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2467 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2468 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2469 glBindTexture(GL_TEXTURE_BUFFER, 0);
2470
2471 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2472 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2473 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2474 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2475 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2476
2477 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2478 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2479 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2480 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2481 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2482
2483 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2484 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2485 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2486 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2487 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2488 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2489 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2490 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2491
2492 glUseProgram(program);
2493 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2494 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2495 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2496 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2497 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2498 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2499 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2500 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2501
2502 glBindVertexArray(m_vao);
2503 glViewport(0, 0, kSize, kSize);
2504 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2505
2506 bool status = true;
2507
2508 glBindTexture(GL_TEXTURE_1D, textures[0]);
2509 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2510 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2511 glBindTexture(GL_TEXTURE_1D, 0);
2512 for (int i = 0; i < kSize; ++i)
2513 {
2514 if (!tcu::allEqual(data[i], expected_value))
2515 {
2516 status = false;
2517 m_context.getTestContext().getLog()
2518 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2519 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2520 break;
2521 }
2522 }
2523 std::fill(data.begin(), data.end(), T(0));
2524
2525 glBindTexture(GL_TEXTURE_2D, textures[1]);
2526 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2527 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2528 glBindTexture(GL_TEXTURE_2D, 0);
2529 for (int i = 0; i < kSize * kSize; ++i)
2530 {
2531 if (!tcu::allEqual(data[i], expected_value))
2532 {
2533 status = false;
2534 m_context.getTestContext().getLog()
2535 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2536 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2537 break;
2538 }
2539 }
2540
2541 glBindTexture(GL_TEXTURE_3D, textures[2]);
2542 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2543 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2544 glBindTexture(GL_TEXTURE_3D, 0);
2545 for (int i = 0; i < kSize * kSize * 2; ++i)
2546 {
2547 if (!tcu::allEqual(data[i], expected_value))
2548 {
2549 status = false;
2550 m_context.getTestContext().getLog()
2551 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2552 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2553 break;
2554 }
2555 }
2556
2557 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2558 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2559 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2560 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2561 for (int i = 0; i < kSize * kSize; ++i)
2562 {
2563 if (!tcu::allEqual(data[i], expected_value))
2564 {
2565 status = false;
2566 m_context.getTestContext().getLog()
2567 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2568 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2569 break;
2570 }
2571 }
2572
2573 {
2574 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2575 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2576 for (int face = 0; face < 6; ++face)
2577 {
2578 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2579 for (int i = 0; i < kSize * kSize; ++i)
2580 {
2581 if (!tcu::allEqual(data[i], expected_value))
2582 {
2583 status = false;
2584 m_context.getTestContext().getLog()
2585 << tcu::TestLog::Message
2586 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2587 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2588 break;
2589 }
2590 }
2591 }
2592 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2593 }
2594
2595 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2596 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2597 glBindTexture(GL_TEXTURE_BUFFER, 0);
2598 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2599 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2600 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2601 for (int i = 0; i < kSize; ++i)
2602 {
2603 if (!tcu::allEqual(data[i], expected_value))
2604 {
2605 status = false;
2606 m_context.getTestContext().getLog()
2607 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2608 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2609 break;
2610 }
2611 }
2612
2613 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2614 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2615 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2616 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2617 for (int i = 0; i < kSize * 2; ++i)
2618 {
2619 if (!tcu::allEqual(data[i], expected_value))
2620 {
2621 status = false;
2622 m_context.getTestContext().getLog()
2623 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2624 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2625 break;
2626 }
2627 }
2628
2629 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2630 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2631 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2632 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2633 for (int i = 0; i < kSize * kSize * 2; ++i)
2634 {
2635 if (!tcu::allEqual(data[i], expected_value))
2636 {
2637 status = false;
2638 m_context.getTestContext().getLog()
2639 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2640 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2641 break;
2642 }
2643 }
2644
2645 glUseProgram(0);
2646 glDeleteProgram(program);
2647 glDeleteTextures(8, textures);
2648 glDeleteBuffers(1, &buffer);
2649
2650 return status;
2651 }
2652
2653 template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2654 bool WriteMS(GLenum internalformat, const T &write_value, const T &expected_value)
2655 {
2656
2657 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2658 " gl_Position = i_position;" NL "}";
2659 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2660 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2661 GLuint textures[2];
2662 glGenTextures(2, textures);
2663
2664 const int kSize = 16;
2665
2666 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2667 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2668 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2669
2670 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2671 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2672 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2673
2674 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2675 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2676
2677 glClear(GL_COLOR_BUFFER_BIT);
2678 glUseProgram(program);
2679 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2680 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2681
2682 glBindVertexArray(m_vao);
2683 glViewport(0, 0, kSize, kSize);
2684 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2685
2686 bool status = true;
2687
2688 glActiveTexture(GL_TEXTURE0);
2689 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2690 glActiveTexture(GL_TEXTURE1);
2691 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2692
2693 glUseProgram(val_program);
2694 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2695 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2696
2697 glBindVertexArray(m_vao);
2698 glViewport(0, 0, kSize, kSize);
2699 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2700 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2701
2702 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2703 {
2704 status = false;
2705 m_context.getTestContext().getLog()
2706 << tcu::TestLog::Message
2707 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2708 << tcu::TestLog::EndMessage;
2709 }
2710
2711 glActiveTexture(GL_TEXTURE0);
2712 glDeleteTextures(2, textures);
2713 glUseProgram(0);
2714 glDeleteProgram(program);
2715 glDeleteProgram(val_program);
2716
2717 return status;
2718 }
2719
2720 template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2721 bool WriteCubeArray(GLenum internalformat, const T &write_value, const T &expected_value)
2722 {
2723 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2724 " gl_Position = i_position;" NL "}";
2725 const GLuint program =
2726 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2727 GLuint textures[1];
2728 glGenTextures(1, textures);
2729
2730 const int kSize = 16;
2731
2732 std::vector<T> data(kSize * kSize * 12);
2733 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2734 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2735 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2736 &data[0]);
2737 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2738
2739 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2740
2741 glUseProgram(program);
2742 glBindVertexArray(m_vao);
2743 glViewport(0, 0, kSize, kSize);
2744 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2745
2746 bool status = true;
2747
2748 std::fill(data.begin(), data.end(), T(0));
2749 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2750 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2751 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2752 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2753 for (int i = 0; i < kSize * kSize * 12; ++i)
2754 {
2755 if (!tcu::allEqual(data[i], expected_value))
2756 {
2757 status = false;
2758 m_context.getTestContext().getLog()
2759 << tcu::TestLog::Message
2760 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2761 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2762 break;
2763 }
2764 }
2765
2766 glDeleteTextures(1, textures);
2767 glUseProgram(0);
2768 glDeleteProgram(program);
2769
2770 return status;
2771 }
2772
2773 template <typename T>
GenFS(GLenum internalformat,const T & write_value)2774 std::string GenFS(GLenum internalformat, const T &write_value)
2775 {
2776 std::ostringstream os;
2777 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2778 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2779 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2780 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2781 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2782 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2783 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2784 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2785 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2786 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2787 << ") writeonly uniform " << TypePrefix<T>()
2788 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2789 " imageStore(g_image_1d, coord.x, "
2790 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>()
2791 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2792 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2793 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2794 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2797 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2798 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2799 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2800 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2801 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2802 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2803 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2804 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2805 << write_value << ");" NL " discard;" NL "}";
2806 return os.str();
2807 }
2808
2809 template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2810 std::string GenFSMS(GLenum internalformat, const T &write_value)
2811 {
2812 std::ostringstream os;
2813 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2814 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2815 << ") writeonly uniform " << TypePrefix<T>()
2816 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2817 " imageStore(g_image_2dms, coord, 0, "
2818 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, "
2819 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, "
2820 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, "
2821 << TypePrefix<T>() << "vec4" << write_value
2822 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2823 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2824 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2825 << TypePrefix<T>() << "vec4" << write_value
2826 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2827 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2828 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2829 << TypePrefix<T>() << "vec4" << write_value
2830 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2831 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2832 << "vec4" << write_value << ");" NL " discard;" NL "}";
2833 return os.str();
2834 }
2835
2836 template <typename T>
GenFSMSVal(const T & expected_value)2837 std::string GenFSMSVal(const T &expected_value)
2838 {
2839 std::ostringstream os;
2840 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2841 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2842 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2843 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != "
2844 << TypePrefix<T>() << "vec4" << expected_value
2845 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != "
2846 << TypePrefix<T>() << "vec4" << expected_value
2847 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != "
2848 << TypePrefix<T>() << "vec4" << expected_value
2849 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != "
2850 << TypePrefix<T>() << "vec4" << expected_value
2851 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2852 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2853 << TypePrefix<T>() << "vec4" << expected_value
2854 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2856 << TypePrefix<T>() << "vec4" << expected_value
2857 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2858 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2859 << TypePrefix<T>() << "vec4" << expected_value
2860 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2861 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2862 << TypePrefix<T>() << "vec4" << expected_value
2863 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2864 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2865 << TypePrefix<T>() << "vec4" << expected_value
2866 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2867 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2868 << TypePrefix<T>() << "vec4" << expected_value
2869 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2870 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2871 << TypePrefix<T>() << "vec4" << expected_value
2872 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2873 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2874 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2875 return os.str();
2876 }
2877
2878 template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2879 std::string GenFSCubeArray(GLenum internalformat, const T &write_value)
2880 {
2881 std::ostringstream os;
2882 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2883 << TypePrefix<T>()
2884 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2885 " imageStore(g_image_cube_array, ivec3(coord, 0), "
2886 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), "
2887 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), "
2888 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), "
2889 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), "
2890 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), "
2891 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), "
2892 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), "
2893 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), "
2894 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), "
2895 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), "
2896 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), "
2897 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}";
2898 return os.str();
2899 }
2900 };
2901 //-----------------------------------------------------------------------------
2902 // 1.3.2.1 BasicAllTargetsLoadNonMS
2903 //-----------------------------------------------------------------------------
2904 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2905 {
2906 GLuint m_vao;
2907 GLuint m_vbo;
2908
Setup()2909 virtual long Setup()
2910 {
2911 m_vao = 0;
2912 m_vbo = 0;
2913 return NO_ERROR;
2914 }
2915
Run()2916 virtual long Run()
2917 {
2918 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2919
2920 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2921 return ERROR;
2922 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2923 return ERROR;
2924 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2925 return ERROR;
2926
2927 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2928 return ERROR;
2929 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2930 return ERROR;
2931 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2932 return ERROR;
2933
2934 return NO_ERROR;
2935 }
2936
Cleanup()2937 virtual long Cleanup()
2938 {
2939 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2940 glDeleteVertexArrays(1, &m_vao);
2941 glDeleteBuffers(1, &m_vbo);
2942 return NO_ERROR;
2943 }
2944
2945 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2946 bool Read(GLenum internalformat, const T &value, const T &expected_value)
2947 {
2948 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2949 " gl_Position = i_position;" NL "}";
2950 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2951 GLuint textures[7];
2952 GLuint buffer;
2953 glGenTextures(7, textures);
2954 glGenBuffers(1, &buffer);
2955
2956 const int kSize = 16;
2957 std::vector<T> data(kSize * kSize * 2, value);
2958
2959 glBindTexture(GL_TEXTURE_1D, textures[0]);
2960 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2961 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2962 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2963 glBindTexture(GL_TEXTURE_1D, 0);
2964
2965 glBindTexture(GL_TEXTURE_2D, textures[1]);
2966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2968 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2969 glBindTexture(GL_TEXTURE_2D, 0);
2970
2971 glBindTexture(GL_TEXTURE_3D, textures[2]);
2972 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2973 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2974 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2975 glBindTexture(GL_TEXTURE_3D, 0);
2976
2977 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2978 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2979 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2980 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2981 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2982
2983 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2984 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2985 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2986 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2987 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2988 glBindTexture(GL_TEXTURE_BUFFER, 0);
2989
2990 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2991 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2992 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2993 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2994 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2995
2996 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2997 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2998 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2999 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3000 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3001
3002 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3003 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3004 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3005 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3006 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3007 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3008 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3009
3010 glClear(GL_COLOR_BUFFER_BIT);
3011
3012 glUseProgram(program);
3013 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3014 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3015 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3016 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3017 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3018 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3019 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3020
3021 glBindVertexArray(m_vao);
3022 glViewport(0, 0, kSize, kSize);
3023 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3024
3025 bool status = true;
3026
3027 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3028 {
3029 status = false;
3030 }
3031
3032 std::map<std::string, GLuint> name_index_map;
3033 GLint uniforms;
3034 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3035 if (uniforms != 7)
3036 {
3037 status = false;
3038 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3039 << " should be 7." << tcu::TestLog::EndMessage;
3040 }
3041 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3042 {
3043 GLchar name[32];
3044 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3045 name_index_map.insert(std::make_pair(std::string(name), index));
3046 }
3047
3048 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3049 status = false;
3050 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3051 status = false;
3052 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3053 status = false;
3054 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3055 status = false;
3056 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3057 status = false;
3058 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3059 status = false;
3060 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3061 status = false;
3062
3063 glUseProgram(0);
3064 glDeleteProgram(program);
3065 glDeleteTextures(7, textures);
3066 glDeleteBuffers(1, &buffer);
3067
3068 return status;
3069 }
3070
3071 template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3072 bool ReadCube(GLenum internalformat, const T &value, const T &expected_value)
3073 {
3074 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3075 " gl_Position = i_position;" NL "}";
3076 const GLuint program =
3077 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3078 GLuint textures[2];
3079 glGenTextures(2, textures);
3080
3081 const int kSize = 16;
3082 std::vector<T> data(kSize * kSize * 12, value);
3083
3084 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3085 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3086 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3087 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088 &data[0]);
3089 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3090 &data[0]);
3091 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3092 &data[0]);
3093 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3094 &data[0]);
3095 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3096 &data[0]);
3097 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3098 &data[0]);
3099 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3100
3101 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3102 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3103 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3104 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3105 &data[0]);
3106 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3107
3108 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3109 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3110
3111 glClear(GL_COLOR_BUFFER_BIT);
3112
3113 glUseProgram(program);
3114 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3115 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3116
3117 glBindVertexArray(m_vao);
3118 glViewport(0, 0, kSize, kSize);
3119 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3120
3121 bool status = true;
3122
3123 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3124 {
3125 status = false;
3126 }
3127
3128 std::map<std::string, GLuint> name_index_map;
3129 GLint uniforms;
3130 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3131 if (uniforms != 2)
3132 {
3133 status = false;
3134 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3135 << " should be 2." << tcu::TestLog::EndMessage;
3136 }
3137 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3138 {
3139 GLchar name[32];
3140 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3141 name_index_map.insert(std::make_pair(std::string(name), index));
3142 }
3143
3144 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3145 status = false;
3146 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3147 status = false;
3148
3149 glUseProgram(0);
3150 glDeleteProgram(program);
3151 glDeleteTextures(2, textures);
3152
3153 return status;
3154 }
3155
3156 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3157 std::string GenFS(GLenum internalformat, const T &expected_value)
3158 {
3159 std::ostringstream os;
3160 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3161 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3162 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3163 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3164 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3165 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3166 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3167 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3168 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3169 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3170 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3171 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3172 << TypePrefix<T>()
3173 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4"
3174 << expected_value
3175 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != "
3176 << TypePrefix<T>() << "vec4" << expected_value
3177 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3178 " if (v != "
3179 << TypePrefix<T>() << "vec4" << expected_value
3180 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3181 " if (v != "
3182 << TypePrefix<T>() << "vec4" << expected_value
3183 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != "
3184 << TypePrefix<T>() << "vec4" << expected_value
3185 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != "
3186 << TypePrefix<T>() << "vec4" << expected_value
3187 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3188 " if (v != "
3189 << TypePrefix<T>() << "vec4" << expected_value
3190 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3191 " if (v != "
3192 << TypePrefix<T>() << "vec4" << expected_value
3193 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3194 " if (v != "
3195 << TypePrefix<T>() << "vec4" << expected_value
3196 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3197 " if (v != "
3198 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3199 return os.str();
3200 }
3201
3202 template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3203 std::string GenFSCube(GLenum internalformat, const T &expected_value)
3204 {
3205 std::ostringstream os;
3206 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3207 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3208 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3209 << TypePrefix<T>()
3210 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3211 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3212 << TypePrefix<T>()
3213 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>()
3214 << "vec4" << expected_value
3215 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL
3216 " if (v != "
3217 << TypePrefix<T>() << "vec4" << expected_value
3218 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3219 " if (v != "
3220 << TypePrefix<T>() << "vec4" << expected_value
3221 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3222 " if (v != "
3223 << TypePrefix<T>() << "vec4" << expected_value
3224 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3225 " if (v != "
3226 << TypePrefix<T>() << "vec4" << expected_value
3227 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3228 " if (v != "
3229 << TypePrefix<T>() << "vec4" << expected_value
3230 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3231 " if (v != "
3232 << TypePrefix<T>() << "vec4" << expected_value
3233 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3234 " if (v != "
3235 << TypePrefix<T>() << "vec4" << expected_value
3236 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3237 " if (v != "
3238 << TypePrefix<T>() << "vec4" << expected_value
3239 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3240 " if (v != "
3241 << TypePrefix<T>() << "vec4" << expected_value
3242 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3243 " if (v != "
3244 << TypePrefix<T>() << "vec4" << expected_value
3245 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3246 " if (v != "
3247 << TypePrefix<T>() << "vec4" << expected_value
3248 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3249 " if (v != "
3250 << TypePrefix<T>() << "vec4" << expected_value
3251 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3252 " if (v != "
3253 << TypePrefix<T>() << "vec4" << expected_value
3254 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3255 " if (v != "
3256 << TypePrefix<T>() << "vec4" << expected_value
3257 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3258 " if (v != "
3259 << TypePrefix<T>() << "vec4" << expected_value
3260 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3261 " if (v != "
3262 << TypePrefix<T>() << "vec4" << expected_value
3263 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3264 " if (v != "
3265 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3266 return os.str();
3267 }
3268 };
3269 //-----------------------------------------------------------------------------
3270 // 1.3.2.2 BasicAllTargetsLoadMS
3271 //-----------------------------------------------------------------------------
3272 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3273 {
3274 GLuint m_vao;
3275 GLuint m_vbo;
3276
Setup()3277 virtual long Setup()
3278 {
3279 m_vao = 0;
3280 m_vbo = 0;
3281 return NO_ERROR;
3282 }
3283
Run()3284 virtual long Run()
3285 {
3286 if (!SupportedSamples(4))
3287 return NOT_SUPPORTED;
3288
3289 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3290
3291 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3292 return ERROR;
3293
3294 GLint isamples;
3295 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3296 if (isamples >= 4)
3297 {
3298 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3299 return ERROR;
3300 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3301 return ERROR;
3302 }
3303
3304 return NO_ERROR;
3305 }
3306
Cleanup()3307 virtual long Cleanup()
3308 {
3309 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3310 glDeleteVertexArrays(1, &m_vao);
3311 glDeleteBuffers(1, &m_vbo);
3312 return NO_ERROR;
3313 }
3314
3315 template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3316 bool ReadMS(GLenum internalformat, const T &value, const T &expected_value)
3317 {
3318 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3319 " gl_Position = i_position;" NL "}";
3320 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3321 GLuint textures[2];
3322 glGenTextures(2, textures);
3323
3324 const int kSize = 16;
3325
3326 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3327 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3328 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3329
3330 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3331 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3332 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3333
3334 GLuint fbo;
3335 glGenFramebuffers(1, &fbo);
3336 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3337 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3338 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3339 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3340 const GLenum draw_buffers[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
3341 glDrawBuffers(3, draw_buffers);
3342 ClearBuffer(GL_COLOR, 0, value);
3343 ClearBuffer(GL_COLOR, 1, value);
3344 ClearBuffer(GL_COLOR, 2, value);
3345 glDeleteFramebuffers(1, &fbo);
3346
3347 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3348 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3349
3350 glUseProgram(program);
3351 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3352 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3353
3354 glClear(GL_COLOR_BUFFER_BIT);
3355 glBindVertexArray(m_vao);
3356 glViewport(0, 0, kSize, kSize);
3357 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3358
3359 bool status = true;
3360
3361 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3362 {
3363 status = false;
3364 }
3365
3366 std::map<std::string, GLuint> name_index_map;
3367 GLint uniforms;
3368 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3369 if (uniforms != 2)
3370 {
3371 status = false;
3372 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3373 << " should be 2." << tcu::TestLog::EndMessage;
3374 }
3375 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3376 {
3377 GLchar name[32];
3378 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3379 name_index_map.insert(std::make_pair(std::string(name), index));
3380 }
3381
3382 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3383 status = false;
3384 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3385 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3386 status = false;
3387
3388 glDeleteTextures(2, textures);
3389 glUseProgram(0);
3390 glDeleteProgram(program);
3391
3392 return status;
3393 }
3394
3395 template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3396 std::string GenFSMS(GLenum internalformat, const T &expected_value)
3397 {
3398 std::ostringstream os;
3399 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3400 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3401 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3402 << TypePrefix<T>()
3403 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3404 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != "
3405 << TypePrefix<T>() << "vec4" << expected_value
3406 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != "
3407 << TypePrefix<T>() << "vec4" << expected_value
3408 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != "
3409 << TypePrefix<T>() << "vec4" << expected_value
3410 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != "
3411 << TypePrefix<T>() << "vec4" << expected_value
3412 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3413 << TypePrefix<T>() << "vec4" << expected_value
3414 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3415 << TypePrefix<T>() << "vec4" << expected_value
3416 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3417 << TypePrefix<T>() << "vec4" << expected_value
3418 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3419 << TypePrefix<T>() << "vec4" << expected_value
3420 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3421 << TypePrefix<T>() << "vec4" << expected_value
3422 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3423 << TypePrefix<T>() << "vec4" << expected_value
3424 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3425 << TypePrefix<T>() << "vec4" << expected_value
3426 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3427 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3428 return os.str();
3429 }
3430 };
3431 //-----------------------------------------------------------------------------
3432 // 1.3.3 BasicAllTargetsAtomic
3433 //-----------------------------------------------------------------------------
3434 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3435 {
3436 GLuint m_vao;
3437 GLuint m_vbo;
3438
Setup()3439 virtual long Setup()
3440 {
3441 m_vao = 0;
3442 m_vbo = 0;
3443 return NO_ERROR;
3444 }
3445
Run()3446 virtual long Run()
3447 {
3448 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3449
3450 if (!Atomic<GLint>(GL_R32I))
3451 return ERROR;
3452 if (!Atomic<GLuint>(GL_R32UI))
3453 return ERROR;
3454
3455 if (!AtomicCube<GLint>(GL_R32I))
3456 return ERROR;
3457 if (!AtomicCube<GLuint>(GL_R32UI))
3458 return ERROR;
3459
3460 GLint isamples;
3461 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3462 if (SupportedSamples(4) && isamples >= 4)
3463 {
3464 if (!AtomicMS<GLint>(GL_R32I))
3465 return ERROR;
3466 if (!AtomicMS<GLuint>(GL_R32UI))
3467 return ERROR;
3468 }
3469
3470 return NO_ERROR;
3471 }
3472
Cleanup()3473 virtual long Cleanup()
3474 {
3475 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3476 glDeleteVertexArrays(1, &m_vao);
3477 glDeleteBuffers(1, &m_vbo);
3478 return NO_ERROR;
3479 }
3480
3481 template <typename T>
Atomic(GLenum internalformat)3482 bool Atomic(GLenum internalformat)
3483 {
3484 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3485 " gl_Position = i_position;" NL "}";
3486 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3487 GLuint textures[7];
3488 GLuint buffer;
3489 glGenTextures(7, textures);
3490 glGenBuffers(1, &buffer);
3491
3492 const int kSize = 16;
3493 std::vector<T> data(kSize * kSize * 2);
3494
3495 glBindTexture(GL_TEXTURE_1D, textures[0]);
3496 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3497 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3498 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3499 glBindTexture(GL_TEXTURE_1D, 0);
3500
3501 glBindTexture(GL_TEXTURE_2D, textures[1]);
3502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3503 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3504 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3505 glBindTexture(GL_TEXTURE_2D, 0);
3506
3507 glBindTexture(GL_TEXTURE_3D, textures[2]);
3508 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3509 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3510 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3511 glBindTexture(GL_TEXTURE_3D, 0);
3512
3513 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3514 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3515 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3516 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3517 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3518
3519 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3520 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3521 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3522 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3523 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3524 glBindTexture(GL_TEXTURE_BUFFER, 0);
3525
3526 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3527 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3528 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3529 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3530 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3531
3532 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3533 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3534 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3535 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3536 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3537
3538 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3539 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3540 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3541 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3542 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3543 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3544 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3545
3546 glClear(GL_COLOR_BUFFER_BIT);
3547
3548 glUseProgram(program);
3549 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3550 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3551 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3552 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3553 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3554 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3555 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3556
3557 glBindVertexArray(m_vao);
3558 glViewport(0, 0, kSize, 1);
3559 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3560
3561 bool status = true;
3562
3563 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3564 {
3565 status = false;
3566 }
3567
3568 glUseProgram(0);
3569 glDeleteProgram(program);
3570 glDeleteTextures(7, textures);
3571 glDeleteBuffers(1, &buffer);
3572
3573 return status;
3574 }
3575
3576 template <typename T>
AtomicCube(GLenum internalformat)3577 bool AtomicCube(GLenum internalformat)
3578 {
3579 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3580 " gl_Position = i_position;" NL "}";
3581 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3582 GLuint textures[2];
3583 glGenTextures(2, textures);
3584
3585 const int kSize = 16;
3586 std::vector<T> data(kSize * kSize * 12);
3587
3588 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3589 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3590 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3591 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3592 &data[0]);
3593 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3594 &data[0]);
3595 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3596 &data[0]);
3597 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3598 &data[0]);
3599 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3600 &data[0]);
3601 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3602 &data[0]);
3603 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3604
3605 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3606 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3607 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3608 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3609 &data[0]);
3610 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3611
3612 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3613 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3614
3615 glClear(GL_COLOR_BUFFER_BIT);
3616
3617 glUseProgram(program);
3618 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3619 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3620
3621 glBindVertexArray(m_vao);
3622 glViewport(0, 0, kSize, kSize);
3623 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3624
3625 bool status = true;
3626
3627 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3628 {
3629 status = false;
3630 }
3631
3632 glUseProgram(0);
3633 glDeleteProgram(program);
3634 glDeleteTextures(2, textures);
3635
3636 return status;
3637 }
3638
3639 template <typename T>
AtomicMS(GLenum internalformat)3640 bool AtomicMS(GLenum internalformat)
3641 {
3642 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3643 " gl_Position = i_position;" NL "}";
3644 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3645 GLuint textures[2];
3646 glGenTextures(2, textures);
3647
3648 const int kSize = 16;
3649
3650 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3651 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3652 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3653
3654 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3655 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3656 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3657
3658 GLuint fbo;
3659 glGenFramebuffers(1, &fbo);
3660 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3661 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3662 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3663 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3664 const GLenum draw_buffers[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
3665 glDrawBuffers(3, draw_buffers);
3666 if (internalformat == GL_R32I)
3667 {
3668 const GLint value[4] = {0, 0, 0, 0};
3669 glClearBufferiv(GL_COLOR, 0, value);
3670 glClearBufferiv(GL_COLOR, 1, value);
3671 glClearBufferiv(GL_COLOR, 2, value);
3672 }
3673 else
3674 {
3675 const GLuint value[4] = {0, 0, 0, 0};
3676 glClearBufferuiv(GL_COLOR, 0, value);
3677 glClearBufferuiv(GL_COLOR, 1, value);
3678 glClearBufferuiv(GL_COLOR, 2, value);
3679 }
3680 glDeleteFramebuffers(1, &fbo);
3681
3682 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3683 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3684
3685 glUseProgram(program);
3686 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3687 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3688
3689 glClear(GL_COLOR_BUFFER_BIT);
3690 glBindVertexArray(m_vao);
3691 glViewport(0, 0, kSize, kSize);
3692 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3693
3694 bool status = true;
3695
3696 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3697 {
3698 status = false;
3699 }
3700
3701 glDeleteTextures(2, textures);
3702 glUseProgram(0);
3703 glDeleteProgram(program);
3704
3705 return status;
3706 }
3707
3708 template <typename T>
GenFS(GLenum internalformat)3709 std::string GenFS(GLenum internalformat)
3710 {
3711 std::ostringstream os;
3712 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3713 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3714 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3715 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3716 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3717 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3718 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3719 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3720 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3721 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3722 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3723 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3724
3725 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3734
3735 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3743 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3744
3745 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3746 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3753 "1.0);" NL
3754 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3755
3756 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3765
3766 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3767 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3774 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3775
3776 NL
3777 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3778 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3784 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3785 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3786 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3787
3788 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3789 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3790 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3791 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3792 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3793 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3794 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3795 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3796 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3797 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3798 return os.str();
3799 }
3800
3801 template <typename T>
GenFSCube(GLenum internalformat)3802 std::string GenFSCube(GLenum internalformat)
3803 {
3804 std::ostringstream os;
3805 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3806 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3807 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3808 << TypePrefix<T>()
3809 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3810 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3811
3812 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3813 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3814 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3815 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3816 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3817 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3818 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3820 "1.0);" NL
3821 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3822
3823 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3824 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3825 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3826 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, "
3827 "ivec3(coord, 0), 0) != 4) o_color = "
3828 "vec4(1.0, 0.0, 0.0, 1.0);" NL
3829 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3830 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3831 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3832 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3833 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3834 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3835 "1.0);" NL "}";
3836 return os.str();
3837 }
3838
3839 template <typename T>
GenFSMS(GLenum internalformat)3840 std::string GenFSMS(GLenum internalformat)
3841 {
3842 std::ostringstream os;
3843 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3844 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3845 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3846 << TypePrefix<T>()
3847 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3848 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3849 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3850 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3851 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3853 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3854 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3855 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3857 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3858 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3859 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3860 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3861 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3862 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3863 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3864 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3865 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3866 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3867 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3868 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, "
3869 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3870 "0.0, 1.0);" NL "}";
3871 return os.str();
3872 }
3873 };
3874 //-----------------------------------------------------------------------------
3875 // LoadStoreMachine
3876 //-----------------------------------------------------------------------------
3877 class LoadStoreMachine : public ShaderImageLoadStoreBase
3878 {
3879 GLuint m_vao;
3880 int m_stage;
3881
Setup()3882 virtual long Setup()
3883 {
3884 glGenVertexArrays(1, &m_vao);
3885 return NO_ERROR;
3886 }
3887
Cleanup()3888 virtual long Cleanup()
3889 {
3890 glDisable(GL_RASTERIZER_DISCARD);
3891 glDeleteVertexArrays(1, &m_vao);
3892 return NO_ERROR;
3893 }
3894
3895 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3896 bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
3897 {
3898 const GLenum targets[] = {
3899 GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE,
3900 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY};
3901 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3902 GLuint program_store = 0;
3903 GLuint program_load = 0;
3904 if (m_stage == 0)
3905 { // VS
3906 program_store =
3907 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3908 program_load =
3909 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3910 }
3911 else if (m_stage == 1)
3912 { // TCS
3913 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
3914 const char *const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3915 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3916 glsl_tes, NULL, NULL);
3917 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3918 glsl_tes, NULL, NULL);
3919 }
3920 else if (m_stage == 2)
3921 { // TES
3922 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
3923 program_store =
3924 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3925 program_load =
3926 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3927 }
3928 else if (m_stage == 3)
3929 { // GS
3930 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
3931 program_store =
3932 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3933 program_load =
3934 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3935 }
3936 else if (m_stage == 4)
3937 { // CS
3938 {
3939 std::string source = GenStoreShader(m_stage, internalformat, write_value);
3940 const char *const src = source.c_str();
3941 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3942 glShaderSource(sh, 1, &src, NULL);
3943 glCompileShader(sh);
3944 program_store = glCreateProgram();
3945 glAttachShader(program_store, sh);
3946 glLinkProgram(program_store);
3947 glDeleteShader(sh);
3948 }
3949 {
3950 std::string source = GenLoadShader(m_stage, internalformat, expected_value);
3951 const char *const src = source.c_str();
3952 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3953 glShaderSource(sh, 1, &src, NULL);
3954 glCompileShader(sh);
3955 program_load = glCreateProgram();
3956 glAttachShader(program_load, sh);
3957 glLinkProgram(program_load);
3958 glDeleteShader(sh);
3959 }
3960 }
3961 GLuint textures[kTargets], texture_result;
3962 glGenTextures(kTargets, textures);
3963 glGenTextures(1, &texture_result);
3964
3965 glBindTexture(GL_TEXTURE_2D, texture_result);
3966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3968 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3969
3970 for (int i = 0; i < kTargets; ++i)
3971 {
3972 glBindTexture(targets[i], textures[i]);
3973 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3974 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3975
3976 if (targets[i] == GL_TEXTURE_1D)
3977 {
3978 glTexStorage1D(targets[i], 1, internalformat, 1);
3979 }
3980 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3981 {
3982 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3983 }
3984 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3985 {
3986 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3987 }
3988 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3989 {
3990 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3991 }
3992 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3993 {
3994 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3995 }
3996 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3997 {
3998 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3999 }
4000 }
4001 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4002 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4003 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4004 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4005 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4006 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4007 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4008 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4009
4010 glUseProgram(program_store);
4011 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4012 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4013 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4014 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4015 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4016 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4017 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4018 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4019
4020 glBindVertexArray(m_vao);
4021 if (m_stage == 1 || m_stage == 2)
4022 { // TCS or TES
4023 glPatchParameteri(GL_PATCH_VERTICES, 1);
4024 glDrawArrays(GL_PATCHES, 0, 1);
4025 glPatchParameteri(GL_PATCH_VERTICES, 3);
4026 }
4027 else if (m_stage == 4)
4028 { // CS
4029 glDispatchCompute(1, 1, 1);
4030 }
4031 else
4032 {
4033 glDrawArrays(GL_POINTS, 0, 1);
4034 }
4035
4036 bool status = true;
4037 for (int i = 0; i < kTargets; ++i)
4038 {
4039 glBindTexture(targets[i], textures[i]);
4040 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4041
4042 if (targets[i] == GL_TEXTURE_CUBE_MAP)
4043 {
4044 for (int face = 0; face < 6; ++face)
4045 {
4046 T data;
4047 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4048 if (!Equal(data, expected_value, internalformat))
4049 {
4050 status = false;
4051 m_context.getTestContext().getLog()
4052 << tcu::TestLog::Message << "Value is: " << ToString(data)
4053 << ". Value should be: " << ToString(expected_value)
4054 << ". Format is: " << FormatEnumToString(internalformat)
4055 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4056 << tcu::TestLog::EndMessage;
4057 }
4058 }
4059 }
4060 else
4061 {
4062 T data[12];
4063
4064 for (uint32_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4065 data[ndx] = T(0);
4066
4067 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4068
4069 int count = 1;
4070 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4071 count = 2;
4072 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4073 count = 12;
4074 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4075 count = 2;
4076
4077 for (int j = 0; j < count; ++j)
4078 {
4079 if (!Equal(data[j], expected_value, internalformat))
4080 {
4081 status = false;
4082 m_context.getTestContext().getLog()
4083 << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4084 << ". Value should be: " << ToString(expected_value)
4085 << ". Format is: " << FormatEnumToString(internalformat)
4086 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4087 << tcu::TestLog::EndMessage;
4088 }
4089 }
4090 }
4091 }
4092 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4093 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4094 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4095 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4096 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4097 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4098 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4099 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4100
4101 glUseProgram(program_load);
4102 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4103 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4104 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4105 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4106 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4107 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4108 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4109 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4110
4111 if (m_stage == 1 || m_stage == 2)
4112 { // TCS or TES
4113 glPatchParameteri(GL_PATCH_VERTICES, 1);
4114 glDrawArrays(GL_PATCHES, 0, 1);
4115 glPatchParameteri(GL_PATCH_VERTICES, 3);
4116 }
4117 else if (m_stage == 4)
4118 { // CS
4119 glDispatchCompute(1, 1, 1);
4120 }
4121 else
4122 {
4123 glDrawArrays(GL_POINTS, 0, 1);
4124 }
4125 {
4126 vec4 color;
4127 glBindTexture(GL_TEXTURE_2D, texture_result);
4128 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4129 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4130 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4131 {
4132 status = false;
4133 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4134 << ". Format is: " << FormatEnumToString(internalformat)
4135 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4136 }
4137 }
4138 glUseProgram(0);
4139 glDeleteProgram(program_store);
4140 glDeleteProgram(program_load);
4141 glDeleteTextures(kTargets, textures);
4142 glDeleteTextures(1, &texture_result);
4143 return status;
4144 }
4145
4146 template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4147 std::string GenStoreShader(int stage, GLenum internalformat, const T &write_value)
4148 {
4149 std::ostringstream os;
4150 os << "#version 420 core";
4151 if (stage == 4)
4152 { // CS
4153 os << NL "#extension GL_ARB_compute_shader : require";
4154 }
4155 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4156 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4157 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4158 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4159 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4160 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4161 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4162 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4163 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4164 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4165 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4166 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4167 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4168 if (stage == 0)
4169 { // VS
4170 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4171 }
4172 else if (stage == 1)
4173 { // TCS
4174 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4175 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4176 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4177 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4178 }
4179 else if (stage == 2)
4180 { // TES
4181 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4182 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4183 }
4184 else if (stage == 3)
4185 { // GS
4186 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4187 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4188 }
4189 else if (stage == 4)
4190 { // CS
4191 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4192 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4193 }
4194 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL
4195 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4196 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4197 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL
4198 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4199 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4200 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4201 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4202 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4203 " for (int i = 0; i < 6; ++i) {" NL
4204 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4205 " for (int i = 0; i < 6; ++i) {" NL
4206 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}";
4207 return os.str();
4208 }
4209
4210 template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4211 std::string GenLoadShader(int stage, GLenum internalformat, const T &expected_value)
4212 {
4213 std::ostringstream os;
4214 os << "#version 420 core";
4215 if (stage == 4)
4216 { // CS
4217 os << NL "#extension GL_ARB_compute_shader : require";
4218 }
4219 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4220 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4221 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4222 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4223 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4224 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4225 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4226 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4227 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4228 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4229 "uniform "
4230 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4231 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4232 if (stage == 0)
4233 { // VS
4234 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4235 }
4236 else if (stage == 1)
4237 { // TCS
4238 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4239 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4240 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4241 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4242 }
4243 else if (stage == 2)
4244 { // TES
4245 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4246 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4247 }
4248 else if (stage == 3)
4249 { // GS
4250 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4251 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4252 }
4253 else if (stage == 4)
4254 { // CS
4255 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4256 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4257 }
4258 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>()
4259 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
4260 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4261 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4262 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL
4263 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4264 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4265 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL
4266 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4267 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4268 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4269 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4270 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}";
4271 return os.str();
4272 }
4273
4274 protected:
RunStage(int stage)4275 long RunStage(int stage)
4276 {
4277 if (!SupportedInStage(stage, 8))
4278 return NOT_SUPPORTED;
4279
4280 glEnable(GL_RASTERIZER_DISCARD);
4281 m_stage = stage;
4282
4283 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4284 return ERROR;
4285 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4286 return ERROR;
4287 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4288 return ERROR;
4289
4290 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4291 return ERROR;
4292 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4293 return ERROR;
4294 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4295 return ERROR;
4296
4297 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4298 return ERROR;
4299 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4300 return ERROR;
4301 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302 return ERROR;
4303
4304 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4305 return ERROR;
4306
4307 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4308 return ERROR;
4309 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4310 return ERROR;
4311 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4312 return ERROR;
4313
4314 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4315 return ERROR;
4316 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4317 return ERROR;
4318 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4319 return ERROR;
4320
4321 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4322 return ERROR;
4323 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4324 return ERROR;
4325 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4326 return ERROR;
4327 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4328 return ERROR;
4329
4330 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4331 return ERROR;
4332 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4333 return ERROR;
4334 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4335 return ERROR;
4336
4337 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4338 return ERROR;
4339 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4340 return ERROR;
4341 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4342 return ERROR;
4343
4344 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4345 return ERROR;
4346 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4347 return ERROR;
4348 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4349 return ERROR;
4350 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4351 return ERROR;
4352
4353 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4354 return ERROR;
4355 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4356 return ERROR;
4357 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4358 return ERROR;
4359
4360 //
4361 {
4362 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4363 return ERROR;
4364 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4365 return ERROR;
4366 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4367 return ERROR;
4368
4369 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4370 return ERROR;
4371 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4372 return ERROR;
4373 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4374 return ERROR;
4375 }
4376 return NO_ERROR;
4377 }
4378 };
4379 //-----------------------------------------------------------------------------
4380 // AtomicMachine
4381 //-----------------------------------------------------------------------------
4382 class AtomicMachine : public ShaderImageLoadStoreBase
4383 {
4384 GLuint m_vao;
4385
Setup()4386 virtual long Setup()
4387 {
4388 glEnable(GL_RASTERIZER_DISCARD);
4389 glGenVertexArrays(1, &m_vao);
4390 return NO_ERROR;
4391 }
4392
Cleanup()4393 virtual long Cleanup()
4394 {
4395 glDisable(GL_RASTERIZER_DISCARD);
4396 glDeleteVertexArrays(1, &m_vao);
4397 return NO_ERROR;
4398 }
4399
4400 template <typename T>
Atomic(int stage,GLenum internalformat)4401 bool Atomic(int stage, GLenum internalformat)
4402 {
4403 GLuint program = 0;
4404 if (stage == 0)
4405 { // VS
4406 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4407 }
4408 else if (stage == 1)
4409 { // TCS
4410 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
4411 const char *const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4412 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4413 }
4414 else if (stage == 2)
4415 { // TES
4416 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
4417 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4418 }
4419 else if (stage == 3)
4420 { // GS
4421 const char *const glsl_vs = "#version 420 core" NL "void main() {}";
4422 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4423 }
4424 else if (stage == 4)
4425 { // CS
4426 std::string source = GenShader<T>(stage, internalformat);
4427 const char *const src = source.c_str();
4428 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4429 glShaderSource(sh, 1, &src, NULL);
4430 glCompileShader(sh);
4431 program = glCreateProgram();
4432 glAttachShader(program, sh);
4433 glLinkProgram(program);
4434 glDeleteShader(sh);
4435 }
4436 GLuint texture_result;
4437 glGenTextures(1, &texture_result);
4438 glBindTexture(GL_TEXTURE_2D, texture_result);
4439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4441 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4442
4443 const GLenum targets[] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4444 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY};
4445 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4446
4447 GLuint textures[kTargets];
4448 GLuint buffer;
4449 glGenTextures(kTargets, textures);
4450 glGenBuffers(1, &buffer);
4451
4452 for (int i = 0; i < kTargets; ++i)
4453 {
4454 glBindTexture(targets[i], textures[i]);
4455 if (targets[i] != GL_TEXTURE_BUFFER)
4456 {
4457 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4458 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4459 }
4460 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4461 {
4462 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4463 }
4464 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4465 {
4466 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4467 }
4468 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4469 {
4470 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4471 }
4472 else if (targets[i] == GL_TEXTURE_BUFFER)
4473 {
4474 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4475 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4476 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4477 glTexBuffer(targets[i], internalformat, buffer);
4478 }
4479 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4480 {
4481 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4482 }
4483 }
4484 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4485 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4486 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4487 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4488 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4489 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4490 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4491 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4492
4493 glUseProgram(program);
4494 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4495 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4496 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4497 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4498 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4499 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4500 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4501 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4502
4503 glBindVertexArray(m_vao);
4504 if (stage == 1 || stage == 2)
4505 { // TCS or TES
4506 glPatchParameteri(GL_PATCH_VERTICES, 1);
4507 glDrawArrays(GL_PATCHES, 0, 1);
4508 glPatchParameteri(GL_PATCH_VERTICES, 3);
4509 }
4510 else if (stage == 4)
4511 { // CS
4512 glDispatchCompute(1, 1, 1);
4513 }
4514 else
4515 {
4516 glDrawArrays(GL_POINTS, 0, 1);
4517 }
4518
4519 bool status = true;
4520 {
4521 vec4 color;
4522 glBindTexture(GL_TEXTURE_2D, texture_result);
4523 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4524 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4525 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4526 {
4527 status = false;
4528 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4529 << ". Format is: " << FormatEnumToString(internalformat)
4530 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4531 }
4532 }
4533 glUseProgram(0);
4534 glDeleteProgram(program);
4535 glDeleteTextures(7, textures);
4536 glDeleteTextures(1, &texture_result);
4537 glDeleteBuffers(1, &buffer);
4538 return status;
4539 }
4540
4541 template <typename T>
GenShader(int stage,GLenum internalformat)4542 std::string GenShader(int stage, GLenum internalformat)
4543 {
4544 std::ostringstream os;
4545 os << "#version 420 core";
4546 if (stage == 4)
4547 { // CS
4548 os << NL "#extension GL_ARB_compute_shader : require";
4549 }
4550 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4551 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4552 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4553 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4554 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4555 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4556 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4557 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4558 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4559 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4560 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4561 if (stage == 0)
4562 { // VS
4563 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4564 }
4565 else if (stage == 1)
4566 { // TCS
4567 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4568 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4569 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4570 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4571 }
4572 else if (stage == 2)
4573 { // TES
4574 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4575 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4576 }
4577 else if (stage == 3)
4578 { // GS
4579 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4580 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4581 }
4582 else if (stage == 4)
4583 { // CS
4584 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4585 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4586 }
4587 os << NL
4588 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL
4589 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4590 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4598
4599 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4600 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4601 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4609
4610 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL
4611 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4613 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4619 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4620
4621 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, "
4622 "ivec3(coord, 0), g_value[2]) != 0) "
4623 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4624 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4625 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4631 "0.0, 1.0);" NL
4632 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4633
4634 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4635 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4636 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4637 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4638 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4641 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4642 "1.0);" NL
4643 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4645
4646 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4647 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4648 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4649 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4650 "1.0);" NL
4651 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4655 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4656 "0.0, 0.0, 1.0);" NL
4657 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4658
4659 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4660 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4661 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4662 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4663 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4664 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4665 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4666 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4667 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4668 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4669 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4670
4671 NL " imageStore(g_image_result, coord, o_color);" NL "}";
4672 return os.str();
4673 }
4674
4675 protected:
RunStage(int stage)4676 long RunStage(int stage)
4677 {
4678 if (!SupportedInStage(stage, 8))
4679 return NOT_SUPPORTED;
4680 if (!Atomic<GLint>(stage, GL_R32I))
4681 return ERROR;
4682 if (!Atomic<GLuint>(stage, GL_R32UI))
4683 return ERROR;
4684 return NO_ERROR;
4685 }
4686 };
4687 //-----------------------------------------------------------------------------
4688 // 1.3.4 BasicAllTargetsLoadStoreVS
4689 //-----------------------------------------------------------------------------
4690 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4691 {
Run()4692 virtual long Run()
4693 {
4694 return RunStage(0);
4695 }
4696 };
4697 //-----------------------------------------------------------------------------
4698 // 1.3.5 BasicAllTargetsLoadStoreTCS
4699 //-----------------------------------------------------------------------------
4700 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4701 {
Run()4702 virtual long Run()
4703 {
4704 return RunStage(1);
4705 }
4706 };
4707 //-----------------------------------------------------------------------------
4708 // 1.3.6 BasicAllTargetsLoadStoreTES
4709 //-----------------------------------------------------------------------------
4710 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4711 {
Run()4712 virtual long Run()
4713 {
4714 return RunStage(2);
4715 }
4716 };
4717 //-----------------------------------------------------------------------------
4718 // 1.3.7 BasicAllTargetsLoadStoreGS
4719 //-----------------------------------------------------------------------------
4720 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4721 {
Run()4722 virtual long Run()
4723 {
4724 return RunStage(3);
4725 }
4726 };
4727 //-----------------------------------------------------------------------------
4728 // 1.3.8 BasicAllTargetsLoadStoreCS
4729 //-----------------------------------------------------------------------------
4730 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4731 {
Run()4732 virtual long Run()
4733 {
4734 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4735 {
4736 m_context.getTestContext().getLog()
4737 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4738 << tcu::TestLog::EndMessage;
4739 return NO_ERROR;
4740 }
4741
4742 return RunStage(4);
4743 }
4744 };
4745 //-----------------------------------------------------------------------------
4746 // 1.3.9 BasicAllTargetsAtomicVS
4747 //-----------------------------------------------------------------------------
4748 class BasicAllTargetsAtomicVS : public AtomicMachine
4749 {
Run()4750 virtual long Run()
4751 {
4752 return RunStage(0);
4753 }
4754 };
4755 //-----------------------------------------------------------------------------
4756 // 1.3.10 BasicAllTargetsAtomicTCS
4757 //-----------------------------------------------------------------------------
4758 class BasicAllTargetsAtomicTCS : public AtomicMachine
4759 {
Run()4760 virtual long Run()
4761 {
4762 return RunStage(1);
4763 }
4764 };
4765 //-----------------------------------------------------------------------------
4766 // 1.3.11 BasicAllTargetsAtomicTES
4767 //-----------------------------------------------------------------------------
4768 class BasicAllTargetsAtomicTES : public AtomicMachine
4769 {
Run()4770 virtual long Run()
4771 {
4772 return RunStage(2);
4773 }
4774 };
4775 //-----------------------------------------------------------------------------
4776 // 1.3.12 BasicAllTargetsAtomicGS
4777 //-----------------------------------------------------------------------------
4778 class BasicAllTargetsAtomicGS : public AtomicMachine
4779 {
Run()4780 virtual long Run()
4781 {
4782 return RunStage(3);
4783 }
4784 };
4785 //-----------------------------------------------------------------------------
4786 // 1.3.13 BasicAllTargetsAtomicCS
4787 //-----------------------------------------------------------------------------
4788 class BasicAllTargetsAtomicCS : public AtomicMachine
4789 {
Run()4790 virtual long Run()
4791 {
4792 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4793 {
4794 m_context.getTestContext().getLog()
4795 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4796 << tcu::TestLog::EndMessage;
4797 return NO_ERROR;
4798 }
4799
4800 return RunStage(4);
4801 }
4802 };
4803 //-----------------------------------------------------------------------------
4804 // 1.4.1 BasicGLSLMisc
4805 //-----------------------------------------------------------------------------
4806 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4807 {
4808 GLuint m_texture;
4809 GLuint m_program;
4810 GLuint m_vao, m_vbo;
4811
Setup()4812 virtual long Setup()
4813 {
4814 m_texture = 0;
4815 m_program = 0;
4816 m_vao = m_vbo = 0;
4817 return NO_ERROR;
4818 }
4819
Run()4820 virtual long Run()
4821 {
4822 const int kSize = 32;
4823 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4824
4825 glGenTextures(1, &m_texture);
4826 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4827 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4828 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4829 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4830
4831 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4832 " gl_Position = i_position;" NL "}";
4833 const char *src_fs =
4834 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4835 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4836 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
4837 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image_layer0, coord, vec4(1.0));" NL
4838 " memoryBarrier();" NL " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL
4839 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL
4840 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4841 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4842
4843 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4844
4845 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4846 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4847
4848 glClear(GL_COLOR_BUFFER_BIT);
4849 glViewport(0, 0, kSize, kSize);
4850
4851 glUseProgram(m_program);
4852 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4853 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4854
4855 glBindVertexArray(m_vao);
4856 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4857
4858 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4859 {
4860 return ERROR;
4861 }
4862 return NO_ERROR;
4863 }
4864
Cleanup()4865 virtual long Cleanup()
4866 {
4867 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4868 glDeleteTextures(1, &m_texture);
4869 glDeleteVertexArrays(1, &m_vao);
4870 glDeleteBuffers(1, &m_vbo);
4871 glUseProgram(0);
4872 glDeleteProgram(m_program);
4873 return NO_ERROR;
4874 }
4875 };
4876 //-----------------------------------------------------------------------------
4877 // 1.4.2 BasicGLSLEarlyFragTests
4878 //-----------------------------------------------------------------------------
4879 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4880 {
4881 GLuint m_texture[2];
4882 GLuint m_program[2];
4883 GLuint m_vao, m_vbo;
4884
Setup()4885 virtual long Setup()
4886 {
4887 m_texture[0] = m_texture[1] = 0;
4888 m_program[0] = m_program[1] = 0;
4889 m_vao = m_vbo = 0;
4890 return NO_ERROR;
4891 }
4892
Run()4893 virtual long Run()
4894 {
4895 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4896
4897 const int kSize = 32;
4898 std::vector<vec4> data(kSize * kSize);
4899
4900 glGenTextures(2, m_texture);
4901 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4902 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4903 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4904 glBindTexture(GL_TEXTURE_2D, 0);
4905
4906 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4908 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4909 glBindTexture(GL_TEXTURE_2D, 0);
4910
4911 const char *glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4912 " gl_Position = i_position;" NL "}";
4913 const char *glsl_early_frag_tests_fs =
4914 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4915 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4916 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4917 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4918 const char *glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4919 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4920 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4921 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4922 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4923 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4924
4925 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4926
4927 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4928 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4929
4930 glViewport(0, 0, kSize, kSize);
4931 glBindVertexArray(m_vao);
4932
4933 glEnable(GL_DEPTH_TEST);
4934 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4935 glClearDepthf(0.0f);
4936
4937 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4938 glUseProgram(m_program[0]);
4939 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4940
4941 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4942
4943 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4944 glUseProgram(m_program[1]);
4945 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4946 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4947
4948 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4949 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4950 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4951 for (int i = 0; i < kSize * kSize; ++i)
4952 {
4953 if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4954 return ERROR;
4955 }
4956
4957 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4958 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4959 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4960 for (int i = 0; i < kSize * kSize; ++i)
4961 {
4962 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4963 return ERROR;
4964 }
4965
4966 return NO_ERROR;
4967 }
4968
Cleanup()4969 virtual long Cleanup()
4970 {
4971 glDisable(GL_DEPTH_TEST);
4972 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4973 glClearDepthf(1.0f);
4974 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4975 glDeleteTextures(2, m_texture);
4976 glDeleteVertexArrays(1, &m_vao);
4977 glDeleteBuffers(1, &m_vbo);
4978 glUseProgram(0);
4979 glDeleteProgram(m_program[0]);
4980 glDeleteProgram(m_program[1]);
4981 return NO_ERROR;
4982 }
4983 };
4984 //-----------------------------------------------------------------------------
4985 // 1.4.3 BasicGLSLConst
4986 //-----------------------------------------------------------------------------
4987 class BasicGLSLConst : public ShaderImageLoadStoreBase
4988 {
4989 GLuint m_program;
4990 GLuint m_vao, m_vbo;
4991
Setup()4992 virtual long Setup()
4993 {
4994 m_program = 0;
4995 m_vao = m_vbo = 0;
4996 return NO_ERROR;
4997 }
4998
Run()4999 virtual long Run()
5000 {
5001 bool isAtLeast44Context =
5002 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
5003
5004 const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
5005 " gl_Position = i_position;" NL "}";
5006 std::ostringstream src_fs;
5007 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
5008 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5009 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5010 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5011 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5012 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5013 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5014 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5015 if (isAtLeast44Context)
5016 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5017 "vec4(0.2, 0.0, 0.0, 0.2);";
5018 else
5019 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5020 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5021 src_fs << NL
5022 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5023 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5024 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5025 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5026 "0.0, 0.0, 0.6);" NL
5027 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5028 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5029 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5030
5031 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5032 glUseProgram(m_program);
5033
5034 GLint i;
5035 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5036 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5037
5038 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5039 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5040
5041 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5042 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5043
5044 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5045 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5046
5047 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5048 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5049
5050 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5051 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5052
5053 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5054 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5055
5056 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5057 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5058
5059 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5060 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5061
5062 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5063
5064 glClear(GL_COLOR_BUFFER_BIT);
5065 glBindVertexArray(m_vao);
5066 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5067
5068 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5069 {
5070 return ERROR;
5071 }
5072 return NO_ERROR;
5073 }
5074
Cleanup()5075 virtual long Cleanup()
5076 {
5077 glDeleteVertexArrays(1, &m_vao);
5078 glDeleteBuffers(1, &m_vbo);
5079 glUseProgram(0);
5080 glDeleteProgram(m_program);
5081 return NO_ERROR;
5082 }
5083 };
5084 //-----------------------------------------------------------------------------
5085 // 2.1.1 AdvancedSyncImageAccess
5086 //-----------------------------------------------------------------------------
5087 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5088 {
5089 GLuint m_buffer;
5090 GLuint m_buffer_tex;
5091 GLuint m_store_program;
5092 GLuint m_draw_program;
5093 GLuint m_attribless_vao;
5094
Setup()5095 virtual long Setup()
5096 {
5097 m_buffer = 0;
5098 m_buffer_tex = 0;
5099 m_store_program = 0;
5100 m_draw_program = 0;
5101 m_attribless_vao = 0;
5102 return NO_ERROR;
5103 }
5104
Run()5105 virtual long Run()
5106 {
5107 if (!SupportedInVS(1))
5108 return NOT_SUPPORTED;
5109 const char *const glsl_store_vs =
5110 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5111 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5112 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5113 const char *const glsl_draw_vs =
5114 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5115 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5116 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5117 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5118 " gl_Position = pi;" NL "}";
5119 const char *const glsl_draw_fs =
5120 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5121 " o_color = vs_color;" NL "}";
5122 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5123 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5124
5125 glGenVertexArrays(1, &m_attribless_vao);
5126 glBindVertexArray(m_attribless_vao);
5127
5128 glGenBuffers(1, &m_buffer);
5129 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5130 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5131 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5132
5133 glGenTextures(1, &m_buffer_tex);
5134 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5135 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5136
5137 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5138
5139 glEnable(GL_RASTERIZER_DISCARD);
5140 glUseProgram(m_store_program);
5141 glDrawArrays(GL_POINTS, 0, 4);
5142
5143 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5144
5145 glDisable(GL_RASTERIZER_DISCARD);
5146 glClear(GL_COLOR_BUFFER_BIT);
5147 glUseProgram(m_draw_program);
5148 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5149
5150 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5151 {
5152 return ERROR;
5153 }
5154 return NO_ERROR;
5155 }
5156
Cleanup()5157 virtual long Cleanup()
5158 {
5159 glUseProgram(0);
5160 glDeleteBuffers(1, &m_buffer);
5161 glDeleteTextures(1, &m_buffer_tex);
5162 glDeleteProgram(m_store_program);
5163 glDeleteProgram(m_draw_program);
5164 glDeleteVertexArrays(1, &m_attribless_vao);
5165 return NO_ERROR;
5166 }
5167 };
5168 //-----------------------------------------------------------------------------
5169 // 2.1.2 AdvancedSyncVertexArray
5170 //-----------------------------------------------------------------------------
5171 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5172 {
5173 GLuint m_position_buffer;
5174 GLuint m_color_buffer;
5175 GLuint m_element_buffer;
5176 GLuint m_position_buffer_tex;
5177 GLuint m_color_buffer_tex;
5178 GLuint m_element_buffer_tex;
5179 GLuint m_store_program;
5180 GLuint m_draw_program;
5181 GLuint m_attribless_vao;
5182 GLuint m_draw_vao;
5183
Setup()5184 virtual long Setup()
5185 {
5186 m_position_buffer = 0;
5187 m_color_buffer = 0;
5188 m_element_buffer = 0;
5189 m_position_buffer_tex = 0;
5190 m_color_buffer_tex = 0;
5191 m_element_buffer_tex = 0;
5192 m_store_program = 0;
5193 m_draw_program = 0;
5194 m_attribless_vao = 0;
5195 m_draw_vao = 0;
5196 return NO_ERROR;
5197 }
5198
Run()5199 virtual long Run()
5200 {
5201 if (!SupportedInVS(3))
5202 return NOT_SUPPORTED;
5203 const char *const glsl_store_vs =
5204 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5205 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5206 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5207 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5208 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5209 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5210 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5211 const char *const glsl_draw_vs =
5212 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5213 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5214 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
5215 const char *const glsl_draw_fs =
5216 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5217 " o_color = vs_color;" NL "}";
5218 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5219 glUseProgram(m_store_program);
5220 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5221 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5222 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5223 glUseProgram(0);
5224
5225 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5226
5227 glGenBuffers(1, &m_position_buffer);
5228 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5229 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5230 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5231
5232 glGenBuffers(1, &m_color_buffer);
5233 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5234 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5235 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5236
5237 glGenBuffers(1, &m_element_buffer);
5238 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5239 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5240 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5241
5242 glGenTextures(1, &m_position_buffer_tex);
5243 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5244 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5245 glBindTexture(GL_TEXTURE_BUFFER, 0);
5246
5247 glGenTextures(1, &m_color_buffer_tex);
5248 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5249 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5250 glBindTexture(GL_TEXTURE_BUFFER, 0);
5251
5252 glGenTextures(1, &m_element_buffer_tex);
5253 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5254 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5255 glBindTexture(GL_TEXTURE_BUFFER, 0);
5256
5257 glGenVertexArrays(1, &m_attribless_vao);
5258
5259 glGenVertexArrays(1, &m_draw_vao);
5260 glBindVertexArray(m_draw_vao);
5261 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5262 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5263 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5264 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5265 glBindBuffer(GL_ARRAY_BUFFER, 0);
5266 glEnableVertexAttribArray(0);
5267 glEnableVertexAttribArray(1);
5268 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5269 glBindVertexArray(0);
5270
5271 glEnable(GL_RASTERIZER_DISCARD);
5272 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5273 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5274 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5275 glUseProgram(m_store_program);
5276 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5277 glBindVertexArray(m_attribless_vao);
5278 glDrawArrays(GL_POINTS, 0, 4);
5279
5280 glDisable(GL_RASTERIZER_DISCARD);
5281 glClear(GL_COLOR_BUFFER_BIT);
5282 glUseProgram(m_draw_program);
5283 glBindVertexArray(m_draw_vao);
5284 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5285 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5286
5287 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5288 {
5289 return ERROR;
5290 }
5291
5292 glEnable(GL_RASTERIZER_DISCARD);
5293 glUseProgram(m_store_program);
5294 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5295 glBindVertexArray(m_attribless_vao);
5296 glDrawArrays(GL_POINTS, 0, 4);
5297
5298 glDisable(GL_RASTERIZER_DISCARD);
5299 glClear(GL_COLOR_BUFFER_BIT);
5300 glUseProgram(m_draw_program);
5301 glBindVertexArray(m_draw_vao);
5302 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5303 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5304
5305 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5306 {
5307 return ERROR;
5308 }
5309 return NO_ERROR;
5310 }
5311
Cleanup()5312 virtual long Cleanup()
5313 {
5314 glDisable(GL_RASTERIZER_DISCARD);
5315 glUseProgram(0);
5316 glDeleteBuffers(1, &m_position_buffer);
5317 glDeleteBuffers(1, &m_color_buffer);
5318 glDeleteBuffers(1, &m_element_buffer);
5319 glDeleteTextures(1, &m_position_buffer_tex);
5320 glDeleteTextures(1, &m_color_buffer_tex);
5321 glDeleteTextures(1, &m_element_buffer_tex);
5322 glDeleteProgram(m_store_program);
5323 glDeleteProgram(m_draw_program);
5324 glDeleteVertexArrays(1, &m_attribless_vao);
5325 glDeleteVertexArrays(1, &m_draw_vao);
5326 return NO_ERROR;
5327 }
5328 };
5329
5330 //-----------------------------------------------------------------------------
5331 // 2.1.4 AdvancedSyncDrawIndirect
5332 //-----------------------------------------------------------------------------
5333 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5334 {
5335 GLuint m_draw_command_buffer;
5336 GLuint m_draw_command_buffer_tex;
5337 GLuint m_store_program;
5338 GLuint m_draw_program;
5339 GLuint m_attribless_vao;
5340 GLuint m_draw_vao;
5341 GLuint m_draw_vbo;
5342
Setup()5343 virtual long Setup()
5344 {
5345 m_draw_command_buffer = 0;
5346 m_draw_command_buffer_tex = 0;
5347 m_store_program = 0;
5348 m_draw_program = 0;
5349 m_attribless_vao = 0;
5350 m_draw_vao = 0;
5351 m_draw_vbo = 0;
5352 return NO_ERROR;
5353 }
5354
Run()5355 virtual long Run()
5356 {
5357 if (!SupportedInVS(1))
5358 return NOT_SUPPORTED;
5359 const char *const glsl_store_vs =
5360 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5361 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5362 const char *const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5363 "void main() {" NL " gl_Position = i_position;" NL "}";
5364 const char *const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5365 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5366 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5367 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5368
5369 glGenBuffers(1, &m_draw_command_buffer);
5370 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5371 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5372 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5373
5374 glGenTextures(1, &m_draw_command_buffer_tex);
5375 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5376 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5377 glBindTexture(GL_TEXTURE_BUFFER, 0);
5378
5379 glGenVertexArrays(1, &m_attribless_vao);
5380 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5381
5382 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5383
5384 glEnable(GL_RASTERIZER_DISCARD);
5385 glUseProgram(m_store_program);
5386 glBindVertexArray(m_attribless_vao);
5387 glDrawArrays(GL_POINTS, 0, 1);
5388
5389 glDisable(GL_RASTERIZER_DISCARD);
5390 glClear(GL_COLOR_BUFFER_BIT);
5391 glUseProgram(m_draw_program);
5392 glBindVertexArray(m_draw_vao);
5393 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5394 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5395 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5396
5397 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5398 {
5399 return ERROR;
5400 }
5401 return NO_ERROR;
5402 }
5403
Cleanup()5404 virtual long Cleanup()
5405 {
5406 glUseProgram(0);
5407 glDeleteBuffers(1, &m_draw_command_buffer);
5408 glDeleteTextures(1, &m_draw_command_buffer_tex);
5409 glDeleteProgram(m_store_program);
5410 glDeleteProgram(m_draw_program);
5411 glDeleteVertexArrays(1, &m_attribless_vao);
5412 glDeleteVertexArrays(1, &m_draw_vao);
5413 glDeleteBuffers(1, &m_draw_vbo);
5414 return NO_ERROR;
5415 }
5416 };
5417 //-----------------------------------------------------------------------------
5418 // 2.1.5 AdvancedSyncTextureUpdate
5419 //-----------------------------------------------------------------------------
5420 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5421 {
5422 GLuint m_texture;
5423 GLuint m_store_program;
5424 GLuint m_draw_program;
5425 GLuint m_vao;
5426 GLuint m_vbo;
5427 GLuint m_pbo;
5428
Setup()5429 virtual long Setup()
5430 {
5431 m_texture = 0;
5432 m_store_program = 0;
5433 m_draw_program = 0;
5434 m_vao = 0;
5435 m_vbo = 0;
5436 m_pbo = 0;
5437 return NO_ERROR;
5438 }
5439
Run()5440 virtual long Run()
5441 {
5442 const char *const glsl_vs =
5443 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5444 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5445 const char *const glsl_store_fs =
5446 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5447 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}";
5448 const char *const glsl_draw_fs =
5449 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5450 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5451 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5452 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5453
5454 std::vector<vec4> data(16 * 16, vec4(1.0f));
5455 glGenBuffers(1, &m_pbo);
5456 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5457 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5458 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5459
5460 glGenTextures(1, &m_texture);
5461 glBindTexture(GL_TEXTURE_2D, m_texture);
5462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5463 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5464 glBindTexture(GL_TEXTURE_2D, 0);
5465
5466 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5467
5468 glViewport(0, 0, 16, 16);
5469 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5470 glUseProgram(m_store_program);
5471 glBindVertexArray(m_vao);
5472 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5473
5474 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5475 glBindTexture(GL_TEXTURE_2D, m_texture);
5476 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5477 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5478 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5479
5480 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5481 glClear(GL_COLOR_BUFFER_BIT);
5482 glUseProgram(m_draw_program);
5483 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5484
5485 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5486 {
5487 return ERROR;
5488 }
5489 return NO_ERROR;
5490 }
5491
Cleanup()5492 virtual long Cleanup()
5493 {
5494 glUseProgram(0);
5495 glDeleteBuffers(1, &m_vbo);
5496 glDeleteBuffers(1, &m_pbo);
5497 glDeleteTextures(1, &m_texture);
5498 glDeleteProgram(m_store_program);
5499 glDeleteProgram(m_draw_program);
5500 glDeleteVertexArrays(1, &m_vao);
5501 return NO_ERROR;
5502 }
5503 };
5504 //-----------------------------------------------------------------------------
5505 // 2.1.6 AdvancedSyncImageAccess2
5506 //-----------------------------------------------------------------------------
5507 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5508 {
5509 GLuint m_texture;
5510 GLuint m_store_program;
5511 GLuint m_draw_program;
5512 GLuint m_vao;
5513 GLuint m_vbo;
5514
Setup()5515 virtual long Setup()
5516 {
5517 m_texture = 0;
5518 m_store_program = 0;
5519 m_draw_program = 0;
5520 m_vao = 0;
5521 m_vbo = 0;
5522 return NO_ERROR;
5523 }
5524
Run()5525 virtual long Run()
5526 {
5527 const char *const glsl_vs =
5528 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5529 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5530 const char *const glsl_store_fs =
5531 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5532 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
5533 const char *const glsl_draw_fs =
5534 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5535 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5536 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5537 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5538
5539 int width = getWindowWidth();
5540 int height = getWindowHeight();
5541 scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5542
5543 glGenTextures(1, &m_texture);
5544 glBindTexture(GL_TEXTURE_2D, m_texture);
5545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5546 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5547 glBindTexture(GL_TEXTURE_2D, 0);
5548
5549 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5550
5551 glViewport(0, 0, width, height);
5552 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5553 glUseProgram(m_store_program);
5554 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5555 glBindVertexArray(m_vao);
5556 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5557
5558 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5559
5560 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5561 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5562
5563 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
5564
5565 glClear(GL_COLOR_BUFFER_BIT);
5566 glBindTexture(GL_TEXTURE_2D, m_texture);
5567 glUseProgram(m_draw_program);
5568 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5569
5570 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5571 {
5572 return ERROR;
5573 }
5574 return NO_ERROR;
5575 }
5576
Cleanup()5577 virtual long Cleanup()
5578 {
5579 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5580 glUseProgram(0);
5581 glDeleteBuffers(1, &m_vbo);
5582 glDeleteTextures(1, &m_texture);
5583 glDeleteProgram(m_store_program);
5584 glDeleteProgram(m_draw_program);
5585 glDeleteVertexArrays(1, &m_vao);
5586 return NO_ERROR;
5587 }
5588 };
5589 //-----------------------------------------------------------------------------
5590 // 2.1.7 AdvancedSyncBufferUpdate
5591 //-----------------------------------------------------------------------------
5592 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5593 {
5594 GLuint m_buffer;
5595 GLuint m_buffer_tex;
5596 GLuint m_store_program;
5597 GLuint m_attribless_vao;
5598
Setup()5599 virtual long Setup()
5600 {
5601 m_buffer = 0;
5602 m_buffer_tex = 0;
5603 m_store_program = 0;
5604 m_attribless_vao = 0;
5605 return NO_ERROR;
5606 }
5607
Run()5608 virtual long Run()
5609 {
5610 if (!SupportedInVS(1))
5611 return NOT_SUPPORTED;
5612 const char *const glsl_store_vs =
5613 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5614 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5615 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5616
5617 glGenVertexArrays(1, &m_attribless_vao);
5618 glBindVertexArray(m_attribless_vao);
5619
5620 glGenBuffers(1, &m_buffer);
5621 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5622 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5623 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5624
5625 glGenTextures(1, &m_buffer_tex);
5626 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5627 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5628
5629 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5630
5631 glEnable(GL_RASTERIZER_DISCARD);
5632 glUseProgram(m_store_program);
5633 glDrawArrays(GL_POINTS, 0, 1000);
5634
5635 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5636
5637 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5638 vec4 *ptr =
5639 reinterpret_cast<vec4 *>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5640 for (int i = 0; i < 1000; ++i)
5641 {
5642 if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5643 {
5644 m_context.getTestContext().getLog()
5645 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5646 return ERROR;
5647 }
5648 }
5649 return NO_ERROR;
5650 }
5651
Cleanup()5652 virtual long Cleanup()
5653 {
5654 glDisable(GL_RASTERIZER_DISCARD);
5655 glUseProgram(0);
5656 glDeleteBuffers(1, &m_buffer);
5657 glDeleteTextures(1, &m_buffer_tex);
5658 glDeleteProgram(m_store_program);
5659 glDeleteVertexArrays(1, &m_attribless_vao);
5660 return NO_ERROR;
5661 }
5662 };
5663 //-----------------------------------------------------------------------------
5664 // 2.2.1 AdvancedAllStagesOneImage
5665 //-----------------------------------------------------------------------------
5666 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5667 {
5668 GLuint m_program;
5669 GLuint m_vao;
5670 GLuint m_vbo;
5671 GLuint m_ebo;
5672 GLuint m_buffer;
5673 GLuint m_buffer_tex;
5674 GLuint m_texture;
5675
Setup()5676 virtual long Setup()
5677 {
5678 m_program = 0;
5679 m_vao = 0;
5680 m_vbo = 0;
5681 m_ebo = 0;
5682 m_buffer = 0;
5683 m_buffer_tex = 0;
5684 m_texture = 0;
5685 return NO_ERROR;
5686 }
5687
Run()5688 virtual long Run()
5689 {
5690 if (!SupportedInGeomStages(2))
5691 return NOT_SUPPORTED;
5692 const char *const glsl_vs =
5693 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5694 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5695 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5696 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5697 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5698 const char *const glsl_tcs =
5699 "#version 420 core" NL "layout(vertices = 1) out;" NL
5700 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5701 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5702 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL
5703 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
5704 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5705 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5706 const char *const glsl_tes =
5707 "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5708 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5709 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5710 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5711 " gl_Position = gl_in[0].gl_Position;" NL "}";
5712 const char *const glsl_gs =
5713 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5714 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5715 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5716 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5717 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}";
5718 const char *const glsl_fs =
5719 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5720 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5721 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5722 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5723 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5724 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5725 glUseProgram(m_program);
5726 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5727 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5728
5729 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5730
5731 GLint i32 = 0;
5732 glGenBuffers(1, &m_buffer);
5733 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5734 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5735 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5736
5737 glGenTextures(1, &m_buffer_tex);
5738 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5739 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5740 glBindTexture(GL_TEXTURE_BUFFER, 0);
5741
5742 GLuint ui32 = 0;
5743 glGenTextures(1, &m_texture);
5744 glBindTexture(GL_TEXTURE_2D, m_texture);
5745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5747 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5748 glBindTexture(GL_TEXTURE_2D, 0);
5749
5750 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5751 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5752
5753 glBindVertexArray(m_vao);
5754 glPatchParameteri(GL_PATCH_VERTICES, 1);
5755
5756 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5757 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5758
5759 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5760 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5761 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5762 if (i32 < 20 || i32 > 50)
5763 {
5764 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5765 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5766 return ERROR;
5767 }
5768
5769 glBindTexture(GL_TEXTURE_2D, m_texture);
5770 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5771 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5772 {
5773 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5774 << (2 * i32) << tcu::TestLog::EndMessage;
5775 return ERROR;
5776 }
5777
5778 return NO_ERROR;
5779 }
5780
Cleanup()5781 virtual long Cleanup()
5782 {
5783 glPatchParameteri(GL_PATCH_VERTICES, 3);
5784 glUseProgram(0);
5785 glDeleteBuffers(1, &m_buffer);
5786 glDeleteBuffers(1, &m_vbo);
5787 glDeleteBuffers(1, &m_ebo);
5788 glDeleteTextures(1, &m_buffer_tex);
5789 glDeleteTextures(1, &m_texture);
5790 glDeleteProgram(m_program);
5791 glDeleteVertexArrays(1, &m_vao);
5792 return NO_ERROR;
5793 }
5794 };
5795 //-----------------------------------------------------------------------------
5796 // 2.3.1 AdvancedMemoryDependentInvocation
5797 //-----------------------------------------------------------------------------
5798 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5799 {
5800 GLuint m_buffer;
5801 GLuint m_buffer_tex;
5802 GLuint m_texture;
5803 GLuint m_program;
5804 GLuint m_vao;
5805 GLuint m_vbo;
5806
Setup()5807 virtual long Setup()
5808 {
5809 m_buffer = 0;
5810 m_buffer_tex = 0;
5811 m_texture = 0;
5812 m_program = 0;
5813 m_vao = 0;
5814 m_vbo = 0;
5815 return NO_ERROR;
5816 }
5817
Run()5818 virtual long Run()
5819 {
5820 if (!SupportedInVS(2))
5821 return NOT_SUPPORTED;
5822 const char *const glsl_vs =
5823 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5824 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5825 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5826 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL
5827 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL
5828 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}";
5829 const char *const glsl_fs =
5830 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5831 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5832 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5833 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5834 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5835 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5836 glUseProgram(m_program);
5837 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5838 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5839
5840 vec4 zero(0);
5841 glGenBuffers(1, &m_buffer);
5842 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5843 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5844 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5845
5846 glGenTextures(1, &m_buffer_tex);
5847 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5848 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5849 glBindTexture(GL_TEXTURE_BUFFER, 0);
5850
5851 glGenTextures(1, &m_texture);
5852 glBindTexture(GL_TEXTURE_2D, m_texture);
5853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5854 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5855 glBindTexture(GL_TEXTURE_2D, 0);
5856
5857 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5858 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5859
5860 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5861
5862 glClear(GL_COLOR_BUFFER_BIT);
5863 glBindVertexArray(m_vao);
5864 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5865
5866 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5867 {
5868 return ERROR;
5869 }
5870 return NO_ERROR;
5871 }
5872
Cleanup()5873 virtual long Cleanup()
5874 {
5875 glUseProgram(0);
5876 glDeleteBuffers(1, &m_vbo);
5877 glDeleteBuffers(1, &m_buffer);
5878 glDeleteTextures(1, &m_texture);
5879 glDeleteTextures(1, &m_buffer_tex);
5880 glDeleteProgram(m_program);
5881 glDeleteVertexArrays(1, &m_vao);
5882 return NO_ERROR;
5883 }
5884 };
5885 //-----------------------------------------------------------------------------
5886 // 2.3.2 AdvancedMemoryOrder
5887 //-----------------------------------------------------------------------------
5888 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5889 {
5890 GLuint m_buffer;
5891 GLuint m_buffer_tex;
5892 GLuint m_texture;
5893 GLuint m_program;
5894 GLuint m_vao;
5895 GLuint m_vbo;
5896
Setup()5897 virtual long Setup()
5898 {
5899 m_buffer = 0;
5900 m_buffer_tex = 0;
5901 m_texture = 0;
5902 m_program = 0;
5903 m_vao = 0;
5904 m_vbo = 0;
5905 return NO_ERROR;
5906 }
5907
Run()5908 virtual long Run()
5909 {
5910 if (!SupportedInVS(1))
5911 return NOT_SUPPORTED;
5912 const char *const glsl_vs =
5913 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5914 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5915 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL
5916 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5917 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5918 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5919 const char *const glsl_fs =
5920 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5921 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5922 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL
5923 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL
5924 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL
5925 "}";
5926 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5927 glUseProgram(m_program);
5928 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5929 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5930
5931 glGenBuffers(1, &m_buffer);
5932 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5933 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5934 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5935
5936 glGenTextures(1, &m_buffer_tex);
5937 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5938 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5939 glBindTexture(GL_TEXTURE_BUFFER, 0);
5940
5941 int width = getWindowWidth();
5942 int height = getWindowHeight();
5943 scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5944
5945 std::vector<vec4> data(width * height);
5946 glGenTextures(1, &m_texture);
5947 glBindTexture(GL_TEXTURE_2D, m_texture);
5948 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5949 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5950 glBindTexture(GL_TEXTURE_2D, 0);
5951
5952 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5953 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5954
5955 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5956
5957 glClear(GL_COLOR_BUFFER_BIT);
5958 glViewport(0, 0, width, height);
5959 glBindVertexArray(m_vao);
5960 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5961
5962 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5963 {
5964 return ERROR;
5965 }
5966 return NO_ERROR;
5967 }
5968
Cleanup()5969 virtual long Cleanup()
5970 {
5971 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5972 glUseProgram(0);
5973 glDeleteBuffers(1, &m_vbo);
5974 glDeleteBuffers(1, &m_buffer);
5975 glDeleteTextures(1, &m_texture);
5976 glDeleteTextures(1, &m_buffer_tex);
5977 glDeleteProgram(m_program);
5978 glDeleteVertexArrays(1, &m_vao);
5979 return NO_ERROR;
5980 }
5981 };
5982 //-----------------------------------------------------------------------------
5983 // 2.4.1 AdvancedSSOSimple
5984 //-----------------------------------------------------------------------------
5985 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5986 {
5987 GLuint m_texture;
5988 GLuint m_pipeline[2];
5989 GLuint m_vsp, m_fsp0, m_fsp1;
5990 GLuint m_vao, m_vbo;
5991
Setup()5992 virtual long Setup()
5993 {
5994 glGenTextures(1, &m_texture);
5995 glGenProgramPipelines(2, m_pipeline);
5996 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5997
5998 const char *const glsl_vs =
5999 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6000 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6001 const char *const glsl_fs0 =
6002 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
6003 " for (int i = 0; i < g_image.length(); ++i) {" NL
6004 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}";
6005 const char *const glsl_fs1 =
6006 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
6007 " for (int i = 0; i < g_image.length(); ++i) {" NL
6008 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}";
6009 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6010 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6011 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6012
6013 return NO_ERROR;
6014 }
6015
Run()6016 virtual long Run()
6017 {
6018 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6019 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6020 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6021 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6022
6023 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6024 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6025 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6026 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6027
6028 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6029 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6030
6031 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6032 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6033
6034 int width = getWindowWidth();
6035 int height = getWindowHeight();
6036 scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6037
6038 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6039 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6040 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6041
6042 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6043 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6044 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6045 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6046 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6047 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6048 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6049 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6050
6051 glBindVertexArray(m_vao);
6052
6053 glViewport(0, 0, width, height);
6054 glBindProgramPipeline(m_pipeline[0]);
6055 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6056
6057 glBindProgramPipeline(m_pipeline[1]);
6058 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6059
6060 std::vector<vec4> data(width * height * 8);
6061 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6062
6063 for (int layer = 0; layer < 8; ++layer)
6064 {
6065 for (int h = 0; h < height; ++h)
6066 {
6067 for (int w = 0; w < width; ++w)
6068 {
6069 const vec4 c = data[layer * width * height + h * width + w];
6070 if (layer % 2)
6071 {
6072 if (!IsEqual(c, vec4(2.0f)))
6073 {
6074 return ERROR;
6075 }
6076 }
6077 else
6078 {
6079 if (!IsEqual(c, vec4(1.0f)))
6080 {
6081 return ERROR;
6082 }
6083 }
6084 }
6085 }
6086 }
6087 return NO_ERROR;
6088 }
6089
Cleanup()6090 virtual long Cleanup()
6091 {
6092 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6093 glDeleteBuffers(1, &m_vbo);
6094 glDeleteTextures(1, &m_texture);
6095 glDeleteProgram(m_vsp);
6096 glDeleteProgram(m_fsp0);
6097 glDeleteProgram(m_fsp1);
6098 glDeleteVertexArrays(1, &m_vao);
6099 glDeleteProgramPipelines(2, m_pipeline);
6100 return NO_ERROR;
6101 }
6102 };
6103 //-----------------------------------------------------------------------------
6104 // 2.4.2 AdvancedSSOAtomicCounters
6105 //-----------------------------------------------------------------------------
6106 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6107 {
6108 GLuint m_buffer, m_buffer_tex;
6109 GLuint m_counter_buffer;
6110 GLuint m_transform_buffer;
6111 GLuint m_pipeline;
6112 GLuint m_vao, m_vbo;
6113 GLuint m_vsp, m_fsp;
6114
Setup()6115 virtual long Setup()
6116 {
6117 m_vao = 0;
6118 m_vbo = 0;
6119 m_vsp = 0;
6120 m_fsp = 0;
6121 glGenBuffers(1, &m_buffer);
6122 glGenTextures(1, &m_buffer_tex);
6123 glGenBuffers(1, &m_counter_buffer);
6124 glGenBuffers(1, &m_transform_buffer);
6125 glGenProgramPipelines(1, &m_pipeline);
6126 return NO_ERROR;
6127 }
6128
Run()6129 virtual long Run()
6130 {
6131 if (!SupportedInVS(1))
6132 return NOT_SUPPORTED;
6133
6134 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6135 const char *const glsl_vs =
6136 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6137 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6138 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6139 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6140 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6141 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL
6142 " const uint index = atomicCounterIncrement(g_counter);" NL
6143 " imageStore(g_buffer, int(index), gl_Position);" NL "}";
6144 const char *const glsl_fs =
6145 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6146 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}";
6147 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6148 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6149
6150 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6151 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6152
6153 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6154 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6155
6156 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6157 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6158
6159 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6160 vec4 zero(0);
6161 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6162
6163 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6164 mat4 identity(1);
6165 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6166
6167 glClear(GL_COLOR_BUFFER_BIT);
6168 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6169 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6170 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6171 glBindVertexArray(m_vao);
6172 glBindProgramPipeline(m_pipeline);
6173 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6174
6175 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6176 {
6177 return ERROR;
6178 }
6179
6180 std::vector<vec4> data(4);
6181 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6182 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6183
6184 for (int i = 0; i < 4; ++i)
6185 {
6186 if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6187 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6188 {
6189 return ERROR;
6190 }
6191 }
6192
6193 return NO_ERROR;
6194 }
6195
Cleanup()6196 virtual long Cleanup()
6197 {
6198 glDeleteBuffers(1, &m_buffer);
6199 glDeleteBuffers(1, &m_vbo);
6200 glDeleteBuffers(1, &m_counter_buffer);
6201 glDeleteBuffers(1, &m_transform_buffer);
6202 glDeleteTextures(1, &m_buffer_tex);
6203 glDeleteProgram(m_vsp);
6204 glDeleteProgram(m_fsp);
6205 glDeleteVertexArrays(1, &m_vao);
6206 glDeleteProgramPipelines(1, &m_pipeline);
6207 return NO_ERROR;
6208 }
6209 };
6210 //-----------------------------------------------------------------------------
6211 // 2.4.3 AdvancedSSOSubroutine
6212 //-----------------------------------------------------------------------------
6213 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6214 {
6215 GLuint m_texture;
6216 GLuint m_attribless_vao;
6217 GLuint m_program;
6218 GLint m_draw_buffer;
6219
Setup()6220 virtual long Setup()
6221 {
6222 glGenTextures(1, &m_texture);
6223 glGenVertexArrays(1, &m_attribless_vao);
6224
6225 const char *const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6226 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6227 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6228 const char *const glsl_fs =
6229 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6230 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6231 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6232 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6233 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6234 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6235 "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6236 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6237 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6238 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6239 " g_brush(ivec2(gl_FragCoord));" NL "}";
6240 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6241
6242 return NO_ERROR;
6243 }
6244
Run()6245 virtual long Run()
6246 {
6247 int width = getWindowWidth();
6248 int height = getWindowHeight();
6249 scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6250
6251 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6252 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6253
6254 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6255 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6256 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6257
6258 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6259
6260 glDrawBuffer(GL_NONE);
6261 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6262 glUseProgram(m_program);
6263 glBindVertexArray(m_attribless_vao);
6264
6265 const GLuint indices[2] = {glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6266 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1")};
6267
6268 glViewport(0, 0, width, height);
6269 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6270 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6271
6272 std::vector<vec4> data(width * height * 3);
6273 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6274 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6275
6276 for (int layer = 0; layer < 3; ++layer)
6277 {
6278 for (int h = 0; h < height; ++h)
6279 {
6280 for (int w = 0; w < width; ++w)
6281 {
6282 const vec4 c = data[layer * width * height + h * width + w];
6283 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6284 {
6285 m_context.getTestContext().getLog()
6286 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6287 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6288 return ERROR;
6289 }
6290 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6291 {
6292 m_context.getTestContext().getLog()
6293 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6294 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6295 return ERROR;
6296 }
6297 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6298 {
6299 m_context.getTestContext().getLog()
6300 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6301 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6302 return ERROR;
6303 }
6304 }
6305 }
6306 }
6307
6308 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6309 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6310
6311 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6312 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6313
6314 for (int layer = 0; layer < 3; ++layer)
6315 {
6316 for (int h = 0; h < height; ++h)
6317 {
6318 for (int w = 0; w < width; ++w)
6319 {
6320 const vec4 c = data[layer * width * height + h * width + w];
6321 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6322 {
6323 m_context.getTestContext().getLog()
6324 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6325 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6326 return ERROR;
6327 }
6328 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6329 {
6330 m_context.getTestContext().getLog()
6331 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6332 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6333 return ERROR;
6334 }
6335 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6336 {
6337 m_context.getTestContext().getLog()
6338 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6339 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6340 return ERROR;
6341 }
6342 }
6343 }
6344 }
6345 return NO_ERROR;
6346 }
6347
Cleanup()6348 virtual long Cleanup()
6349 {
6350 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6351 glDrawBuffer(m_draw_buffer);
6352 glDeleteTextures(1, &m_texture);
6353 glUseProgram(0);
6354 glDeleteProgram(m_program);
6355 glDeleteVertexArrays(1, &m_attribless_vao);
6356 return NO_ERROR;
6357 }
6358 };
6359 //-----------------------------------------------------------------------------
6360 // 2.4.4 AdvancedSSOPerSample
6361 //-----------------------------------------------------------------------------
6362 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6363 {
6364 GLuint m_texture;
6365 GLuint m_pipeline;
6366 GLuint m_vao, m_vbo, m_ebo;
6367 GLuint m_vsp, m_store_fsp, m_load_fsp;
6368
Setup()6369 virtual long Setup()
6370 {
6371 m_vao = 0;
6372 m_vbo = 0;
6373 m_ebo = 0;
6374 m_vsp = 0;
6375 m_store_fsp = 0;
6376 m_load_fsp = 0;
6377 glGenTextures(1, &m_texture);
6378 glGenProgramPipelines(1, &m_pipeline);
6379
6380 return NO_ERROR;
6381 }
6382
Run()6383 virtual long Run()
6384 {
6385 if (!SupportedSamples(4))
6386 return NOT_SUPPORTED;
6387
6388 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6389
6390 const char *const glsl_vs =
6391 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6392 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6393 const char *const glsl_store_fs =
6394 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6395 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6396 const char *const glsl_load_fs =
6397 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6398 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6399 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6400 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6401 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6402 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6403 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6404
6405 int width = getWindowWidth();
6406 int height = getWindowHeight();
6407 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6408
6409 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6410 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6411 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6412
6413 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6414 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6415
6416 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6417
6418 glClear(GL_COLOR_BUFFER_BIT);
6419 glViewport(0, 0, width, height);
6420 glBindVertexArray(m_vao);
6421 glBindProgramPipeline(m_pipeline);
6422 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6423
6424 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6425
6426 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6427 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6428
6429 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6430 {
6431 return ERROR;
6432 }
6433 return NO_ERROR;
6434 }
6435
Cleanup()6436 virtual long Cleanup()
6437 {
6438 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6439 glDeleteBuffers(1, &m_vbo);
6440 glDeleteBuffers(1, &m_ebo);
6441 glDeleteTextures(1, &m_texture);
6442 glDeleteProgram(m_vsp);
6443 glDeleteProgram(m_store_fsp);
6444 glDeleteProgram(m_load_fsp);
6445 glDeleteVertexArrays(1, &m_vao);
6446 glDeleteProgramPipelines(1, &m_pipeline);
6447 return NO_ERROR;
6448 }
6449 };
6450
6451 //-----------------------------------------------------------------------------
6452 // 2.5 AdvancedCopyImage
6453 //-----------------------------------------------------------------------------
6454 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6455 {
6456 GLuint m_texture[2];
6457 GLuint m_program;
6458 GLuint m_vao, m_vbo, m_ebo;
6459
Setup()6460 virtual long Setup()
6461 {
6462 glGenTextures(2, m_texture);
6463 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6464
6465 const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6466 "void main() {" NL " gl_Position = i_position;" NL "}";
6467 const char *const glsl_fs =
6468 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6469 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6470 " ivec2 coord = ivec2(gl_FragCoord);" NL
6471 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
6472 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6473
6474 return NO_ERROR;
6475 }
6476
Run()6477 virtual long Run()
6478 {
6479 int width = getWindowWidth();
6480 int height = getWindowHeight();
6481 scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6482
6483 glUseProgram(m_program);
6484 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6485 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6486
6487 std::vector<vec4> data(width * height, vec4(7.0f));
6488 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6490 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6491
6492 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6494 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6495
6496 glBindTexture(GL_TEXTURE_2D, 0);
6497
6498 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6499 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6500
6501 glClear(GL_COLOR_BUFFER_BIT);
6502 glViewport(0, 0, width, height);
6503 glBindVertexArray(m_vao);
6504 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6505
6506 std::vector<vec4> rdata(width * height);
6507 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6508 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6509
6510 for (int h = 0; h < height; ++h)
6511 {
6512 for (int w = 0; w < width; ++w)
6513 {
6514 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6515 {
6516 return ERROR;
6517 }
6518 }
6519 }
6520 return NO_ERROR;
6521 }
6522
Cleanup()6523 virtual long Cleanup()
6524 {
6525 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6526 glUseProgram(0);
6527 glDeleteBuffers(1, &m_vbo);
6528 glDeleteBuffers(1, &m_ebo);
6529 glDeleteTextures(2, m_texture);
6530 glDeleteProgram(m_program);
6531 glDeleteVertexArrays(1, &m_vao);
6532 return NO_ERROR;
6533 }
6534 };
6535 //-----------------------------------------------------------------------------
6536 // 2.6 AdvancedAllMips
6537 //-----------------------------------------------------------------------------
6538 class AdvancedAllMips : public ShaderImageLoadStoreBase
6539 {
6540 GLuint m_texture;
6541 GLuint m_store_program, m_load_program;
6542 GLuint m_vao, m_vbo, m_ebo;
6543
Setup()6544 virtual long Setup()
6545 {
6546 glGenTextures(1, &m_texture);
6547 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6548
6549 const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6550 "void main() {" NL " gl_Position = i_position;" NL "}";
6551 const char *const glsl_store_fs =
6552 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6553 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL
6554 " discard;" NL "}";
6555 const char *const glsl_load_fs =
6556 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6557 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6558 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL
6559 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL
6560 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}";
6561 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6562 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6563
6564 return NO_ERROR;
6565 }
6566
Run()6567 virtual long Run()
6568 {
6569 glUseProgram(m_store_program);
6570 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6571 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6572 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6573 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6574 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6575 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6576 glUseProgram(0);
6577
6578 glUseProgram(m_load_program);
6579 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6580 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6581 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6582 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6583 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6584 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6585 glUseProgram(0);
6586
6587 glBindTexture(GL_TEXTURE_2D, m_texture);
6588 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6589 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6590 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6591 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6592 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6593 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6594 glBindTexture(GL_TEXTURE_2D, 0);
6595
6596 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6597 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6598 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6599 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6600 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6601 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6602
6603 glViewport(0, 0, 32, 32);
6604 glBindVertexArray(m_vao);
6605
6606 glClear(GL_COLOR_BUFFER_BIT);
6607 glUseProgram(m_store_program);
6608 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6609
6610 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6611
6612 glUseProgram(m_load_program);
6613 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6614
6615 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6616 {
6617 return ERROR;
6618 }
6619 return NO_ERROR;
6620 }
6621
Cleanup()6622 virtual long Cleanup()
6623 {
6624 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6625 glUseProgram(0);
6626 glDeleteBuffers(1, &m_vbo);
6627 glDeleteBuffers(1, &m_ebo);
6628 glDeleteTextures(1, &m_texture);
6629 glDeleteProgram(m_store_program);
6630 glDeleteProgram(m_load_program);
6631 glDeleteVertexArrays(1, &m_vao);
6632 return NO_ERROR;
6633 }
6634 };
6635 //-----------------------------------------------------------------------------
6636 // 2.7 AdvancedCast
6637 //-----------------------------------------------------------------------------
6638 class AdvancedCast : public ShaderImageLoadStoreBase
6639 {
6640 GLuint m_texture[2];
6641 GLuint m_program;
6642 GLuint m_vao, m_vbo, m_ebo;
6643
Setup()6644 virtual long Setup()
6645 {
6646 glGenTextures(2, m_texture);
6647 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6648
6649 const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6650 "void main() {" NL " gl_Position = i_position;" NL "}";
6651 const char *const glsl_fs =
6652 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6653 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6654 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL
6655 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6656 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6657 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6658 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6659 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6660
6661 return NO_ERROR;
6662 }
6663
Run()6664 virtual long Run()
6665 {
6666 glUseProgram(m_program);
6667 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6668 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6669
6670 {
6671 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6672 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6673 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6674 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6675 &data[0]);
6676
6677 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6678 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6679 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6680 &data[0]);
6681
6682 glBindTexture(GL_TEXTURE_2D, 0);
6683 }
6684
6685 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6686 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6687
6688 glClear(GL_COLOR_BUFFER_BIT);
6689 glBindVertexArray(m_vao);
6690 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6691
6692 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6693 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6694 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6695 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6696
6697 for (int h = 0; h < getWindowHeight(); ++h)
6698 {
6699 for (int w = 0; w < getWindowWidth(); ++w)
6700 {
6701 const GLubyte c[4] = {
6702 data[h * (getWindowWidth() * 4) + w * 4 + 0],
6703 data[h * (getWindowWidth() * 4) + w * 4 + 1],
6704 data[h * (getWindowWidth() * 4) + w * 4 + 2],
6705 data[h * (getWindowWidth() * 4) + w * 4 + 3],
6706 };
6707 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6708 {
6709 m_context.getTestContext().getLog()
6710 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6711 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6712 return ERROR;
6713 }
6714 }
6715 }
6716
6717 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6718 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6719
6720 for (int h = 0; h < getWindowHeight(); ++h)
6721 {
6722 for (int w = 0; w < getWindowWidth(); ++w)
6723 {
6724 const GLubyte c[4] = {
6725 data[h * (getWindowWidth() * 4) + w * 4 + 0],
6726 data[h * (getWindowWidth() * 4) + w * 4 + 1],
6727 data[h * (getWindowWidth() * 4) + w * 4 + 2],
6728 data[h * (getWindowWidth() * 4) + w * 4 + 3],
6729 };
6730 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6731 {
6732 m_context.getTestContext().getLog()
6733 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6734 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6735 return ERROR;
6736 }
6737 }
6738 }
6739
6740 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6741 {
6742 return ERROR;
6743 }
6744 return NO_ERROR;
6745 }
6746
Cleanup()6747 virtual long Cleanup()
6748 {
6749 glUseProgram(0);
6750 glDeleteBuffers(1, &m_vbo);
6751 glDeleteBuffers(1, &m_ebo);
6752 glDeleteTextures(2, m_texture);
6753 glDeleteProgram(m_program);
6754 glDeleteVertexArrays(1, &m_vao);
6755 return NO_ERROR;
6756 }
6757 };
6758
6759 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6760 *
6761 * Steps:
6762 * - create two textures: "source" and "destination". Fill "source"
6763 * texture with unique values. Fill "destination" texture with zeros,
6764 * - prepare a program object that will read texel from "source" image at given
6765 * coordinates and write its value to "destination" image at same
6766 * coordinates,
6767 * - bind "source" and "destination" textures as "source" and "destination"
6768 * image uniforms,
6769 * - render "full screen" quad (left bottom corner at -1,-1 and right top
6770 * corner at 1,1),
6771 * - verify that texel values in "destination" texture match those in
6772 * "source" texture (use glGetTexImage).
6773 *
6774 * Test with 2D R8UI textures with following dimensions:
6775 * - 16x16,
6776 * - 16x17,
6777 * - 17x16,
6778 * - 17x17,
6779 * - 16x18,
6780 * - 18x16,
6781 * - 18x18,
6782 * - 19x16,
6783 * - 16x19,
6784 * - 19x19.
6785 *
6786 * Note that default data alignment should cause problems with packing/
6787 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6788 * of pixel storage mode have to be changed to one byte alignment.
6789 *
6790 * Program should consist of vertex and fragment shader. Vertex shader should
6791 * pass vertex position through. Fragment shader should do imageLoad() and
6792 * imageStore() operations at coordinates gl_FragCoord.
6793 **/
6794 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6795 {
6796 private:
6797 /* Structures */
6798 struct TextureDimensions
6799 {
6800 GLuint m_width;
6801 GLuint m_height;
6802
TextureDimensionsgl4cts::__anonf7c7fa4f0111::ImageLoadStoreDataAlignmentTest::TextureDimensions6803 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6804 {
6805 }
6806 };
6807
6808 /* Typedefs */
6809 typedef std::deque<TextureDimensions> TextureDimensionsList;
6810
6811 /* Fields */
6812 GLuint m_destination_texture_id;
6813 GLuint m_program_id;
6814 TextureDimensionsList m_texture_dimensions;
6815 GLuint m_source_texture_id;
6816 GLuint m_vertex_array_object_id;
6817 GLuint m_vertex_buffer_id;
6818
6819 public:
6820 /* Constructor */
ImageLoadStoreDataAlignmentTest()6821 ImageLoadStoreDataAlignmentTest()
6822 : m_destination_texture_id(0)
6823 , m_program_id(0)
6824 , m_source_texture_id(0)
6825 , m_vertex_array_object_id(0)
6826 , m_vertex_buffer_id(0)
6827 {
6828 /* Nothing to be done here */
6829 }
6830
6831 /* Methods inherited from SubcaseBase */
Setup()6832 virtual long Setup()
6833 {
6834 /* Shaders code */
6835 const char *const vertex_shader_code = "#version 400 core\n"
6836 "#extension GL_ARB_shader_image_load_store : require\n"
6837 "\n"
6838 "precision highp float;\n"
6839 "\n"
6840 "in vec4 vs_in_position;\n"
6841 "\n"
6842 "void main()\n"
6843 "{\n"
6844 " gl_Position = vs_in_position;\n"
6845 "}\n";
6846
6847 const char *const fragment_shader_code =
6848 "#version 400 core\n"
6849 "#extension GL_ARB_shader_image_load_store : require\n"
6850 "\n"
6851 "precision highp float;\n"
6852 "\n"
6853 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6854 "layout(r8ui) readonly uniform uimage2D u_source_image;\n"
6855 "\n"
6856 "void main()\n"
6857 "{\n"
6858 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
6859 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6860 "\n"
6861 " discard;\n"
6862 "}\n";
6863
6864 /* Vertex postions for "full screen" quad, made with triangle strip */
6865 static const GLfloat m_vertex_buffer_data[] = {
6866 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6867 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
6868 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
6869 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
6870 };
6871
6872 /* Result of BuildProgram operation */
6873 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6874
6875 /* Add all tested texture dimensions */
6876 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6877 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6878 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6879 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6880 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6881 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6882 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6883 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6884 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6885 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6886
6887 /* Clean previous error */
6888 glGetError();
6889
6890 /* Set single-byte data alignment */
6891 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6892 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6893 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6894
6895 /* Prepare buffer with vertex positions of "full screen" quad" */
6896 glGenBuffers(1, &m_vertex_buffer_id);
6897 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6898
6899 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6900 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6901
6902 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6903 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6904
6905 /* Generate vertex array object */
6906 glGenVertexArrays(1, &m_vertex_array_object_id);
6907 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6908
6909 /* Prepare program object */
6910 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6911 fragment_shader_code, &is_program_correct);
6912 if (false == is_program_correct)
6913 {
6914 return ERROR;
6915 }
6916
6917 /* Done */
6918 return NO_ERROR;
6919 }
6920
Cleanup()6921 virtual long Cleanup()
6922 {
6923 /* Reset OpenGL state */
6924 glBindBuffer(GL_ARRAY_BUFFER, 0);
6925 glBindTexture(GL_TEXTURE_2D, 0);
6926 glBindVertexArray(0);
6927 glUseProgram(0);
6928
6929 /* Delete program */
6930 if (0 != m_program_id)
6931 {
6932 glDeleteProgram(m_program_id);
6933 m_program_id = 0;
6934 }
6935
6936 /* Delete textures */
6937 if (0 != m_destination_texture_id)
6938 {
6939 glDeleteTextures(1, &m_destination_texture_id);
6940 m_destination_texture_id = 0;
6941 }
6942
6943 if (0 != m_source_texture_id)
6944 {
6945 glDeleteTextures(1, &m_source_texture_id);
6946 m_source_texture_id = 0;
6947 }
6948
6949 /* Delete vertex array object */
6950 if (0 != m_vertex_array_object_id)
6951 {
6952 glDeleteVertexArrays(1, &m_vertex_array_object_id);
6953 m_vertex_array_object_id = 0;
6954 }
6955
6956 /* Delete buffer */
6957 if (0 != m_vertex_buffer_id)
6958 {
6959 glDeleteBuffers(1, &m_vertex_buffer_id);
6960 m_vertex_buffer_id = 0;
6961 }
6962
6963 /* Done */
6964 return NO_ERROR;
6965 }
6966
Run()6967 virtual long Run()
6968 {
6969 bool result = true;
6970
6971 /* For each dimension */
6972 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6973 ++it)
6974 {
6975 /* Prepare "source" and "destination" textures */
6976 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6977 "Create2DR8UIDestinationTexture");
6978 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6979 "Create2DR8UISourceTexture");
6980
6981 /* Copy texture data with imageLoad() and imageStore() operations */
6982 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6983
6984 /* Compare "source" and "destination" textures */
6985 if (false ==
6986 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6987 {
6988 m_context.getTestContext().getLog()
6989 << tcu::TestLog::Message
6990 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6991 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6992
6993 result = false;
6994 }
6995
6996 /* Destroy "source" and "destination" textures */
6997 glDeleteTextures(1, &m_destination_texture_id);
6998 glDeleteTextures(1, &m_source_texture_id);
6999
7000 m_destination_texture_id = 0;
7001 m_source_texture_id = 0;
7002 }
7003
7004 if (false == result)
7005 {
7006 return ERROR;
7007 }
7008
7009 /* Done */
7010 return NO_ERROR;
7011 }
7012
7013 private:
7014 /* Private methods */
7015
7016 /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7017 *
7018 * @param program_id Program object id
7019 * @param texture_id Texture id
7020 * @param image_unit Index of image unit
7021 * @param uniform_name Name of image uniform
7022 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7023 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char *uniform_name)
7024 {
7025 /* Uniform location and invalid value */
7026 static const GLint invalid_uniform_location = -1;
7027 GLint image_uniform_location = 0;
7028
7029 /* Get uniform location */
7030 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7031 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7032 if (invalid_uniform_location == image_uniform_location)
7033 {
7034 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7035 }
7036
7037 /* Bind texture to image unit */
7038 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7039 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7040
7041 /* Set uniform to image unit */
7042 glUniform1i(image_uniform_location, image_unit);
7043 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7044 }
7045
7046 /** Compare two 2D R8UI textures
7047 *
7048 * @param left_texture_id Id of "left" texture object
7049 * @param right_texture_id Id of "right" texture object
7050 * @param width Width of the textures
7051 * @param height Height of the textures
7052 *
7053 * @return true when texture data is identical, false otherwise
7054 **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7055 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7056 {
7057 /* Size of textures */
7058 const GLuint texture_data_size = width * height;
7059
7060 /* Storage for texture data */
7061 std::vector<GLubyte> left_texture_data;
7062 std::vector<GLubyte> right_texture_data;
7063
7064 /* Alocate memory for texture data */
7065 left_texture_data.resize(texture_data_size);
7066 right_texture_data.resize(texture_data_size);
7067
7068 /* Get "left" texture data */
7069 glBindTexture(GL_TEXTURE_2D, left_texture_id);
7070 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7071
7072 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7073 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7074
7075 /* Get "right" texture data */
7076 glBindTexture(GL_TEXTURE_2D, right_texture_id);
7077 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7078
7079 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7080 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7081
7082 /* Compare texels */
7083 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7084 }
7085
7086 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7087 *
7088 * @param destination_texture_id Id of "destination" texture object
7089 * @param source_texture_id Id of "source" texture object
7090 **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7091 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7092 {
7093 /* Uniform names */
7094 static const char *const destination_image_uniform_name = "u_destination_image";
7095 static const char *const source_image_uniform_name = "u_source_image";
7096
7097 /* Attribute name */
7098 static const char *const position_attribute_name = "vs_in_position";
7099
7100 /* Attribute location and invalid value */
7101 static const GLint invalid_attribute_location = -1;
7102 GLint position_attribute_location = 0;
7103
7104 /* Set current program */
7105 glUseProgram(m_program_id);
7106 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7107
7108 /* Bind vertex array object */
7109 glBindVertexArray(m_vertex_array_object_id);
7110 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7111
7112 /* Bind buffer with quad vertex positions */
7113 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7114 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7115
7116 /* Set up position attribute */
7117 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7118 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7119 if (invalid_attribute_location == position_attribute_location)
7120 {
7121 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7122 __LINE__);
7123 }
7124
7125 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7126 0 /* stride */, 0);
7127 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7128
7129 glEnableVertexAttribArray(position_attribute_location);
7130 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7131
7132 /* Set up textures as source and destination images */
7133 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7134 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7135
7136 /* Execute draw */
7137 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7138 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7139 }
7140
7141 /** Create 2D R8UI texture and fills it with zeros
7142 *
7143 * @param width Width of created texture
7144 * @param height Height of created texture
7145 * @param out_texture_id Id of created texture, not modified if operation fails
7146 *
7147 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7148 **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7149 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint &out_texture_id)
7150 {
7151 /* Texture size */
7152 const GLuint texture_size = width * height;
7153
7154 /* Prepare storage for texture data */
7155 std::vector<GLubyte> texture_data;
7156 texture_data.resize(texture_size);
7157
7158 /* Set all texels */
7159 for (GLuint i = 0; i < texture_size; ++i)
7160 {
7161 texture_data[i] = 0;
7162 }
7163
7164 /* Create texture */
7165 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7166 }
7167
7168 /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7169 *
7170 * @param width Width of created texture
7171 * @param height Height of created texture
7172 * @param out_texture_id Id of created texture, not modified if operation fails
7173 *
7174 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7175 **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7176 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint &out_texture_id)
7177 {
7178 /* Texture size */
7179 const GLuint texture_size = width * height;
7180
7181 /* Value of texel */
7182 GLubyte texel_value = 0;
7183
7184 /* Prepare storage for texture data */
7185 std::vector<GLubyte> texture_data;
7186 texture_data.resize(texture_size);
7187
7188 /* Set all texels */
7189 for (GLuint i = 0; i < texture_size; ++i)
7190 {
7191 texture_data[i] = texel_value++;
7192 }
7193
7194 /* Create texture */
7195 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7196 }
7197
7198 /** Create 2D R8UI texture and fills it with user-provided data
7199 *
7200 * @param width Width of created texture
7201 * @param height Height of created texture
7202 * @param texture_data Texture data
7203 * @param out_texture_id Id of created texture, not modified if operation fails
7204 *
7205 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7206 **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7207 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte> &texture_data,
7208 GLuint &out_texture_id)
7209 {
7210 GLenum err = 0;
7211 GLuint texture_id = 0;
7212
7213 /* Generate texture */
7214 glGenTextures(1, &texture_id);
7215 err = glGetError();
7216 if (GL_NO_ERROR != err)
7217 {
7218 return err;
7219 }
7220
7221 /* Bind texture */
7222 glBindTexture(GL_TEXTURE_2D, texture_id);
7223 err = glGetError();
7224 if (GL_NO_ERROR != err)
7225 {
7226 glDeleteTextures(1, &texture_id);
7227 return err;
7228 }
7229
7230 /* Allocate storage and fill texture */
7231 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7232 GL_UNSIGNED_BYTE, &texture_data[0]);
7233 err = glGetError();
7234 if (GL_NO_ERROR != err)
7235 {
7236 glDeleteTextures(1, &texture_id);
7237 return err;
7238 }
7239
7240 /* Make texture complete */
7241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7244 err = glGetError();
7245 if (GL_NO_ERROR != err)
7246 {
7247 glDeleteTextures(1, &texture_id);
7248 return err;
7249 }
7250
7251 /* Set out_texture_id */
7252 out_texture_id = texture_id;
7253
7254 /* Done */
7255 return GL_NO_ERROR;
7256 }
7257 };
7258
7259 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7260 *
7261 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7262 *
7263 * Test non-layered image bindings (BindImageTexture <layered>: false) with:
7264 * | Type | Dimensions |
7265 * | 2D_ARRAY | 64x64x6 |
7266 * | 3D | 64x64x6 |
7267 * | CUBE_MAP | 64 |
7268 * | CUBE_MAP_ARRAY | 64x3 |
7269 *
7270 * Use RGBA8 format. All layers shall be tested.
7271 *
7272 * Program should consist of vertex and fragment shader. Vertex shader should
7273 * pass vertex position through. Fragment shader should do imageLoad() and
7274 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7275 * use image2D as image type.
7276 **/
7277 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7278 {
7279 private:
7280 /* Structures */
7281 struct TextureShapeDefinition
7282 {
7283 GLuint m_edge;
7284 GLuint m_n_elements;
7285 GLenum m_type;
7286
TextureShapeDefinitiongl4cts::__anonf7c7fa4f0111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7287 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7288 : m_edge(edge)
7289 , m_n_elements(n_elements)
7290 , m_type(type)
7291 {
7292 }
7293 };
7294
7295 /* Typedefs */
7296 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7297
7298 /* Fields */
7299 GLuint m_destination_texture_id;
7300 GLuint m_program_id;
7301 TextureShapeDefinitionList m_texture_shape_definitions;
7302 GLuint m_source_texture_id;
7303 GLuint m_vertex_array_object_id;
7304 GLuint m_vertex_buffer_id;
7305
7306 public:
7307 /* Constructor */
ImageLoadStoreNonLayeredBindingTest()7308 ImageLoadStoreNonLayeredBindingTest()
7309 : m_destination_texture_id(0)
7310 , m_program_id(0)
7311 , m_source_texture_id(0)
7312 , m_vertex_array_object_id(0)
7313 , m_vertex_buffer_id(0)
7314 {
7315 /* Nothing to be done here */
7316 }
7317
7318 /* Methods inherited from SubcaseBase */
Setup()7319 virtual long Setup()
7320 {
7321 /* Shaders code */
7322 const char *const vertex_shader_code = "#version 400 core\n"
7323 "#extension GL_ARB_shader_image_load_store : require\n"
7324 "\n"
7325 "precision highp float;\n"
7326 "\n"
7327 "in vec4 vs_in_position;\n"
7328 "\n"
7329 "void main()\n"
7330 "{\n"
7331 " gl_Position = vs_in_position;\n"
7332 "}\n";
7333
7334 const char *const fragment_shader_code =
7335 "#version 400 core\n"
7336 "#extension GL_ARB_shader_image_load_store : require\n"
7337 "\n"
7338 "precision highp float;\n"
7339 "\n"
7340 "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7341 "layout(rgba8) readonly uniform image2D u_source_image;\n"
7342 "\n"
7343 "void main()\n"
7344 "{\n"
7345 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
7346 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7347 "\n"
7348 " discard;\n"
7349 "}\n";
7350
7351 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7352 static const GLfloat m_vertex_buffer_data[] = {
7353 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7354 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7355 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7356 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7357 };
7358
7359 /* Result of BuildProgram operation */
7360 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7361
7362 /* Add all tested texture shapes */
7363 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7364 m_texture_shape_definitions.push_back(
7365 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7366 m_texture_shape_definitions.push_back(
7367 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7368 m_texture_shape_definitions.push_back(
7369 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7370 m_texture_shape_definitions.push_back(
7371 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7372
7373 /* Prepare buffer with vertex positions of "full screen" quad" */
7374 glGenBuffers(1, &m_vertex_buffer_id);
7375 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7376
7377 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7378 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7379
7380 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7381 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7382
7383 /* Generate vertex array object */
7384 glGenVertexArrays(1, &m_vertex_array_object_id);
7385 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7386
7387 /* Prepare program object */
7388 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7389 fragment_shader_code, &is_program_correct);
7390 if (false == is_program_correct)
7391 {
7392 return ERROR;
7393 }
7394
7395 /* Done */
7396 return NO_ERROR;
7397 }
7398
Cleanup()7399 virtual long Cleanup()
7400 {
7401 /* Reset OpenGL state */
7402 glBindBuffer(GL_ARRAY_BUFFER, 0);
7403 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7404 glBindTexture(GL_TEXTURE_3D, 0);
7405 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7406 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7407 glBindVertexArray(0);
7408 glUseProgram(0);
7409
7410 /* Delete program */
7411 if (0 != m_program_id)
7412 {
7413 glDeleteProgram(m_program_id);
7414 m_program_id = 0;
7415 }
7416
7417 /* Delete textures */
7418 if (0 != m_destination_texture_id)
7419 {
7420 glDeleteTextures(1, &m_destination_texture_id);
7421 m_destination_texture_id = 0;
7422 }
7423
7424 if (0 != m_source_texture_id)
7425 {
7426 glDeleteTextures(1, &m_source_texture_id);
7427 m_source_texture_id = 0;
7428 }
7429
7430 /* Delete vertex array object */
7431 if (0 != m_vertex_array_object_id)
7432 {
7433 glDeleteVertexArrays(1, &m_vertex_array_object_id);
7434 m_vertex_array_object_id = 0;
7435 }
7436
7437 /* Delete buffer */
7438 if (0 != m_vertex_buffer_id)
7439 {
7440 glDeleteBuffers(1, &m_vertex_buffer_id);
7441 m_vertex_buffer_id = 0;
7442 }
7443
7444 /* Done */
7445 return NO_ERROR;
7446 }
7447
Run()7448 virtual long Run()
7449 {
7450 bool result = true;
7451
7452 /* For each shape */
7453 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7454 m_texture_shape_definitions.end() != it; ++it)
7455 {
7456 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7457
7458 /* Prepare "source" and "destination" textures */
7459 GLU_EXPECT_NO_ERROR(
7460 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7461 "Create2DR8UIDestinationTexture");
7462 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7463 "Create2DR8UISourceTexture");
7464
7465 /* Copy texture data with imageLoad() and imageStore() operations */
7466 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7467
7468 /* Compare "source" and "destination" textures */
7469 if (false ==
7470 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7471 {
7472 const char *texture_type = "";
7473 switch (it->m_type)
7474 {
7475 case GL_TEXTURE_2D_ARRAY:
7476 texture_type = "2d array";
7477 break;
7478 case GL_TEXTURE_3D:
7479 texture_type = "3d";
7480 break;
7481 case GL_TEXTURE_CUBE_MAP:
7482 texture_type = "Cube map";
7483 break;
7484 case GL_TEXTURE_CUBE_MAP_ARRAY:
7485 texture_type = "Cube map array";
7486 break;
7487 }
7488
7489 m_context.getTestContext().getLog()
7490 << tcu::TestLog::Message
7491 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type
7492 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7493
7494 result = false;
7495 }
7496
7497 /* Destroy "source" and "destination" textures */
7498 glDeleteTextures(1, &m_destination_texture_id);
7499 glDeleteTextures(1, &m_source_texture_id);
7500
7501 m_destination_texture_id = 0;
7502 m_source_texture_id = 0;
7503 }
7504
7505 if (false == result)
7506 {
7507 return ERROR;
7508 }
7509
7510 /* Done */
7511 return NO_ERROR;
7512 }
7513
7514 private:
7515 /* Private methods */
7516
7517 /** Binds a texture to user-specified image unit and update relevant sampler uniform
7518 *
7519 * @param program_id Program object id
7520 * @param texture_id Texture id
7521 * @param image_unit Index of image unit
7522 * @param layer Index of layer bound to unit
7523 * @param uniform_name Name of image uniform
7524 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7525 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7526 const char *uniform_name)
7527 {
7528 static const GLint invalid_uniform_location = -1;
7529 GLint image_uniform_location = 0;
7530
7531 /* Get uniform location */
7532 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7533 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7534 if (invalid_uniform_location == image_uniform_location)
7535 {
7536 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7537 }
7538
7539 /* Bind texture to image unit */
7540 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7541 GL_RGBA8);
7542 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7543
7544 /* Set uniform to image unit */
7545 glUniform1i(image_uniform_location, image_unit);
7546 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7547 }
7548
7549 /** Compare two 2D R8UI textures
7550 *
7551 * @param left_texture_id Id of "left" texture object
7552 * @param right_texture_id Id of "right" texture object
7553 * @param edge Length of texture edge
7554 * @param n_layers Number of layers to compare
7555 * @param type Type of texture
7556 *
7557 * @return true when texture data is found identical, false otherwise
7558 **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7559 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7560 GLenum type)
7561 {
7562 static const GLuint n_components = 4; /* RGBA */
7563 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7564
7565 /* Storage for texture data */
7566 std::vector<GLubyte> left_texture_data;
7567 std::vector<GLubyte> right_texture_data;
7568
7569 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7570 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7571
7572 /* Compare texels */
7573 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7574 }
7575
7576 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7577 *
7578 * @param destination_texture_id Id of "destination" texture object
7579 * @param source_texture_id Id of "source" texture object
7580 * @param n_layers Number of layers
7581 **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7582 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7583 {
7584 for (GLuint layer = 0; layer < n_layers; ++layer)
7585 {
7586 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7587 }
7588 }
7589
7590 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7591 *
7592 * @param destination_texture_id Id of "destination" texture object
7593 * @param source_texture_id Id of "source" texture object
7594 * @param layer Index of layer
7595 **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7596 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7597 {
7598 /* Uniform names */
7599 static const char *const destination_image_uniform_name = "u_destination_image";
7600 static const char *const source_image_uniform_name = "u_source_image";
7601
7602 /* Attribute name */
7603 static const char *const position_attribute_name = "vs_in_position";
7604
7605 /* Attribute location and invalid value */
7606 static const GLint invalid_attribute_location = -1;
7607 GLint position_attribute_location = 0;
7608
7609 /* Set current program */
7610 glUseProgram(m_program_id);
7611 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7612
7613 /* Bind vertex array object */
7614 glBindVertexArray(m_vertex_array_object_id);
7615 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7616
7617 /* Bind buffer with quad vertex positions */
7618 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7619 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7620
7621 /* Set up vertex attribute array for position attribute */
7622 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7623 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7624 if (invalid_attribute_location == position_attribute_location)
7625 {
7626 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7627 __LINE__);
7628 }
7629
7630 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7631 0 /* stride */, 0 /* pointer */);
7632 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7633
7634 glEnableVertexAttribArray(position_attribute_location);
7635 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7636
7637 /* Set up textures as source and destination image samplers */
7638 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7639 destination_image_uniform_name);
7640 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7641
7642 /* Execute draw */
7643 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7644 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7645 }
7646
7647 /** Creates RGBA8 texture of given type and fills it with zeros
7648 *
7649 * @param edge Edge of created texture
7650 * @param n_elements Number of elements in texture array
7651 * @param target Target of created texture
7652 * @param out_texture_id Id of created texture, not modified if operation fails
7653 *
7654 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7655 **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7656 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint &out_texture_id)
7657 {
7658 /* Constasts to calculate texture size */
7659 static const GLuint n_components = 4; /* RGBA */
7660 const GLuint layer_size = edge * edge * n_components;
7661 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7662 const GLuint texture_size = layer_size * n_layers;
7663
7664 /* Prepare storage for texture data */
7665 std::vector<GLubyte> texture_data;
7666 texture_data.resize(texture_size);
7667
7668 /* Set all texels */
7669 for (GLuint i = 0; i < texture_size; ++i)
7670 {
7671 texture_data[i] = 0;
7672 }
7673
7674 /* Create texture */
7675 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7676 }
7677
7678 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7679 *
7680 * @param edge Edge of created texture
7681 * @param n_elements Number of elements in texture array
7682 * @param target Target of created texture
7683 * @param out_texture_id Id of created texture, not modified if operation fails
7684 *
7685 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7686 **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7687 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint &out_texture_id)
7688 {
7689 /* Constants to calculate texture size */
7690 static const GLuint n_components = 4; /* RGBA */
7691 const GLuint layer_size = edge * edge * n_components;
7692 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7693 const GLuint texture_size = layer_size * n_layers;
7694
7695 /* Value of texel */
7696 GLubyte texel[4] = {0, 0, 0, 0xaa};
7697
7698 /* Prepare storage for texture data */
7699 std::vector<GLubyte> texture_data;
7700 texture_data.resize(texture_size);
7701
7702 /* Set all texels */
7703 for (GLuint layer = 0; layer < n_layers; ++layer)
7704 {
7705 const GLuint layer_offset = layer_size * layer;
7706
7707 texel[2] = static_cast<GLubyte>(layer);
7708
7709 for (GLuint y = 0; y < edge; ++y)
7710 {
7711 const GLuint line_offset = y * edge * n_components + layer_offset;
7712
7713 texel[1] = static_cast<GLubyte>(y);
7714
7715 for (GLuint x = 0; x < edge; ++x)
7716 {
7717 const GLuint texel_offset = x * n_components + line_offset;
7718 texel[0] = static_cast<GLubyte>(x);
7719
7720 for (GLuint component = 0; component < n_components; ++component)
7721 {
7722 texture_data[texel_offset + component] = texel[component];
7723 }
7724 }
7725 }
7726 }
7727
7728 /* Create texture */
7729 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7730 }
7731
7732 /** Creates RGBA8 texture of given type and fills it provided data
7733 *
7734 * @param edge Edge of created texture
7735 * @param n_elements Number of elements in texture array
7736 * @param target Target of created texture
7737 * @param texture_data Texture data
7738 * @param out_texture_id Id of created texture, not modified if operation fails
7739 *
7740 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7741 **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7742 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte> &texture_data,
7743 GLuint &out_texture_id)
7744 {
7745 GLenum err = 0;
7746 GLuint texture_id = 0;
7747
7748 /* Generate texture */
7749 glGenTextures(1, &texture_id);
7750 err = glGetError();
7751 if (GL_NO_ERROR != err)
7752 {
7753 return err;
7754 }
7755
7756 /* Bind texture */
7757 glBindTexture(target, texture_id);
7758 err = glGetError();
7759 if (GL_NO_ERROR != err)
7760 {
7761 glDeleteTextures(1, &texture_id);
7762 return err;
7763 }
7764
7765 /* Allocate storage and fill texture */
7766 if (GL_TEXTURE_CUBE_MAP != target)
7767 {
7768 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7769 GL_UNSIGNED_BYTE, &texture_data[0]);
7770 }
7771 else
7772 {
7773 const GLuint n_components = 4;
7774 const GLuint layer_size = edge * edge * n_components;
7775
7776 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7777 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7778 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7779 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7780 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7781 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7782 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7783 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7784 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7785 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7786 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7787 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7788 }
7789 err = glGetError();
7790 if (GL_NO_ERROR != err)
7791 {
7792 glDeleteTextures(1, &texture_id);
7793 return err;
7794 }
7795
7796 /* Make texture complete */
7797 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7798 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7799 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7800 err = glGetError();
7801 if (GL_NO_ERROR != err)
7802 {
7803 glDeleteTextures(1, &texture_id);
7804 return err;
7805 }
7806
7807 /* Set out_texture_id */
7808 out_texture_id = texture_id;
7809
7810 /* Done */
7811 return GL_NO_ERROR;
7812 }
7813
7814 /** Extracts texture data
7815 *
7816 * @param texture_id Id of texture object
7817 * @param edge Length of texture edge
7818 * @param n_layers Number of layers
7819 * @param target Target of texture
7820 * @param texture_data Extracted texture data
7821 **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7822 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7823 std::vector<GLubyte> &texture_data)
7824 {
7825 static const GLuint n_components = 4; /* RGBA */
7826 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7827
7828 /* Alocate memory for texture data */
7829 texture_data.resize(texture_data_size);
7830
7831 /* Bind texture */
7832 glBindTexture(target, texture_id);
7833 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7834
7835 /* Get data */
7836 if (GL_TEXTURE_CUBE_MAP != target)
7837 {
7838 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7839 }
7840 else
7841 {
7842 const GLuint layer_size = edge * edge * n_components;
7843
7844 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7845 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7846 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7847 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7848 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7849 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7850 }
7851
7852 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7853 }
7854
7855 /** Get number of layers per single element for given type of texture
7856 *
7857 * @param target Target of texture
7858 *
7859 * @return Number of layers
7860 **/
GetLayersPerElement(GLenum target)7861 GLuint GetLayersPerElement(GLenum target)
7862 {
7863 switch (target)
7864 {
7865 case GL_TEXTURE_2D_ARRAY:
7866 case GL_TEXTURE_3D:
7867 return 1;
7868 case GL_TEXTURE_CUBE_MAP:
7869 case GL_TEXTURE_CUBE_MAP_ARRAY:
7870 return 6;
7871 default:
7872 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7873 }
7874 }
7875
7876 /** Get total number of layers in texture of given type and number of array elements
7877 *
7878 * @param n_elements Number of elements in texture array
7879 * @param target Target of texture
7880 *
7881 * @return Number of layers
7882 **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7883 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7884 {
7885 return GetLayersPerElement(target) * n_elements;
7886 }
7887 };
7888
7889 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7890 *
7891 * Load from incomplete textures should return 0.
7892 * Store to incomplete textures should be ignored.
7893 *
7894 * Steps:
7895 * - create two incomplete textures: "incomplete_source" and
7896 * "incomplete_destination",
7897 * - create two complete textures: "complete_source" and
7898 * "complete_destination",
7899 * - fill all textures with unique values,
7900 * - prepare program that will:
7901 * * load texel from "incomplete_source" and store its value to
7902 * "complete_destination",
7903 * * load texel from "complete_source" and store its value to
7904 * "incomplete_destination".
7905 * - bind textures to corresponding image uniforms
7906 * - execute program for all texels,
7907 * - verify that "incomplete_destination" was not modified and
7908 * "complete_destination" is filled with zeros.
7909 *
7910 * Texture is considered incomplete when it has enabled mipmaping (see below)
7911 * and does not have all mipmap levels defined. But for the case of Image
7912 * accessing, it is considered invalid if it is mipmap-incomplete and the
7913 * level is different to the base level (base-incomplete).
7914 *
7915 * Creation of incomplete texture:
7916 * - generate and bind texture object id,
7917 * - call TexImage2D with <level>: 0,
7918 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7919 * sure, it should be initial value),
7920 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7921 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7922 * height)).
7923 *
7924 * Creation of complete texture:
7925 * - generate and bind texture object id,
7926 * - call TexImage2D with <level>: 0,
7927 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7928 * - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7929 *
7930 * Binding:
7931 * - Set level == base_level for complete destinations.
7932 * - Set level != base_level for incomplete destinations that are using
7933 * mipmap-incomplete textures.
7934 *
7935 * Test with 2D 64x64 RGBA8 textures.
7936 *
7937 * Program should consist of vertex and fragment shader. Vertex shader should
7938 * pass vertex position through. Fragment shader should do imageLoad() and
7939 * imageStore() operations at coordinates gl_FragCoord.
7940 **/
7941 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7942 {
7943 private:
7944 /* Constants */
7945 /* Magic numbers that will identify textures, which will be used as their
7946 * texel value.
7947 */
7948 static const GLubyte m_complete_destination_magic_number = 0x11;
7949 static const GLubyte m_complete_source_magic_number = 0x22;
7950 static const GLubyte m_incomplete_destination_magic_number = 0x33;
7951 static const GLubyte m_incomplete_source_magic_number = 0x44;
7952
7953 /* Texture edge */
7954 GLuint m_texture_edge;
7955
7956 /* Fields */
7957 GLuint m_complete_destination_texture_id;
7958 GLuint m_complete_source_texture_id;
7959 GLuint m_incomplete_destination_texture_id;
7960 GLuint m_incomplete_source_texture_id;
7961 GLuint m_program_id;
7962 GLuint m_vertex_array_object_id;
7963 GLuint m_vertex_buffer_id;
7964
7965 public:
7966 /* Constructor */
ImageLoadStoreIncompleteTexturesTest()7967 ImageLoadStoreIncompleteTexturesTest()
7968 : m_texture_edge(0)
7969 , m_complete_destination_texture_id(0)
7970 , m_complete_source_texture_id(0)
7971 , m_incomplete_destination_texture_id(0)
7972 , m_incomplete_source_texture_id(0)
7973 , m_program_id(0)
7974 , m_vertex_array_object_id(0)
7975 , m_vertex_buffer_id(0)
7976 {
7977 /* Nothing to be done here */
7978 }
7979
7980 /* Methods inherited from SubcaseBase */
Setup()7981 virtual long Setup()
7982 {
7983 /* Shaders code */
7984 const char *const vertex_shader_code = "#version 400 core\n"
7985 "#extension GL_ARB_shader_image_load_store : require\n"
7986 "\n"
7987 "precision highp float;\n"
7988 "\n"
7989 "in vec4 vs_in_position;\n"
7990 "\n"
7991 "void main()\n"
7992 "{\n"
7993 " gl_Position = vs_in_position;\n"
7994 "}\n";
7995
7996 const char *const fragment_shader_code =
7997 "#version 400 core\n"
7998 "#extension GL_ARB_shader_image_load_store : require\n"
7999 "\n"
8000 "precision highp float;\n"
8001 "\n"
8002 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
8003 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n"
8004 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
8005 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n"
8006 "\n"
8007 "void main()\n"
8008 "{\n"
8009 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n"
8010 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
8011
8012 " imageStore(u_complete_destination_image,\n"
8013 " ivec2(gl_FragCoord),\n"
8014 " incomplete_loaded_color);\n"
8015 " imageStore(u_incomplete_destination_image,\n"
8016 " ivec2(gl_FragCoord),\n"
8017 " complete_loaded_color);\n"
8018 "\n"
8019 " discard;\n"
8020 "}\n";
8021
8022 /* Vertex postions for "full screen" quad, made with triangle strip */
8023 static const GLfloat m_vertex_buffer_data[] = {
8024 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8025 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
8026 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
8027 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
8028 };
8029
8030 /* Result of BuildProgram operation */
8031 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8032
8033 /* Clean previous error */
8034 glGetError();
8035
8036 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8037
8038 /* Prepare textures */
8039 GLU_EXPECT_NO_ERROR(
8040 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8041 "Create2DRGBA8CompleteTexture");
8042 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8043 "Create2DRGBA8CompleteTexture");
8044 GLU_EXPECT_NO_ERROR(
8045 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8046 "Create2DRGBA8IncompleteTexture");
8047 GLU_EXPECT_NO_ERROR(
8048 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8049 "Create2DRGBA8IncompleteTexture");
8050
8051 /* Prepare buffer with vertex positions of "full screen" quad" */
8052 glGenBuffers(1, &m_vertex_buffer_id);
8053 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8054
8055 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8056 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8057
8058 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8059 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8060
8061 /* Generate vertex array object */
8062 glGenVertexArrays(1, &m_vertex_array_object_id);
8063 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8064
8065 /* Prepare program object */
8066 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8067 fragment_shader_code, &is_program_correct);
8068
8069 if (false == is_program_correct)
8070 {
8071 return ERROR;
8072 }
8073
8074 /* Done */
8075 return NO_ERROR;
8076 }
8077
Cleanup()8078 virtual long Cleanup()
8079 {
8080 /* Reset OpenGL state */
8081 glBindBuffer(GL_ARRAY_BUFFER, 0);
8082 glBindTexture(GL_TEXTURE_2D, 0);
8083 glBindVertexArray(0);
8084 glUseProgram(0);
8085
8086 /* Delete program */
8087 if (0 != m_program_id)
8088 {
8089 glDeleteProgram(m_program_id);
8090 m_program_id = 0;
8091 }
8092
8093 /* Delete textures */
8094 if (0 != m_complete_destination_texture_id)
8095 {
8096 glDeleteTextures(1, &m_complete_destination_texture_id);
8097 m_complete_destination_texture_id = 0;
8098 }
8099
8100 if (0 != m_complete_source_texture_id)
8101 {
8102 glDeleteTextures(1, &m_complete_source_texture_id);
8103 m_complete_source_texture_id = 0;
8104 }
8105
8106 if (0 != m_incomplete_destination_texture_id)
8107 {
8108 glDeleteTextures(1, &m_incomplete_destination_texture_id);
8109 m_incomplete_destination_texture_id = 0;
8110 }
8111
8112 if (0 != m_incomplete_source_texture_id)
8113 {
8114 glDeleteTextures(1, &m_incomplete_source_texture_id);
8115 m_incomplete_source_texture_id = 0;
8116 }
8117
8118 /* Delete vertex array object */
8119 if (0 != m_vertex_array_object_id)
8120 {
8121 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8122 m_vertex_array_object_id = 0;
8123 }
8124
8125 /* Delete buffer */
8126 if (0 != m_vertex_buffer_id)
8127 {
8128 glDeleteBuffers(1, &m_vertex_buffer_id);
8129 m_vertex_buffer_id = 0;
8130 }
8131
8132 /* Done */
8133 return NO_ERROR;
8134 }
8135
Run()8136 virtual long Run()
8137 {
8138 bool result = true;
8139
8140 /* Copy textures data with imageLoad() and imageStore() operations */
8141 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8142 m_complete_source_texture_id, m_incomplete_source_texture_id);
8143
8144 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8145
8146 /* Verify that store to "incomplete destination" was ignored */
8147 if (true ==
8148 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8149 {
8150 m_context.getTestContext().getLog()
8151 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8152 << tcu::TestLog::EndMessage;
8153
8154 result = false;
8155 }
8156
8157 /* Verify that load from "incomplete source" returned 0 */
8158 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8159 {
8160 m_context.getTestContext().getLog()
8161 << tcu::TestLog::Message
8162 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8163 << tcu::TestLog::EndMessage;
8164
8165 result = false;
8166 }
8167
8168 if (false == result)
8169 {
8170 return ERROR;
8171 }
8172
8173 /* Done */
8174 return NO_ERROR;
8175 }
8176
8177 private:
8178 /* Private methods */
8179
8180 /** Bind texture to image unit and sets image uniform to that unit
8181 *
8182 * @param program_id Program object id
8183 * @param texture_id Texture id
8184 * @param level Texture level
8185 * @param image_unit Index of image unit
8186 * @param uniform_name Name of image uniform
8187 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8188 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit,
8189 const char *uniform_name)
8190 {
8191 /* Uniform location and invalid value */
8192 static const GLint invalid_uniform_location = -1;
8193 GLint image_uniform_location = 0;
8194
8195 /* Get uniform location */
8196 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8197 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8198 if (invalid_uniform_location == image_uniform_location)
8199 {
8200 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8201 }
8202
8203 /* Bind texture to image unit */
8204 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8205 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8206
8207 /* Set uniform to image unit */
8208 glUniform1i(image_uniform_location, image_unit);
8209 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8210 }
8211
8212 /** Check if texture is filled with black color, zeros
8213 *
8214 * @param texture_id Id of texture object
8215 *
8216 * @return true when texture is fully black, false otherwise
8217 **/
CheckIfTextureIsBlack(GLuint texture_id)8218 bool CheckIfTextureIsBlack(GLuint texture_id)
8219 {
8220 /* Constants to calculate size of texture */
8221 static const GLuint n_components = 4; /* RGBA */
8222 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8223
8224 /* Storage for texture data */
8225 std::vector<GLubyte> black_texture_data;
8226 std::vector<GLubyte> texture_data;
8227
8228 /* Allocate memory */
8229 black_texture_data.resize(texture_data_size);
8230 texture_data.resize(texture_data_size);
8231
8232 /* Set all texels to black */
8233 for (GLuint i = 0; i < texture_data_size; ++i)
8234 {
8235 black_texture_data[i] = 0;
8236 }
8237
8238 /* Bind texture */
8239 glBindTexture(GL_TEXTURE_2D, texture_id);
8240 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8241
8242 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8243 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8244
8245 /* Compare texels */
8246 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8247 }
8248
8249 /** Check if texture was modified
8250 *
8251 * @param texture_id Id of texture object
8252 * @param nagic_number Magic number that was to create texture
8253 *
8254 * @return true if texture contents match expected values, false otherwise
8255 **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8256 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8257 {
8258 /* Constants to calculate size of texture */
8259 static const GLuint n_components = 4; /* RGBA */
8260 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8261
8262 /* Storage for texture data */
8263 std::vector<GLubyte> expected_texture_data;
8264 std::vector<GLubyte> texture_data;
8265
8266 /* Allocate memory */
8267 expected_texture_data.resize(texture_data_size);
8268 texture_data.resize(texture_data_size);
8269
8270 /* Prepare expected texels */
8271 for (GLuint y = 0; y < m_texture_edge; ++y)
8272 {
8273 const GLuint line_offset = y * m_texture_edge * n_components;
8274
8275 for (GLuint x = 0; x < m_texture_edge; ++x)
8276 {
8277 const GLuint texel_offset = x * n_components + line_offset;
8278
8279 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8280 magic_number);
8281 }
8282 }
8283
8284 /* Bind texture */
8285 glBindTexture(GL_TEXTURE_2D, texture_id);
8286 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8287
8288 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8289 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8290
8291 /* Compare texels, true when textures are different */
8292 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8293 }
8294
8295 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8296 *
8297 * @param complete_destination_texture_id Id of "complete destination" texture object
8298 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8299 * @param complete_source_texture_id Id of "complete source" texture object
8300 * @param incomplete_source_texture_id Id of "incomplete source" texture object
8301 **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8302 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8303 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8304 {
8305 /* Uniform names */
8306 static const char *const complete_destination_image_uniform_name = "u_complete_destination_image";
8307 static const char *const complete_source_image_uniform_name = "u_complete_source_image";
8308 static const char *const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8309 static const char *const incomplete_source_image_uniform_name = "u_incomplete_source_image";
8310
8311 /* Attribute name */
8312 static const char *const position_attribute_name = "vs_in_position";
8313
8314 /* Attribute location and invalid value */
8315 static const GLint invalid_attribute_location = -1;
8316 GLint position_attribute_location = 0;
8317
8318 /* Set current program */
8319 glUseProgram(m_program_id);
8320 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8321
8322 /* Bind vertex array object */
8323 glBindVertexArray(m_vertex_array_object_id);
8324 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8325
8326 /* Bind buffer with quad vertex positions */
8327 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8328 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8329
8330 /* Setup position attribute */
8331 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8332 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8333 if (invalid_attribute_location == position_attribute_location)
8334 {
8335 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8336 __LINE__);
8337 }
8338
8339 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8340 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8341
8342 glEnableVertexAttribArray(position_attribute_location);
8343 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8344
8345 /* Setup textures as source and destination images */
8346 BindTextureToImage(m_program_id, complete_destination_texture_id, 0 /* texture level */, 0 /* image_unit */,
8347 complete_destination_image_uniform_name);
8348 BindTextureToImage(m_program_id, complete_source_texture_id, 0 /* texture level */, 1 /* image_unit */,
8349 complete_source_image_uniform_name);
8350 BindTextureToImage(m_program_id, incomplete_destination_texture_id, 2 /* texture level */, 2 /* image_unit */,
8351 incomplete_destination_image_uniform_name);
8352 BindTextureToImage(m_program_id, incomplete_source_texture_id, 2 /* texture level */, 3 /* image_unit */,
8353 incomplete_source_image_uniform_name);
8354
8355 /* Execute draw */
8356 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8357 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8358 }
8359
8360 /** Create complete 2D RGBA8 texture.
8361 *
8362 * @param magic_number Magic number of texture
8363 * @param out_texture_id Id of created texture, not modified if operation fails
8364 *
8365 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8366 **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8367 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint &out_texture_id)
8368 {
8369 /* Constants to calculate size of texture */
8370 static const GLuint n_components = 4; /* RGBA */
8371 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8372
8373 /* Error code */
8374 GLenum err = 0;
8375
8376 /* Texture id */
8377 GLuint texture_id = 0;
8378
8379 /* Prepare storage for texture data */
8380 std::vector<GLubyte> texture_data;
8381 texture_data.resize(texture_data_size);
8382
8383 /* Prepare texture data */
8384 for (GLuint y = 0; y < m_texture_edge; ++y)
8385 {
8386 const GLuint line_offset = y * m_texture_edge * n_components;
8387
8388 for (GLuint x = 0; x < m_texture_edge; ++x)
8389 {
8390 const GLuint texel_offset = x * n_components + line_offset;
8391
8392 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8393 }
8394 }
8395
8396 /* Generate texture */
8397 glGenTextures(1, &texture_id);
8398 err = glGetError();
8399 if (GL_NO_ERROR != err)
8400 {
8401 return err;
8402 }
8403
8404 /* Bind texture */
8405 glBindTexture(GL_TEXTURE_2D, texture_id);
8406 err = glGetError();
8407 if (GL_NO_ERROR != err)
8408 {
8409 glDeleteTextures(1, &texture_id);
8410 return err;
8411 }
8412
8413 /* Allocate storage and fill texture */
8414 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8415 GL_UNSIGNED_BYTE, &texture_data[0]);
8416 err = glGetError();
8417 if (GL_NO_ERROR != err)
8418 {
8419 glDeleteTextures(1, &texture_id);
8420 return err;
8421 }
8422
8423 /* Make texture complete */
8424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8427 err = glGetError();
8428 if (GL_NO_ERROR != err)
8429 {
8430 glDeleteTextures(1, &texture_id);
8431 return err;
8432 }
8433
8434 /* Set out_texture_id */
8435 out_texture_id = texture_id;
8436
8437 /* Done */
8438 return GL_NO_ERROR;
8439 }
8440
8441 /** Create incomplete 2D RGBA8 texture
8442 *
8443 * @param magic_number Magic number of texture
8444 * @param out_texture_id Id of created texture, not modified if operation fails
8445 *
8446 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8447 **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8448 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint &out_texture_id)
8449 {
8450 /* Constants to calculate size of texture */
8451 static const GLuint n_components = 4; /* RGBA */
8452 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8453
8454 /* Error code */
8455 GLenum err = 0;
8456
8457 /* Texture id */
8458 GLuint texture_id = 0;
8459
8460 /* Prepare storage for texture data */
8461 std::vector<GLubyte> texture_data;
8462 texture_data.resize(texture_data_size);
8463
8464 /* Prepare texture data */
8465 for (GLuint y = 0; y < m_texture_edge; ++y)
8466 {
8467 const GLuint line_offset = y * m_texture_edge * n_components;
8468
8469 for (GLuint x = 0; x < m_texture_edge; ++x)
8470 {
8471 const GLuint texel_offset = x * n_components + line_offset;
8472
8473 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8474 }
8475 }
8476
8477 /* Generate texture */
8478 glGenTextures(1, &texture_id);
8479 err = glGetError();
8480 if (GL_NO_ERROR != err)
8481 {
8482 return err;
8483 }
8484
8485 /* Bind texture */
8486 glBindTexture(GL_TEXTURE_2D, texture_id);
8487 err = glGetError();
8488 if (GL_NO_ERROR != err)
8489 {
8490 glDeleteTextures(1, &texture_id);
8491 return err;
8492 }
8493
8494 /* Allocate storage and fill texture */
8495 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8496 GL_UNSIGNED_BYTE, &texture_data[0]);
8497 err = glGetError();
8498 if (GL_NO_ERROR != err)
8499 {
8500 glDeleteTextures(1, &texture_id);
8501 return err;
8502 }
8503
8504 /* Make texture incomplete */
8505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8508 err = glGetError();
8509 if (GL_NO_ERROR != err)
8510 {
8511 glDeleteTextures(1, &texture_id);
8512 return err;
8513 }
8514
8515 /* Set out_texture_id */
8516 out_texture_id = texture_id;
8517
8518 /* Done */
8519 return GL_NO_ERROR;
8520 }
8521
8522 /** Prepare "unique" texels.
8523 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8524 *
8525 * @param texel Storage of texel
8526 * @param x_coordinate X coordiante of texel
8527 * @param y_coordinate Y coordinate of texel
8528 * @param magic_number Magic number of texture
8529 **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8530 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8531 {
8532 texel[0] = x_coordinate;
8533 texel[1] = y_coordinate;
8534 texel[2] = magic_number;
8535 texel[3] = 0xcc;
8536 }
8537 };
8538
8539 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8540 *
8541 * Steps:
8542 * - prepare program object, see details below,
8543 * - prepare 2D R32I texture, width should be equal to the number of image
8544 * uniforms used by program object, height should be 2, fill first row with
8545 * unique values, fill second row with zeros,
8546 * - bind texture to first image unit,
8547 * - set all image uniforms to first image unit,
8548 * - execute program for a single vertex,
8549 * - verify that:
8550 * - values in first row were negated,
8551 * - values from first row were copied to second row,
8552 *
8553 * Repeat steps to test all shader stages that support at least 2 image
8554 * uniforms.
8555 *
8556 * Program has to contain all necessary shader stages. Use boilerplate shaders
8557 * for shader stages that are not important for the test.
8558 *
8559 * Tested shader stage should:
8560 * - Use as many different image formats as possible, image formats compatible
8561 * with R32I:
8562 * * rg16f
8563 * * r11f_g11f_b10f
8564 * * r32f
8565 * * rgb10_a2ui
8566 * * rgba8ui
8567 * * rg16ui
8568 * * r32ui
8569 * * rgba8i
8570 * * rg16i
8571 * * r32i
8572 * * rgb10_a2
8573 * * rgba8
8574 * * rg16
8575 * * rgba8_snorm
8576 * * rg16_snorm.
8577 * - Declare maximum allowed number of image uniforms,
8578 *
8579 * layout(format) uniform gimage2D u_image;
8580 *
8581 * where <format> is selected image format, <gimage2D> is type of 2D image
8582 * compatible with <format> and <u_image> is unique name of uniform.
8583 * Note that image uniforms cannot be declared as array, due to different image
8584 * formats. Therefore separate uniforms have to be used.
8585 * - Include following code snippet:
8586 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8587 * {
8588 * vec row_1_coord(i,0);
8589 * vec row_2_coord(i,1);
8590 *
8591 * row_1_value = imageLoad(u_image[i], row_1_coord);
8592 * imageStore(u_image[i], row_1_coord, -row_1_value);
8593 * imageStore(u_image[i], row_2_coord, row_1_value);
8594 * }
8595 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8596 * stage.
8597 **/
8598 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8599 {
8600 private:
8601 /* Types */
8602 /** Details of image format
8603 *
8604 **/
8605 struct imageFormatDetails
8606 {
8607 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8608
8609 const char *m_image_format;
8610 const char *m_image_type;
8611 const char *m_color_type;
8612 GLenum m_image_unit_format;
8613 verificationRoutine m_verification_routine;
8614 };
8615
8616 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8617 struct Masks
8618 {
8619 /** Get mask of bits used to store in bit-field
8620 *
8621 * @return Mask
8622 **/
RawMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8623 static inline T RawMask()
8624 {
8625 static const T mask = ValueMask() << OFFSET;
8626
8627 return mask;
8628 }
8629
8630 /** Get mask of bits used to store value.
8631 *
8632 * @return Mask
8633 **/
ValueMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8634 static inline T ValueMask()
8635 {
8636 static const T mask = (1 << SIZE) - 1;
8637
8638 return mask;
8639 }
8640
8641 /** Get offset.
8642 *
8643 * @return offset
8644 **/
Offsetgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8645 static inline T Offset()
8646 {
8647 return OFFSET;
8648 }
8649 };
8650
8651 template <typename T, GLuint SIZE, GLuint OFFSET>
8652 struct Masks<T, SIZE, OFFSET, false>
8653 {
8654 /** Get mask of bits used to store in bit-field
8655 *
8656 * @return Mask
8657 **/
RawMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8658 static inline T RawMask()
8659 {
8660 DE_ASSERT(false && "Shouldn't be called");
8661 return 0;
8662 }
8663
8664 /** Get mask of bits used to store value.
8665 *
8666 * @return Mask
8667 **/
ValueMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8668 static inline T ValueMask()
8669 {
8670 DE_ASSERT(false && "Shouldn't be called");
8671 return 0;
8672 }
8673
8674 /** Get offset.
8675 *
8676 * @return offset
8677 **/
Offsetgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8678 static inline T Offset()
8679 {
8680 DE_ASSERT(false && "Shouldn't be called");
8681 return 0;
8682 }
8683 };
8684
8685 /** Template class for accessing integer values stored in bit-fields
8686 *
8687 **/
8688 template <typename T, GLuint SIZE, GLuint OFFSET>
8689 class Integer
8690 {
8691 public:
8692 /** Constructor
8693 *
8694 **/
Integer(T raw)8695 Integer(T raw) : m_raw(raw)
8696 {
8697 }
8698
8699 /** Extract value from bit-field
8700 *
8701 * @return Value
8702 **/
Get() const8703 T Get() const
8704 {
8705 const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8706
8707 const T bits = m_raw & mask;
8708 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8709
8710 return result;
8711 }
8712
8713 /** Extract value from bit-field and negate it
8714 *
8715 * @return Negated value
8716 **/
GetNegated() const8717 T GetNegated() const
8718 {
8719 const T mask = Masks<T, SIZE, OFFSET>::ValueMask();
8720 const T value = Get();
8721
8722 return Clamp((~value) + 1) & mask;
8723 }
8724
Clamp(T n) const8725 T Clamp(T n) const
8726 {
8727 const bool isUnsigned = (T(0) < T(-1));
8728 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8729 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8730 const T x = n > max ? max : n;
8731 return x < min ? min : x;
8732 }
8733
8734 private:
8735 T m_raw;
8736 };
8737
8738 /* Enums */
8739 /** Shader stage identification
8740 *
8741 **/
8742 enum shaderStage
8743 {
8744 fragmentShaderStage = 2,
8745 geometryShaderStage = 4,
8746 tesselationControlShaderStage = 8,
8747 tesselationEvalutaionShaderStage = 16,
8748 vertexShaderStage = 32,
8749 };
8750
8751 /** Test result
8752 *
8753 **/
8754 enum testResult
8755 {
8756 testFailed = -1,
8757 testNotSupported = 1,
8758 testPassed = 0
8759 };
8760
8761 /* Constants */
8762 static const GLint m_min_required_image_uniforms = 2;
8763
8764 /* Fields */
8765 GLuint m_program_to_test_fs_stage_id;
8766 GLuint m_program_to_test_gs_stage_id;
8767 GLuint m_program_to_test_tcs_stage_id;
8768 GLuint m_program_to_test_tes_stage_id;
8769 GLuint m_program_to_test_vs_stage_id;
8770 GLuint m_texture_to_test_fs_stage_id;
8771 GLuint m_texture_to_test_gs_stage_id;
8772 GLuint m_texture_to_test_tcs_stage_id;
8773 GLuint m_texture_to_test_tes_stage_id;
8774 GLuint m_texture_to_test_vs_stage_id;
8775 GLuint m_vertex_array_object_id;
8776
8777 public:
8778 /* Constructor */
ImageLoadStoreMultipleUniformsTest()8779 ImageLoadStoreMultipleUniformsTest()
8780 : m_program_to_test_fs_stage_id(0)
8781 , m_program_to_test_gs_stage_id(0)
8782 , m_program_to_test_tcs_stage_id(0)
8783 , m_program_to_test_tes_stage_id(0)
8784 , m_program_to_test_vs_stage_id(0)
8785 , m_texture_to_test_fs_stage_id(0)
8786 , m_texture_to_test_gs_stage_id(0)
8787 , m_texture_to_test_tcs_stage_id(0)
8788 , m_texture_to_test_tes_stage_id(0)
8789 , m_texture_to_test_vs_stage_id(0)
8790 , m_vertex_array_object_id(0)
8791 {
8792 /* Nothing to be done here */
8793 }
8794
8795 /* Methods inherited from SubcaseBase */
Setup()8796 virtual long Setup()
8797 {
8798 /* Prepare programs */
8799 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage);
8800 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage);
8801 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8802 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8803 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage);
8804
8805 /* Prepare textures */
8806 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage);
8807 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage);
8808 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8809 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8810 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage);
8811
8812 /* Generate vertex array object */
8813 glGenVertexArrays(1, &m_vertex_array_object_id);
8814 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8815
8816 /* Bind vertex array object */
8817 glBindVertexArray(m_vertex_array_object_id);
8818 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8819
8820 /* Set vertices number for patches */
8821 glPatchParameteri(GL_PATCH_VERTICES, 1);
8822
8823 /* Done */
8824 return NO_ERROR;
8825 }
8826
Cleanup()8827 virtual long Cleanup()
8828 {
8829 glUseProgram(0);
8830
8831 /* Delete programs */
8832 if (0 != m_program_to_test_fs_stage_id)
8833 {
8834 glDeleteProgram(m_program_to_test_fs_stage_id);
8835 m_program_to_test_fs_stage_id = 0;
8836 }
8837
8838 if (0 != m_program_to_test_gs_stage_id)
8839 {
8840 glDeleteProgram(m_program_to_test_gs_stage_id);
8841 m_program_to_test_gs_stage_id = 0;
8842 }
8843
8844 if (0 != m_program_to_test_tcs_stage_id)
8845 {
8846 glDeleteProgram(m_program_to_test_tcs_stage_id);
8847 m_program_to_test_tcs_stage_id = 0;
8848 }
8849
8850 if (0 != m_program_to_test_tes_stage_id)
8851 {
8852 glDeleteProgram(m_program_to_test_tes_stage_id);
8853 m_program_to_test_tes_stage_id = 0;
8854 }
8855
8856 if (0 != m_program_to_test_vs_stage_id)
8857 {
8858 glDeleteProgram(m_program_to_test_vs_stage_id);
8859 m_program_to_test_vs_stage_id = 0;
8860 }
8861
8862 /* Delete textures */
8863 if (0 != m_texture_to_test_fs_stage_id)
8864 {
8865 glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8866 m_texture_to_test_fs_stage_id = 0;
8867 }
8868
8869 if (0 != m_texture_to_test_gs_stage_id)
8870 {
8871 glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8872 m_texture_to_test_gs_stage_id = 0;
8873 }
8874
8875 if (0 != m_texture_to_test_tcs_stage_id)
8876 {
8877 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8878 m_texture_to_test_tcs_stage_id = 0;
8879 }
8880
8881 if (0 != m_texture_to_test_tes_stage_id)
8882 {
8883 glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8884 m_texture_to_test_tes_stage_id = 0;
8885 }
8886
8887 if (0 != m_texture_to_test_vs_stage_id)
8888 {
8889 glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8890 m_texture_to_test_vs_stage_id = 0;
8891 }
8892
8893 /* Delete vertex array object id */
8894 if (0 != m_vertex_array_object_id)
8895 {
8896 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8897 m_vertex_array_object_id = 0;
8898 }
8899
8900 /* Done */
8901 return NO_ERROR;
8902 }
8903
Run()8904 virtual long Run()
8905 {
8906 bool result = true;
8907
8908 if (testFailed == testShaderStage(fragmentShaderStage))
8909 {
8910 m_context.getTestContext().getLog()
8911 << tcu::TestLog::Message << "Problems with fragment shader stage!" << tcu::TestLog::EndMessage;
8912
8913 result = false;
8914 }
8915
8916 if (testFailed == testShaderStage(geometryShaderStage))
8917 {
8918 m_context.getTestContext().getLog()
8919 << tcu::TestLog::Message << "Problems with geometry shader stage!" << tcu::TestLog::EndMessage;
8920
8921 result = false;
8922 }
8923
8924 if (testFailed == testShaderStage(tesselationControlShaderStage))
8925 {
8926 m_context.getTestContext().getLog()
8927 << tcu::TestLog::Message << "Problems with tesselation control shader stage!"
8928 << tcu::TestLog::EndMessage;
8929
8930 result = false;
8931 }
8932
8933 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8934 {
8935 m_context.getTestContext().getLog()
8936 << tcu::TestLog::Message << "Problems with tesselation evaluation shader stage!"
8937 << tcu::TestLog::EndMessage;
8938
8939 result = false;
8940 }
8941
8942 if (testFailed == testShaderStage(vertexShaderStage))
8943 {
8944 m_context.getTestContext().getLog()
8945 << tcu::TestLog::Message << "Problems with vertex shader stage!" << tcu::TestLog::EndMessage;
8946
8947 result = false;
8948 }
8949
8950 if (false == result)
8951 {
8952 return ERROR;
8953 }
8954
8955 /* Done */
8956 return NO_ERROR;
8957 }
8958
8959 private:
8960 /* Static routines */
8961 /** Provide image format details for given index
8962 *
8963 * @param index Index
8964 * @param out_details Image format detail instance
8965 **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8966 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails &out_details)
8967 {
8968 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8969 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger};
8970
8971 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8972 {"rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort>},
8973 {"r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8974 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8975 {"r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint>},
8976 {"rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8977 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8978 {"rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8979 {"rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8980 {"rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8981 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte>},
8982 {"rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8983 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort>},
8984 {"rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8985 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint>},
8986 {"rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8987 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint>},
8988 {"rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8989 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint>},
8990 {"r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger},
8991 {"rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8992 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint>},
8993 {"rg16i", "iimage2D", "ivec4", GL_RG16I,
8994 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint>}};
8995
8996 static const GLuint n_imageUniformFormatDetails =
8997 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8998
8999 if (n_imageUniformFormatDetails <= index)
9000 {
9001 out_details = default_format_details;
9002 }
9003 else
9004 {
9005 out_details = format_details[index];
9006 }
9007 }
9008
9009 /** Write name of image uniform at given index to output stream
9010 *
9011 * @param stream Output stream
9012 * @param index Index
9013 **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9014 static void writeImageUniformNameToStream(std::ostream &stream, GLuint index)
9015 {
9016 /* u_image_0 */
9017 stream << "u_image_" << index;
9018 }
9019
9020 /** Write name of variable used to store value loaded from image at given index to output stream
9021 *
9022 * @param stream Output stream
9023 * @param index Index
9024 **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9025 static void writeLoadedValueVariableNameToStream(std::ostream &stream, GLuint index)
9026 {
9027 /* loaded_value_0 */
9028 stream << "loaded_value_" << index;
9029 }
9030
9031 /** Write name of variable used to store coordinate of texel at given row to output stream
9032 *
9033 * @param stream Output stream
9034 * @param index Index of image uniform
9035 * @param row Row of image
9036 **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9037 static void writeCoordinatesVariableNameToStream(std::ostream &stream, GLuint index, GLuint row)
9038 {
9039 /* row_0_coordinates_0 */
9040 stream << "row_" << row << "_coordinates_" << index;
9041 }
9042
9043 struct imageUniformDeclaration
9044 {
imageUniformDeclarationgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9045 imageUniformDeclaration(GLuint index) : m_index(index)
9046 {
9047 }
9048
9049 GLuint m_index;
9050 };
9051
9052 /** Write declaration of image uniform at given index to output stream
9053 *
9054 * @param stream Output stream
9055 * @param imageUniformDeclaration Declaration details
9056 *
9057 * @return stream
9058 **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9059 friend std::ostream &operator<<(std::ostream &stream, const imageUniformDeclaration &declaration)
9060 {
9061 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9062 getImageUniformDeclarationDetails(declaration.m_index, format_details);
9063
9064 /* layout(r32f) uniform image2D u_image_0; */
9065 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9066
9067 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9068
9069 stream << ";";
9070
9071 return stream;
9072 }
9073
9074 struct imageLoadCall
9075 {
imageLoadCallgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9076 imageLoadCall(GLuint index) : m_index(index)
9077 {
9078 }
9079
9080 GLuint m_index;
9081 };
9082
9083 /* Stream operators */
9084 /** Write code that execute imageLoad routine for image at given index to output stream
9085 *
9086 * @param stream Output stream
9087 * @param load imageLoad call details
9088 *
9089 * @return stream
9090 **/
operator <<(std::ostream & stream,const imageLoadCall & load)9091 friend std::ostream &operator<<(std::ostream &stream, const imageLoadCall &load)
9092 {
9093 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9094 getImageUniformDeclarationDetails(load.m_index, format_details);
9095
9096 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9097 stream << format_details.m_color_type << " ";
9098
9099 writeLoadedValueVariableNameToStream(stream, load.m_index);
9100
9101 stream << " = imageLoad(";
9102
9103 writeImageUniformNameToStream(stream, load.m_index);
9104
9105 stream << ", ";
9106
9107 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9108
9109 stream << ");";
9110
9111 return stream;
9112 }
9113
9114 struct imageStoreCall
9115 {
imageStoreCallgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9116 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9117 {
9118 }
9119
9120 GLuint m_index;
9121 GLuint m_row;
9122 };
9123
9124 /** Write code that execute imageStore to image at given index to output stream
9125 *
9126 * @param stream Output stream
9127 * @param store imageStore call details
9128 *
9129 * @return stream
9130 **/
operator <<(std::ostream & stream,const imageStoreCall & store)9131 friend std::ostream &operator<<(std::ostream &stream, const imageStoreCall &store)
9132 {
9133 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9134 stream << "imageStore(";
9135
9136 writeImageUniformNameToStream(stream, store.m_index);
9137
9138 stream << ", ";
9139
9140 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9141
9142 if (0 == store.m_row)
9143 {
9144 stream << ", -";
9145 }
9146 else
9147 {
9148 stream << ", ";
9149 }
9150
9151 writeLoadedValueVariableNameToStream(stream, store.m_index);
9152 stream << ");";
9153
9154 return stream;
9155 }
9156
9157 struct coordinatesVariableDeclaration
9158 {
coordinatesVariableDeclarationgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9159 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9160 {
9161 }
9162 GLuint m_index;
9163 GLuint m_row;
9164 };
9165
9166 /** Write declaration of variable for coordinate at given row to output stream
9167 *
9168 * @param stream Output stream
9169 * @param declaration Declaration details
9170 *
9171 * @return stream
9172 **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9173 friend std::ostream &operator<<(std::ostream &stream, const coordinatesVariableDeclaration &declaration)
9174 {
9175 stream << "const ivec2 ";
9176
9177 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9178
9179 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9180
9181 return stream;
9182 }
9183
9184 /* Methods */
9185 /** Build program to test specified shader stage
9186 *
9187 * Throws exception in case of any failure
9188 *
9189 * @param stage Stage id
9190 *
9191 * @return Program id
9192 **/
buildProgramToTestShaderStage(shaderStage stage)9193 GLuint buildProgramToTestShaderStage(shaderStage stage)
9194 {
9195 static const char *const boilerplate_fragment_shader_code =
9196 "#version 400 core\n"
9197 "#extension GL_ARB_shader_image_load_store : require\n"
9198 "\n"
9199 "precision highp float;\n"
9200 "\n"
9201 "void main()\n"
9202 "{\n"
9203 " discard;\n"
9204 "}\n";
9205
9206 static const char *const boilerplate_tesselation_evaluation_shader_code =
9207 "#version 400 core\n"
9208 "#extension GL_ARB_shader_image_load_store : require\n"
9209 "\n"
9210 "precision highp float;\n"
9211 "\n"
9212 "layout(quads, equal_spacing, ccw) in;\n"
9213 "\n"
9214 "void main()\n"
9215 "{\n"
9216 "\n"
9217 "}\n";
9218
9219 static const char *const boilerplate_vertex_shader_code =
9220 "#version 400 core\n"
9221 "#extension GL_ARB_shader_image_load_store : require\n"
9222 "\n"
9223 "precision highp float;\n"
9224 "\n"
9225 "layout(location = 0) in vec4 i_position;\n"
9226 "\n"
9227 "void main()\n"
9228 "{\n"
9229 " gl_Position = i_position;\n"
9230 "}\n";
9231
9232 const char *fragment_shader_code = boilerplate_fragment_shader_code;
9233 const char *geometry_shader_code = 0;
9234 bool is_program_built = true;
9235 GLuint program_object_id = 0;
9236 const char *tesselation_control_shader_code = 0;
9237 const char *tesselation_evaluation_shader_code = 0;
9238 std::string tested_shader_stage_code;
9239 const char *vertex_shader_code = boilerplate_vertex_shader_code;
9240
9241 /* Get source code for tested shader stage */
9242 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9243
9244 if (true == tested_shader_stage_code.empty())
9245 {
9246 return 0;
9247 }
9248
9249 /* Set up source code for all required stages */
9250 switch (stage)
9251 {
9252 case fragmentShaderStage:
9253 fragment_shader_code = tested_shader_stage_code.c_str();
9254 break;
9255
9256 case geometryShaderStage:
9257 geometry_shader_code = tested_shader_stage_code.c_str();
9258 break;
9259
9260 case tesselationControlShaderStage:
9261 tesselation_control_shader_code = tested_shader_stage_code.c_str();
9262 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9263 break;
9264
9265 case tesselationEvalutaionShaderStage:
9266 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9267 break;
9268
9269 case vertexShaderStage:
9270 vertex_shader_code = tested_shader_stage_code.c_str();
9271 break;
9272
9273 default:
9274 TCU_FAIL("Invalid shader stage");
9275 }
9276
9277 /* Build program */
9278 program_object_id =
9279 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9280 geometry_shader_code, fragment_shader_code, &is_program_built);
9281
9282 /* Check if program was built */
9283 if (false == is_program_built)
9284 {
9285 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9286 }
9287
9288 /* Done */
9289 return program_object_id;
9290 }
9291
9292 /** Create texture to test given shader stage
9293 *
9294 * Throws exception in case of any failure
9295 *
9296 * @param stage Stage id
9297 *
9298 * @return Texture id
9299 **/
createTextureToTestShaderStage(shaderStage stage)9300 GLuint createTextureToTestShaderStage(shaderStage stage)
9301 {
9302 GLenum error = glGetError();
9303 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9304 GLuint texture_id = 0;
9305 std::vector<GLint> texture_data;
9306
9307 const GLsizei height = 2;
9308 const GLsizei width = max_image_uniforms;
9309
9310 if (m_min_required_image_uniforms > max_image_uniforms)
9311 {
9312 return 0;
9313 }
9314
9315 /* Generate texture id */
9316 glGenTextures(1, &texture_id);
9317 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9318
9319 /* Bind texture */
9320 glBindTexture(GL_TEXTURE_2D, texture_id);
9321 error = glGetError();
9322 if (GL_NO_ERROR != error)
9323 {
9324 glDeleteTextures(1, &texture_id);
9325 GLU_EXPECT_NO_ERROR(error, "BindTexture");
9326 }
9327
9328 /* Prepare storage for texture data */
9329 texture_data.resize(width * height);
9330 for (GLint i = 0; i < max_image_uniforms; ++i)
9331 {
9332 texture_data[i] = getExpectedValue(i);
9333 texture_data[i + width] = 0;
9334 }
9335
9336 /* Create first level of texture */
9337 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9338 &texture_data[0]);
9339 error = glGetError();
9340 if (GL_NO_ERROR != error)
9341 {
9342 glDeleteTextures(1, &texture_id);
9343 GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9344 }
9345
9346 /* Make texture complete */
9347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9350 error = glGetError();
9351 if (GL_NO_ERROR != error)
9352 {
9353 glDeleteTextures(1, &texture_id);
9354 GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9355 }
9356
9357 /* Done */
9358 return texture_id;
9359 }
9360
9361 /** Get value of texel for image at given index
9362 *
9363 * @param index Index of image uniform
9364 *
9365 * @return Value of texel
9366 **/
getExpectedValue(GLint index)9367 GLint getExpectedValue(GLint index)
9368 {
9369 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9370 // we set one bit in the exponent of each component of those pixel format
9371 return 0x40104200 + index;
9372 }
9373
9374 /** Get name of uniform at given index
9375 *
9376 * @param index Index of uniform
9377 * @param out_name Name of uniform
9378 **/
getImageUniformName(GLuint index,std::string & out_name)9379 void getImageUniformName(GLuint index, std::string &out_name)
9380 {
9381 std::stringstream stream;
9382
9383 writeImageUniformNameToStream(stream, index);
9384
9385 out_name = stream.str();
9386 }
9387
9388 /** Get maximum number of image uniforms allowed for given shader stage
9389 *
9390 * @param stage Stage id
9391 *
9392 * @return Maximum allowed image uniforms
9393 **/
getMaximumImageUniformsForStage(shaderStage stage)9394 GLint getMaximumImageUniformsForStage(shaderStage stage)
9395 {
9396 GLint max_image_uniforms = 0;
9397 GLenum pname = 0;
9398
9399 switch (stage)
9400 {
9401 case fragmentShaderStage:
9402 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9403 break;
9404
9405 case geometryShaderStage:
9406 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9407 break;
9408
9409 case tesselationControlShaderStage:
9410 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9411 break;
9412
9413 case tesselationEvalutaionShaderStage:
9414 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9415 break;
9416
9417 case vertexShaderStage:
9418 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9419 break;
9420
9421 default:
9422 TCU_FAIL("Invalid shader stage");
9423 }
9424
9425 glGetIntegerv(pname, &max_image_uniforms);
9426 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9427
9428 return max_image_uniforms;
9429 }
9430
9431 /** Prepare source for tested shader stage
9432 *
9433 * @param stage Stage id
9434 * @param out_code Source code
9435 **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9436 void prepareShaderForTestedShaderStage(shaderStage stage, std::string &out_code)
9437 {
9438 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9439 const char *stage_specific_layout = "";
9440 const char *stage_specific_predicate = "true";
9441 std::stringstream stream;
9442
9443 if (m_min_required_image_uniforms > max_image_uniforms)
9444 {
9445 return;
9446 }
9447
9448 /* Expected result follows
9449 *
9450 * #version 400 core
9451 * #extension GL_ARB_shader_image_load_store : require
9452 *
9453 * precision highp float;
9454 *
9455 * stage_specific_layout goes here
9456 *
9457 * Uniform declarations go here
9458 *
9459 * void main()
9460 * {
9461 * const ivec2 row_0_coordinates(0, 0);
9462 * const ivec2 row_1_coordinates(0, 1);
9463 *
9464 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9465 *
9466 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9467 *
9468 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9469 * imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9470 * }
9471 */
9472
9473 /* Get piece of code specific for stage */
9474 switch (stage)
9475 {
9476 case fragmentShaderStage:
9477 break;
9478
9479 case geometryShaderStage:
9480 stage_specific_layout = "layout(points) in;\n"
9481 "layout(points, max_vertices = 1) out;\n"
9482 "\n";
9483 break;
9484
9485 case tesselationControlShaderStage:
9486 stage_specific_layout = "layout(vertices = 4) out;\n"
9487 "\n";
9488 stage_specific_predicate = "gl_InvocationID == 0";
9489 break;
9490
9491 case tesselationEvalutaionShaderStage:
9492 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9493 "\n";
9494 break;
9495
9496 case vertexShaderStage:
9497 break;
9498
9499 default:
9500 TCU_FAIL("Invalid shader stage");
9501 }
9502
9503 /* Preamble */
9504 stream << "#version 400 core\n"
9505 "#extension GL_ARB_shader_image_load_store : require\n"
9506 "\n"
9507 "precision highp float;\n"
9508 "\n"
9509 << stage_specific_layout;
9510
9511 /* Image uniforms declarations */
9512 for (GLint i = 0; i < max_image_uniforms; ++i)
9513 {
9514 stream << imageUniformDeclaration(i) << "\n";
9515 }
9516
9517 /* Main opening */
9518 stream << "\n"
9519 "void main()\n"
9520 "{\n";
9521
9522 stream << " if (" << stage_specific_predicate << ")\n";
9523 stream << " {\n";
9524
9525 /* imageLoad and imageStores for each uniform */
9526 for (GLint i = 0; i < max_image_uniforms; ++i)
9527 {
9528 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n"
9529 << " " << coordinatesVariableDeclaration(i, 1) << "\n"
9530 << "\n"
9531 << " " << imageLoadCall(i) << "\n"
9532 << "\n"
9533 << " " << imageStoreCall(i, 0) << "\n"
9534 << " " << imageStoreCall(i, 1) << "\n";
9535
9536 if (max_image_uniforms > i + 1)
9537 {
9538 stream << "\n";
9539 }
9540 }
9541
9542 stream << " }\n";
9543
9544 /* Main closing */
9545 stream << "}\n\n";
9546
9547 /* Done */
9548 out_code = stream.str();
9549 }
9550
9551 /** Test given shader stage
9552 *
9553 * @param stage Stage id
9554 *
9555 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9556 * testFailed when test result is negative;
9557 * m_test_passed when test result is positive;
9558 **/
testShaderStage(shaderStage stage)9559 testResult testShaderStage(shaderStage stage)
9560 {
9561 std::string image_uniform_name;
9562 static const GLint invalid_uniform_location = -1;
9563 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9564 GLenum primitive_mode = GL_POINTS;
9565 GLuint program_id = 0;
9566 testResult result = testPassed;
9567 std::vector<GLint> texture_data;
9568 GLuint texture_id = 0;
9569
9570 static const GLuint height = 2;
9571 const GLuint width = max_image_uniforms;
9572
9573 const GLuint positive_value_index = width;
9574 static const GLuint negated_value_index = 0;
9575
9576 if (m_min_required_image_uniforms > max_image_uniforms)
9577 {
9578 return testNotSupported;
9579 }
9580
9581 /* Select program and texture ids for given stage */
9582 switch (stage)
9583 {
9584 case fragmentShaderStage:
9585 program_id = m_program_to_test_fs_stage_id;
9586 texture_id = m_texture_to_test_fs_stage_id;
9587 break;
9588
9589 case geometryShaderStage:
9590 program_id = m_program_to_test_gs_stage_id;
9591 texture_id = m_texture_to_test_gs_stage_id;
9592 break;
9593
9594 case tesselationControlShaderStage:
9595 primitive_mode = GL_PATCHES;
9596 program_id = m_program_to_test_tcs_stage_id;
9597 texture_id = m_texture_to_test_tcs_stage_id;
9598 break;
9599
9600 case tesselationEvalutaionShaderStage:
9601 primitive_mode = GL_PATCHES;
9602 program_id = m_program_to_test_tes_stage_id;
9603 texture_id = m_texture_to_test_tes_stage_id;
9604 break;
9605
9606 case vertexShaderStage:
9607 program_id = m_program_to_test_vs_stage_id;
9608 texture_id = m_texture_to_test_vs_stage_id;
9609 break;
9610
9611 default:
9612 TCU_FAIL("Invalid shader stage");
9613 }
9614
9615 /* Set program */
9616 glUseProgram(program_id);
9617 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9618
9619 /* Bind texture to image units */
9620 for (GLint i = 0; i < max_image_uniforms; ++i)
9621 {
9622 imageFormatDetails format_details;
9623 getImageUniformDeclarationDetails(i, format_details);
9624
9625 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9626 GL_READ_WRITE, format_details.m_image_unit_format);
9627 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9628 }
9629
9630 /* Set all image uniforms to corresponding image units */
9631 for (GLint i = 0; i < max_image_uniforms; ++i)
9632 {
9633 /* Get name */
9634 getImageUniformName(i, image_uniform_name);
9635
9636 /* Get location */
9637 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9638 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9639
9640 if (invalid_uniform_location == image_uniform_location)
9641 {
9642 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9643 __LINE__);
9644 }
9645
9646 /* Set uniform value */
9647 glUniform1i(image_uniform_location, i /* image_unit */);
9648 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9649 }
9650
9651 /* Execute draw */
9652 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9653 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9654
9655 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9656
9657 texture_data.resize(width * height);
9658
9659 /* Get texture data */
9660 glBindTexture(GL_TEXTURE_2D, texture_id);
9661 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9662
9663 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9664 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9665
9666 /* Verify each image uniform */
9667 for (GLint i = 0; i < max_image_uniforms; ++i)
9668 {
9669 imageFormatDetails format_details;
9670 getImageUniformDeclarationDetails(i, format_details);
9671
9672 if (false == format_details.m_verification_routine(getExpectedValue(i),
9673 texture_data[positive_value_index + i],
9674 texture_data[negated_value_index + i]))
9675 {
9676 m_context.getTestContext().getLog()
9677 << tcu::TestLog::Message << "Invalid result!"
9678 << " Image format: " << format_details.m_image_format << " Original value: "
9679 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9680 << " Copied value: "
9681 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9682 << texture_data[positive_value_index + i] << " Negated value: "
9683 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9684 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9685
9686 result = testFailed;
9687 }
9688 }
9689
9690 /* Done */
9691 return result;
9692 }
9693
9694 /** Verifies if original_value, positive_value and negated_value match
9695 *
9696 * @tparam T Type used during verification process, it should match float values by size
9697 *
9698 * @param original_value Original value of texel, used when creating a texture
9699 * @param positive_value Value stored by shader as read
9700 * @param negated_value Value stored by shader after negation
9701 *
9702 * @return true if values match, false otherwise
9703 **/
9704 template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9705 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9706 {
9707 if (original_value != positive_value)
9708 {
9709 return false;
9710 }
9711
9712 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9713 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */
9714 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */
9715 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */
9716
9717 const T *positive_elements = (T *)&positive_value;
9718 const T *negated_elements = (T *)&negated_value;
9719
9720 for (GLuint i = 0; i < n_elements; ++i)
9721 {
9722 const T positive_element = positive_elements[i];
9723 const T negated_element = negated_elements[i];
9724
9725 const T positive_sign_bit = positive_element & sign_bit_mask;
9726 const T negated_sign_bit = negated_element & sign_bit_mask;
9727
9728 const T positive_data = positive_element & sign_bit_inv_mask;
9729 const T negated_data = negated_element & sign_bit_inv_mask;
9730
9731 /* Compare data bits */
9732 if (positive_data != negated_data)
9733 {
9734 return false;
9735 }
9736
9737 /* Verify that sign bit is inverted */
9738 if (positive_sign_bit == negated_sign_bit)
9739 {
9740 return false;
9741 }
9742 }
9743
9744 return true;
9745 }
9746
9747 /** Verifies if original_value, positive_value and negated_value match
9748 *
9749 * @tparam T Type used during verification process, it should match float values by size
9750 *
9751 * @param original_value Original value of texel, used when creating a texture
9752 * @param positive_value Value stored by shader as read
9753 * @param negated_value Value stored by shader after negation
9754 *
9755 * @return true if values match, false otherwise
9756 **/
9757 template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9758 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9759 {
9760 if (original_value != positive_value)
9761 {
9762 return false;
9763 }
9764
9765 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9766
9767 const T *positive_elements = (T *)&positive_value;
9768 const T *negated_elements = (T *)&negated_value;
9769
9770 for (GLuint i = 0; i < n_elements; ++i)
9771 {
9772 const T positive_element = positive_elements[i];
9773 const T negated_element = negated_elements[i];
9774
9775 /* Compare data bits */
9776 if (positive_element != -negated_element)
9777 {
9778 return false;
9779 }
9780 }
9781
9782 return true;
9783 }
9784
9785 /** Verifies if original_value, positive_value and negated_value match
9786 *
9787 * @tparam R Number of bits for red channel
9788 * @tparam G Number of bits for green channel
9789 * @tparam B Number of bits for blue channel
9790 * @tparam A Number of bits for alpha channel
9791 *
9792 * @param original_value Original value of texel, used when creating a texture
9793 * @param positive_value Value stored by shader as read
9794 * @param negated_value Value stored by shader after negation
9795 *
9796 * @return true if values match, false otherwise
9797 **/
9798 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9799 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9800 {
9801 if (original_value != positive_value)
9802 {
9803 return false;
9804 }
9805
9806 Integer<T, R, 0> positive_red(positive_value);
9807 Integer<T, R, 0> negated_red(negated_value);
9808
9809 Integer<T, G, R> positive_green(positive_value);
9810 Integer<T, G, R> negated_green(negated_value);
9811
9812 Integer<T, B, R + G> positive_blue(positive_value);
9813 Integer<T, B, R + G> negated_blue(negated_value);
9814
9815 Integer<T, A, R + G + B> positive_alpha(positive_value);
9816 Integer<T, A, R + G + B> negated_alpha(negated_value);
9817
9818 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9819 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9820 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9821 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9822 {
9823 return false;
9824 }
9825
9826 return true;
9827 }
9828
9829 /** Verifies if original_value, positive_value and negated_value match
9830 *
9831 * @param original_value Original value of texel, used when creating a texture
9832 * @param positive_value Value stored by shader as read
9833 * @param negated_value Value stored by shader after negation
9834 *
9835 * @return true if values match, false otherwise
9836 **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9837 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9838 {
9839 if (original_value != positive_value)
9840 {
9841 return false;
9842 }
9843
9844 if (positive_value != -negated_value)
9845 {
9846 return false;
9847 }
9848
9849 return true;
9850 }
9851
9852 /** Verifies if original_value, positive_value and negated_value match
9853 *
9854 * @param original_value Original value of texel, used when creating a texture
9855 * @param positive_value Value stored by shader as read
9856 * @param negated_value Value stored by shader after negation
9857 *
9858 * @return true if values match, false otherwise
9859 **/
9860 template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9861 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9862 {
9863 if (original_value != positive_value)
9864 {
9865 return false;
9866 }
9867
9868 if (0 != negated_value)
9869 {
9870 return false;
9871 }
9872
9873 return true;
9874 }
9875 };
9876
9877 /** Test "Early fragment tests" description follows.
9878 *
9879 * BasicGLSLEarlyFragTests verifies that:
9880 * - early z test is applied when enabled,
9881 * - early z test is not applied when disabled.
9882 *
9883 * Proposed modifications:
9884 * - verify that early z test does not discard all fragments when enabled,
9885 * - verify that early stencil test is applied when enabled,
9886 * - verify that early stencil test does not discard all fragments when
9887 * enabled,
9888 * - verify that early stencil test is not applied when disabled.
9889 *
9890 * Steps:
9891 * - prepare 2 programs that store 1.0 at red channel to image in fragment
9892 * shader stage:
9893 * a) one program should enable early fragment tests
9894 * ("layout(early_fragment_tests) in;"),
9895 * b) second program should disable early fragment tests,
9896 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9897 * depth-stencil attachments,
9898 * - prepare 2D texture 64x64 R32F,
9899 * - enable depth test,
9900 * - verify that early z test is applied when enabled:
9901 * - use program enabling early fragment tests,
9902 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9903 * - fill texture with zeros,
9904 * - bind texture to image uniform,
9905 * - draw "full screen" quad (left bottom corner at -1,-1 and right top
9906 * corner at 1,1) at z: 0.75
9907 * - verify that texture is still filled with zeros,
9908 * - verify that early z test does not discard all fragments:
9909 * - use program enabling early fragment tests,
9910 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9911 * - fill texture with zeros,
9912 * - bind texture to image uniform,
9913 * - draw "full screen" quad at z: 0.25
9914 * - verify that texture is now filled with 1.0,
9915 * -verify that early z test is not applied when disabled:
9916 * - use program disabling early fragment tests,
9917 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9918 * - fill texture with zeros,
9919 * - bind texture to image uniform,
9920 * - draw "full screen" quad at z: 0.75
9921 * - verify that texture is now filled with 1.0.
9922 * - disable depth test
9923 * - enable stencil test
9924 * - verify that early stencil test is applied when enabled:
9925 * - use program enabling early fragment tests,
9926 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9927 * - fill texture with zeros,
9928 * - set stencil test to:
9929 * - <func> to GL_LESS,
9930 * - <ref> to 128,
9931 * - <mask> 0xffffffff,
9932 * - bind texture to image uniform,
9933 * - draw "full screen" quad at z: 0,
9934 * - verify that texture is still filled with zeros,
9935 * - verify that early stencil test does not discard all fragments:
9936 * - use program enabling early fragment tests,
9937 * - clean frame buffer with color: 0, stencil: 128 and depth 1,
9938 * - fill texture with zeros,
9939 * - set stencil test to:
9940 * - <func> to GL_LESS,
9941 * - <ref> to 0,
9942 * - <mask> 0xffffffff,
9943 * - bind texture to image uniform,
9944 * - draw "full screen" quad at z: 0,
9945 * - verify that texture is now filled with 1.0,
9946 * - verify that early stencil test is not applied when disabled:
9947 * - use program disabling early fragment tests,
9948 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9949 * - fill texture with zeros,
9950 * - set stencil test to:
9951 * - <func> to GL_LESS,
9952 * - <ref> to 128,
9953 * - <mask> 0xffffffff,
9954 * - bind texture to image uniform,
9955 * - draw "full screen" quad at z: 0,
9956 * - verify that texture is now filled with 1.0
9957 **/
9958 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9959 {
9960 private:
9961 /* Constants */
9962 GLuint m_image_edge;
9963 static const GLint m_invalid_uniform_location = -1;
9964
9965 /* Types */
9966 /** Store id and uniform locations for a single program object
9967 *
9968 **/
9969 struct programDetails
9970 {
9971 GLint m_depth_uniform_location;
9972 GLint m_image_uniform_location;
9973 GLuint m_program_id;
9974
programDetailsgl4cts::__anonf7c7fa4f0111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9975 programDetails()
9976 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9977 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9978 , m_program_id(0)
9979 {
9980 /* Nothing to be done here */
9981 }
9982 };
9983
9984 /* Fileds */
9985 /* Storage for texture data */
9986 std::vector<GLfloat> m_clean_texture_data;
9987 std::vector<GLfloat> m_extracted_texture_data;
9988
9989 /* Program details */
9990 programDetails m_disabled_early_tests;
9991 programDetails m_enabled_early_tests;
9992
9993 /* Ids of GL objects */
9994 GLuint m_color_renderbuffer_id;
9995 GLuint m_depth_stencil_renderbuffer_id;
9996 GLuint m_framebuffer_id;
9997 GLuint m_texture_id;
9998 GLuint m_vertex_array_object_id;
9999
10000 public:
10001 /* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()10002 ImageLoadStoreEarlyFragmentTestsTest()
10003 : m_image_edge(0)
10004 , m_color_renderbuffer_id(0)
10005 , m_depth_stencil_renderbuffer_id(0)
10006 , m_framebuffer_id(0)
10007 , m_texture_id(0)
10008 , m_vertex_array_object_id(0)
10009 {
10010 /* Nothing to be done here */
10011 }
10012
10013 /* Methods inherited from SubcaseBase */
Cleanup()10014 virtual long Cleanup()
10015 {
10016 /* Restore defaults */
10017 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10018 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10019 glBindTexture(GL_TEXTURE_2D, 0);
10020 glBindVertexArray(0);
10021 glDisable(GL_DEPTH_TEST);
10022 glDisable(GL_STENCIL_TEST);
10023 glUseProgram(0);
10024
10025 /* Delete objects */
10026 if (0 != m_disabled_early_tests.m_program_id)
10027 {
10028 glDeleteProgram(m_disabled_early_tests.m_program_id);
10029 m_disabled_early_tests.m_program_id = 0;
10030 }
10031
10032 if (0 != m_enabled_early_tests.m_program_id)
10033 {
10034 glDeleteProgram(m_enabled_early_tests.m_program_id);
10035 m_enabled_early_tests.m_program_id = 0;
10036 }
10037
10038 if (0 != m_color_renderbuffer_id)
10039 {
10040 glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10041 m_color_renderbuffer_id = 0;
10042 }
10043
10044 if (0 != m_depth_stencil_renderbuffer_id)
10045 {
10046 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10047 m_depth_stencil_renderbuffer_id = 0;
10048 }
10049
10050 if (0 != m_framebuffer_id)
10051 {
10052 glDeleteFramebuffers(1, &m_framebuffer_id);
10053 m_framebuffer_id = 0;
10054 }
10055
10056 if (0 != m_texture_id)
10057 {
10058 glDeleteTextures(1, &m_texture_id);
10059 m_texture_id = 0;
10060 }
10061
10062 if (0 != m_vertex_array_object_id)
10063 {
10064 glDeleteVertexArrays(1, &m_vertex_array_object_id);
10065 m_vertex_array_object_id = 0;
10066 }
10067
10068 /* Done */
10069 return NO_ERROR;
10070 }
10071
Run()10072 virtual long Run()
10073 {
10074 bool result = true;
10075
10076 /* Bind texture to first image unit */
10077 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10078 GL_READ_WRITE, GL_R32F);
10079 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10080
10081 /* Run tests for depth test */
10082 if (false == testEarlyZ())
10083 {
10084 result = false;
10085 }
10086
10087 /* Run tests for stencil test */
10088 if (false == testEarlyStencil())
10089 {
10090 result = false;
10091 }
10092
10093 /* Return ERROR if any problem was found */
10094 if (false == result)
10095 {
10096 return ERROR;
10097 }
10098
10099 /* Done */
10100 return NO_ERROR;
10101 }
10102
Setup()10103 virtual long Setup()
10104 {
10105 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10106
10107 /* Prepare storage for texture data */
10108 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10109 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10110
10111 /* Prepare programs, framebuffer and texture */
10112 buildPrograms();
10113 createFramebuffer();
10114 createTexture();
10115
10116 /* Generate vertex array object */
10117 glGenVertexArrays(1, &m_vertex_array_object_id);
10118 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10119
10120 /* Bind vertex array object */
10121 glBindVertexArray(m_vertex_array_object_id);
10122 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10123
10124 /* Set clear color */
10125 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10126 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10127
10128 /* Done */
10129 return NO_ERROR;
10130 }
10131
10132 private:
10133 /** Build two programs: with enabled and disabled early fragment tests
10134 *
10135 **/
buildPrograms()10136 void buildPrograms()
10137 {
10138 static const char *const fragment_shader_with_disabled_early_tests =
10139 "#version 400 core\n"
10140 "#extension GL_ARB_shader_image_load_store : require\n"
10141 "\n"
10142 "precision highp float;\n"
10143 "\n"
10144 "layout(r32f) uniform image2D u_image;\n"
10145 "\n"
10146 "void main()\n"
10147 "{\n"
10148 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10149 "\n"
10150 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10151 "\n"
10152 " discard;\n"
10153 "}\n\n";
10154
10155 static const char *const fragment_shader_with_enabled_early_tests =
10156 "#version 400 core\n"
10157 "#extension GL_ARB_shader_image_load_store : require\n"
10158 "\n"
10159 "precision highp float;\n"
10160 "\n"
10161 "layout(early_fragment_tests) in;\n"
10162 "\n"
10163 "layout(r32f) uniform image2D u_image;\n"
10164 "\n"
10165 "void main()\n"
10166 "{\n"
10167 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10168 "\n"
10169 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10170 "\n"
10171 " discard;\n"
10172 "}\n\n";
10173
10174 static const char *const geometry_shader_code = "#version 400 core\n"
10175 "#extension GL_ARB_shader_image_load_store : require\n"
10176 "\n"
10177 "precision highp float;\n"
10178 "\n"
10179 "layout(points) in;\n"
10180 "layout(triangle_strip, max_vertices = 4) out;\n"
10181 "\n"
10182 "uniform float u_depth;\n"
10183 "\n"
10184 "void main()\n"
10185 "{\n"
10186 " // Left-bottom\n"
10187 " gl_Position = vec4(-1, -1, u_depth, 1);\n"
10188 " EmitVertex();\n"
10189 "\n"
10190 " // Left-top\n"
10191 " gl_Position = vec4(-1, 1, u_depth, 1);\n"
10192 " EmitVertex();\n"
10193 "\n"
10194 " // Right-bottom\n"
10195 " gl_Position = vec4( 1, -1, u_depth, 1);\n"
10196 " EmitVertex();\n"
10197 "\n"
10198 " // Right-top\n"
10199 " gl_Position = vec4( 1, 1, u_depth, 1);\n"
10200 " EmitVertex();\n"
10201 "}\n\n";
10202
10203 static const char *const vertex_shader_code = "#version 400 core\n"
10204 "#extension GL_ARB_shader_image_load_store : require\n"
10205 "\n"
10206 "precision highp float;\n"
10207 "\n"
10208 "void main()\n"
10209 "{\n"
10210 "}\n\n";
10211
10212 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10213 m_disabled_early_tests);
10214
10215 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10216 m_enabled_early_tests);
10217 }
10218
10219 /** Fill texture with zeros
10220 *
10221 **/
cleanTexture()10222 void cleanTexture()
10223 {
10224 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10225 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10226 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10227 }
10228
10229 /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10230 *
10231 **/
createFramebuffer()10232 void createFramebuffer()
10233 {
10234 /* Generate render buffers */
10235 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10236 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10237
10238 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10239 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10240
10241 /* Generate and bind framebuffer object */
10242 glGenFramebuffers(1, &m_framebuffer_id);
10243 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10244
10245 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10246 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10247
10248 /* Prepare color render buffer */
10249 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10250 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10251
10252 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10253 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10254
10255 /* Set up color attachment */
10256 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10257 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10258
10259 /* Prepare depth-stencil render buffer */
10260 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10261 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10262
10263 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10264 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10265
10266 /* Set up depth-stencil attachment */
10267 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10268 m_depth_stencil_renderbuffer_id);
10269 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10270 }
10271
10272 /** Create 2D R32F texture
10273 *
10274 **/
createTexture()10275 void createTexture()
10276 {
10277 glGenTextures(1, &m_texture_id);
10278 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10279
10280 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10281 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10282
10283 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10284 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10285 }
10286
10287 /** Extracts red channel from texture and verify if all texels are set to specified value
10288 *
10289 * @param value Expected value
10290 *
10291 * @return true if all texel match expected value, false otherwise
10292 **/
isTextureFilledWithValue(GLfloat value)10293 bool isTextureFilledWithValue(GLfloat value)
10294 {
10295 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10296 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10297
10298 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10299 {
10300 if (value != m_extracted_texture_data[i])
10301 {
10302 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10303 << " has invalid value: " << m_extracted_texture_data[i]
10304 << " expected: " << value << tcu::TestLog::EndMessage;
10305
10306 return false;
10307 }
10308 }
10309
10310 return true;
10311 }
10312
10313 /** Build program, extract location of uniforms and store results in programDetails instance
10314 *
10315 * Throws tcu::InternalError if uniforms are inactive
10316 *
10317 * @param fragment_shader_code Source of fragment shader
10318 * @param geometry_shader_code Source of geometry shader
10319 * @param vertex_shader_code Source of vertex shader
10320 * @param out_program_details Instance of programDetails
10321 **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10322 void prepareProgramDetails(const char *fragment_shader_code, const char *geometry_shader_code,
10323 const char *vertex_shader_code, programDetails &out_program_details)
10324 {
10325 static const char *const depth_uniform_name = "u_depth";
10326 static const char *const image_uniform_name = "u_image";
10327 bool is_program_built = true;
10328
10329 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10330 fragment_shader_code, &is_program_built);
10331
10332 if (false == is_program_built)
10333 {
10334 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10335 }
10336
10337 /* Get depth uniform location */
10338 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10339 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10340
10341 if (m_invalid_uniform_location == depth_uniform_location)
10342 {
10343 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10344 }
10345
10346 /* Get image uniform location */
10347 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10348 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10349
10350 if (m_invalid_uniform_location == image_uniform_location)
10351 {
10352 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10353 }
10354
10355 /* Store results */
10356 out_program_details.m_depth_uniform_location = depth_uniform_location;
10357 out_program_details.m_image_uniform_location = image_uniform_location;
10358 out_program_details.m_program_id = program_id;
10359 }
10360
10361 /** Test if early fragment stencil test works as expected.
10362 *
10363 * @return true if successful, false otherwise
10364 **/
testEarlyStencil()10365 bool testEarlyStencil()
10366 {
10367 bool result = true;
10368
10369 glEnable(GL_STENCIL_TEST);
10370 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10371
10372 glClearDepthf(1.0f);
10373 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10374
10375 /* verify that early stencil test is applied when enabled */
10376 {
10377 glUseProgram(m_enabled_early_tests.m_program_id);
10378 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10379
10380 glClearStencil(0);
10381 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10382
10383 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10384 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10385
10386 cleanTexture();
10387
10388 glStencilFunc(GL_LESS, 128, 0xffffffff);
10389 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10390
10391 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10392 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10393
10394 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10395 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10396
10397 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10398 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10399
10400 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10401 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10402
10403 if (false == isTextureFilledWithValue(0.0f))
10404 {
10405 m_context.getTestContext().getLog()
10406 << tcu::TestLog::Message << "Problem with early stencil test. It is not applied"
10407 << tcu::TestLog::EndMessage;
10408
10409 result = false;
10410 }
10411 }
10412
10413 /* verify that early stencil test does not discard all fragments */
10414 {
10415 glClearStencil(128);
10416 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10417
10418 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10419 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10420
10421 cleanTexture();
10422
10423 glStencilFunc(GL_LESS, 0, 0xffffffff);
10424 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10425
10426 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10427 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10428
10429 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10430 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10431
10432 if (false == isTextureFilledWithValue(1.0f))
10433 {
10434 m_context.getTestContext().getLog()
10435 << tcu::TestLog::Message
10436 << "Problem with early stencil test. It discards fragments, that shall be drawn"
10437 << tcu::TestLog::EndMessage;
10438
10439 result = false;
10440 }
10441 }
10442
10443 /* verify that early stencil test is not applied when disabled */
10444 {
10445 glUseProgram(m_disabled_early_tests.m_program_id);
10446 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10447
10448 glClearStencil(0);
10449 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10450
10451 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10452 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10453
10454 cleanTexture();
10455
10456 glStencilFunc(GL_LESS, 128, 0xffffffff);
10457 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10458
10459 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10460 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10461
10462 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10463 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10464
10465 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10466 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10467
10468 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10469 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10470
10471 if (false == isTextureFilledWithValue(1.0f))
10472 {
10473 m_context.getTestContext().getLog()
10474 << tcu::TestLog::Message << "Problem with early stencil test. It is applied when disabled"
10475 << tcu::TestLog::EndMessage;
10476
10477 result = false;
10478 }
10479 }
10480
10481 glDisable(GL_STENCIL_TEST);
10482 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10483
10484 /* Done */
10485 return result;
10486 }
10487
10488 /** Test if early fragment depth test works as expected.
10489 *
10490 * @return true if successful, false otherwise
10491 **/
testEarlyZ()10492 bool testEarlyZ()
10493 {
10494 bool result = true;
10495
10496 glEnable(GL_DEPTH_TEST);
10497 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10498
10499 glClearDepthf(0.5f);
10500 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10501
10502 glClearStencil(0);
10503 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10504
10505 /* verify that early z test is applied when enabled */
10506 {
10507 glUseProgram(m_enabled_early_tests.m_program_id);
10508 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10509
10510 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10511 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10512
10513 cleanTexture();
10514
10515 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10516 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10517
10518 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10519 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10520
10521 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10522 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10523
10524 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10525 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10526
10527 if (false == isTextureFilledWithValue(0.0f))
10528 {
10529 m_context.getTestContext().getLog()
10530 << tcu::TestLog::Message << "Problem with early z test. It is not applied"
10531 << tcu::TestLog::EndMessage;
10532
10533 result = false;
10534 }
10535 }
10536
10537 /* verify that early z test does not discard all fragments */
10538 {
10539 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10540 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10541
10542 cleanTexture();
10543
10544 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10545 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10546
10547 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10548 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10549
10550 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10551 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10552
10553 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10554 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10555
10556 if (false == isTextureFilledWithValue(1.0f))
10557 {
10558 m_context.getTestContext().getLog()
10559 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10560 << tcu::TestLog::EndMessage;
10561
10562 result = false;
10563 }
10564 }
10565
10566 /* verify that early z test is not applied when disabled */
10567 {
10568 glUseProgram(m_disabled_early_tests.m_program_id);
10569 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10570
10571 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10572 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10573
10574 cleanTexture();
10575
10576 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10577 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10578
10579 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10580 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10581
10582 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10583 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10584
10585 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10586 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10587
10588 if (false == isTextureFilledWithValue(1.0f))
10589 {
10590 m_context.getTestContext().getLog()
10591 << tcu::TestLog::Message << "Problem with early z test. It is applied when disabled"
10592 << tcu::TestLog::EndMessage;
10593
10594 result = false;
10595 }
10596 }
10597
10598 glDisable(GL_DEPTH_TEST);
10599 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10600
10601 /* Done */
10602 return result;
10603 }
10604 };
10605
10606 //-----------------------------------------------------------------------------
10607 // 4.1 NegativeUniform
10608 //-----------------------------------------------------------------------------
10609 class NegativeUniform : public ShaderImageLoadStoreBase
10610 {
10611 GLuint m_program;
10612
Setup()10613 virtual long Setup()
10614 {
10615 m_program = 0;
10616 return NO_ERROR;
10617 }
10618
Run()10619 virtual long Run()
10620 {
10621 const char *glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10622 " gl_Position = i_position;" NL "}";
10623 const char *glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10624 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL
10625 " discard;" NL "}";
10626 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10627
10628 GLint max_image_units;
10629 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10630 glUseProgram(m_program);
10631
10632 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10633 if (glGetError() != GL_INVALID_VALUE)
10634 {
10635 m_context.getTestContext().getLog()
10636 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10637 << tcu::TestLog::EndMessage;
10638 return ERROR;
10639 }
10640 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10641 if (glGetError() != GL_INVALID_VALUE)
10642 {
10643 m_context.getTestContext().getLog()
10644 << tcu::TestLog::Message
10645 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10646 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10647 return ERROR;
10648 }
10649
10650 GLint i = -3;
10651 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10652 if (glGetError() != GL_INVALID_VALUE)
10653 {
10654 m_context.getTestContext().getLog()
10655 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10656 << tcu::TestLog::EndMessage;
10657 return ERROR;
10658 }
10659 i = max_image_units + 1;
10660 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10661 if (glGetError() != GL_INVALID_VALUE)
10662 {
10663 m_context.getTestContext().getLog() << tcu::TestLog::Message
10664 << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10665 "than or equal to the value of MAX_IMAGE_UNITS."
10666 << tcu::TestLog::EndMessage;
10667 return ERROR;
10668 }
10669
10670 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10671 if (glGetError() != GL_INVALID_OPERATION)
10672 {
10673 m_context.getTestContext().getLog()
10674 << tcu::TestLog::Message
10675 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10676 << tcu::TestLog::EndMessage;
10677 return ERROR;
10678 }
10679 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10680 if (glGetError() != GL_INVALID_OPERATION)
10681 {
10682 m_context.getTestContext().getLog()
10683 << tcu::TestLog::Message
10684 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10685 << tcu::TestLog::EndMessage;
10686 return ERROR;
10687 }
10688
10689 {
10690 glUseProgram(0);
10691
10692 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10693 if (glGetError() != GL_INVALID_VALUE)
10694 {
10695 m_context.getTestContext().getLog()
10696 << tcu::TestLog::Message
10697 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10698 << tcu::TestLog::EndMessage;
10699 return ERROR;
10700 }
10701 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10702 if (glGetError() != GL_INVALID_VALUE)
10703 {
10704 m_context.getTestContext().getLog()
10705 << tcu::TestLog::Message
10706 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10707 "value of MAX_IMAGE_UNITS."
10708 << tcu::TestLog::EndMessage;
10709 return ERROR;
10710 }
10711
10712 GLint ii = -3;
10713 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10714 if (glGetError() != GL_INVALID_VALUE)
10715 {
10716 m_context.getTestContext().getLog()
10717 << tcu::TestLog::Message
10718 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10719 << tcu::TestLog::EndMessage;
10720 return ERROR;
10721 }
10722 ii = max_image_units + 1;
10723 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10724 if (glGetError() != GL_INVALID_VALUE)
10725 {
10726 m_context.getTestContext().getLog() << tcu::TestLog::Message
10727 << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10728 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10729 << tcu::TestLog::EndMessage;
10730 return ERROR;
10731 }
10732
10733 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10734 if (glGetError() != GL_INVALID_OPERATION)
10735 {
10736 m_context.getTestContext().getLog() << tcu::TestLog::Message
10737 << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10738 "location refers to an image variable."
10739 << tcu::TestLog::EndMessage;
10740 return ERROR;
10741 }
10742 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10743 if (glGetError() != GL_INVALID_OPERATION)
10744 {
10745 m_context.getTestContext().getLog() << tcu::TestLog::Message
10746 << "glProgramUniform2i should generate INVALID_OPERATION if the "
10747 "location refers to an image variable."
10748 << tcu::TestLog::EndMessage;
10749 return ERROR;
10750 }
10751 }
10752
10753 return NO_ERROR;
10754 }
10755
Cleanup()10756 virtual long Cleanup()
10757 {
10758 glUseProgram(0);
10759 glDeleteProgram(m_program);
10760 return NO_ERROR;
10761 }
10762 };
10763 //-----------------------------------------------------------------------------
10764 // 4.2 NegativeBind
10765 //-----------------------------------------------------------------------------
10766 class NegativeBind : public ShaderImageLoadStoreBase
10767 {
Setup()10768 virtual long Setup()
10769 {
10770 return NO_ERROR;
10771 }
10772
Run()10773 virtual long Run()
10774 {
10775 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10776 if (glGetError() != GL_INVALID_VALUE)
10777 {
10778 m_context.getTestContext().getLog() << tcu::TestLog::Message
10779 << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10780 "greater than or equal to the value of MAX_IMAGE_UNITS."
10781 << tcu::TestLog::EndMessage;
10782 return ERROR;
10783 }
10784
10785 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10786 if (glGetError() != GL_INVALID_VALUE)
10787 {
10788 m_context.getTestContext().getLog() << tcu::TestLog::Message
10789 << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10790 "the name of an existing texture object."
10791 << tcu::TestLog::EndMessage;
10792 return ERROR;
10793 }
10794
10795 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10796 if (glGetError() != GL_INVALID_VALUE)
10797 {
10798 m_context.getTestContext().getLog()
10799 << tcu::TestLog::Message
10800 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10801 << tcu::TestLog::EndMessage;
10802 return ERROR;
10803 }
10804 return NO_ERROR;
10805 }
10806
Cleanup()10807 virtual long Cleanup()
10808 {
10809 return NO_ERROR;
10810 }
10811 };
10812 //-----------------------------------------------------------------------------
10813 // 4.3 NegativeCompileErrors
10814 //-----------------------------------------------------------------------------
10815 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10816 {
Run()10817 virtual long Run()
10818 {
10819 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10820 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10821 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10822 return ERROR;
10823
10824 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10825 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10826 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10827 return ERROR;
10828
10829 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10830 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10831 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
10832 return ERROR;
10833
10834 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10835 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10836 return ERROR;
10837
10838 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10839 "readonly uniform image2D g_image;" NL "void main() {" NL
10840 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10841 return ERROR;
10842
10843 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10844 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10845 return ERROR;
10846
10847 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10848 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10849 return ERROR;
10850
10851 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10852 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10853 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
10854 return ERROR;
10855
10856 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10857 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10858 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}"))
10859 return ERROR;
10860
10861 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10862 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10863 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10864 return ERROR;
10865
10866 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10867 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10868 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10869 return ERROR;
10870
10871 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10872 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10873 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL
10874 "}"))
10875 return ERROR;
10876
10877 return NO_ERROR;
10878 }
10879
Compile(const std::string & source)10880 bool Compile(const std::string &source)
10881 {
10882 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10883
10884 const char *const src = source.c_str();
10885 glShaderSource(sh, 1, &src, NULL);
10886 glCompileShader(sh);
10887
10888 GLchar log[1024];
10889 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10890 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10891 << log << tcu::TestLog::EndMessage;
10892
10893 GLint status;
10894 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10895 glDeleteShader(sh);
10896
10897 if (status == GL_TRUE)
10898 {
10899 m_context.getTestContext().getLog()
10900 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10901 return false;
10902 }
10903
10904 return true;
10905 }
10906 };
10907 //-----------------------------------------------------------------------------
10908 // 4.4 NegativeLinkErrors
10909 //-----------------------------------------------------------------------------
10910 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10911 {
Run()10912 virtual long Run()
10913 {
10914 if (!SupportedInVS(1))
10915 return NOT_SUPPORTED;
10916
10917 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10918 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10919 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10920 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10921 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10922 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10923 return ERROR;
10924
10925 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10926 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10927 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10928 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10929 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10930 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10931 return ERROR;
10932
10933 return NO_ERROR;
10934 }
10935
Link(const std::string & vs,const std::string & fs)10936 bool Link(const std::string &vs, const std::string &fs)
10937 {
10938 const GLuint p = glCreateProgram();
10939
10940 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10941 glAttachShader(p, vsh);
10942 glDeleteShader(vsh);
10943 const char *const vssrc = vs.c_str();
10944 glShaderSource(vsh, 1, &vssrc, NULL);
10945 glCompileShader(vsh);
10946
10947 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10948 glAttachShader(p, fsh);
10949 glDeleteShader(fsh);
10950 const char *const fssrc = fs.c_str();
10951 glShaderSource(fsh, 1, &fssrc, NULL);
10952 glCompileShader(fsh);
10953
10954 GLint status;
10955 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10956 if (status == GL_FALSE)
10957 {
10958 glDeleteProgram(p);
10959 m_context.getTestContext().getLog()
10960 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10961 return false;
10962 }
10963 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10964 if (status == GL_FALSE)
10965 {
10966 glDeleteProgram(p);
10967 m_context.getTestContext().getLog()
10968 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10969 return false;
10970 }
10971
10972 glLinkProgram(p);
10973
10974 GLchar log[1024];
10975 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10976 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10977 << log << tcu::TestLog::EndMessage;
10978
10979 glGetProgramiv(p, GL_LINK_STATUS, &status);
10980 glDeleteProgram(p);
10981
10982 if (status == GL_TRUE)
10983 {
10984 m_context.getTestContext().getLog()
10985 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10986 return false;
10987 }
10988
10989 return true;
10990 }
10991 };
10992
10993 /** Negative Test "Active image uniform limits", description follows.
10994 *
10995 * Program that exceeds resource limits should not compile and/or link.
10996 *
10997 * Steps:
10998 * - try to compile and link a program that uses too many image uniforms in
10999 * fragment shader stage,
11000 * - try to compile and link a program that uses too many image uniforms in
11001 * vertex shader stage,
11002 * - try to compile and link a program that uses too many image uniforms in
11003 * tessellation control shader stage,
11004 * - try to compile and link a program that uses too many image uniforms in
11005 * tessellation evaluation shader stage,
11006 * - try to compile and link a program that uses too many image uniforms in
11007 * geometry shader stage,
11008 * - try to compile and link a program that uses too many image uniforms in all
11009 * shader stages combined, any single stage should not exceed its limits, this
11010 * step might be impossible to fulfill.
11011 *
11012 * Test should use the following declaration of image uniforms:
11013 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11014 *
11015 * For cases where limit for single stage is tested, N_UNIFORMS should be
11016 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11017 * corresponding to tested shader stage.
11018 *
11019 * For case where limit for combined stages is tested:
11020 * - u_image name should be appended with the name of shader stage, like
11021 * u_image_vertex,
11022 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11023 * gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11024 * - compilation and linking shall succeed, when sum of all
11025 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11026 * gl_MaxCombinedImageUniforms.
11027 *
11028 * All defined image uniforms have to be active. Each shader stage that declare
11029 * image uniforms should include following code snippet:
11030 * value = 1;
11031 * for (int i = 0; i < N_UNIFORMS; ++i)
11032 * {
11033 * value = imageAtomicAdd(u_image[i], coord, value);
11034 * }
11035 **/
11036 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11037 {
11038 private:
11039 /* Fields */
11040 /* Results */
11041 bool m_result_for_combined;
11042 bool m_result_for_fragment_shader;
11043 bool m_result_for_geometry_shader;
11044 bool m_result_for_tesselation_control_shader;
11045 bool m_result_for_tesselatioon_evaluation_shader;
11046 bool m_result_for_vertex_shader;
11047
11048 public:
11049 /* Constructor */
ImageLoadStoreUniformLimitsTest()11050 ImageLoadStoreUniformLimitsTest()
11051 : m_result_for_combined(false)
11052 , m_result_for_fragment_shader(false)
11053 , m_result_for_geometry_shader(false)
11054 , m_result_for_tesselation_control_shader(false)
11055 , m_result_for_tesselatioon_evaluation_shader(false)
11056 , m_result_for_vertex_shader(false)
11057 {
11058 /* Nothing to be done */
11059 }
11060
11061 /* Methods inherited from SubcaseBase */
Cleanup()11062 virtual long Cleanup()
11063 {
11064 /* Done */
11065 return NO_ERROR;
11066 }
11067
Run()11068 virtual long Run()
11069 {
11070 m_context.getTestContext().getLog() << tcu::TestLog::Message
11071 << "This test tries to build invalid programs, expect error messages about "
11072 "exceeded number of active image uniforms"
11073 << tcu::TestLog::EndMessage;
11074
11075 testFragmentShaderStage();
11076 testGeometryShaderStage();
11077 testTesselationControlShaderStage();
11078 testTesselationEvaluationShaderStage();
11079 testVertexShaderStage();
11080 testCombinedShaderStages();
11081
11082 /* Return error if any stage failed */
11083 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11084 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11085 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11086 {
11087 return ERROR;
11088 }
11089
11090 /* Done */
11091 return NO_ERROR;
11092 }
11093
Setup()11094 virtual long Setup()
11095 {
11096 /* Done */
11097 return NO_ERROR;
11098 }
11099
11100 private:
11101 /** Test fragment shader stage
11102 *
11103 **/
testFragmentShaderStage()11104 void testFragmentShaderStage()
11105 {
11106 static const char *const fragment_shader_code =
11107 "#version 400 core\n"
11108 "#extension GL_ARB_shader_image_load_store : require\n"
11109 "\n"
11110 "precision highp float;\n"
11111 "\n"
11112 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11113 "\n"
11114 "flat in ivec2 vs_fs_coord;\n"
11115 "\n"
11116 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11117 "\n"
11118 "void main()\n"
11119 "{\n"
11120 " int value = 1;\n"
11121 "\n"
11122 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11123 " {\n"
11124 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11125 " }\n"
11126 "\n"
11127 " discard;\n"
11128 "}\n\n";
11129
11130 static const char *const vertex_shader_code = "#version 400 core\n"
11131 "#extension GL_ARB_shader_image_load_store : require\n"
11132 "\n"
11133 "precision highp float;\n"
11134 "\n"
11135 " in ivec2 vs_in_coord;\n"
11136 "flat out ivec2 vs_fs_coord;\n"
11137 "\n"
11138 "void main()\n"
11139 "{\n"
11140 " vs_fs_coord = vs_in_coord;\n"
11141 "}\n\n";
11142
11143 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11144 0 /* tesselation_control_shader_code */,
11145 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11146
11147 if (false == m_result_for_fragment_shader)
11148 {
11149 m_context.getTestContext().getLog()
11150 << tcu::TestLog::Message
11151 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11152 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11153 << fragment_shader_code << tcu::TestLog::EndMessage;
11154 }
11155 }
11156
11157 /** Test geometry shader stage
11158 *
11159 **/
testGeometryShaderStage()11160 void testGeometryShaderStage()
11161 {
11162 static const char *const fragment_shader_code = "#version 400 core\n"
11163 "#extension GL_ARB_shader_image_load_store : require\n"
11164 "\n"
11165 "precision highp float;\n"
11166 "\n"
11167 "void main()\n"
11168 "{\n"
11169 " discard;\n"
11170 "}\n\n";
11171
11172 static const char *const geometry_shader_code =
11173 "#version 400 core\n"
11174 "#extension GL_ARB_shader_image_load_store : require\n"
11175 "\n"
11176 "precision highp float;\n"
11177 "\n"
11178 "layout(points) in;\n"
11179 "layout(points, max_vertices = 1) out;\n"
11180 "\n"
11181 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11182 "\n"
11183 "in ivec2 vs_gs_coord[];\n"
11184 "\n"
11185 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11186 "\n"
11187 "void main()\n"
11188 "{\n"
11189 " int value = 1;\n"
11190 "\n"
11191 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11192 " {\n"
11193 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11194 " }\n"
11195 "}\n\n";
11196
11197 static const char *const vertex_shader_code = "#version 400 core\n"
11198 "#extension GL_ARB_shader_image_load_store : require\n"
11199 "\n"
11200 "precision highp float;\n"
11201 "\n"
11202 "in ivec2 vs_in_coord;\n"
11203 "out ivec2 vs_gs_coord;\n"
11204 "\n"
11205 "void main()\n"
11206 "{\n"
11207 " vs_gs_coord = vs_in_coord;\n"
11208 "}\n\n";
11209
11210 m_result_for_geometry_shader =
11211 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11212 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11213
11214 if (false == m_result_for_geometry_shader)
11215 {
11216 m_context.getTestContext().getLog()
11217 << tcu::TestLog::Message
11218 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11219 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11220 << geometry_shader_code << tcu::TestLog::EndMessage;
11221 }
11222 }
11223
11224 /** Test tesselation control shader stage
11225 *
11226 **/
testTesselationControlShaderStage()11227 void testTesselationControlShaderStage()
11228 {
11229 static const char *const fragment_shader_code = "#version 400 core\n"
11230 "#extension GL_ARB_shader_image_load_store : require\n"
11231 "\n"
11232 "precision highp float;\n"
11233 "\n"
11234 "void main()\n"
11235 "{\n"
11236 " discard;\n"
11237 "}\n\n";
11238
11239 static const char *const tesselation_control_shader_code =
11240 "#version 400 core\n"
11241 "#extension GL_ARB_shader_image_load_store : require\n"
11242 "\n"
11243 "precision highp float;\n"
11244 "\n"
11245 "layout(vertices = 4) out;\n"
11246 "\n"
11247 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11248 "\n"
11249 "in ivec2 vs_tcs_coord[];\n"
11250 "\n"
11251 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11252 "\n"
11253 "void main()\n"
11254 "{\n"
11255 " int value = 1;\n"
11256 "\n"
11257 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11258 " {\n"
11259 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11260 " }\n"
11261 "}\n\n";
11262
11263 static const char *const tesselation_evaluation_shader_code =
11264 "#version 400 core\n"
11265 "#extension GL_ARB_shader_image_load_store : require\n"
11266 "\n"
11267 "precision highp float;\n"
11268 "\n"
11269 "layout(quads, equal_spacing, ccw) in;\n"
11270 "\n"
11271 "void main()\n"
11272 "{\n"
11273 "}\n";
11274
11275 static const char *const vertex_shader_code = "#version 400 core\n"
11276 "#extension GL_ARB_shader_image_load_store : require\n"
11277 "\n"
11278 "precision highp float;\n"
11279 "\n"
11280 "in ivec2 vs_in_coord;\n"
11281 "out ivec2 vs_tcs_coord;\n"
11282 "\n"
11283 "void main()\n"
11284 "{\n"
11285 " vs_tcs_coord = vs_in_coord;\n"
11286 "}\n\n";
11287
11288 m_result_for_tesselation_control_shader =
11289 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11290 tesselation_evaluation_shader_code, vertex_shader_code);
11291
11292 if (false == m_result_for_tesselation_control_shader)
11293 {
11294 m_context.getTestContext().getLog()
11295 << tcu::TestLog::Message
11296 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11297 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11298 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11299 }
11300 }
11301
11302 /** Test teselation evaluation shader stage
11303 *
11304 **/
testTesselationEvaluationShaderStage()11305 void testTesselationEvaluationShaderStage()
11306 {
11307 static const char *const fragment_shader_code = "#version 400 core\n"
11308 "#extension GL_ARB_shader_image_load_store : require\n"
11309 "\n"
11310 "precision highp float;\n"
11311 "\n"
11312 "void main()\n"
11313 "{\n"
11314 " discard;\n"
11315 "}\n\n";
11316
11317 static const char *const tesselation_evaluation_shader_code =
11318 "#version 400 core\n"
11319 "#extension GL_ARB_shader_image_load_store : require\n"
11320 "\n"
11321 "precision highp float;\n"
11322 "\n"
11323 "layout(quads, equal_spacing, ccw) in;\n"
11324 "\n"
11325 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11326 "\n"
11327 "in ivec2 vs_tes_coord[];\n"
11328 "\n"
11329 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11330 "\n"
11331 "void main()\n"
11332 "{\n"
11333 " int value = 1;\n"
11334 "\n"
11335 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11336 " {\n"
11337 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11338 " }\n"
11339 "}\n\n";
11340
11341 static const char *const vertex_shader_code = "#version 400 core\n"
11342 "#extension GL_ARB_shader_image_load_store : require\n"
11343 "\n"
11344 "precision highp float;\n"
11345 "\n"
11346 "in ivec2 vs_in_coord;\n"
11347 "out ivec2 vs_tes_coord;\n"
11348 "\n"
11349 "void main()\n"
11350 "{\n"
11351 " vs_tes_coord = vs_in_coord;\n"
11352 "}\n\n";
11353
11354 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11355 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11356 tesselation_evaluation_shader_code, vertex_shader_code);
11357
11358 if (false == m_result_for_tesselatioon_evaluation_shader)
11359 {
11360 m_context.getTestContext().getLog()
11361 << tcu::TestLog::Message
11362 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11363 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11364 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11365 }
11366 }
11367
11368 /** Test vertex shader stage
11369 *
11370 **/
testVertexShaderStage()11371 void testVertexShaderStage()
11372 {
11373 static const char *const fragment_shader_code = "#version 400 core\n"
11374 "#extension GL_ARB_shader_image_load_store : require\n"
11375 "\n"
11376 "precision highp float;\n"
11377 "\n"
11378 "void main()\n"
11379 "{\n"
11380 " discard;\n"
11381 "}\n\n";
11382
11383 static const char *const vertex_shader_code =
11384 "#version 400 core\n"
11385 "#extension GL_ARB_shader_image_load_store : require\n"
11386 "\n"
11387 "precision highp float;\n"
11388 "\n"
11389 "in ivec2 vs_in_coord;\n"
11390 "\n"
11391 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11392 "\n"
11393 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11394 "\n"
11395 "void main()\n"
11396 "{\n"
11397 " int value = 1;\n"
11398 "\n"
11399 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11400 " {\n"
11401 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11402 " }\n"
11403 "}\n\n";
11404
11405 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11406 0 /* tesselation_control_shader_code */,
11407 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11408
11409 if (false == m_result_for_vertex_shader)
11410 {
11411 m_context.getTestContext().getLog()
11412 << tcu::TestLog::Message
11413 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11414 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11415 << vertex_shader_code << tcu::TestLog::EndMessage;
11416 }
11417 }
11418
11419 /** Test combined shader stages
11420 *
11421 **/
testCombinedShaderStages()11422 void testCombinedShaderStages()
11423 {
11424 std::string fragment_shader_code = "#version 400 core\n"
11425 "#extension GL_ARB_shader_image_load_store : require\n"
11426 "\n"
11427 "precision highp float;\n"
11428 "\n"
11429 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11430 "\n"
11431 "flat in ivec2 gs_fs_coord;\n"
11432 "\n"
11433 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11434 "\n"
11435 "void main()\n"
11436 "{\n"
11437 " int value = 1;\n"
11438 "\n"
11439 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11440 " {\n"
11441 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11442 " }\n"
11443 "\n"
11444 " discard;\n"
11445 "}\n\n";
11446
11447 std::string geometry_shader_code =
11448 "#version 400 core\n"
11449 "#extension GL_ARB_shader_image_load_store : require\n"
11450 "\n"
11451 "precision highp float;\n"
11452 "\n"
11453 "layout(points) in;\n"
11454 "layout(points, max_vertices = 1) out;\n"
11455 "\n"
11456 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11457 "\n"
11458 "flat in ivec2 tes_gs_coord[];\n"
11459 "flat out ivec2 gs_fs_coord;\n"
11460 "\n"
11461 "#ifdef IMAGES\n"
11462 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11463 "#endif\n"
11464 "\n"
11465 "void main()\n"
11466 "{\n"
11467 "#ifdef IMAGES\n"
11468 " int value = 1;\n"
11469 "\n"
11470 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11471 " {\n"
11472 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11473 " }\n"
11474 "\n"
11475 "#endif\n"
11476 " gs_fs_coord = tes_gs_coord[0];\n"
11477 " EmitVertex();\n"
11478 "}\n\n";
11479
11480 std::string tesselation_control_shader_code =
11481 "#version 400 core\n"
11482 "#extension GL_ARB_shader_image_load_store : require\n"
11483 "\n"
11484 "precision highp float;\n"
11485 "\n"
11486 "layout(vertices = 4) out;\n"
11487 "\n"
11488 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11489 "\n"
11490 "flat in ivec2 vs_tcs_coord[];\n"
11491 "flat out ivec2 tcs_tes_coord[];\n"
11492 "\n"
11493 "#ifdef IMAGES\n"
11494 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11495 "#endif\n"
11496 "\n"
11497 "void main()\n"
11498 "{\n"
11499 "#ifdef IMAGES\n"
11500 " int value = 1;\n"
11501 "\n"
11502 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11503 " {\n"
11504 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11505 " }\n"
11506 "\n"
11507 "#endif\n"
11508 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11509 "}\n\n";
11510
11511 std::string tesselation_evaluation_shader_code =
11512 "#version 400 core\n"
11513 "#extension GL_ARB_shader_image_load_store : require\n"
11514 "\n"
11515 "precision highp float;\n"
11516 "\n"
11517 "layout(quads, equal_spacing, ccw) in;\n"
11518 "\n"
11519 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11520 "\n"
11521 "flat in ivec2 tcs_tes_coord[];\n"
11522 "flat out ivec2 tes_gs_coord;\n"
11523 "\n"
11524 "#ifdef IMAGES\n"
11525 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11526 "#endif\n"
11527 "\n"
11528 "void main()\n"
11529 "{\n"
11530 "#ifdef IMAGES\n"
11531 " int value = 1;\n"
11532 "\n"
11533 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11534 " {\n"
11535 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11536 " }\n"
11537 "\n"
11538 "#endif\n"
11539 " tes_gs_coord = tcs_tes_coord[0];\n"
11540 "}\n\n";
11541
11542 std::string vertex_shader_code = "#version 400 core\n"
11543 "#extension GL_ARB_shader_image_load_store : require\n"
11544 "\n"
11545 "precision highp float;\n"
11546 "\n"
11547 " in ivec2 vs_in_coord;\n"
11548 "flat out ivec2 vs_tcs_coord;\n"
11549 "\n"
11550 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11551 "\n"
11552 "#ifdef IMAGES\n"
11553 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11554 "#endif\n"
11555 "\n"
11556 "void main()\n"
11557 "{\n"
11558 "#ifdef IMAGES\n"
11559 " int value = 1;\n"
11560 "\n"
11561 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11562 " {\n"
11563 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11564 " }\n"
11565 "\n"
11566 "#endif\n"
11567 " vs_tcs_coord = vs_tcs_coord;\n"
11568 "}\n\n";
11569
11570 /* Active image uniform limits */
11571 GLint max_combined_image_uniforms = 0;
11572 GLint max_fragment_image_uniforms = 0;
11573 GLint max_geometry_image_uniforms = 0;
11574 GLint max_tesselation_control_image_uniforms = 0;
11575 GLint max_tesselation_evaluation_image_uniforms = 0;
11576 GLint max_vertex_image_uniforms = 0;
11577
11578 /* Get limit values */
11579 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11580 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11581 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11582 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11583 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11584 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11585 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11586
11587 if (max_vertex_image_uniforms)
11588 vertex_shader_code.insert(18, "#define IMAGES\n");
11589 if (max_geometry_image_uniforms)
11590 geometry_shader_code.insert(18, "#define IMAGES\n");
11591 if (max_tesselation_control_image_uniforms)
11592 tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11593 if (max_tesselation_evaluation_image_uniforms)
11594 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11595
11596 /* Check if program builds */
11597 m_result_for_combined = !doesProgramLink(
11598 fragment_shader_code.c_str(), geometry_shader_code.c_str(), tesselation_control_shader_code.c_str(),
11599 tesselation_evaluation_shader_code.c_str(), vertex_shader_code.c_str());
11600
11601 /* Result depends on the limit values */
11602 if (max_combined_image_uniforms >=
11603 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11604 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11605 {
11606 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11607 m_result_for_combined = !m_result_for_combined;
11608
11609 if (false == m_result_for_combined)
11610 {
11611 m_context.getTestContext().getLog()
11612 << tcu::TestLog::Message << "There was an error while building a program."
11613 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11614 << vertex_shader_code << "\nTesselation control shader code:\n"
11615 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11616 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11617 << geometry_shader_code << "\nFragment shader code:\n"
11618 << fragment_shader_code << tcu::TestLog::EndMessage;
11619 }
11620 }
11621 else
11622 {
11623 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11624 if (false == m_result_for_combined)
11625 {
11626 m_context.getTestContext().getLog()
11627 << tcu::TestLog::Message
11628 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11629 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11630 << vertex_shader_code << "\nTesselation control shader code:\n"
11631 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11632 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11633 << geometry_shader_code << "\nFragment shader code:\n"
11634 << fragment_shader_code << tcu::TestLog::EndMessage;
11635 }
11636 }
11637 }
11638
11639 /** Check if program builds successfully
11640 *
11641 * @param fragment_shader_code Source code for fragment shader stage
11642 * @param geometry_shader_code Source code for geometry shader stage
11643 * @param tesselation_control_shader_code Source code for tesselation control shader stage
11644 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11645 * @param vertex_shader_code Source code for vertex shader stage
11646 *
11647 * @return true if program was built without errors, false otherwise
11648 **/
doesProgramLink(const char * fragment_shader_code,const char * geometry_shader_code,const char * tesselation_control_shader_code,const char * tesselation_evaluation_shader_code,const char * vertex_shader_code)11649 bool doesProgramLink(const char *fragment_shader_code, const char *geometry_shader_code,
11650 const char *tesselation_control_shader_code, const char *tesselation_evaluation_shader_code,
11651 const char *vertex_shader_code)
11652 {
11653 bool is_program_built = true;
11654 GLuint program_id = 0;
11655
11656 program_id =
11657 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11658 geometry_shader_code, fragment_shader_code, &is_program_built);
11659
11660 if (0 != program_id)
11661 {
11662 glDeleteProgram(program_id);
11663 }
11664
11665 return is_program_built;
11666 }
11667 };
11668 } // namespace
11669
ShaderImageLoadStoreTests(deqp::Context & context)11670 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context &context)
11671 : TestCaseGroup(context, "shader_image_load_store", "")
11672 {
11673 }
11674
~ShaderImageLoadStoreTests(void)11675 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11676 {
11677 }
11678
init()11679 void ShaderImageLoadStoreTests::init()
11680 {
11681 using namespace deqp;
11682 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11683 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11684 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11685 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11686 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11687 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11688 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11689 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11690 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11691 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11692 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11693 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11694 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11695 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11696 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11697 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11698 addChild(
11699 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11700 addChild(
11701 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11702 addChild(
11703 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11704 addChild(
11705 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11706 addChild(
11707 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11708 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11709 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11710 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11711 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11712 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11713 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11714 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11715 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11716 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11717 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11718 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11719 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11720 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11721 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11722 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11723 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11724 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11725 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11726 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11727 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11728 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11729 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11730 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11731 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11732 addChild(
11733 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11734 addChild(
11735 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11736 addChild(
11737 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11738 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11739 addChild(
11740 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11741 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11742 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11743 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11744 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11745 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11746 }
11747 } // namespace gl4cts
11748