1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-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 /**
25 * \file gl4cMultiBindTests.cpp
26 * \brief Implements conformance tests for "Multi Bind" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cMultiBindTests.hpp"
30
31 #include "gluDefs.hpp"
32 #include "gluStrUtil.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuTestLog.hpp"
36
37 #include <string>
38
39 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0
40
41 #if DEBUG_ENBALE_MESSAGE_CALLBACK
42 #include <iomanip>
43 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
44
45 using namespace glw;
46
47 namespace gl4cts
48 {
49 namespace MultiBind
50 {
51
52 #if DEBUG_ENBALE_MESSAGE_CALLBACK
53 /** Debuging procedure. Logs parameters.
54 *
55 * @param source As specified in GL spec.
56 * @param type As specified in GL spec.
57 * @param id As specified in GL spec.
58 * @param severity As specified in GL spec.
59 * @param ignored
60 * @param message As specified in GL spec.
61 * @param info Pointer to instance of deqp::Context used by test.
62 */
debug_proc(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei,const GLchar * message,void * info)63 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */,
64 const GLchar* message, void* info)
65 {
66 deqp::Context* ctx = (deqp::Context*)info;
67
68 const GLchar* source_str = "Unknown";
69 const GLchar* type_str = "Unknown";
70 const GLchar* severity_str = "Unknown";
71
72 switch (source)
73 {
74 case GL_DEBUG_SOURCE_API:
75 source_str = "API";
76 break;
77 case GL_DEBUG_SOURCE_APPLICATION:
78 source_str = "APP";
79 break;
80 case GL_DEBUG_SOURCE_OTHER:
81 source_str = "OTR";
82 break;
83 case GL_DEBUG_SOURCE_SHADER_COMPILER:
84 source_str = "COM";
85 break;
86 case GL_DEBUG_SOURCE_THIRD_PARTY:
87 source_str = "3RD";
88 break;
89 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
90 source_str = "WS";
91 break;
92 default:
93 break;
94 }
95
96 switch (type)
97 {
98 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
99 type_str = "DEPRECATED_BEHAVIOR";
100 break;
101 case GL_DEBUG_TYPE_ERROR:
102 type_str = "ERROR";
103 break;
104 case GL_DEBUG_TYPE_MARKER:
105 type_str = "MARKER";
106 break;
107 case GL_DEBUG_TYPE_OTHER:
108 type_str = "OTHER";
109 break;
110 case GL_DEBUG_TYPE_PERFORMANCE:
111 type_str = "PERFORMANCE";
112 break;
113 case GL_DEBUG_TYPE_POP_GROUP:
114 type_str = "POP_GROUP";
115 break;
116 case GL_DEBUG_TYPE_PORTABILITY:
117 type_str = "PORTABILITY";
118 break;
119 case GL_DEBUG_TYPE_PUSH_GROUP:
120 type_str = "PUSH_GROUP";
121 break;
122 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
123 type_str = "UNDEFINED_BEHAVIOR";
124 break;
125 default:
126 break;
127 }
128
129 switch (severity)
130 {
131 case GL_DEBUG_SEVERITY_HIGH:
132 severity_str = "H";
133 break;
134 case GL_DEBUG_SEVERITY_LOW:
135 severity_str = "L";
136 break;
137 case GL_DEBUG_SEVERITY_MEDIUM:
138 severity_str = "M";
139 break;
140 case GL_DEBUG_SEVERITY_NOTIFICATION:
141 severity_str = "N";
142 break;
143 default:
144 break;
145 }
146
147 ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|"
148 << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id
149 << ": " << message << tcu::TestLog::EndMessage;
150 }
151
152 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
153
154 /** Represents buffer instance
155 * Provides basic buffer functionality
156 **/
157 class Buffer
158 {
159 public:
160 /* Public methods */
161 /* Ctr & Dtr */
162 Buffer();
163 ~Buffer();
164
165 /* Init & Release */
166 void Init(deqp::Context& context);
167
168 void InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
169 const glw::GLvoid* data);
170
171 void Release();
172
173 /* Functionality */
174 void Bind() const;
175 void BindBase(glw::GLuint index) const;
176
177 /* Public static routines */
178 /* Functionality */
179 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
180
181 static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index);
182
183 static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
184 const glw::GLvoid* data);
185
186 static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
187
188 static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
189 glw::GLvoid* data);
190
191 /* Public fields */
192 glw::GLuint m_id;
193
194 /* Public constants */
195 static const glw::GLuint m_invalid_id;
196
197 private:
198 /* Private enums */
199
200 /* Private fields */
201 deqp::Context* m_context;
202 glw::GLenum m_target;
203 };
204
205 /** Represents framebuffer
206 * Provides basic functionality
207 **/
208 class Framebuffer
209 {
210 public:
211 /* Public methods */
212 /* Ctr & Dtr */
213 Framebuffer(deqp::Context& context);
214 ~Framebuffer();
215
216 /* Init & Release */
217 void Release();
218
219 /* Public static routines */
220 static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
221 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height);
222
223 static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id);
224
225 static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
226
227 /* Public fields */
228 glw::GLuint m_id;
229
230 /* Public constants */
231 static const glw::GLuint m_invalid_id;
232
233 private:
234 /* Private fields */
235 deqp::Context& m_context;
236 };
237
238 /** Represents shader instance.
239 * Provides basic functionality for shaders.
240 **/
241 class Shader
242 {
243 public:
244 /* Public methods */
245 /* Ctr & Dtr */
246 Shader(deqp::Context& context);
247 ~Shader();
248
249 /* Init & Realese */
250 void Init(glw::GLenum stage, const std::string& source);
251 void Release();
252
253 /* Public static routines */
254 /* Functionality */
255 static void Compile(const glw::Functions& gl, glw::GLuint id);
256
257 static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id);
258
259 static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source);
260
261 /* Public fields */
262 glw::GLuint m_id;
263
264 /* Public constants */
265 static const glw::GLuint m_invalid_id;
266
267 private:
268 /* Private fields */
269 deqp::Context& m_context;
270 };
271
272 /** Represents program instance.
273 * Provides basic functionality
274 **/
275 class Program
276 {
277 public:
278 /* Public methods */
279 /* Ctr & Dtr */
280 Program(deqp::Context& context);
281 ~Program();
282
283 /* Init & Release */
284 void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader,
285 const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader,
286 const std::string& vertex_shader);
287 void Release();
288
289 /* Functionality */
290 void Use() const;
291
292 /* Public static routines */
293 /* Functionality */
294 static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id);
295
296 static void Create(const glw::Functions& gl, glw::GLuint& out_id);
297
298 static void Link(const glw::Functions& gl, glw::GLuint id);
299
300 static void Use(const glw::Functions& gl, glw::GLuint id);
301
302 /* Public fields */
303 glw::GLuint m_id;
304
305 Shader m_compute;
306 Shader m_fragment;
307 Shader m_geometry;
308 Shader m_tess_ctrl;
309 Shader m_tess_eval;
310 Shader m_vertex;
311
312 /* Public constants */
313 static const glw::GLuint m_invalid_id;
314
315 private:
316 /* Private fields */
317 deqp::Context& m_context;
318 };
319
320 /** Represents texture instance
321 **/
322 class Texture
323 {
324 public:
325 /* Public methods */
326 /* Ctr & Dtr */
327 Texture();
328 ~Texture();
329
330 /* Init & Release */
331 void Init(deqp::Context& context);
332
333 void InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id);
334
335 void InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
336 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error = false);
337
338 void Release();
339
340 /* Public static routines */
341 /* Functionality */
342 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
343
344 static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
345 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
346 glw::GLsizei image_size, const glw::GLvoid* data);
347
348 static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
349
350 static void GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
351 glw::GLenum type, glw::GLvoid* out_data);
352
353 static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
354 glw::GLint* param);
355
356 static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
357 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
358 const glw::GLvoid* data);
359
360 static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
361 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error);
362
363 static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
364 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
365 glw::GLenum type, const glw::GLvoid* pixels);
366
367 /* Public fields */
368 glw::GLuint m_id;
369
370 /* Public constants */
371 static const glw::GLuint m_invalid_id;
372
373 private:
374 /* Private fields */
375 deqp::Context* m_context;
376 };
377
378 /* Buffer constants */
379 const GLuint Buffer::m_invalid_id = -1;
380
381 /** Constructor.
382 *
383 **/
Buffer()384 Buffer::Buffer() : m_id(m_invalid_id), m_context(0), m_target(GL_ARRAY_BUFFER)
385 {
386 }
387
388 /** Destructor
389 *
390 **/
~Buffer()391 Buffer::~Buffer()
392 {
393 Release();
394
395 m_context = 0;
396 }
397
398 /** Initialize buffer instance
399 *
400 * @param context CTS context.
401 **/
Init(deqp::Context & context)402 void Buffer::Init(deqp::Context& context)
403 {
404 Release();
405
406 m_context = &context;
407 }
408
409 /** Initialize buffer instance with some data
410 *
411 * @param context CTS context.
412 * @param target Buffer target
413 * @param usage Buffer usage enum
414 * @param size <size> parameter
415 * @param data <data> parameter
416 **/
InitData(deqp::Context & context,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)417 void Buffer::InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
418 const glw::GLvoid* data)
419 {
420 Init(context);
421
422 m_target = target;
423
424 const Functions& gl = m_context->getRenderContext().getFunctions();
425
426 Generate(gl, m_id);
427 Bind(gl, m_id, m_target);
428 Data(gl, m_target, usage, size, data);
429 }
430
431 /** Release buffer instance
432 *
433 **/
Release()434 void Buffer::Release()
435 {
436 if (m_invalid_id != m_id)
437 {
438 const Functions& gl = m_context->getRenderContext().getFunctions();
439
440 gl.deleteBuffers(1, &m_id);
441 m_id = m_invalid_id;
442 }
443 }
444
445 /** Binds buffer to its target
446 *
447 **/
Bind() const448 void Buffer::Bind() const
449 {
450 if (m_invalid_id == m_id)
451 {
452 return;
453 }
454
455 const Functions& gl = m_context->getRenderContext().getFunctions();
456
457 Bind(gl, m_id, m_target);
458 }
459
460 /** Binds indexed buffer
461 *
462 * @param index <index> parameter
463 **/
BindBase(glw::GLuint index) const464 void Buffer::BindBase(glw::GLuint index) const
465 {
466 if (m_invalid_id == m_id)
467 {
468 return;
469 }
470
471 const Functions& gl = m_context->getRenderContext().getFunctions();
472
473 BindBase(gl, m_id, m_target, index);
474 }
475
476 /** Bind buffer to given target
477 *
478 * @param gl GL functions
479 * @param id Id of buffer
480 * @param target Buffer target
481 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)482 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
483 {
484 gl.bindBuffer(target, id);
485 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
486 }
487
488 /** Binds indexed buffer
489 *
490 * @param gl GL functions
491 * @param id Id of buffer
492 * @param target Buffer target
493 * @param index <index> parameter
494 **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)495 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
496 {
497 gl.bindBufferBase(target, index, id);
498 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
499 }
500
501 /** Allocate memory for buffer and sends initial content
502 *
503 * @param gl GL functions
504 * @param target Buffer target
505 * @param usage Buffer usage enum
506 * @param size <size> parameter
507 * @param data <data> parameter
508 **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)509 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
510 const glw::GLvoid* data)
511 {
512 gl.bufferData(target, size, data, usage);
513 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
514 }
515
516 /** Generate buffer
517 *
518 * @param gl GL functions
519 * @param out_id Id of buffer
520 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)521 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
522 {
523 GLuint id = m_invalid_id;
524
525 gl.genBuffers(1, &id);
526 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
527
528 if (m_invalid_id == id)
529 {
530 TCU_FAIL("Got invalid id");
531 }
532
533 out_id = id;
534 }
535
536 /** Update range of buffer
537 *
538 * @param gl GL functions
539 * @param target Buffer target
540 * @param offset Offset in buffer
541 * @param size <size> parameter
542 * @param data <data> parameter
543 **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)544 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
545 glw::GLvoid* data)
546 {
547 gl.bufferSubData(target, offset, size, data);
548 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
549 }
550
551 /* Framebuffer constants */
552 const GLuint Framebuffer::m_invalid_id = -1;
553
554 /** Constructor.
555 *
556 * @param context CTS context.
557 **/
Framebuffer(deqp::Context & context)558 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
559 {
560 /* Nothing to done here */
561 }
562
563 /** Destructor
564 *
565 **/
~Framebuffer()566 Framebuffer::~Framebuffer()
567 {
568 Release();
569 }
570
571 /** Release texture instance
572 *
573 **/
Release()574 void Framebuffer::Release()
575 {
576 if (m_invalid_id != m_id)
577 {
578 const Functions& gl = m_context.getRenderContext().getFunctions();
579
580 gl.deleteFramebuffers(1, &m_id);
581 m_id = m_invalid_id;
582 }
583 }
584
585 /** Attach texture to specified attachment
586 *
587 * @param gl GL functions
588 * @param target Framebuffer target
589 * @param attachment Attachment
590 * @param texture_id Texture id
591 * @param level Level of mipmap
592 * @param width Texture width
593 * @param height Texture height
594 **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLint level,glw::GLuint width,glw::GLuint height)595 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
596 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
597 {
598 gl.framebufferTexture(target, attachment, texture_id, level);
599 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
600
601 gl.viewport(0 /* x */, 0 /* y */, width, height);
602 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
603 }
604
605 /** Binds framebuffer to DRAW_FRAMEBUFFER
606 *
607 * @param gl GL functions
608 * @param target Framebuffer target
609 * @param id ID of framebuffer
610 **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)611 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
612 {
613 gl.bindFramebuffer(target, id);
614 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
615 }
616
617 /** Generate framebuffer
618 *
619 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)620 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
621 {
622 GLuint id = m_invalid_id;
623
624 gl.genFramebuffers(1, &id);
625 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
626
627 if (m_invalid_id == id)
628 {
629 TCU_FAIL("Invalid id");
630 }
631
632 out_id = id;
633 }
634
635 /* Program constants */
636 const GLuint Program::m_invalid_id = 0;
637
638 /** Constructor.
639 *
640 * @param context CTS context.
641 **/
Program(deqp::Context & context)642 Program::Program(deqp::Context& context)
643 : m_id(m_invalid_id)
644 , m_compute(context)
645 , m_fragment(context)
646 , m_geometry(context)
647 , m_tess_ctrl(context)
648 , m_tess_eval(context)
649 , m_vertex(context)
650 , m_context(context)
651 {
652 /* Nothing to be done here */
653 }
654
655 /** Destructor
656 *
657 **/
~Program()658 Program::~Program()
659 {
660 Release();
661 }
662
663 /** Initialize program instance
664 *
665 * @param compute_shader Compute shader source code
666 * @param fragment_shader Fragment shader source code
667 * @param geometry_shader Geometry shader source code
668 * @param tesselation_control_shader Tesselation control shader source code
669 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
670 * @param vertex_shader Vertex shader source code
671 **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tesselation_control_shader,const std::string & tesselation_evaluation_shader,const std::string & vertex_shader)672 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
673 const std::string& geometry_shader, const std::string& tesselation_control_shader,
674 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
675 {
676 /* Delete previous program */
677 Release();
678
679 /* GL entry points */
680 const Functions& gl = m_context.getRenderContext().getFunctions();
681
682 /* Initialize shaders */
683 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
684 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
685 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
686 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
687 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
688 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
689
690 /* Create program, set up transform feedback and attach shaders */
691 Create(gl, m_id);
692 Attach(gl, m_id, m_compute.m_id);
693 Attach(gl, m_id, m_fragment.m_id);
694 Attach(gl, m_id, m_geometry.m_id);
695 Attach(gl, m_id, m_tess_ctrl.m_id);
696 Attach(gl, m_id, m_tess_eval.m_id);
697 Attach(gl, m_id, m_vertex.m_id);
698
699 /* Link program */
700 Link(gl, m_id);
701 }
702
703 /** Release program instance
704 *
705 **/
Release()706 void Program::Release()
707 {
708 const Functions& gl = m_context.getRenderContext().getFunctions();
709
710 if (m_invalid_id != m_id)
711 {
712 Use(gl, m_invalid_id);
713
714 gl.deleteProgram(m_id);
715 m_id = m_invalid_id;
716 }
717
718 m_compute.Release();
719 m_fragment.Release();
720 m_geometry.Release();
721 m_tess_ctrl.Release();
722 m_tess_eval.Release();
723 m_vertex.Release();
724 }
725
726 /** Set program as active
727 *
728 **/
Use() const729 void Program::Use() const
730 {
731 const Functions& gl = m_context.getRenderContext().getFunctions();
732
733 Use(gl, m_id);
734 }
735
736 /** Attach shader to program
737 *
738 * @param gl GL functions
739 * @param program_id Id of program
740 * @param shader_id Id of shader
741 **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)742 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
743 {
744 /* Sanity checks */
745 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
746 {
747 return;
748 }
749
750 gl.attachShader(program_id, shader_id);
751 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
752 }
753
754 /** Create program instance
755 *
756 * @param gl GL functions
757 * @param out_id Id of program
758 **/
Create(const glw::Functions & gl,glw::GLuint & out_id)759 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
760 {
761 const GLuint id = gl.createProgram();
762 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
763
764 if (m_invalid_id == id)
765 {
766 TCU_FAIL("Failed to create program");
767 }
768
769 out_id = id;
770 }
771
772 /** Link program
773 *
774 * @param gl GL functions
775 * @param id Id of program
776 **/
Link(const glw::Functions & gl,glw::GLuint id)777 void Program::Link(const glw::Functions& gl, glw::GLuint id)
778 {
779 GLint status = GL_FALSE;
780
781 gl.linkProgram(id);
782 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
783
784 /* Get link status */
785 gl.getProgramiv(id, GL_LINK_STATUS, &status);
786 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
787
788 /* Log link error */
789 if (GL_TRUE != status)
790 {
791 glw::GLint length = 0;
792 std::string message;
793
794 /* Get error log length */
795 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
796 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
797
798 message.resize(length, 0);
799
800 /* Get error log */
801 gl.getProgramInfoLog(id, length, 0, &message[0]);
802 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
803
804 TCU_FAIL(message.c_str());
805 }
806 }
807
808 /** Use program
809 *
810 * @param gl GL functions
811 * @param id Id of program
812 **/
Use(const glw::Functions & gl,glw::GLuint id)813 void Program::Use(const glw::Functions& gl, glw::GLuint id)
814 {
815 gl.useProgram(id);
816 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
817 }
818
819 /* Shader's constants */
820 const GLuint Shader::m_invalid_id = 0;
821
822 /** Constructor.
823 *
824 * @param context CTS context.
825 **/
Shader(deqp::Context & context)826 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
827 {
828 /* Nothing to be done here */
829 }
830
831 /** Destructor
832 *
833 **/
~Shader()834 Shader::~Shader()
835 {
836 Release();
837 }
838
839 /** Initialize shader instance
840 *
841 * @param stage Shader stage
842 * @param source Source code
843 **/
Init(glw::GLenum stage,const std::string & source)844 void Shader::Init(glw::GLenum stage, const std::string& source)
845 {
846 if (true == source.empty())
847 {
848 /* No source == no shader */
849 return;
850 }
851
852 /* Delete any previous shader */
853 Release();
854
855 /* Create, set source and compile */
856 const Functions& gl = m_context.getRenderContext().getFunctions();
857
858 Create(gl, stage, m_id);
859 Source(gl, m_id, source);
860
861 Compile(gl, m_id);
862 }
863
864 /** Release shader instance
865 *
866 **/
Release()867 void Shader::Release()
868 {
869 if (m_invalid_id != m_id)
870 {
871 const Functions& gl = m_context.getRenderContext().getFunctions();
872
873 gl.deleteShader(m_id);
874 m_id = m_invalid_id;
875 }
876 }
877
878 /** Compile shader
879 *
880 * @param gl GL functions
881 * @param id Shader id
882 **/
Compile(const glw::Functions & gl,glw::GLuint id)883 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
884 {
885 GLint status = GL_FALSE;
886
887 /* Compile */
888 gl.compileShader(id);
889 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
890
891 /* Get compilation status */
892 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
893 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
894
895 /* Log compilation error */
896 if (GL_TRUE != status)
897 {
898 glw::GLint length = 0;
899 std::string message;
900
901 /* Error log length */
902 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
903 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
904
905 /* Prepare storage */
906 message.resize(length, 0);
907
908 /* Get error log */
909 gl.getShaderInfoLog(id, length, 0, &message[0]);
910 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
911
912 TCU_FAIL(message.c_str());
913 }
914 }
915
916 /** Create shader
917 *
918 * @param gl GL functions
919 * @param stage Shader stage
920 * @param out_id Shader id
921 **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)922 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
923 {
924 const GLuint id = gl.createShader(stage);
925 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
926
927 if (m_invalid_id == id)
928 {
929 TCU_FAIL("Failed to create shader");
930 }
931
932 out_id = id;
933 }
934
935 /** Set shader's source code
936 *
937 * @param gl GL functions
938 * @param id Shader id
939 * @param source Shader source code
940 **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)941 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
942 {
943 const GLchar* code = source.c_str();
944
945 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
946 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
947 }
948
949 /* Texture static fields */
950 const GLuint Texture::m_invalid_id = -1;
951
952 /** Constructor.
953 *
954 **/
Texture()955 Texture::Texture() : m_id(m_invalid_id), m_context(0)
956 {
957 /* Nothing to done here */
958 }
959
960 /** Destructor
961 *
962 **/
~Texture()963 Texture::~Texture()
964 {
965 Release();
966 }
967
968 /** Initialize texture instance
969 *
970 * @param context Test context
971 **/
Init(deqp::Context & context)972 void Texture::Init(deqp::Context& context)
973 {
974 Release();
975
976 m_context = &context;
977 }
978
979 /** Initialize texture instance as texture buffer
980 *
981 * @param context Test context
982 * @param internal_format Internal format of texture
983 * @param buufer_id ID of buffer that will be used as storage
984 **/
InitBuffer(deqp::Context & context,glw::GLenum internal_format,glw::GLuint buffer_id)985 void Texture::InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id)
986 {
987 Init(context);
988
989 const Functions& gl = m_context->getRenderContext().getFunctions();
990
991 Generate(gl, m_id);
992 Bind(gl, m_id, GL_TEXTURE_BUFFER);
993 Buffer::Bind(gl, buffer_id, GL_TEXTURE_BUFFER);
994
995 gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id);
996 GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
997 }
998
999 /** Initialize texture instance with storage
1000 *
1001 * @param context Test context
1002 * @param target Texture target
1003 * @param levels Number of levels
1004 * @param internal_format Internal format of texture
1005 * @param width Width of texture
1006 * @param height Height of texture
1007 * @param depth Depth of texture
1008 **/
InitStorage(deqp::Context & context,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,bool allow_error)1009 void Texture::InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1010 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1011 {
1012 Init(context);
1013
1014 const Functions& gl = m_context->getRenderContext().getFunctions();
1015
1016 Generate(gl, m_id);
1017 Bind(gl, m_id, target);
1018 Storage(gl, target, levels, internal_format, width, height, depth, allow_error);
1019 }
1020
1021 /** Release texture instance
1022 *
1023 * @param context CTS context.
1024 **/
Release()1025 void Texture::Release()
1026 {
1027 if (m_invalid_id != m_id)
1028 {
1029 const Functions& gl = m_context->getRenderContext().getFunctions();
1030
1031 gl.deleteTextures(1, &m_id);
1032 m_id = m_invalid_id;
1033 }
1034 }
1035
1036 /** Bind texture to target
1037 *
1038 * @param gl GL functions
1039 * @param id Id of texture
1040 * @param tex_type Type of texture
1041 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1042 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
1043 {
1044 gl.bindTexture(target, id);
1045 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1046 }
1047
1048 /** Set contents of compressed texture
1049 *
1050 * @param gl GL functions
1051 * @param target Texture target
1052 * @param level Mipmap level
1053 * @param internal_format Format of data
1054 * @param width Width of texture
1055 * @param height Height of texture
1056 * @param depth Depth of texture
1057 * @param image_size Size of data
1058 * @param data Buffer with image data
1059 **/
CompressedImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLsizei image_size,const glw::GLvoid * data)1060 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
1061 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1062 glw::GLsizei image_size, const glw::GLvoid* data)
1063 {
1064 switch (target)
1065 {
1066 case GL_TEXTURE_1D:
1067 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1068 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1069 break;
1070 case GL_TEXTURE_1D_ARRAY:
1071 case GL_TEXTURE_2D:
1072 case GL_TEXTURE_RECTANGLE:
1073 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1074 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1075 break;
1076 case GL_TEXTURE_CUBE_MAP:
1077 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1078 image_size, data);
1079 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1080 image_size, data);
1081 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1082 image_size, data);
1083 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1084 image_size, data);
1085 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1086 image_size, data);
1087 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1088 image_size, data);
1089 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1090 break;
1091 case GL_TEXTURE_3D:
1092 case GL_TEXTURE_2D_ARRAY:
1093 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1094 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1095 break;
1096 default:
1097 TCU_FAIL("Invliad enum");
1098 }
1099 }
1100
1101 /** Generate texture instance
1102 *
1103 * @param gl GL functions
1104 * @param out_id Id of texture
1105 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1106 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1107 {
1108 GLuint id = m_invalid_id;
1109
1110 gl.genTextures(1, &id);
1111 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1112
1113 if (m_invalid_id == id)
1114 {
1115 TCU_FAIL("Invalid id");
1116 }
1117
1118 out_id = id;
1119 }
1120
1121 /** Get texture data
1122 *
1123 * @param gl GL functions
1124 * @param target Texture target
1125 * @param format Format of data
1126 * @param type Type of data
1127 * @param out_data Buffer for data
1128 **/
GetData(const glw::Functions & gl,glw::GLint level,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1129 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
1130 glw::GLenum type, glw::GLvoid* out_data)
1131 {
1132 gl.getTexImage(target, level, format, type, out_data);
1133 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1134 }
1135
1136 /** Generate texture instance
1137 *
1138 * @param gl GL functions
1139 * @param target Texture target
1140 * @param level Mipmap level
1141 * @param pname Parameter to query
1142 * @param param Result of query
1143 **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1144 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1145 glw::GLint* param)
1146 {
1147 gl.getTexLevelParameteriv(target, level, pname, param);
1148 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1149 }
1150
1151 /** Set contents of texture
1152 *
1153 * @param gl GL functions
1154 * @param target Texture target
1155 * @param level Mipmap level
1156 * @param internal_format Format of data
1157 * @param width Width of texture
1158 * @param height Height of texture
1159 * @param depth Depth of texture
1160 * @param format Format of data
1161 * @param type Type of data
1162 * @param data Buffer with image data
1163 **/
Image(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * data)1164 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1165 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1166 const glw::GLvoid* data)
1167 {
1168 switch (target)
1169 {
1170 case GL_TEXTURE_1D:
1171 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1172 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1173 break;
1174 case GL_TEXTURE_1D_ARRAY:
1175 case GL_TEXTURE_2D:
1176 case GL_TEXTURE_RECTANGLE:
1177 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1178 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1179 break;
1180 case GL_TEXTURE_CUBE_MAP:
1181 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1182 type, data);
1183 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1184 type, data);
1185 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1186 type, data);
1187 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1188 type, data);
1189 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1190 type, data);
1191 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1192 type, data);
1193 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1194 break;
1195 case GL_TEXTURE_3D:
1196 case GL_TEXTURE_2D_ARRAY:
1197 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1198 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1199 break;
1200 default:
1201 TCU_FAIL("Invliad enum");
1202 }
1203 }
1204
1205 /** Allocate storage for texture
1206 *
1207 * @param gl GL functions
1208 * @param target Texture target
1209 * @param levels Number of levels
1210 * @param internal_format Internal format of texture
1211 * @param width Width of texture
1212 * @param height Height of texture
1213 * @param depth Depth of texture
1214 **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,bool allow_error)1215 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1216 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1217 {
1218 switch (target)
1219 {
1220 case GL_TEXTURE_1D:
1221 gl.texStorage1D(target, levels, internal_format, width);
1222 if (!allow_error)
1223 {
1224 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1225 }
1226 break;
1227 case GL_TEXTURE_1D_ARRAY:
1228 case GL_TEXTURE_2D:
1229 case GL_TEXTURE_RECTANGLE:
1230 case GL_TEXTURE_CUBE_MAP:
1231 gl.texStorage2D(target, levels, internal_format, width, height);
1232 if (!allow_error)
1233 {
1234 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1235 }
1236 break;
1237 case GL_TEXTURE_2D_MULTISAMPLE:
1238 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
1239 if (!allow_error)
1240 {
1241 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
1242 }
1243 break;
1244 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1245 gl.texStorage3DMultisample(target, levels, internal_format, width, height, depth, GL_FALSE);
1246 if (!allow_error)
1247 {
1248 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3DMultisample");
1249 }
1250 break;
1251 case GL_TEXTURE_3D:
1252 case GL_TEXTURE_2D_ARRAY:
1253 case GL_TEXTURE_CUBE_MAP_ARRAY:
1254 gl.texStorage3D(target, levels, internal_format, width, height, depth);
1255 if (!allow_error)
1256 {
1257 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1258 }
1259 break;
1260 default:
1261 TCU_FAIL("Invliad enum");
1262 }
1263 }
1264
1265 /** Set contents of texture
1266 *
1267 * @param gl GL functions
1268 * @param target Texture target
1269 * @param level Mipmap level
1270 * @param x X offset
1271 * @param y Y offset
1272 * @param z Z offset
1273 * @param width Width of texture
1274 * @param height Height of texture
1275 * @param depth Depth of texture
1276 * @param format Format of data
1277 * @param type Type of data
1278 * @param pixels Buffer with image data
1279 **/
SubImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLint x,glw::GLint y,glw::GLint z,glw::GLsizei width,glw::GLsizei height,glw::GLsizei depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * pixels)1280 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1281 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1282 glw::GLenum type, const glw::GLvoid* pixels)
1283 {
1284 switch (target)
1285 {
1286 case GL_TEXTURE_1D:
1287 gl.texSubImage1D(target, level, x, width, format, type, pixels);
1288 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1289 break;
1290 case GL_TEXTURE_1D_ARRAY:
1291 case GL_TEXTURE_2D:
1292 case GL_TEXTURE_RECTANGLE:
1293 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1294 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1295 break;
1296 case GL_TEXTURE_CUBE_MAP:
1297 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1298 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1299 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1300 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1301 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1302 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1303 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1304 break;
1305 case GL_TEXTURE_3D:
1306 case GL_TEXTURE_2D_ARRAY:
1307 case GL_TEXTURE_CUBE_MAP_ARRAY:
1308 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1309 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1310 break;
1311 default:
1312 TCU_FAIL("Invliad enum");
1313 }
1314 }
1315
1316 /* Gather info about buffer target */
1317 struct bufferTargetInfo
1318 {
1319 GLenum m_target;
1320 GLenum m_pname_alignment;
1321 GLenum m_pname_binding;
1322 GLenum m_pname_max;
1323 GLenum m_pname_max_size;
1324 };
1325
1326 /* Gather info about texture target */
1327 struct textureTargetInfo
1328 {
1329 GLenum m_target;
1330 GLenum m_pname_binding;
1331 const GLchar* m_name;
1332 };
1333
1334 /* Collects information about buffers */
1335 static const bufferTargetInfo s_buffer_infos[] = {
1336 { GL_ATOMIC_COUNTER_BUFFER, 0, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
1337 GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE },
1338 {
1339 GL_TRANSFORM_FEEDBACK_BUFFER, 0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS,
1340 GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
1341 },
1342 { GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1343 GL_MAX_UNIFORM_BLOCK_SIZE },
1344 { GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, GL_SHADER_STORAGE_BUFFER_BINDING,
1345 GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE },
1346 };
1347
1348 static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]);
1349
1350 /* Collects information about textures */
1351 static const textureTargetInfo s_texture_infos[] = {
1352 { GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1D" },
1353 { GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1D_ARRAY" },
1354 { GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2D" },
1355 { GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2D_ARRAY" },
1356 { GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, "3D" },
1357 { GL_TEXTURE_BUFFER, GL_TEXTURE_BINDING_BUFFER, "BUFFER" },
1358 { GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, "CUBE" },
1359 { GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, "CUBE_ARRAY" },
1360 { GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE, "RECTANGLE" },
1361 { GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BINDING_2D_MULTISAMPLE, "2D_MS" },
1362 { GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, "2D_MS_ARRAY" }
1363 };
1364
1365 static const size_t s_n_texture_tragets = sizeof(s_texture_infos) / sizeof(s_texture_infos[0]);
1366
1367 /** Macro, verifies generated error, logs error message and throws failure
1368 *
1369 * @param expected_error Expected error value
1370 * @param error_message Message logged if generated error is not the expected one
1371 **/
1372 #define CHECK_ERROR(expected_error, error_message) \
1373 do { \
1374 GLenum generated_error = gl.getError(); \
1375 \
1376 if (expected_error != generated_error) \
1377 { \
1378 m_context.getTestContext().getLog() \
1379 << tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__ \
1380 << ". Got wrong error: " << glu::getErrorStr(generated_error) \
1381 << ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
1382 << tcu::TestLog::EndMessage; \
1383 TCU_FAIL("Invalid error generated"); \
1384 } \
1385 } while (0)
1386
1387 /* Prototypes */
1388 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string);
1389
1390 /** Checks binding
1391 *
1392 * @param context Test contex
1393 * @param pname Pname of binding
1394 * @param index Index of binding
1395 * @param target_name Name of target
1396 * @param expected_value Expected value of binding
1397 **/
checkBinding(deqp::Context & context,GLenum pname,GLuint index,const std::string & target_name,GLint expected_value)1398 void checkBinding(deqp::Context& context, GLenum pname, GLuint index, const std::string& target_name,
1399 GLint expected_value)
1400 {
1401 const Functions& gl = context.getRenderContext().getFunctions();
1402
1403 GLint binding = -1;
1404
1405 gl.getIntegeri_v(pname, index, &binding);
1406 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1407
1408 if (binding != expected_value)
1409 {
1410 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1411 << ", expected: " << expected_value << ". Target: " << target_name
1412 << " at index: " << index << tcu::TestLog::EndMessage;
1413 TCU_FAIL("Invalid binding");
1414 }
1415 }
1416
1417 /** Checks bindings for given texture unit
1418 *
1419 * @param context Test contex
1420 * @param pname Binding pname of <expected_value>
1421 * @param index Index of texture unit
1422 * @param expected_value Expected value of binding at <pname> target
1423 **/
checkTextureBinding(deqp::Context & context,GLenum pname,GLuint index,GLint expected_value)1424 void checkTextureBinding(deqp::Context& context, GLenum pname, GLuint index, GLint expected_value)
1425 {
1426 const Functions& gl = context.getRenderContext().getFunctions();
1427
1428 for (size_t i = 0; i < s_n_texture_tragets; ++i)
1429 {
1430 const GLenum pname_binding = s_texture_infos[i].m_pname_binding;
1431 const GLchar* target_name = s_texture_infos[i].m_name;
1432
1433 GLint binding = -1;
1434 GLint value = 0;
1435
1436 gl.getIntegeri_v(pname_binding, index, &binding);
1437 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1438
1439 if (pname_binding == pname)
1440 {
1441 value = (GLint)expected_value;
1442 }
1443
1444 if (binding != value)
1445 {
1446 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1447 << ", expected: " << expected_value << ". Target: " << target_name
1448 << " at index: " << index << tcu::TestLog::EndMessage;
1449 TCU_FAIL("Invalid binding");
1450 }
1451 }
1452 }
1453
1454 /** Checks binding
1455 *
1456 * @param context Test context
1457 * @param index Index of binding
1458 * @param expected_value Expected value of binding
1459 **/
checkVertexAttribBinding(deqp::Context & context,GLuint index,GLint expected_value)1460 void checkVertexAttribBinding(deqp::Context& context, GLuint index, GLint expected_value)
1461 {
1462 const Functions& gl = context.getRenderContext().getFunctions();
1463
1464 GLint binding = -1;
1465
1466 gl.getVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding);
1467 GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1468
1469 if (binding != expected_value)
1470 {
1471 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1472 << ", expected: " << expected_value << ". Target: Vertex attribute"
1473 << " at index: " << index << tcu::TestLog::EndMessage;
1474 TCU_FAIL("Invalid binding");
1475 }
1476 }
1477
1478 /** Fills MS texture with specified value
1479 *
1480 * @param context Test context
1481 * @param texture_id Index of binding
1482 * @param value Value for texture
1483 * @param is_array Selects if array target should be used
1484 **/
fillMSTexture(deqp::Context & context,GLuint texture_id,GLuint value,bool is_array)1485 void fillMSTexture(deqp::Context& context, GLuint texture_id, GLuint value, bool is_array)
1486 {
1487 /* */
1488 static const GLchar* cs = "#version 430 core\n"
1489 "\n"
1490 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1491 "\n"
1492 "layout (location = 0) writeonly uniform IMAGE uni_image;\n"
1493 "\n"
1494 "layout (location = 1) uniform uint uni_value;\n"
1495 "\n"
1496 "void main()\n"
1497 "{\n"
1498 " const POINT;\n"
1499 "\n"
1500 " imageStore(uni_image, point, 0, uvec4(uni_value, 0, 0, 0));\n"
1501 "}\n"
1502 "\n";
1503
1504 static const GLchar* array_image = "uimage2DMSArray";
1505 static const GLchar* array_point = "ivec3 point = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, 0)";
1506 static const GLchar* regular_image = "uimage2DMS";
1507 static const GLchar* regular_point = "ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
1508
1509 /* */
1510 const Functions& gl = context.getRenderContext().getFunctions();
1511 const GLchar* image = (true == is_array) ? array_image : regular_image;
1512 const GLchar* point = (true == is_array) ? array_point : regular_point;
1513 size_t position = 0;
1514 std::string source = cs;
1515
1516 /* */
1517 replaceToken("IMAGE", position, image, source);
1518 replaceToken("POINT", position, point, source);
1519
1520 /* */
1521 Program program(context);
1522 program.Init(source.c_str(), "", "", "", "", "");
1523 program.Use();
1524
1525 /* */
1526 if (true == is_array)
1527 {
1528 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_TRUE /* layered */, 0 /* layer */,
1529 GL_WRITE_ONLY, GL_R32UI);
1530 }
1531 else
1532 {
1533 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1534 GL_WRITE_ONLY, GL_R32UI);
1535 }
1536
1537 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1538
1539 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1540 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1541
1542 gl.uniform1ui(1 /* location */, value /* uni_value */);
1543 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1ui");
1544
1545 /* */
1546 gl.dispatchCompute(6, 6, 1);
1547 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1548 }
1549
1550 /** Get texture binding pname for given index
1551 *
1552 * @param index Index of texture target
1553 *
1554 * @return Pname
1555 **/
getBinding(GLuint index)1556 GLenum getBinding(GLuint index)
1557 {
1558 if (index < s_n_texture_tragets)
1559 {
1560 return s_texture_infos[index].m_pname_binding;
1561 }
1562 else
1563 {
1564 return GL_TEXTURE_BINDING_2D;
1565 }
1566 }
1567
1568 /** Get texture target for given index
1569 *
1570 * @param index Index of texture target
1571 *
1572 * @return Target
1573 **/
getTarget(GLuint index)1574 GLenum getTarget(GLuint index)
1575 {
1576 if (index < s_n_texture_tragets)
1577 {
1578 return s_texture_infos[index].m_target;
1579 }
1580 else
1581 {
1582 return GL_TEXTURE_2D;
1583 }
1584 }
1585
1586 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1587 *
1588 * @param token Token string
1589 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1590 * @param text String that will be used as replacement for <token>
1591 * @param string String to work on
1592 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1593 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1594 {
1595 const size_t text_length = strlen(text);
1596 const size_t token_length = strlen(token);
1597 const size_t token_position = string.find(token, search_position);
1598
1599 string.replace(token_position, token_length, text, text_length);
1600
1601 search_position = token_position + text_length;
1602 }
1603
1604 /** Constructor
1605 *
1606 * @param context Test context
1607 **/
ErrorsBindBuffersTest(deqp::Context & context)1608 ErrorsBindBuffersTest::ErrorsBindBuffersTest(deqp::Context& context)
1609 : TestCase(context, "errors_bind_buffers", "Verifies that proper errors are generated by buffer binding routines")
1610 {
1611 /* Nothing to be done */
1612 }
1613
1614 /** Execute test
1615 *
1616 * @return tcu::TestNode::STOP
1617 **/
iterate()1618 tcu::TestNode::IterateResult ErrorsBindBuffersTest::iterate()
1619 {
1620 const Functions& gl = m_context.getRenderContext().getFunctions();
1621
1622 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1623 gl.debugMessageCallback(debug_proc, &m_context);
1624 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1625 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1626
1627 /* - INVALID_ENUM when <target> is not valid; */
1628 {
1629 static const GLintptr buffer_size = 16;
1630 static const GLsizei count = 1;
1631 static const GLuint first = 0;
1632 static const GLintptr offset = 4;
1633 static const GLintptr size = buffer_size - offset;
1634
1635 Buffer buffer;
1636
1637 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1638
1639 gl.bindBuffersBase(GL_ARRAY_BUFFER, first, count, &buffer.m_id);
1640 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersBase with invalid <target>");
1641
1642 gl.bindBuffersRange(GL_ARRAY_BUFFER, first, count, &buffer.m_id, &offset, &size);
1643 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersRange with invalid <target>");
1644 }
1645
1646 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
1647 {
1648 static const GLsizei n_buffers = 4;
1649
1650 const GLenum pname_alignment = s_buffer_infos[i].m_pname_alignment;
1651 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
1652 const GLenum target = s_buffer_infos[i].m_target;
1653 const std::string& target_name = glu::getBufferTargetStr(target).toString();
1654
1655 GLintptr buffer_size = 16;
1656 GLsizei count = n_buffers;
1657 GLuint first = 0;
1658 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1659 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */
1660 GLint offset_alignment = 1;
1661 GLint max_buffers = 0;
1662 GLintptr size = buffer_size - offset;
1663 size_t validated_index = n_buffers - 1;
1664
1665 /* Get alignment */
1666 if (0 != pname_alignment)
1667 {
1668 gl.getIntegerv(pname_alignment, &offset_alignment);
1669 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1670
1671 buffer_size += offset_alignment;
1672 offset = offset_alignment;
1673 size = buffer_size - offset;
1674 }
1675
1676 /* Get max */
1677 gl.getIntegerv(pname_max, &max_buffers);
1678 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1679
1680 /* Select count so <first + count> does not exceed max.
1681 * Validated index shall be in the specified range.
1682 */
1683 if (n_buffers > max_buffers)
1684 {
1685 count = max_buffers;
1686 validated_index = max_buffers - 1;
1687 }
1688
1689 /* Storage */
1690 Buffer buffer[n_buffers];
1691 GLuint buffer_ids[n_buffers];
1692 GLintptr offsets[n_buffers];
1693 GLintptr sizes[n_buffers];
1694
1695 /* Prepare buffers */
1696 for (size_t j = 0; j < n_buffers; ++j)
1697 {
1698 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1699
1700 buffer_ids[j] = buffer[j].m_id;
1701 offsets[j] = offset;
1702 sizes[j] = size;
1703 }
1704
1705 /* - INVALID_OPERATION when <first> + <count> is greater than allowed limit; */
1706 {
1707 GLsizei t_count = n_buffers;
1708 GLuint t_first = 0;
1709
1710 /* Select first so <first + count> exceeds max, avoid negative first */
1711 if (n_buffers <= max_buffers)
1712 {
1713 t_first = max_buffers - n_buffers + 1;
1714 }
1715 else
1716 {
1717 t_count = max_buffers + 1;
1718 /* first = 0; */
1719 }
1720
1721 /* Test */
1722 gl.bindBuffersBase(target, t_first, t_count, buffer_ids);
1723 CHECK_ERROR(GL_INVALID_OPERATION,
1724 "BindBuffersBase with invalid <first> + <count>, target: " << target_name);
1725
1726 gl.bindBuffersRange(target, t_first, t_count, buffer_ids, offsets, sizes);
1727 CHECK_ERROR(GL_INVALID_OPERATION,
1728 "BindBuffersRange with invalid <first> + <count>, target: " << target_name);
1729 }
1730
1731 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1732 * existing buffer;
1733 */
1734 {
1735 GLuint t_buffer_ids[n_buffers];
1736
1737 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
1738
1739 /* Find invalid id */
1740 while (1)
1741 {
1742 if (GL_TRUE != gl.isBuffer(invalid_id))
1743 {
1744 break;
1745 }
1746
1747 invalid_id += 1;
1748 }
1749
1750 /* Invalidate the entry */
1751 t_buffer_ids[validated_index] = invalid_id;
1752
1753 /* Test */
1754 gl.bindBuffersBase(target, first, count, t_buffer_ids);
1755 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersBase with invalid buffer id, target: " << target_name);
1756
1757 gl.bindBuffersRange(target, first, count, t_buffer_ids, offsets, sizes);
1758 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id, target: " << target_name);
1759 }
1760
1761 /* - INVALID_VALUE if any value in <offsets> is less than zero; */
1762 {
1763 GLintptr t_offsets[n_buffers];
1764 GLintptr t_sizes[n_buffers];
1765
1766 memcpy(t_offsets, offsets, sizeof(offsets));
1767 memcpy(t_sizes, sizes, sizeof(sizes));
1768
1769 /* Invalidate the entry */
1770 t_offsets[validated_index] = -1;
1771 t_sizes[validated_index] = -1;
1772
1773 /* Test */
1774 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1775 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative offset, target: " << target_name);
1776
1777 /* Test */
1778 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1779 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative size, target: " << target_name);
1780 }
1781
1782 /* - INVALID_VALUE if any pair of <offsets> and <sizes> exceeds limits. */
1783 {
1784 GLintptr t_offsets[n_buffers];
1785 GLintptr t_sizes[n_buffers];
1786
1787 memcpy(t_offsets, offsets, sizeof(offsets));
1788 memcpy(t_sizes, sizes, sizeof(sizes));
1789
1790 /* Invalidate the entry */
1791 t_offsets[validated_index] -= 1; /* Not aligned by required value */
1792 t_sizes[validated_index] = size - 1; /* Not aligned by required value */
1793
1794 /* Test */
1795 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1796 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <offset>, target: " << target_name);
1797
1798 /* Test */
1799 if (GL_TRANSFORM_FEEDBACK_BUFFER == target)
1800 {
1801 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1802 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <size>, target: " << target_name);
1803 }
1804 }
1805 }
1806
1807 /* Set result */
1808 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1809
1810 /* Done */
1811 return tcu::TestNode::STOP;
1812 }
1813
1814 /** Constructor
1815 *
1816 * @param context Test context
1817 **/
ErrorsBindTexturesTest(deqp::Context & context)1818 ErrorsBindTexturesTest::ErrorsBindTexturesTest(deqp::Context& context)
1819 : TestCase(context, "errors_bind_textures", "Verifies that proper errors are generated by texture binding routines")
1820 {
1821 /* Nothing to be done */
1822 }
1823
1824 /** Execute test
1825 *
1826 * @return tcu::TestNode::STOP
1827 **/
iterate()1828 tcu::TestNode::IterateResult ErrorsBindTexturesTest::iterate()
1829 {
1830 static const GLuint depth = 8;
1831 static const GLuint height = 8;
1832 static const GLsizei n_textures = 4;
1833 static const GLuint width = 8;
1834
1835 const Functions& gl = m_context.getRenderContext().getFunctions();
1836
1837 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1838 gl.debugMessageCallback(debug_proc, &m_context);
1839 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1840 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1841
1842 GLsizei count = n_textures;
1843 GLuint first = 0;
1844 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1845 GLint max_textures = 0;
1846 size_t validated_index = n_textures - 1;
1847
1848 /* Get max */
1849 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
1850 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1851
1852 /* Select count so <first + count> does not exceed max.
1853 * Validated index shall be in the specified range.
1854 */
1855 if (n_textures > max_textures)
1856 {
1857 count = max_textures;
1858 validated_index = max_textures - 1;
1859 }
1860
1861 /* Storage */
1862 Texture texture[n_textures];
1863 GLuint texture_ids[n_textures];
1864
1865 /* Prepare textures */
1866 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, depth);
1867 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1868 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1869 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, width, height, depth);
1870
1871 for (size_t i = 0; i < n_textures; ++i)
1872 {
1873 texture_ids[i] = texture[i].m_id;
1874 }
1875
1876 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
1877 {
1878 GLsizei t_count = n_textures;
1879 GLuint t_first = 0;
1880
1881 /* Select first so <first + count> exceeds max, avoid negative first */
1882 if (n_textures <= max_textures)
1883 {
1884 t_first = max_textures - n_textures + 1;
1885 }
1886 else
1887 {
1888 t_count = max_textures + 1;
1889 /* first = 0; */
1890 }
1891
1892 /* Test */
1893 gl.bindTextures(t_first, t_count, texture_ids);
1894 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid <first> + <count>");
1895 }
1896
1897 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1898 * existing buffer;
1899 */
1900 {
1901 GLuint t_texture_ids[n_textures];
1902
1903 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
1904
1905 /* Find invalid id */
1906 while (1)
1907 {
1908 if (GL_TRUE != gl.isTexture(invalid_id))
1909 {
1910 break;
1911 }
1912
1913 invalid_id += 1;
1914 }
1915
1916 /* Invalidate the entry */
1917 t_texture_ids[validated_index] = invalid_id;
1918
1919 /* Test */
1920 gl.bindTextures(first, count, t_texture_ids);
1921 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
1922 }
1923
1924 /* Set result */
1925 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1926
1927 /* Done */
1928 return tcu::TestNode::STOP;
1929 }
1930
1931 /** Constructor
1932 *
1933 * @param context Test context
1934 **/
ErrorsBindSamplersTest(deqp::Context & context)1935 ErrorsBindSamplersTest::ErrorsBindSamplersTest(deqp::Context& context)
1936 : TestCase(context, "errors_bind_samplers", "Verifies that proper errors are generated by sampler binding routines")
1937 {
1938 /* Nothing to be done */
1939 }
1940
1941 /** Execute test
1942 *
1943 * @return tcu::TestNode::STOP
1944 **/
iterate()1945 tcu::TestNode::IterateResult ErrorsBindSamplersTest::iterate()
1946 {
1947 static const GLsizei n_samplers = 4;
1948
1949 const Functions& gl = m_context.getRenderContext().getFunctions();
1950
1951 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1952 gl.debugMessageCallback(debug_proc, &m_context);
1953 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1954 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1955
1956 GLsizei count = n_samplers;
1957 GLuint first = 0;
1958 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1959 GLint max_samplers = 0;
1960 size_t validated_index = n_samplers - 1;
1961
1962 /* Get max */
1963 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
1964 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1965
1966 /* Select count so <first + count> does not exceed max.
1967 * Validated index shall be in the specified range.
1968 */
1969 if (n_samplers > max_samplers)
1970 {
1971 count = max_samplers;
1972 validated_index = max_samplers - 1;
1973 }
1974
1975 /* Storage */
1976 GLuint sampler_ids[n_samplers];
1977
1978 /* Prepare samplers */
1979 gl.genSamplers(n_samplers, sampler_ids);
1980 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
1981
1982 try
1983 {
1984 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
1985 {
1986 GLsizei t_count = n_samplers;
1987 GLuint t_first = 0;
1988
1989 /* Select first so <first + count> exceeds max, avoid negative first */
1990 if (n_samplers <= max_samplers)
1991 {
1992 t_first = max_samplers - n_samplers + 1;
1993 }
1994 else
1995 {
1996 t_count = max_samplers + 1;
1997 /* first = 0; */
1998 }
1999
2000 /* Test */
2001 gl.bindSamplers(t_first, t_count, sampler_ids);
2002 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid <first> + <count>");
2003 }
2004
2005 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2006 * existing buffer;
2007 */
2008 {
2009 GLuint t_sampler_ids[n_samplers];
2010
2011 memcpy(t_sampler_ids, sampler_ids, sizeof(sampler_ids));
2012
2013 /* Find invalid id */
2014 while (1)
2015 {
2016 if (GL_TRUE != gl.isTexture(invalid_id))
2017 {
2018 break;
2019 }
2020
2021 invalid_id += 1;
2022 }
2023
2024 /* Invalidate the entry */
2025 t_sampler_ids[validated_index] = invalid_id;
2026
2027 /* Test */
2028 gl.bindTextures(first, count, t_sampler_ids);
2029 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2030 }
2031 }
2032 catch (const std::exception&)
2033 {
2034 gl.deleteSamplers(n_samplers, sampler_ids);
2035
2036 TCU_FAIL("Invalid error generated");
2037 }
2038
2039 /* Delete samplers */
2040 gl.deleteSamplers(n_samplers, sampler_ids);
2041
2042 /* Set result */
2043 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2044
2045 /* Done */
2046 return tcu::TestNode::STOP;
2047 }
2048
2049 /** Constructor
2050 *
2051 * @param context Test context
2052 **/
ErrorsBindImageTexturesTest(deqp::Context & context)2053 ErrorsBindImageTexturesTest::ErrorsBindImageTexturesTest(deqp::Context& context)
2054 : TestCase(context, "errors_bind_image_textures",
2055 "Verifies that proper errors are generated by image binding routines")
2056 {
2057 /* Nothing to be done */
2058 }
2059
2060 /** Execute test
2061 *
2062 * @return tcu::TestNode::STOP
2063 **/
iterate()2064 tcu::TestNode::IterateResult ErrorsBindImageTexturesTest::iterate()
2065 {
2066 static const GLuint depth = 8;
2067 static const GLuint height = 8;
2068 static const GLsizei n_textures = 4;
2069 static const GLuint width = 8;
2070
2071 const Functions& gl = m_context.getRenderContext().getFunctions();
2072
2073 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2074 gl.debugMessageCallback(debug_proc, &m_context);
2075 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2076 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2077
2078 GLsizei count = n_textures;
2079 GLuint first = 0;
2080 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2081 GLint max_textures = 0;
2082 size_t validated_index = n_textures - 1;
2083
2084 /* Get max */
2085 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
2086 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2087
2088 /* Select count so <first + count> does not exceed max.
2089 * Validated index shall be in the specified range.
2090 */
2091 if (n_textures > max_textures)
2092 {
2093 count = max_textures;
2094 validated_index = max_textures - 1;
2095 }
2096
2097 /* Storage */
2098 Texture texture[n_textures];
2099 GLuint texture_ids[n_textures];
2100
2101 /* Prepare textures */
2102 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2103 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, depth);
2104 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1, GL_RGBA8, width, height, depth);
2105 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1, GL_RGBA8, width, height, depth);
2106
2107 for (size_t i = 0; i < n_textures; ++i)
2108 {
2109 texture_ids[i] = texture[i].m_id;
2110 }
2111
2112 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
2113 {
2114 GLsizei t_count = n_textures;
2115 GLuint t_first = 0;
2116
2117 /* Select first so <first + count> exceeds max, avoid negative first */
2118 if (n_textures <= max_textures)
2119 {
2120 t_first = max_textures - n_textures + 1;
2121 }
2122 else
2123 {
2124 t_count = max_textures + 1;
2125 /* first = 0; */
2126 }
2127
2128 /* Test */
2129 gl.bindImageTextures(t_first, t_count, texture_ids);
2130 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid <first> + <count>");
2131 }
2132
2133 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2134 * existing buffer;
2135 */
2136 {
2137 GLuint t_texture_ids[n_textures];
2138
2139 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2140
2141 /* Find invalid id */
2142 while (1)
2143 {
2144 if (GL_TRUE != gl.isTexture(invalid_id))
2145 {
2146 break;
2147 }
2148
2149 invalid_id += 1;
2150 }
2151
2152 /* Invalidate the entry */
2153 t_texture_ids[validated_index] = invalid_id;
2154
2155 /* Test */
2156 gl.bindImageTextures(first, count, t_texture_ids);
2157 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
2158 }
2159
2160 /* - INVALID_OPERATION if any entry found in <textures> has invalid internal
2161 * format at level 0;
2162 */
2163 {
2164 GLuint t_texture_ids[n_textures];
2165
2166 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2167
2168 /* Prepare texture with invalid format */
2169 Texture t_texture;
2170 t_texture.Init(m_context);
2171 t_texture.Generate(gl, t_texture.m_id);
2172 t_texture.Bind(gl, t_texture.m_id, GL_TEXTURE_2D);
2173 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0);
2174 CHECK_ERROR(GL_INVALID_VALUE, "texStorage2D has height set to 0");
2175
2176 /* Invalidate the entry */
2177 t_texture_ids[validated_index] = t_texture.m_id;
2178
2179 /* Test */
2180 gl.bindImageTextures(first, count, t_texture_ids);
2181 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid internal format");
2182 }
2183
2184 /* - INVALID_VALUE when any entry in <textures> has any of dimensions equal
2185 * to 0 at level 0.
2186 */
2187 {
2188 GLuint t_texture_ids[n_textures];
2189
2190 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2191
2192 /* Prepare texture with invalid format */
2193 Texture t_texture;
2194 t_texture.InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0, depth, true);
2195
2196 /* Invalidate the entry */
2197 t_texture_ids[validated_index] = t_texture.m_id;
2198
2199 /* Test */
2200 gl.bindImageTextures(first, count, t_texture_ids);
2201 CHECK_ERROR(GL_INVALID_VALUE, "BindImageTextures with 2D texture that has height set to 0");
2202 }
2203
2204 /* Set result */
2205 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2206
2207 /* Done */
2208 return tcu::TestNode::STOP;
2209 }
2210
2211 /** Constructor
2212 *
2213 * @param context Test context
2214 **/
ErrorsBindVertexBuffersTest(deqp::Context & context)2215 ErrorsBindVertexBuffersTest::ErrorsBindVertexBuffersTest(deqp::Context& context)
2216 : TestCase(context, "errors_bind_vertex_buffers",
2217 "Verifies that proper errors are generated by vertex buffer binding routines")
2218 {
2219 /* Nothing to be done */
2220 }
2221
2222 /** Execute test
2223 *
2224 * @return tcu::TestNode::STOP
2225 **/
iterate()2226 tcu::TestNode::IterateResult ErrorsBindVertexBuffersTest::iterate()
2227 {
2228 const Functions& gl = m_context.getRenderContext().getFunctions();
2229
2230 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2231 gl.debugMessageCallback(debug_proc, &m_context);
2232 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2233 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2234
2235 static const GLsizei n_buffers = 4;
2236 static const GLsizei stride = 4;
2237
2238 GLintptr buffer_size = 16;
2239 GLsizei count = n_buffers;
2240 GLuint first = 0;
2241 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2242 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */
2243 GLint max_buffers = 0;
2244 size_t validated_index = n_buffers - 1;
2245
2246 /* Get max */
2247 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
2248 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2249
2250 /* Select count so <first + count> does not exceed max.
2251 * Validated index shall be in the specified range.
2252 */
2253 if (n_buffers > max_buffers)
2254 {
2255 count = max_buffers;
2256 validated_index = max_buffers - 1;
2257 }
2258
2259 /* Storage */
2260 Buffer buffer[n_buffers];
2261 GLuint buffer_ids[n_buffers];
2262 GLintptr offsets[n_buffers];
2263 GLsizei strides[n_buffers];
2264
2265 /* Prepare buffers */
2266 for (size_t j = 0; j < n_buffers; ++j)
2267 {
2268 buffer[j].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2269
2270 buffer_ids[j] = buffer[j].m_id;
2271 offsets[j] = offset;
2272 strides[j] = stride;
2273 }
2274
2275 /* Prepare VAO */
2276 GLuint vao = 0;
2277 gl.genVertexArrays(1, &vao);
2278 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
2279 try
2280 {
2281 gl.bindVertexArray(vao);
2282 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
2283
2284 /* - INVALID_OPERATION when <first> + <count> exceeds limits; */
2285 {
2286 GLsizei t_count = n_buffers;
2287 GLuint t_first = 0;
2288
2289 /* Select first so <first + count> exceeds max, avoid negative first */
2290 if (n_buffers <= max_buffers)
2291 {
2292 t_first = max_buffers - n_buffers + 1;
2293 }
2294 else
2295 {
2296 t_count = max_buffers + 1;
2297 /* first = 0; */
2298 }
2299
2300 /* Test */
2301 gl.bindVertexBuffers(t_first, t_count, buffer_ids, offsets, strides);
2302 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid <first> + <count>");
2303 }
2304
2305 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2306 * existing buffer;
2307 */
2308 {
2309 GLuint t_buffer_ids[n_buffers];
2310
2311 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
2312
2313 /* Find invalid id */
2314 while (1)
2315 {
2316 if (GL_TRUE != gl.isBuffer(invalid_id))
2317 {
2318 break;
2319 }
2320
2321 invalid_id += 1;
2322 }
2323
2324 /* Invalidate the entry */
2325 t_buffer_ids[validated_index] = invalid_id;
2326
2327 /* Test */
2328 gl.bindVertexBuffers(first, count, t_buffer_ids, offsets, strides);
2329 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid buffer id");
2330 }
2331
2332 /* - INVALID_VALUE if any value in <offsets> or <strides> is less than zero. */
2333 {
2334 GLintptr t_offsets[n_buffers];
2335 GLsizei t_strides[n_buffers];
2336
2337 memcpy(t_offsets, offsets, sizeof(offsets));
2338 memcpy(t_strides, strides, sizeof(strides));
2339
2340 /* Invalidate the entry */
2341 t_offsets[validated_index] = -1;
2342 t_strides[validated_index] = -1;
2343
2344 /* Test */
2345 gl.bindVertexBuffers(first, count, buffer_ids, t_offsets, strides);
2346 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative offset");
2347
2348 gl.bindVertexBuffers(first, count, buffer_ids, offsets, t_strides);
2349 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative stride");
2350 }
2351 }
2352 catch (const std::exception&)
2353 {
2354 gl.deleteVertexArrays(1, &vao);
2355 TCU_FAIL("Unexpected error generated");
2356 }
2357
2358 gl.deleteVertexArrays(1, &vao);
2359 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
2360
2361 /* Set result */
2362 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2363
2364 /* Done */
2365 return tcu::TestNode::STOP;
2366 }
2367
2368 /** Constructor
2369 *
2370 * @param context Test context
2371 **/
FunctionalBindBuffersBaseTest(deqp::Context & context)2372 FunctionalBindBuffersBaseTest::FunctionalBindBuffersBaseTest(deqp::Context& context)
2373 : TestCase(context, "functional_bind_buffers_base", "Verifies that BindBuffersBase works as expected")
2374 {
2375 /* Nothing to be done */
2376 }
2377
2378 /** Execute test
2379 *
2380 * @return tcu::TestNode::STOP
2381 **/
iterate()2382 tcu::TestNode::IterateResult FunctionalBindBuffersBaseTest::iterate()
2383 {
2384 const Functions& gl = m_context.getRenderContext().getFunctions();
2385
2386 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2387 gl.debugMessageCallback(debug_proc, &m_context);
2388 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2389 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2390
2391 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2392 {
2393 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding;
2394 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
2395 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size;
2396 const GLenum target = s_buffer_infos[i].m_target;
2397 const std::string& target_name = glu::getBufferTargetStr(target).toString();
2398
2399 GLint max_buffers = 0;
2400 GLint max_size = 0;
2401
2402 /* Get max */
2403 gl.getIntegerv(pname_max, &max_buffers);
2404 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2405
2406 /* Get max size */
2407 gl.getIntegerv(pname_max_size, &max_size);
2408 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2409
2410 GLintptr buffer_size = max_size / max_buffers;
2411
2412 /* Storage */
2413 std::vector<Buffer> buffer;
2414 std::vector<GLuint> buffer_ids;
2415
2416 buffer.resize(max_buffers);
2417 buffer_ids.resize(max_buffers);
2418
2419 /* Prepare buffers */
2420 for (GLint j = 0; j < max_buffers; ++j)
2421 {
2422 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2423
2424 buffer_ids[j] = buffer[j].m_id;
2425 }
2426
2427 /*
2428 * - execute BindBufferBase to bind all buffers to tested target;
2429 * - inspect if bindings were modified;
2430 */
2431 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2432 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2433
2434 for (GLint j = 0; j < max_buffers; ++j)
2435 {
2436 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2437 }
2438
2439 /*
2440 *
2441 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2442 * to unbind first half of bindings for tested target;
2443 * - inspect if bindings were modified;
2444 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2445 * to unbind rest of bindings;
2446 * - inspect if bindings were modified;
2447 */
2448 GLint half_index = max_buffers / 2;
2449 gl.bindBuffersBase(target, 0 /* first */, half_index /* count */, 0);
2450 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2451
2452 for (GLint j = 0; j < half_index; ++j)
2453 {
2454 checkBinding(m_context, pname_binding, j, target_name, 0);
2455 }
2456
2457 for (GLint j = half_index; j < max_buffers; ++j)
2458 {
2459 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2460 }
2461
2462 gl.bindBuffersBase(target, half_index /* first */, max_buffers - half_index /* count */, 0);
2463 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2464
2465 for (GLint j = 0; j < max_buffers; ++j)
2466 {
2467 checkBinding(m_context, pname_binding, j, target_name, 0);
2468 }
2469
2470 /*
2471 * - change <buffers> so first entry is invalid;
2472 * - execute BindBufferBase to bind all buffers to tested target; It is
2473 * expected that INVALID_OPERATION will be generated;
2474 * - inspect if all bindings but first were modified;
2475 */
2476
2477 /* Find invalid id */
2478 GLuint invalid_id = 1;
2479 while (1)
2480 {
2481 if (GL_TRUE != gl.isBuffer(invalid_id))
2482 {
2483 break;
2484 }
2485
2486 invalid_id += 1;
2487 }
2488
2489 buffer_ids[0] = invalid_id;
2490
2491 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2492 CHECK_ERROR(GL_INVALID_OPERATION, "BindBufferBase with invalid buffer id");
2493
2494 /* Update buffer_ids */
2495 buffer_ids[0] = 0; /* 0 means unbound */
2496
2497 for (GLint j = 0; j < max_buffers; ++j)
2498 {
2499 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2500 }
2501
2502 /*
2503 * - bind any buffer to first binding;
2504 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2505 * with zeros to unbind 1st binding for tested target;
2506 * - inspect if bindings were modified;
2507 */
2508 gl.bindBufferBase(target, 0, buffer[0].m_id);
2509 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2510 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2511
2512 std::vector<GLuint> t_buffer_ids;
2513 t_buffer_ids.resize(max_buffers);
2514
2515 gl.bindBuffersBase(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0]);
2516 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2517
2518 for (GLint j = 0; j < max_buffers; ++j)
2519 {
2520 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2521 }
2522
2523 /* - unbind all buffers. */
2524 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2525 }
2526
2527 /* Set result */
2528 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2529
2530 /* Done */
2531 return tcu::TestNode::STOP;
2532 }
2533
2534 /** Constructor
2535 *
2536 * @param context Test context
2537 **/
FunctionalBindBuffersRangeTest(deqp::Context & context)2538 FunctionalBindBuffersRangeTest::FunctionalBindBuffersRangeTest(deqp::Context& context)
2539 : TestCase(context, "functional_bind_buffers_range", "Verifies that BindBuffersRange works as expected")
2540 {
2541 /* Nothing to be done */
2542 }
2543
2544 /** Execute test
2545 *
2546 * @return tcu::TestNode::STOP
2547 **/
iterate()2548 tcu::TestNode::IterateResult FunctionalBindBuffersRangeTest::iterate()
2549 {
2550 const Functions& gl = m_context.getRenderContext().getFunctions();
2551
2552 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2553 gl.debugMessageCallback(debug_proc, &m_context);
2554 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2555 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2556
2557 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2558 {
2559 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding;
2560 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
2561 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size;
2562 const GLenum target = s_buffer_infos[i].m_target;
2563 const std::string& target_name = glu::getBufferTargetStr(target).toString();
2564
2565 GLint max_buffers = 0;
2566 GLint max_size = 0;
2567
2568 /* Get max */
2569 gl.getIntegerv(pname_max, &max_buffers);
2570 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2571
2572 /* Get max size */
2573 gl.getIntegerv(pname_max_size, &max_size);
2574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2575
2576 GLintptr buffer_size = max_size / max_buffers;
2577
2578 /* Storage */
2579 std::vector<Buffer> buffer;
2580 std::vector<GLuint> buffer_ids;
2581 std::vector<GLintptr> offsets;
2582 std::vector<GLsizeiptr> sizes;
2583
2584 buffer.resize(max_buffers);
2585 buffer_ids.resize(max_buffers);
2586 offsets.resize(max_buffers);
2587 sizes.resize(max_buffers);
2588
2589 /* Prepare buffers */
2590 for (GLint j = 0; j < max_buffers; ++j)
2591 {
2592 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2593
2594 buffer_ids[j] = buffer[j].m_id;
2595 offsets[j] = 0;
2596 sizes[j] = buffer_size;
2597 }
2598
2599 /*
2600 * - execute BindBufferBase to bind all buffers to tested target;
2601 * - inspect if bindings were modified;
2602 */
2603 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2604 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2605
2606 for (GLint j = 0; j < max_buffers; ++j)
2607 {
2608 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2609 }
2610
2611 /*
2612 *
2613 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2614 * to unbind first half of bindings for tested target;
2615 * - inspect if bindings were modified;
2616 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2617 * to unbind rest of bindings;
2618 * - inspect if bindings were modified;
2619 */
2620 GLint half_index = max_buffers / 2;
2621 gl.bindBuffersRange(target, 0 /* first */, half_index /* count */, 0, &offsets[0], &sizes[0]);
2622 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2623
2624 for (GLint j = 0; j < half_index; ++j)
2625 {
2626 checkBinding(m_context, pname_binding, j, target_name, 0);
2627 }
2628
2629 for (GLint j = half_index; j < max_buffers; ++j)
2630 {
2631 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2632 }
2633
2634 gl.bindBuffersRange(target, half_index /* first */, max_buffers - half_index /* count */, 0, &offsets[0],
2635 &sizes[0]);
2636 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2637
2638 for (GLint j = 0; j < max_buffers; ++j)
2639 {
2640 checkBinding(m_context, pname_binding, j, target_name, 0);
2641 }
2642
2643 /*
2644 * - change <buffers> so first entry is invalid;
2645 * - execute BindBufferBase to bind all buffers to tested target; It is
2646 * expected that INVALID_OPERATION will be generated;
2647 * - inspect if all bindings but first were modified;
2648 */
2649
2650 /* Find invalid id */
2651 GLuint invalid_id = 1;
2652 while (1)
2653 {
2654 if (GL_TRUE != gl.isBuffer(invalid_id))
2655 {
2656 break;
2657 }
2658
2659 invalid_id += 1;
2660 }
2661
2662 buffer_ids[0] = invalid_id;
2663
2664 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2665 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id");
2666
2667 /* Update buffer_ids */
2668 buffer_ids[0] = 0; /* 0 means unbound */
2669
2670 for (GLint j = 0; j < max_buffers; ++j)
2671 {
2672 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2673 }
2674
2675 /*
2676 * - bind any buffer to first binding;
2677 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2678 * with zeros to unbind 1st binding for tested target;
2679 * - inspect if bindings were modified;
2680 */
2681 gl.bindBufferBase(target, 0, buffer[0].m_id);
2682 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2683 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2684
2685 std::vector<GLuint> t_buffer_ids;
2686 t_buffer_ids.resize(max_buffers);
2687
2688 gl.bindBuffersRange(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0], &offsets[0], &sizes[0]);
2689 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2690
2691 for (GLint j = 0; j < max_buffers; ++j)
2692 {
2693 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2694 }
2695
2696 /* - unbind all buffers. */
2697 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2698 }
2699
2700 /* Set result */
2701 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2702
2703 /* Done */
2704 return tcu::TestNode::STOP;
2705 }
2706
2707 /** Constructor
2708 *
2709 * @param context Test context
2710 **/
FunctionalBindTexturesTest(deqp::Context & context)2711 FunctionalBindTexturesTest::FunctionalBindTexturesTest(deqp::Context& context)
2712 : TestCase(context, "functional_bind_textures", "Verifies that BindTextures works as expected")
2713 {
2714 /* Nothing to be done */
2715 }
2716
2717 /** Execute test
2718 *
2719 * @return tcu::TestNode::STOP
2720 **/
iterate()2721 tcu::TestNode::IterateResult FunctionalBindTexturesTest::iterate()
2722 {
2723 static const GLuint depth = 6;
2724 static const GLuint height = 6;
2725 static const GLuint width = 6;
2726
2727 const Functions& gl = m_context.getRenderContext().getFunctions();
2728
2729 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2730 gl.debugMessageCallback(debug_proc, &m_context);
2731 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2732 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2733
2734 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2735 GLint max_textures = 0;
2736
2737 /* Get max */
2738 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
2739 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2740
2741 /* Storage */
2742 Buffer buffer;
2743 std::vector<Texture> texture;
2744 std::vector<GLuint> texture_ids;
2745 std::vector<GLuint> t_texture_ids;
2746
2747 texture.resize(max_textures);
2748 texture_ids.resize(max_textures);
2749 t_texture_ids.resize(max_textures);
2750
2751 /* Prepare buffer */
2752 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
2753
2754 /* Prepare textures */
2755 for (size_t i = 0; i < s_n_texture_tragets; ++i)
2756 {
2757 const GLenum target = s_texture_infos[i].m_target;
2758
2759 if (GL_TEXTURE_BUFFER != target)
2760 {
2761 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
2762 }
2763 else
2764 {
2765 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
2766 }
2767
2768 /* Unbind */
2769 Texture::Bind(gl, 0, target);
2770 }
2771
2772 for (GLint i = s_n_texture_tragets; i < max_textures; ++i)
2773 {
2774 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2775 }
2776
2777 /* Unbind */
2778 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2779
2780 for (GLint i = 0; i < max_textures; ++i)
2781 {
2782 texture_ids[i] = texture[i].m_id;
2783 }
2784
2785 /*
2786 * - execute BindTextures to bind all textures;
2787 * - inspect bindings of all texture units to verify that proper bindings were
2788 * set;
2789 */
2790 gl.bindTextures(0, max_textures, &texture_ids[0]);
2791 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2792
2793 for (GLint i = 0; i < max_textures; ++i)
2794 {
2795 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2796 }
2797
2798 /*
2799 * - execute BindTextures for the first half of units with <textures> filled
2800 * with zeros, to unbind those units;
2801 * - inspect bindings of all texture units to verify that proper bindings were
2802 * unbound;
2803 */
2804 GLint half_index = max_textures / 2;
2805
2806 for (GLint i = 0; i < max_textures; ++i)
2807 {
2808 t_texture_ids[i] = 0;
2809 }
2810
2811 gl.bindTextures(0, half_index, &t_texture_ids[0]);
2812 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2813
2814 for (GLint i = 0; i < half_index; ++i)
2815 {
2816 checkTextureBinding(m_context, getBinding(i), i, 0);
2817 }
2818
2819 for (GLint i = half_index; i < max_textures; ++i)
2820 {
2821 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2822 }
2823
2824 /*
2825 * - execute BindTextures for the second half of units with NULL as<textures>,
2826 * to unbind those units;
2827 * - inspect bindings of all texture units to verify that proper bindings were
2828 * unbound;
2829 */
2830 gl.bindTextures(half_index, max_textures - half_index, 0);
2831 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2832
2833 for (GLint i = 0; i < max_textures; ++i)
2834 {
2835 checkTextureBinding(m_context, getBinding(i), i, 0);
2836 }
2837
2838 /*
2839 * - modify <textures> so first entry is invalid;
2840 * - execute BindTextures to bind all textures; It is expected that
2841 * INVALID_OPERATION will be generated;
2842 * - inspect bindings of all texture units to verify that proper bindings were
2843 * set;
2844 */
2845
2846 /* Find invalid id */
2847 while (1)
2848 {
2849 if (GL_TRUE != gl.isTexture(invalid_id))
2850 {
2851 break;
2852 }
2853
2854 invalid_id += 1;
2855 }
2856
2857 /* Set invalid id */
2858 texture_ids[0] = invalid_id;
2859
2860 gl.bindTextures(0, max_textures, &texture_ids[0]);
2861 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
2862
2863 checkTextureBinding(m_context, getBinding(0), 0, 0);
2864 for (GLint i = 1; i < max_textures; ++i)
2865 {
2866 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2867 }
2868
2869 /* - unbind all textures. */
2870 gl.bindTextures(0, max_textures, 0);
2871 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2872
2873 /* Set result */
2874 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2875
2876 /* Done */
2877 return tcu::TestNode::STOP;
2878 }
2879
2880 /** Constructor
2881 *
2882 * @param context Test context
2883 **/
FunctionalBindSamplersTest(deqp::Context & context)2884 FunctionalBindSamplersTest::FunctionalBindSamplersTest(deqp::Context& context)
2885 : TestCase(context, "functional_bind_samplers", "Verifies that BindSamplers works as expected")
2886 {
2887 /* Nothing to be done */
2888 }
2889
2890 /** Execute test
2891 *
2892 * @return tcu::TestNode::STOP
2893 **/
iterate()2894 tcu::TestNode::IterateResult FunctionalBindSamplersTest::iterate()
2895 {
2896 const Functions& gl = m_context.getRenderContext().getFunctions();
2897
2898 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2899 gl.debugMessageCallback(debug_proc, &m_context);
2900 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2901 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2902
2903 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2904 GLint max_samplers = 0;
2905
2906 /* Get max */
2907 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
2908 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2909
2910 /* Storage */
2911 std::vector<GLuint> sampler_ids;
2912 std::vector<GLuint> t_sampler_ids;
2913
2914 sampler_ids.resize(max_samplers);
2915 t_sampler_ids.resize(max_samplers);
2916
2917 for (GLint i = 0; i < max_samplers; ++i)
2918 {
2919 t_sampler_ids[i] = 0;
2920 }
2921
2922 /* Prepare samplers */
2923 gl.genSamplers(max_samplers, &sampler_ids[0]);
2924 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
2925
2926 try
2927 {
2928 /* - execute BindSamplers to bind all samplers;
2929 * - inspect bindings to verify that proper samplers were set;
2930 */
2931 gl.bindSamplers(0 /* first */, max_samplers /* count */, &sampler_ids[0]);
2932 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2933
2934 for (GLint i = 0; i < max_samplers; ++i)
2935 {
2936 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2937 }
2938
2939 /* - execute BindSamplers for first half of bindings with <samplers> filled
2940 * with zeros, to unbind those samplers;
2941 * - inspect bindings to verify that proper samplers were unbound;
2942 */
2943 GLint half_index = max_samplers / 2;
2944
2945 gl.bindSamplers(0, half_index, &t_sampler_ids[0]);
2946 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2947
2948 for (GLint i = 0; i < half_index; ++i)
2949 {
2950 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2951 }
2952
2953 for (GLint i = half_index; i < max_samplers; ++i)
2954 {
2955 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2956 }
2957
2958 /* - execute BindSamplers for second half of bindings with NULL as <samplers>,
2959 * to unbind those samplers;
2960 * - inspect bindings to verify that proper samplers were unbound;
2961 */
2962 gl.bindSamplers(half_index, max_samplers - half_index, 0);
2963 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2964
2965 for (GLint i = 0; i < max_samplers; ++i)
2966 {
2967 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2968 }
2969
2970 /* - modify <samplers> so first entry is invalid;
2971 * - execute BindSamplers to bind all samplers; It is expected that
2972 * INVALID_OPERATION will be generated;
2973 * - inspect bindings to verify that proper samplers were set;
2974 */
2975
2976 /* Find invalid id */
2977 while (1)
2978 {
2979 if (GL_TRUE != gl.isSampler(invalid_id))
2980 {
2981 break;
2982 }
2983
2984 invalid_id += 1;
2985 }
2986
2987 /* Prepare ids */
2988 t_sampler_ids[0] = invalid_id;
2989
2990 for (GLint i = 1; i < max_samplers; ++i)
2991 {
2992 t_sampler_ids[i] = sampler_ids[i];
2993 }
2994
2995 /* Bind */
2996 gl.bindSamplers(0, max_samplers, &t_sampler_ids[0]);
2997 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2998
2999 /* Set 0 for invalid entry */
3000 t_sampler_ids[0] = 0;
3001
3002 for (GLint i = 0; i < max_samplers; ++i)
3003 {
3004 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", t_sampler_ids[i]);
3005 }
3006
3007 /* - unbind all samplers. */
3008 gl.bindSamplers(0, max_samplers, 0);
3009 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
3010 }
3011 catch (const std::exception&)
3012 {
3013 gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3014
3015 TCU_FAIL("Invalid error generated");
3016 }
3017
3018 /* Delete samplers */
3019 gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3020
3021 /* Set result */
3022 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3023
3024 /* Done */
3025 return tcu::TestNode::STOP;
3026 }
3027
3028 /** Constructor
3029 *
3030 * @param context Test context
3031 **/
FunctionalBindImageTexturesTest(deqp::Context & context)3032 FunctionalBindImageTexturesTest::FunctionalBindImageTexturesTest(deqp::Context& context)
3033 : TestCase(context, "functional_bind_image_textures", "Verifies that BindImageTextures works as expected")
3034 {
3035 /* Nothing to be done */
3036 }
3037
3038 /** Execute test
3039 *
3040 * @return tcu::TestNode::STOP
3041 **/
iterate()3042 tcu::TestNode::IterateResult FunctionalBindImageTexturesTest::iterate()
3043 {
3044 static const GLuint depth = 6;
3045 static const GLuint height = 6;
3046 static const GLuint width = 6;
3047
3048 const Functions& gl = m_context.getRenderContext().getFunctions();
3049
3050 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3051 gl.debugMessageCallback(debug_proc, &m_context);
3052 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3053 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3054
3055 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
3056 GLint max_textures = 0;
3057
3058 /* Get max */
3059 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
3060 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3061
3062 /* Storage */
3063 Buffer buffer;
3064 std::vector<Texture> texture;
3065 std::vector<GLuint> texture_ids;
3066 std::vector<GLuint> t_texture_ids;
3067
3068 texture.resize(max_textures);
3069 texture_ids.resize(max_textures);
3070 t_texture_ids.resize(max_textures);
3071
3072 /* Prepare buffer */
3073 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
3074
3075 /* Prepare textures */
3076 for (GLint i = 0; i < (GLint)s_n_texture_tragets; ++i)
3077 {
3078 const GLenum target = s_texture_infos[i].m_target;
3079
3080 if (i >= max_textures)
3081 {
3082 break;
3083 }
3084
3085 if (GL_TEXTURE_BUFFER != target)
3086 {
3087 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
3088 }
3089 else
3090 {
3091 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
3092 }
3093
3094 /* Unbind */
3095 Texture::Bind(gl, 0, target);
3096 }
3097
3098 for (GLint i = (GLint)s_n_texture_tragets; i < max_textures; ++i)
3099 {
3100 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
3101 }
3102
3103 /* Unbind */
3104 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3105
3106 for (GLint i = 0; i < max_textures; ++i)
3107 {
3108 texture_ids[i] = texture[i].m_id;
3109 }
3110
3111 /*
3112 * - execute BindImageTextures to bind all images;
3113 * - inspect bindings to verify that proper images were set;
3114 */
3115 gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3116 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3117
3118 for (GLint i = 0; i < max_textures; ++i)
3119 {
3120 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3121 }
3122
3123 /*
3124 * - execute BindTextures for the first half of units with <textures> filled
3125 * with zeros, to unbind those units;
3126 * - inspect bindings of all texture units to verify that proper bindings were
3127 * unbound;
3128 */
3129 GLint half_index = max_textures / 2;
3130
3131 for (GLint i = 0; i < max_textures; ++i)
3132 {
3133 t_texture_ids[i] = 0;
3134 }
3135
3136 gl.bindImageTextures(0, half_index, &t_texture_ids[0]);
3137 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3138
3139 for (GLint i = 0; i < half_index; ++i)
3140 {
3141 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3142 }
3143
3144 for (GLint i = half_index; i < max_textures; ++i)
3145 {
3146 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3147 }
3148
3149 /*
3150 * - execute BindTextures for the second half of units with NULL as<textures>,
3151 * to unbind those units;
3152 * - inspect bindings of all texture units to verify that proper bindings were
3153 * unbound;
3154 */
3155 gl.bindImageTextures(half_index, max_textures - half_index, 0);
3156 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3157
3158 for (GLint i = 0; i < max_textures; ++i)
3159 {
3160 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3161 }
3162
3163 /*
3164 * - modify <textures> so first entry is invalid;
3165 * - execute BindTextures to bind all textures; It is expected that
3166 * INVALID_OPERATION will be generated;
3167 * - inspect bindings of all texture units to verify that proper bindings were
3168 * set;
3169 */
3170
3171 /* Find invalid id */
3172 while (1)
3173 {
3174 if (GL_TRUE != gl.isTexture(invalid_id))
3175 {
3176 break;
3177 }
3178
3179 invalid_id += 1;
3180 }
3181
3182 /* Set invalid id */
3183 texture_ids[0] = invalid_id;
3184
3185 gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3186 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
3187
3188 checkBinding(m_context, GL_IMAGE_BINDING_NAME, 0, "Image unit", 0);
3189 for (GLint i = 1; i < max_textures; ++i)
3190 {
3191 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3192 }
3193
3194 /* - unbind all textures. */
3195 gl.bindImageTextures(0, max_textures, 0);
3196 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3197
3198 /* Set result */
3199 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3200
3201 /* Done */
3202 return tcu::TestNode::STOP;
3203 }
3204
3205 /** Constructor
3206 *
3207 * @param context Test context
3208 **/
FunctionalBindVertexBuffersTest(deqp::Context & context)3209 FunctionalBindVertexBuffersTest::FunctionalBindVertexBuffersTest(deqp::Context& context)
3210 : TestCase(context, "functional_bind_vertex_buffers", "Verifies that BindVertexBuffers works as expected")
3211 {
3212 /* Nothing to be done */
3213 }
3214
3215 /** Execute test
3216 *
3217 * @return tcu::TestNode::STOP
3218 **/
iterate()3219 tcu::TestNode::IterateResult FunctionalBindVertexBuffersTest::iterate()
3220 {
3221 const Functions& gl = m_context.getRenderContext().getFunctions();
3222
3223 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3224 gl.debugMessageCallback(debug_proc, &m_context);
3225 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3226 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3227
3228 static const GLintptr buffer_size = 16;
3229 static const GLintptr offset = 4;
3230 static const GLsizei stride = 4;
3231
3232 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
3233 GLint max_buffers = 0;
3234
3235 /* Get max */
3236 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
3237 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3238
3239 /* Storage */
3240 std::vector<Buffer> buffer;
3241 std::vector<GLuint> buffer_ids;
3242 std::vector<GLintptr> offsets;
3243 std::vector<GLsizei> strides;
3244 std::vector<GLuint> t_buffer_ids;
3245
3246 buffer.resize(max_buffers);
3247 buffer_ids.resize(max_buffers);
3248 offsets.resize(max_buffers);
3249 strides.resize(max_buffers);
3250 t_buffer_ids.resize(max_buffers);
3251
3252 /* Prepare buffers */
3253 for (GLint i = 0; i < max_buffers; ++i)
3254 {
3255 buffer[i].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3256
3257 buffer_ids[i] = buffer[i].m_id;
3258 offsets[i] = offset;
3259 strides[i] = stride;
3260 t_buffer_ids[i] = 0;
3261 }
3262
3263 GLuint vao = 0;
3264 gl.genVertexArrays(1, &vao);
3265 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3266 try
3267 {
3268 gl.bindVertexArray(vao);
3269 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
3270
3271 /* - execute BindVertexBuffers to bind all buffer;
3272 * - inspect bindings to verify that proper buffers were set;
3273 */
3274 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3275 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3276
3277 for (GLint i = 0; i < max_buffers; ++i)
3278 {
3279 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3280 }
3281
3282 /* - execute BindVertexBuffers for first half of bindings with <buffers> filled
3283 * with zeros, to unbind those buffers;
3284 * - inspect bindings to verify that proper buffers were unbound;
3285 */
3286 GLint half_index = max_buffers / 2;
3287
3288 gl.bindVertexBuffers(0, half_index, &t_buffer_ids[0], &offsets[0], &strides[0]);
3289 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3290
3291 for (GLint i = 0; i < half_index; ++i)
3292 {
3293 checkVertexAttribBinding(m_context, i, 0);
3294 }
3295
3296 for (GLint i = half_index; i < max_buffers; ++i)
3297 {
3298 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3299 }
3300
3301 /* - execute BindVertexBuffers for second half of bindings with NULL as
3302 * <buffers>, to unbind those buffers;
3303 * - inspect bindings to verify that proper buffers were unbound;
3304 */
3305 gl.bindVertexBuffers(half_index, max_buffers - half_index, 0, &offsets[0], &strides[0]);
3306 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3307
3308 for (GLint i = 0; i < max_buffers; ++i)
3309 {
3310 checkVertexAttribBinding(m_context, i, 0);
3311 }
3312
3313 /* - modify <buffers> so first entry is invalid;
3314 * - execute BindVertexBuffers to bind all buffers; It is expected that
3315 * INVALID_OPERATION will be generated;
3316 * - inspect bindings to verify that proper buffers were set;
3317 */
3318
3319 /* Find invalid id */
3320 while (1)
3321 {
3322 if (GL_TRUE != gl.isBuffer(invalid_id))
3323 {
3324 break;
3325 }
3326
3327 invalid_id += 1;
3328 }
3329
3330 buffer_ids[0] = invalid_id;
3331 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3332 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid id");
3333
3334 checkVertexAttribBinding(m_context, 0, 0);
3335 for (GLint i = 1; i < max_buffers; ++i)
3336 {
3337 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3338 }
3339
3340 /* - unbind all buffers. */
3341 gl.bindVertexBuffers(0, max_buffers, 0, &offsets[0], &strides[0]);
3342 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3343 }
3344 catch (const std::exception&)
3345 {
3346 gl.deleteVertexArrays(1, &vao);
3347
3348 TCU_FAIL("Unexpected error generated");
3349 }
3350
3351 gl.deleteVertexArrays(1, &vao);
3352 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
3353
3354 /* Set result */
3355 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3356
3357 /* Done */
3358 return tcu::TestNode::STOP;
3359 }
3360
3361 /** Constructor
3362 *
3363 * @param context Test context
3364 **/
DispatchBindBuffersBaseTest(deqp::Context & context)3365 DispatchBindBuffersBaseTest::DispatchBindBuffersBaseTest(deqp::Context& context)
3366 : TestCase(context, "dispatch_bind_buffers_base", "Tests BindBuffersBase with dispatch command")
3367 {
3368 /* Nothing to be done */
3369 }
3370
3371 /** Execute test
3372 *
3373 * @return tcu::TestNode::STOP
3374 **/
iterate()3375 tcu::TestNode::IterateResult DispatchBindBuffersBaseTest::iterate()
3376 {
3377 static const GLchar* cs = "#version 440 core\n"
3378 "\n"
3379 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3380 "\n"
3381 "UBO_LIST\n"
3382 "layout (std140, binding = 0) buffer SSB {\n"
3383 " vec4 sum;\n"
3384 "} ssb;\n"
3385 "\n"
3386 "void main()\n"
3387 "{\n"
3388 " ssb.sum = SUM_LIST;\n"
3389 "}\n"
3390 "\n";
3391
3392 static const GLchar* ubo = "layout (std140, binding = XXX) uniform BXXX { vec4 data; } bXXX;";
3393
3394 static const GLintptr buffer_size = 4 * sizeof(GLfloat);
3395
3396 const Functions& gl = m_context.getRenderContext().getFunctions();
3397
3398 bool test_result = true;
3399
3400 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3401 gl.debugMessageCallback(debug_proc, &m_context);
3402 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3403 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3404
3405 GLint max_buffers = 0;
3406 GLfloat sum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3407
3408 /* Get max */
3409 gl.getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &max_buffers);
3410 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3411
3412 /* UBO */
3413 /* Storage */
3414 std::vector<Buffer> uni_buffer;
3415 std::vector<GLuint> uni_buffer_ids;
3416
3417 uni_buffer.resize(max_buffers);
3418 uni_buffer_ids.resize(max_buffers);
3419
3420 /* Prepare buffers */
3421 for (GLint i = 0; i < max_buffers; ++i)
3422 {
3423 const GLfloat data[4] = {
3424 (GLfloat)(i * 4 + 0), (GLfloat)(i * 4 + 1), (GLfloat)(i * 4 + 2), (GLfloat)(i * 4 + 3),
3425 };
3426
3427 sum[0] += data[0];
3428 sum[1] += data[1];
3429 sum[2] += data[2];
3430 sum[3] += data[3];
3431
3432 uni_buffer[i].InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, data);
3433
3434 uni_buffer_ids[i] = uni_buffer[i].m_id;
3435 }
3436
3437 gl.bindBuffersBase(GL_UNIFORM_BUFFER, 0 /* first */, max_buffers /* count */, &uni_buffer_ids[0]);
3438 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
3439
3440 /* SSBO */
3441 Buffer ssb_buffer;
3442 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3443
3444 ssb_buffer.BindBase(0);
3445
3446 /* Prepare program */
3447 size_t ubo_position = 0;
3448 size_t sum_position = 0;
3449 std::string cs_source = cs;
3450 for (GLint i = 0; i < max_buffers; ++i)
3451 {
3452 size_t ubo_start_position = ubo_position;
3453 size_t sum_start_position = sum_position;
3454
3455 GLchar index[16];
3456
3457 sprintf(index, "%d", i);
3458
3459 /* Add entry to ubo list */
3460 replaceToken("UBO_LIST", ubo_position, "UBO\nUBO_LIST", cs_source);
3461 ubo_position = ubo_start_position;
3462
3463 replaceToken("UBO", ubo_position, ubo, cs_source);
3464 ubo_position = ubo_start_position;
3465
3466 replaceToken("XXX", ubo_position, index, cs_source);
3467 replaceToken("XXX", ubo_position, index, cs_source);
3468 replaceToken("XXX", ubo_position, index, cs_source);
3469
3470 /* Add entry to sum list */
3471 replaceToken("SUM_LIST", sum_position, "bXXX.data + SUM_LIST", cs_source);
3472 sum_position = sum_start_position;
3473
3474 replaceToken("XXX", sum_position, index, cs_source);
3475 }
3476
3477 /* Remove token for lists */
3478 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3479 replaceToken("UBO_LIST", ubo_position, "", cs_source);
3480
3481 Program program(m_context);
3482 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3483
3484 program.Use();
3485
3486 gl.dispatchCompute(1, 1, 1);
3487 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3488
3489 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3490 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3491
3492 GLfloat* result = (GLfloat*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3493 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3494
3495 if (0 != memcmp(result, sum, 4 * sizeof(GLfloat)))
3496 {
3497 test_result = false;
3498 }
3499
3500 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3501 gl.getError(); /* Ignore error */
3502
3503 /* Set result */
3504 if (true == test_result)
3505 {
3506 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3507 }
3508 else
3509 {
3510 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3511 }
3512
3513 /* Done */
3514 return tcu::TestNode::STOP;
3515 }
3516
3517 /** Constructor
3518 *
3519 * @param context Test context
3520 **/
DispatchBindBuffersRangeTest(deqp::Context & context)3521 DispatchBindBuffersRangeTest::DispatchBindBuffersRangeTest(deqp::Context& context)
3522 : TestCase(context, "dispatch_bind_buffers_range", "Tests BindBuffersRange with dispatch command")
3523 {
3524 /* Nothing to be done */
3525 }
3526
3527 /** Execute test
3528 *
3529 * @return tcu::TestNode::STOP
3530 **/
iterate()3531 tcu::TestNode::IterateResult DispatchBindBuffersRangeTest::iterate()
3532 {
3533 static const GLchar* cs = "#version 440 core\n"
3534 "\n"
3535 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3536 "\n"
3537 "layout (std140, binding = 0) uniform B0 { int data; } b0;"
3538 "layout (std140, binding = 1) uniform B1 { int data; } b1;"
3539 "layout (std140, binding = 2) uniform B2 { int data; } b2;"
3540 "layout (std140, binding = 3) uniform B3 { int data; } b3;"
3541 "\n"
3542 "layout (std140, binding = 0) buffer SSB {\n"
3543 " int sum;\n"
3544 "} ssb;\n"
3545 "\n"
3546 "void main()\n"
3547 "{\n"
3548 " //ssb.sum = b1.data;// + b1.data + b2.data + b3.data;\n"
3549 " ssb.sum = b0.data + b1.data + b2.data + b3.data;\n"
3550 "}\n"
3551 "\n";
3552
3553 static const GLint data[] = { 0x00010001, 0x01000100 };
3554 static const size_t n_buffers = 4;
3555 static const GLint sum = 0x02020202;
3556
3557 const Functions& gl = m_context.getRenderContext().getFunctions();
3558
3559 bool test_result = true;
3560
3561 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3562 gl.debugMessageCallback(debug_proc, &m_context);
3563 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3564 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3565
3566 /* UBO */
3567 GLint offset_alignment = 0;
3568
3569 gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset_alignment);
3570 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3571
3572 /* Storage */
3573 Buffer uni_buffer;
3574 GLuint uni_buffer_ids[n_buffers];
3575 std::vector<GLubyte> uni_data;
3576 GLintptr uni_offsets[n_buffers];
3577 GLintptr uni_sizes[n_buffers];
3578
3579 const size_t buffer_size = (n_buffers - 1) * offset_alignment + sizeof(GLint);
3580 uni_data.resize(buffer_size);
3581
3582 for (size_t i = 0; i < buffer_size; ++i)
3583 {
3584 uni_data[i] = 0xaa;
3585 }
3586
3587 for (size_t i = 0; i < n_buffers; ++i)
3588 {
3589 void* dst = &uni_data[i * offset_alignment];
3590 const void* src = &data[(i % 2)];
3591
3592 memcpy(dst, src, sizeof(GLint));
3593 }
3594
3595 uni_buffer.InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, &uni_data[0]);
3596
3597 for (size_t i = 0; i < n_buffers; ++i)
3598 {
3599 uni_buffer_ids[i] = uni_buffer.m_id;
3600 uni_offsets[i] = i * offset_alignment;
3601 uni_sizes[i] = sizeof(GLint);
3602 }
3603
3604 gl.bindBuffersRange(GL_UNIFORM_BUFFER, 0 /* first */, n_buffers /* count */, &uni_buffer_ids[0], &uni_offsets[0],
3605 &uni_sizes[0]);
3606 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
3607
3608 /* SSBO */
3609 Buffer ssb_buffer;
3610 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLint), 0 /* data */);
3611
3612 ssb_buffer.BindBase(0);
3613
3614 /* Prepare program */
3615 Program program(m_context);
3616 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3617
3618 program.Use();
3619
3620 gl.dispatchCompute(1, 1, 1);
3621 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3622
3623 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3624 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3625
3626 GLint* result = (GLint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3627 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3628
3629 if (0 != memcmp(result, &sum, sizeof(sum)))
3630 {
3631 test_result = false;
3632 }
3633
3634 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3635 gl.getError(); /* Ignore error */
3636
3637 /* Set result */
3638 if (true == test_result)
3639 {
3640 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3641 }
3642 else
3643 {
3644 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3645 }
3646
3647 /* Done */
3648 return tcu::TestNode::STOP;
3649 }
3650
3651 /** Constructor
3652 *
3653 * @param context Test context
3654 **/
DispatchBindTexturesTest(deqp::Context & context)3655 DispatchBindTexturesTest::DispatchBindTexturesTest(deqp::Context& context)
3656 : TestCase(context, "dispatch_bind_textures", "Tests BindTextures with dispatch command")
3657 {
3658 /* Nothing to be done */
3659 }
3660
3661 /** Execute test
3662 *
3663 * @return tcu::TestNode::STOP
3664 **/
iterate()3665 tcu::TestNode::IterateResult DispatchBindTexturesTest::iterate()
3666 {
3667 static const GLchar* cs = "#version 440 core\n"
3668 "\n"
3669 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3670 "\n"
3671 "SAMPLER_LIST\n"
3672 "layout (std140, binding = 0) buffer SSB {\n"
3673 " uint sum;\n"
3674 "} ssb;\n"
3675 "\n"
3676 "void main()\n"
3677 "{\n"
3678 " uvec4 sum = SUM_LIST;\n"
3679 " ssb.sum = sum.r\n;"
3680 "}\n"
3681 "\n";
3682
3683 static const GLchar* sampler = "layout (location = XXX) uniform SAMPLER sXXX;";
3684
3685 static const GLchar* sampling[] = {
3686 "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)",
3687 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)",
3688 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS, 0)", "texelFetch(sXXX, COORDS, 0)"
3689 };
3690
3691 static const GLchar* samplers[] = { "usampler1D", "usampler1DArray", "usampler2D", "usampler2DArray",
3692 "usampler3D", "usamplerBuffer", "usamplerCube", "usamplerCubeArray",
3693 "usampler2DRect", "usampler2DMS", "usampler2DMSArray" };
3694
3695 static const GLchar* coordinates[] = {
3696 "0.5f",
3697 "vec2(0.5f, 0.0f)",
3698 "vec2(0.5f, 0.5f)",
3699 "vec3(0.5f, 0.5f, 0.0f)",
3700 "vec3(0.5f, 0.5f, 0.5f)",
3701 "0",
3702 "vec3(0.5f, 0.5f, 0.5f)",
3703 "vec4(0.5f, 0.5f, 0.5f, 0.0f)",
3704 "vec2(0.5f, 0.5f)",
3705 "ivec2(0, 0)",
3706 "ivec3(0, 0, 0)",
3707 };
3708
3709 static const GLuint depth = 6;
3710 static const GLuint height = 6;
3711 static const GLuint width = 6;
3712
3713 const Functions& gl = m_context.getRenderContext().getFunctions();
3714
3715 bool test_result = true;
3716
3717 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3718 gl.debugMessageCallback(debug_proc, &m_context);
3719 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3720 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3721
3722 GLint max_textures = 0;
3723 GLint max_image_samples = 0;
3724 GLuint sum = 0;
3725
3726 /* Get max */
3727 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
3728 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3729
3730 /* Check if load/store from multisampled images is supported */
3731 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3732 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3733
3734 /* Textures */
3735 /* Storage */
3736 std::vector<Texture> texture;
3737 std::vector<GLuint> texture_ids;
3738 Buffer texture_buffer;
3739
3740 texture.resize(max_textures);
3741 texture_ids.resize(max_textures);
3742
3743 /* Prepare */
3744 for (GLint i = 0; i < max_textures; ++i)
3745 {
3746 GLenum target = getTarget(i);
3747 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3748 target = GL_TEXTURE_2D;
3749
3750 GLuint data[width * height * depth];
3751
3752 for (GLuint j = 0; j < width * height * depth; ++j)
3753 {
3754 data[j] = i;
3755 }
3756
3757 sum += i;
3758
3759 bool is_array = false;
3760
3761 switch (target)
3762 {
3763 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3764 is_array = true;
3765 /* Intentional fallthrough */
3766
3767 case GL_TEXTURE_2D_MULTISAMPLE:
3768 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3769 fillMSTexture(m_context, texture[i].m_id, i, is_array);
3770 break;
3771
3772 case GL_TEXTURE_BUFFER:
3773 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
3774 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
3775 break;
3776
3777 default:
3778 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3779 Texture::Bind(gl, texture[i].m_id, target);
3780 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
3781 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
3782 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3783 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3784 break;
3785 }
3786
3787 /* Clean */
3788 Texture::Bind(gl, 0, target);
3789
3790 texture_ids[i] = texture[i].m_id;
3791 }
3792
3793 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
3794 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
3795
3796 /* SSBO */
3797 Buffer ssb_buffer;
3798 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
3799
3800 ssb_buffer.BindBase(0);
3801
3802 /* Prepare program */
3803 size_t sam_position = 0;
3804 size_t sum_position = 0;
3805 std::string cs_source = cs;
3806 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
3807 for (GLint i = 0; i < max_textures; ++i)
3808 {
3809 size_t sam_start_position = sam_position;
3810 size_t sum_start_position = sum_position;
3811
3812 GLchar index[16];
3813
3814 sprintf(index, "%d", i);
3815
3816 const GLchar* coords = 0;
3817 const GLchar* sampler_type = 0;
3818 const GLchar* sampling_code = 0;
3819
3820 if (i < max_target_index)
3821 {
3822 coords = coordinates[i];
3823 sampler_type = samplers[i];
3824 sampling_code = sampling[i];
3825 }
3826 else
3827 {
3828 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */
3829 sampler_type = samplers[2]; /* usampler2D */
3830 sampling_code = sampling[2]; /* texture(sXXX, COORDS) */
3831 }
3832
3833 /* Add entry to ubo list */
3834 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
3835 sam_position = sam_start_position;
3836
3837 replaceToken("SAMPLER", sam_position, sampler, cs_source);
3838 sam_position = sam_start_position;
3839
3840 replaceToken("XXX", sam_position, index, cs_source);
3841 replaceToken("SAMPLER", sam_position, sampler_type, cs_source);
3842 replaceToken("XXX", sam_position, index, cs_source);
3843
3844 /* Add entry to sum list */
3845 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
3846 sum_position = sum_start_position;
3847
3848 replaceToken("SAMPLING", sum_position, sampling_code, cs_source);
3849 sum_position = sum_start_position;
3850
3851 replaceToken("XXX", sum_position, index, cs_source);
3852 replaceToken("COORDS", sum_position, coords, cs_source);
3853 }
3854
3855 /* Remove token for lists */
3856 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3857 replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
3858
3859 Program program(m_context);
3860 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3861
3862 program.Use();
3863
3864 /* Set samplers */
3865 for (GLint i = 0; i < max_textures; ++i)
3866 {
3867 gl.uniform1i(i, i);
3868 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3869 }
3870
3871 gl.dispatchCompute(1, 1, 1);
3872 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3873
3874 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3875 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3876
3877 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3878 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3879
3880 if (0 != memcmp(result, &sum, sizeof(sum)))
3881 {
3882 test_result = false;
3883 }
3884
3885 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3886 gl.getError(); /* Ignore error */
3887
3888 /* Set result */
3889 if (true == test_result)
3890 {
3891 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3892 }
3893 else
3894 {
3895 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3896 }
3897
3898 /* Done */
3899 return tcu::TestNode::STOP;
3900 }
3901
3902 /** Constructor
3903 *
3904 * @param context Test context
3905 **/
DispatchBindImageTexturesTest(deqp::Context & context)3906 DispatchBindImageTexturesTest::DispatchBindImageTexturesTest(deqp::Context& context)
3907 : TestCase(context, "dispatch_bind_image_textures", "Tests BindImageTextures with dispatch command")
3908 {
3909 /* Nothing to be done */
3910 }
3911
3912 /** Execute test
3913 *
3914 * @return tcu::TestNode::STOP
3915 **/
iterate()3916 tcu::TestNode::IterateResult DispatchBindImageTexturesTest::iterate()
3917 {
3918 static const GLchar* cs = "#version 440 core\n"
3919 "\n"
3920 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3921 "\n"
3922 "IMAGE_LIST\n"
3923 "layout (std140, binding = 0) buffer SSB {\n"
3924 " uint sum;\n"
3925 "} ssb;\n"
3926 "\n"
3927 "void main()\n"
3928 "{\n"
3929 " uvec4 sum = SUM_LIST;\n"
3930 " ssb.sum = sum.r\n;"
3931 "}\n"
3932 "\n";
3933
3934 static const GLchar* image = "layout (location = XXX, r32ui) readonly uniform IMAGE iXXX;";
3935
3936 static const GLchar* loading[] = {
3937 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",
3938 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",
3939 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS, 0)", "imageLoad(iXXX, COORDS, 0)"
3940 };
3941
3942 static const GLchar* images[] = { "uimage1D", "uimage1DArray", "uimage2D", "uimage2DArray",
3943 "uimage3D", "uimageBuffer", "uimageCube", "uimageCubeArray",
3944 "uimage2DRect", "uimage2DMS", "uimage2DMSArray" };
3945
3946 static const GLchar* coordinates[] = {
3947 "0",
3948 "ivec2(0, 0)",
3949 "ivec2(0, 0)",
3950 "ivec3(0, 0, 0)",
3951 "ivec3(0, 0, 0)",
3952 "0",
3953 "ivec3(0, 0, 0)",
3954 "ivec3(0, 0, 0)",
3955 "ivec2(0, 0)",
3956 "ivec2(0, 0)",
3957 "ivec3(0, 0, 0)",
3958 };
3959
3960 static const GLuint depth = 6;
3961 static const GLuint height = 6;
3962 static const GLuint width = 6;
3963
3964 const Functions& gl = m_context.getRenderContext().getFunctions();
3965
3966 bool test_result = true;
3967
3968 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3969 gl.debugMessageCallback(debug_proc, &m_context);
3970 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3971 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3972
3973 GLint max_textures = 0;
3974 GLint max_image_samples = 0;
3975 GLuint sum = 0;
3976
3977 /* Get max */
3978 gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_textures);
3979 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3980
3981 /* Check if load/store from multisampled images is supported */
3982 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3983 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3984
3985 /* Textures */
3986 /* Storage */
3987 std::vector<Texture> texture;
3988 std::vector<GLuint> texture_ids;
3989 Buffer texture_buffer;
3990
3991 texture.resize(max_textures);
3992 texture_ids.resize(max_textures);
3993
3994 /* Prepare */
3995 for (GLint i = 0; i < max_textures; ++i)
3996 {
3997 GLenum target = getTarget(i);
3998 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3999 target = GL_TEXTURE_2D;
4000
4001 GLuint data[width * height * depth];
4002
4003 for (GLuint j = 0; j < width * height * depth; ++j)
4004 {
4005 data[j] = i;
4006 }
4007
4008 sum += i;
4009
4010 bool is_array = false;
4011
4012 switch (target)
4013 {
4014 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4015 is_array = true;
4016 /* Intentional fallthrough */
4017
4018 case GL_TEXTURE_2D_MULTISAMPLE:
4019 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4020 fillMSTexture(m_context, texture[i].m_id, i, is_array);
4021 break;
4022
4023 case GL_TEXTURE_BUFFER:
4024 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
4025 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
4026 break;
4027
4028 default:
4029 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4030 Texture::Bind(gl, texture[i].m_id, target);
4031 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4032 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4033 break;
4034 }
4035
4036 /* Clean */
4037 Texture::Bind(gl, 0, target);
4038
4039 texture_ids[i] = texture[i].m_id;
4040 }
4041
4042 gl.bindImageTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4043 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
4044
4045 /* SSBO */
4046 Buffer ssb_buffer;
4047 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4048
4049 ssb_buffer.BindBase(0);
4050
4051 /* Prepare program */
4052 size_t load_position = 0;
4053 size_t sum_position = 0;
4054 std::string cs_source = cs;
4055 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
4056 for (GLint i = 0; i < max_textures; ++i)
4057 {
4058 size_t load_start_position = load_position;
4059 size_t sum_start_position = sum_position;
4060
4061 GLchar index[16];
4062
4063 sprintf(index, "%d", i);
4064
4065 const GLchar* coords = 0;
4066 const GLchar* image_type = 0;
4067 const GLchar* loading_code = 0;
4068
4069 if (i < max_target_index)
4070 {
4071 coords = coordinates[i];
4072 image_type = images[i];
4073 loading_code = loading[i];
4074 }
4075 else
4076 {
4077 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */
4078 image_type = images[2]; /* usampler2D */
4079 loading_code = loading[2]; /* texture(sXXX, COORDS) */
4080 }
4081
4082 /* Add entry to ubo list */
4083 replaceToken("IMAGE_LIST", load_position, "IMAGE\nIMAGE_LIST", cs_source);
4084 load_position = load_start_position;
4085
4086 replaceToken("IMAGE", load_position, image, cs_source);
4087 load_position = load_start_position;
4088
4089 replaceToken("XXX", load_position, index, cs_source);
4090 replaceToken("IMAGE", load_position, image_type, cs_source);
4091 replaceToken("XXX", load_position, index, cs_source);
4092
4093 /* Add entry to sum list */
4094 replaceToken("SUM_LIST", sum_position, "LOADING + SUM_LIST", cs_source);
4095 sum_position = sum_start_position;
4096
4097 replaceToken("LOADING", sum_position, loading_code, cs_source);
4098 sum_position = sum_start_position;
4099
4100 replaceToken("XXX", sum_position, index, cs_source);
4101 replaceToken("COORDS", sum_position, coords, cs_source);
4102 }
4103
4104 /* Remove token for lists */
4105 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4106 replaceToken("IMAGE_LIST", load_position, "", cs_source);
4107
4108 Program program(m_context);
4109 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4110
4111 program.Use();
4112
4113 /* Set images */
4114 for (GLint i = 0; i < max_textures; ++i)
4115 {
4116 gl.uniform1i(i, i);
4117 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4118 }
4119
4120 gl.dispatchCompute(1, 1, 1);
4121 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4122
4123 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4124 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4125
4126 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4127 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4128
4129 if (0 != memcmp(result, &sum, sizeof(sum)))
4130 {
4131 test_result = false;
4132 }
4133
4134 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4135 gl.getError(); /* Ignore error */
4136
4137 /* Set result */
4138 if (true == test_result)
4139 {
4140 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4141 }
4142 else
4143 {
4144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4145 }
4146
4147 /* Done */
4148 return tcu::TestNode::STOP;
4149 }
4150
4151 /** Constructor
4152 *
4153 * @param context Test context
4154 **/
DispatchBindSamplersTest(deqp::Context & context)4155 DispatchBindSamplersTest::DispatchBindSamplersTest(deqp::Context& context)
4156 : TestCase(context, "dispatch_bind_samplers", "Tests BindSamplers with dispatch command")
4157 {
4158 /* Nothing to be done */
4159 }
4160
4161 /** Execute test
4162 *
4163 * @return tcu::TestNode::STOP
4164 **/
iterate()4165 tcu::TestNode::IterateResult DispatchBindSamplersTest::iterate()
4166 {
4167 static const GLchar* cs = "#version 440 core\n"
4168 "\n"
4169 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4170 "\n"
4171 "SAMPLER_LIST\n"
4172 "layout (std140, binding = 0) buffer SSB {\n"
4173 " uint sum;\n"
4174 "} ssb;\n"
4175 "\n"
4176 "void main()\n"
4177 "{\n"
4178 " uvec4 sum = SUM_LIST;\n"
4179 " ssb.sum = sum.r\n;"
4180 "}\n"
4181 "\n";
4182
4183 static const GLchar* sampler = "layout (location = XXX) uniform usampler2D sXXX;";
4184
4185 static const GLchar* sampling = "texture(sXXX, vec2(1.5f, 0.5f))";
4186
4187 static const GLuint depth = 1;
4188 static const GLuint height = 8;
4189 static const GLuint width = 8;
4190
4191 const Functions& gl = m_context.getRenderContext().getFunctions();
4192
4193 bool test_result = true;
4194
4195 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4196 gl.debugMessageCallback(debug_proc, &m_context);
4197 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4198 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4199
4200 GLint max_textures = 0;
4201
4202 /* Get max */
4203 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
4204 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4205
4206 /* Textures */
4207 /* Storage */
4208 std::vector<GLuint> sampler_ids;
4209 std::vector<Texture> texture;
4210 std::vector<GLuint> texture_ids;
4211
4212 sampler_ids.resize(max_textures);
4213 texture.resize(max_textures);
4214 texture_ids.resize(max_textures);
4215
4216 GLuint data[width * height * depth];
4217
4218 for (GLuint j = 0; j < width * height; ++j)
4219 {
4220 data[j] = 0;
4221 }
4222
4223 {
4224 const size_t last_line_offset = (height - 1) * width;
4225 const size_t last_pixel_in_line_offset = width - 1;
4226
4227 for (GLuint j = 0; j < width; ++j)
4228 {
4229 data[j] = 1;
4230 data[j + last_line_offset] = 1;
4231 }
4232
4233 for (GLuint j = 0; j < height; ++j)
4234 {
4235 const size_t line_offset = j * width;
4236
4237 data[line_offset] = 1;
4238 data[line_offset + last_pixel_in_line_offset] = 1;
4239 }
4240 }
4241
4242 /* Prepare */
4243 for (GLint i = 0; i < max_textures; ++i)
4244 {
4245 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_R32UI, width, height, depth);
4246 Texture::Bind(gl, texture[i].m_id, GL_TEXTURE_2D);
4247 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4248 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4249
4250 texture_ids[i] = texture[i].m_id;
4251 }
4252
4253 /* Clean */
4254 Texture::Bind(gl, 0, GL_TEXTURE_2D);
4255
4256 /* Execute the test */
4257 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4258 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
4259
4260 /* SSBO */
4261 Buffer ssb_buffer;
4262 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4263
4264 ssb_buffer.BindBase(0);
4265
4266 /* Prepare program */
4267 size_t sam_position = 0;
4268 size_t sum_position = 0;
4269 std::string cs_source = cs;
4270
4271 for (GLint i = 0; i < max_textures; ++i)
4272 {
4273 size_t sam_start_position = sam_position;
4274 size_t sum_start_position = sum_position;
4275
4276 GLchar index[16];
4277
4278 sprintf(index, "%d", i);
4279
4280 /* Add entry to ubo list */
4281 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
4282 sam_position = sam_start_position;
4283
4284 replaceToken("SAMPLER", sam_position, sampler, cs_source);
4285 sam_position = sam_start_position;
4286
4287 replaceToken("XXX", sam_position, index, cs_source);
4288 replaceToken("XXX", sam_position, index, cs_source);
4289
4290 /* Add entry to sum list */
4291 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
4292 sum_position = sum_start_position;
4293
4294 replaceToken("SAMPLING", sum_position, sampling, cs_source);
4295 sum_position = sum_start_position;
4296
4297 replaceToken("XXX", sum_position, index, cs_source);
4298 }
4299
4300 /* Remove token for lists */
4301 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4302 replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
4303
4304 Program program(m_context);
4305 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4306
4307 program.Use();
4308
4309 /* Set texture units */
4310 for (GLint i = 0; i < max_textures; ++i)
4311 {
4312 gl.uniform1i(i, i);
4313 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4314 }
4315
4316 /* Prepare samplers */
4317 gl.genSamplers(max_textures, &sampler_ids[0]);
4318 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
4319
4320 try
4321 {
4322 gl.bindSamplers(0 /* first */, max_textures /* count */, &sampler_ids[0]);
4323 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
4324
4325 for (GLint i = 0; i < max_textures; ++i)
4326 {
4327 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4328 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4329 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4330 GLU_EXPECT_NO_ERROR(gl.getError(), "SamplerParameteri");
4331 }
4332
4333 gl.dispatchCompute(1, 1, 1);
4334 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4335
4336 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4337 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4338 }
4339 catch (const std::exception&)
4340 {
4341 gl.deleteSamplers(max_textures, &sampler_ids[0]);
4342
4343 TCU_FAIL("Unexpected error generated");
4344 }
4345
4346 /* Remove samplers */
4347 gl.deleteSamplers(max_textures, &sampler_ids[0]);
4348
4349 /* Verify results */
4350 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4351 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4352
4353 if (0 != memcmp(result, &max_textures, sizeof(max_textures)))
4354 {
4355 test_result = false;
4356 }
4357
4358 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4359 gl.getError(); /* Ignore error */
4360
4361 /* Set result */
4362 if (true == test_result)
4363 {
4364 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4365 }
4366 else
4367 {
4368 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4369 }
4370
4371 /* Done */
4372 return tcu::TestNode::STOP;
4373 }
4374
4375 /** Constructor
4376 *
4377 * @param context Test context
4378 **/
DrawBindVertexBuffersTest(deqp::Context & context)4379 DrawBindVertexBuffersTest::DrawBindVertexBuffersTest(deqp::Context& context)
4380 : TestCase(context, "draw_bind_vertex_buffers", "Tests BindVertexBuffers command with drawArrays")
4381 {
4382 /* Nothing to be done */
4383 }
4384
4385 /** Execute test
4386 *
4387 * @return tcu::TestNode::STOP
4388 **/
iterate()4389 tcu::TestNode::IterateResult DrawBindVertexBuffersTest::iterate()
4390 {
4391 static const GLchar* vs = "#version 440 core\n"
4392 "\n"
4393 "ATTRIBUTE_LIST\n"
4394 "\n"
4395 "out vec4 vs_gs_sum;\n"
4396 "\n"
4397 "void main()\n"
4398 "{\n"
4399 " vs_gs_sum = SUM_LIST;\n"
4400 "}\n"
4401 "\n";
4402
4403 static const GLchar* gs = "#version 440 core\n"
4404 "\n"
4405 "layout(points) in;\n"
4406 "layout(triangle_strip, max_vertices = 4) out;\n"
4407 "\n"
4408 "in vec4 vs_gs_sum[];\n"
4409 "out vec4 gs_fs_sum;\n"
4410 "\n"
4411 "void main()\n"
4412 "{\n"
4413 " gs_fs_sum = vs_gs_sum[0];\n"
4414 " gl_Position = vec4(-1, -1, 0, 1);\n"
4415 " EmitVertex();\n"
4416 " gs_fs_sum = vs_gs_sum[0];\n"
4417 " gl_Position = vec4(-1, 1, 0, 1);\n"
4418 " EmitVertex();\n"
4419 " gs_fs_sum = vs_gs_sum[0];\n"
4420 " gl_Position = vec4(1, -1, 0, 1);\n"
4421 " EmitVertex();\n"
4422 " gs_fs_sum = vs_gs_sum[0];\n"
4423 " gl_Position = vec4(1, 1, 0, 1);\n"
4424 " EmitVertex();\n"
4425 "}\n"
4426 "\n";
4427
4428 static const GLchar* fs = "#version 440 core\n"
4429 "\n"
4430 "in vec4 gs_fs_sum;\n"
4431 "out vec4 fs_out;\n"
4432 "\n"
4433 "void main()\n"
4434 "{\n"
4435 " fs_out = gs_fs_sum;\n"
4436 "}\n"
4437 "\n";
4438
4439 static const GLchar* attribute = "layout (location = XXX) in vec4 aXXX;";
4440
4441 static const GLuint height = 8;
4442 static const GLuint width = 8;
4443
4444 const Functions& gl = m_context.getRenderContext().getFunctions();
4445
4446 bool test_result = true;
4447
4448 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4449 gl.debugMessageCallback(debug_proc, &m_context);
4450 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4451 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4452
4453 static const GLintptr attribute_size = 4 * sizeof(GLfloat);
4454
4455 GLint max_buffers = 0;
4456 GLuint vao = 0;
4457
4458 /* Get max */
4459 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
4460 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4461
4462 /* Storage */
4463 Buffer buffer;
4464 std::vector<GLuint> buffer_ids;
4465 std::vector<GLfloat> data;
4466 std::vector<GLintptr> offsets;
4467 std::vector<GLsizei> strides;
4468
4469 buffer_ids.resize(max_buffers);
4470 data.resize(max_buffers * 4);
4471 offsets.resize(max_buffers);
4472 strides.resize(max_buffers);
4473
4474 /* Prepare data */
4475 const GLfloat value = 1.0f / (GLfloat)max_buffers;
4476
4477 for (GLint i = 0; i < max_buffers; ++i)
4478 {
4479 data[i * 4 + 0] = value;
4480 data[i * 4 + 1] = value;
4481 data[i * 4 + 2] = value;
4482 data[i * 4 + 3] = value;
4483 }
4484
4485 /* Prepare buffer */
4486 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, data.size() * sizeof(GLfloat), &data[0]);
4487
4488 for (GLint i = 0; i < max_buffers; ++i)
4489 {
4490 buffer_ids[i] = buffer.m_id;
4491 offsets[i] = i * attribute_size;
4492 strides[i] = attribute_size;
4493 }
4494
4495 /* Prepare FBO */
4496 Framebuffer framebuffer(m_context);
4497 Texture texture;
4498
4499 texture.InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 1 /* depth */);
4500
4501 /* */
4502 Framebuffer::Generate(gl, framebuffer.m_id);
4503 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
4504 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
4505 height);
4506
4507 /* Prepare program */
4508 size_t attr_position = 0;
4509 size_t sum_position = 0;
4510 std::string vs_source = vs;
4511 for (GLint i = 0; i < max_buffers; ++i)
4512 {
4513 size_t attr_start_position = attr_position;
4514 size_t sum_start_position = sum_position;
4515
4516 GLchar index[16];
4517
4518 sprintf(index, "%d", i);
4519
4520 /* Add entry to ubo list */
4521 replaceToken("ATTRIBUTE_LIST", attr_position, "ATTRIBUTE\nATTRIBUTE_LIST", vs_source);
4522 attr_position = attr_start_position;
4523
4524 replaceToken("ATTRIBUTE", attr_position, attribute, vs_source);
4525 attr_position = attr_start_position;
4526
4527 replaceToken("XXX", attr_position, index, vs_source);
4528 replaceToken("XXX", attr_position, index, vs_source);
4529
4530 /* Add entry to sum list */
4531 replaceToken("SUM_LIST", sum_position, "aXXX + SUM_LIST", vs_source);
4532 sum_position = sum_start_position;
4533
4534 replaceToken("XXX", sum_position, index, vs_source);
4535 }
4536
4537 /* Remove token for lists */
4538 replaceToken(" + SUM_LIST", sum_position, "", vs_source);
4539 replaceToken("ATTRIBUTE_LIST", attr_position, "", vs_source);
4540
4541 Program program(m_context);
4542 program.Init("" /* cs */, fs, gs, "" /* tcs */, "" /* tes */, vs_source.c_str());
4543
4544 program.Use();
4545
4546 gl.genVertexArrays(1, &vao);
4547 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4548
4549 try
4550 {
4551 gl.bindVertexArray(vao);
4552 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
4553
4554 for (GLint i = 0; i < max_buffers; ++i)
4555 {
4556 gl.enableVertexAttribArray(i);
4557 GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
4558 }
4559
4560 /* */
4561 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
4562 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
4563
4564 /* */
4565 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4566 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4567
4568 for (GLint i = 0; i < max_buffers; ++i)
4569 {
4570 gl.disableVertexAttribArray(i);
4571 GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
4572 }
4573 }
4574 catch (const std::exception&)
4575 {
4576 gl.deleteVertexArrays(1, &vao);
4577
4578 TCU_FAIL("Unexpected error generated");
4579 }
4580
4581 gl.deleteVertexArrays(1, &vao);
4582 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
4583
4584 /* Verify results */
4585 GLuint pixels[width * height];
4586 for (GLuint i = 0; i < width * height; ++i)
4587 {
4588 pixels[i] = 0;
4589 }
4590
4591 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
4592
4593 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
4594
4595 /* Unbind */
4596 Texture::Bind(gl, 0, GL_TEXTURE_2D);
4597
4598 /* Verify */
4599 for (GLuint i = 0; i < width * height; ++i)
4600 {
4601 if (0xffffffff != pixels[i])
4602 {
4603 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
4604 << " at offset: " << i << tcu::TestLog::EndMessage;
4605
4606 test_result = false;
4607
4608 break;
4609 }
4610 }
4611
4612 /* Set result */
4613 if (true == test_result)
4614 {
4615 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4616 }
4617 else
4618 {
4619 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4620 }
4621
4622 /* Done */
4623 return tcu::TestNode::STOP;
4624 }
4625 } /* MultiBind */
4626
4627 /** Constructor.
4628 *
4629 * @param context Rendering context.
4630 **/
MultiBindTests(deqp::Context & context)4631 MultiBindTests::MultiBindTests(deqp::Context& context)
4632 : TestCaseGroup(context, "multi_bind", "Verifies \"multi bind\" functionality")
4633 {
4634 /* Left blank on purpose */
4635 }
4636
4637 /** Initializes a multi_bind test group.
4638 *
4639 **/
init(void)4640 void MultiBindTests::init(void)
4641 {
4642 addChild(new MultiBind::DispatchBindTexturesTest(m_context));
4643
4644 addChild(new MultiBind::ErrorsBindBuffersTest(m_context));
4645 addChild(new MultiBind::ErrorsBindTexturesTest(m_context));
4646 addChild(new MultiBind::ErrorsBindSamplersTest(m_context));
4647 addChild(new MultiBind::ErrorsBindImageTexturesTest(m_context));
4648 addChild(new MultiBind::ErrorsBindVertexBuffersTest(m_context));
4649 addChild(new MultiBind::FunctionalBindBuffersBaseTest(m_context));
4650 addChild(new MultiBind::FunctionalBindBuffersRangeTest(m_context));
4651 addChild(new MultiBind::FunctionalBindTexturesTest(m_context));
4652 addChild(new MultiBind::FunctionalBindSamplersTest(m_context));
4653 addChild(new MultiBind::FunctionalBindImageTexturesTest(m_context));
4654 addChild(new MultiBind::FunctionalBindVertexBuffersTest(m_context));
4655 addChild(new MultiBind::DispatchBindBuffersBaseTest(m_context));
4656 addChild(new MultiBind::DispatchBindBuffersRangeTest(m_context));
4657
4658 addChild(new MultiBind::DispatchBindImageTexturesTest(m_context));
4659 addChild(new MultiBind::DispatchBindSamplersTest(m_context));
4660 addChild(new MultiBind::DrawBindVertexBuffersTest(m_context));
4661 }
4662
4663 } /* gl4cts namespace */
4664