xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cBufferStorageTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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  gl4cBufferStorageTests.cpp
26  * \brief Implements conformance tests for "Buffer storage" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cBufferStorageTests.hpp"
30 
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuImageIO.hpp"
37 #include "tcuTestLog.hpp"
38 #include "tcuTexture.hpp"
39 
40 #include <iomanip>
41 #include <string>
42 
43 using namespace glw;
44 
45 namespace gl4cts
46 {
47 namespace BufferStorage
48 {
49 /* Enums */
50 
51 /* Represents how functionality is supported */
52 enum FUNCTIONALITY_SUPPORT
53 {
54     FUNCTIONALITY_SUPPORT_NONE = 0,
55     FUNCTIONALITY_SUPPORT_EXTENSION,
56     FUNCTIONALITY_SUPPORT_CORE,
57     FUNCTIONALITY_SUPPORT_NOT_DETERMINED,
58 };
59 
60 /* Prototypes of functions  */
61 FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context &context);
62 bool isGLVersionAtLeast(const glw::Functions &gl, glw::GLint required_major, glw::GLint required_minor);
63 
64 /* Classes */
65 
66 /** Represents buffer instance
67  * Provides basic buffer functionality
68  **/
69 class Buffer
70 {
71 public:
72     // I don't quite understand how the old code *ever* worked...
73     // This is uglyish hack to make it actually compile on any sane
74     // compiler, and not crash.
75     struct MoveMapOwner
76     {
MoveMapOwnergl4cts::BufferStorage::Buffer::MoveMapOwner77         MoveMapOwner(Buffer *buffer_, glw::GLvoid *data_) : buffer(buffer_), data(data_)
78         {
79         }
80 
81         Buffer *buffer;
82         glw::GLvoid *data;
83     };
84 
85     /* Public classes */
86     class MapOwner
87     {
88         friend class Buffer;
89 
90     public:
91         MapOwner(MapOwner &map_owner);
92         MapOwner(const MoveMapOwner &moveOwner);
93         ~MapOwner();
94 
95         glw::GLvoid *m_data;
96 
97     private:
98         MapOwner(Buffer &buffer, glw::GLvoid *data);
99 
100         Buffer *m_buffer;
101     };
102 
103     /* Public methods */
104     /* Ctr & Dtr */
105     Buffer(deqp::Context &context);
106     ~Buffer();
107 
108     /* Init & Release */
109     void InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid *data);
110 
111     void InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid *data);
112 
113     void Release();
114 
115     /* Functionality */
116     void Bind() const;
117     void BindBase(glw::GLuint index) const;
118 
119     void BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const;
120 
121     MoveMapOwner MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access);
122 
123     void UnMap();
124 
125     /* Public static routines */
126     /* Extensions */
127     static void LoadExtDirectStateAccess(deqp::Context &context);
128 
129     /* Functionality */
130     static void Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target);
131 
132     static void BindBase(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index);
133 
134     static void BindRange(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
135                           glw::GLintptr offset, glw::GLsizeiptr size);
136 
137     static void Data(const glw::Functions &gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
138                      const glw::GLvoid *data);
139 
140     static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
141 
142     static void GetNamedParameter(const glw::Functions &gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint *data);
143 
144     static void GetParameter(const glw::Functions &gl, glw::GLenum target, glw::GLenum value, glw::GLint *data);
145 
146     static void GetSubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
147                            glw::GLvoid *data);
148 
149     static void *Map(const glw::Functions &gl, glw::GLenum target, glw::GLenum access);
150 
151     static void *MapRange(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
152                           glw::GLenum access);
153 
154     static void Storage(const glw::Functions &gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
155                         const glw::GLvoid *data);
156 
157     static void SubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
158                         glw::GLvoid *data);
159 
160     static void UnMap(const glw::Functions &gl, glw::GLenum target);
161 
162     /* Public fields */
163     glw::GLuint m_id;
164 
165     /* Public constants */
166     static const glw::GLuint m_invalid_id;
167     static const glw::GLuint m_n_targets = 13;
168     static const glw::GLenum m_targets[m_n_targets];
169 
170 private:
171     /* Private enums */
172 
173     /* Private fields */
174     deqp::Context &m_context;
175     glw::GLenum m_target;
176 };
177 
178 /** Represents framebuffer
179  * Provides basic functionality
180  **/
181 class Framebuffer
182 {
183 public:
184     /* Public methods */
185     /* Ctr & Dtr */
186     Framebuffer(deqp::Context &context);
187     ~Framebuffer();
188 
189     /* Init & Release */
190     void Release();
191 
192     /* Public static routines */
193     static void AttachTexture(const glw::Functions &gl, glw::GLenum target, glw::GLenum attachment,
194                               glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
195 
196     static void Bind(const glw::Functions &gl, glw::GLenum target, glw::GLuint id);
197 
198     static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
199 
200     /* Public fields */
201     glw::GLuint m_id;
202 
203     /* Public constants */
204     static const glw::GLuint m_invalid_id;
205 
206 private:
207     /* Private fields */
208     deqp::Context &m_context;
209 };
210 
211 /** Represents shader instance.
212  * Provides basic functionality for shaders.
213  **/
214 class Shader
215 {
216 public:
217     /* Public methods */
218     /* Ctr & Dtr */
219     Shader(deqp::Context &context);
220     ~Shader();
221 
222     /* Init & Realese */
223     void Init(glw::GLenum stage, const std::string &source);
224     void Release();
225 
226     /* Public static routines */
227     /* Functionality */
228     static void Compile(const glw::Functions &gl, glw::GLuint id);
229 
230     static void Create(const glw::Functions &gl, glw::GLenum stage, glw::GLuint &out_id);
231 
232     static void Source(const glw::Functions &gl, glw::GLuint id, const std::string &source);
233 
234     /* Public fields */
235     glw::GLuint m_id;
236 
237     /* Public constants */
238     static const glw::GLuint m_invalid_id;
239 
240 private:
241     /* Private fields */
242     deqp::Context &m_context;
243 };
244 
245 /** Represents program instance.
246  * Provides basic functionality
247  **/
248 class Program
249 {
250 public:
251     /* Public methods */
252     /* Ctr & Dtr */
253     Program(deqp::Context &context);
254     ~Program();
255 
256     /* Init & Release */
257     void Init(const std::string &compute_shader, const std::string &fragment_shader, const std::string &geometry_shader,
258               const std::string &tesselation_control_shader, const std::string &tesselation_evaluation_shader,
259               const std::string &vertex_shader);
260 
261     void Release();
262 
263     /* Public static routines */
264     /* Functionality */
265     static void Attach(const glw::Functions &gl, glw::GLuint program_id, glw::GLuint shader_id);
266 
267     static void Create(const glw::Functions &gl, glw::GLuint &out_id);
268 
269     static void Link(const glw::Functions &gl, glw::GLuint id);
270 
271     static void Use(const glw::Functions &gl, glw::GLuint id);
272 
273     /* Public fields */
274     glw::GLuint m_id;
275 
276     Shader m_compute;
277     Shader m_fragment;
278     Shader m_geometry;
279     Shader m_tess_ctrl;
280     Shader m_tess_eval;
281     Shader m_vertex;
282 
283     /* Public constants */
284     static const glw::GLuint m_invalid_id;
285 
286 private:
287     /* Private fields */
288     deqp::Context &m_context;
289 };
290 
291 /** Represents texture instance
292  **/
293 class Texture
294 {
295 public:
296     /* Public types */
297     /* Public methods */
298     /* Ctr & Dtr */
299     Texture(deqp::Context &context);
300     ~Texture();
301 
302     /* Init & Release */
303     void Release();
304 
305     /* Public static routines */
306     /* Extensions */
307     static void LoadExtDirectStateAccess(deqp::Context &context);
308 
309     /* Functionality */
310     static void Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target);
311 
312     static void CompressedImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level,
313                                 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
314                                 glw::GLsizei image_size, const glw::GLvoid *data);
315 
316     static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
317 
318     static void GetData(const glw::Functions &gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
319                         glw::GLvoid *out_data);
320 
321     static void GetLevelParameter(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
322                                   glw::GLint *param);
323 
324     static void Image(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
325                       glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
326                       const glw::GLvoid *data);
327 
328     static void Storage(const glw::Functions &gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
329                         glw::GLuint width, glw::GLuint height, glw::GLuint depth);
330 
331     static void SubImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
332                          glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
333                          glw::GLenum type, const glw::GLvoid *pixels);
334 
335     /* Public fields */
336     glw::GLuint m_id;
337 
338     /* Public constants */
339     static const glw::GLuint m_invalid_id;
340 
341 private:
342     /* Private fields */
343     deqp::Context &m_context;
344 
345     /* Private static fields */
346     static FUNCTIONALITY_SUPPORT m_direct_state_access_support;
347 };
348 
349 /** Represents Vertex array object
350  * Provides basic functionality
351  **/
352 class VertexArray
353 {
354 public:
355     /* Public methods */
356     /* Ctr & Dtr */
357     VertexArray(deqp::Context &Context);
358     ~VertexArray();
359 
360     /* Init & Release */
361     void Release();
362 
363     /* Public static methods */
364     static void Bind(const glw::Functions &gl, glw::GLuint id);
365     static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
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 /* Global variables */
379 static FUNCTIONALITY_SUPPORT m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
380 
381 /* Implementations of functions */
382 /** Get support for direct state access
383  *
384  * @param context CTS context
385  **/
getDirectStateAccessSupport(deqp::Context & context)386 FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context &context)
387 {
388     if (FUNCTIONALITY_SUPPORT_NOT_DETERMINED == m_direct_state_access_support)
389     {
390         const Functions &gl = context.getRenderContext().getFunctions();
391 
392         if (true == isGLVersionAtLeast(gl, 4, 5))
393         {
394             m_direct_state_access_support = FUNCTIONALITY_SUPPORT_CORE;
395         }
396         else
397         {
398             bool is_supported = context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
399 
400             if (true == is_supported)
401             {
402                 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_EXTENSION;
403             }
404             else
405             {
406                 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NONE;
407             }
408         }
409     }
410 
411     return m_direct_state_access_support;
412 }
413 
414 /** Check if GL context meets version requirements
415  *
416  * @param gl             Functions
417  * @param required_major Minimum required MAJOR_VERSION
418  * @param required_minor Minimum required MINOR_VERSION
419  *
420  * @return true if GL context version is at least as requested, false otherwise
421  **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)422 bool isGLVersionAtLeast(const glw::Functions &gl, glw::GLint required_major, glw::GLint required_minor)
423 {
424     glw::GLint major = 0;
425     glw::GLint minor = 0;
426 
427     gl.getIntegerv(GL_MAJOR_VERSION, &major);
428     gl.getIntegerv(GL_MINOR_VERSION, &minor);
429 
430     GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
431 
432     if (major > required_major)
433     {
434         /* Major is higher than required one */
435         return true;
436     }
437     else if (major == required_major)
438     {
439         if (minor >= required_minor)
440         {
441             /* Major is equal to required one */
442             /* Minor is higher than or equal to required one */
443             return true;
444         }
445         else
446         {
447             /* Major is equal to required one */
448             /* Minor is lower than required one */
449             return false;
450         }
451     }
452     else
453     {
454         /* Major is lower than required one */
455         return false;
456     }
457 }
458 
459 /* Buffer constants */
460 const GLuint Buffer::m_invalid_id = -1;
461 
462 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
463     GL_ARRAY_BUFFER,              /*  0 */
464     GL_ATOMIC_COUNTER_BUFFER,     /*  1 */
465     GL_COPY_READ_BUFFER,          /*  2 */
466     GL_COPY_WRITE_BUFFER,         /*  3 */
467     GL_DISPATCH_INDIRECT_BUFFER,  /*  4 */
468     GL_DRAW_INDIRECT_BUFFER,      /*  5 */
469     GL_ELEMENT_ARRAY_BUFFER,      /*  6 */
470     GL_PIXEL_PACK_BUFFER,         /*  7 */
471     GL_PIXEL_UNPACK_BUFFER,       /*  8 */
472     GL_QUERY_BUFFER,              /*  9 */
473     GL_SHADER_STORAGE_BUFFER,     /* 10 */
474     GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
475     GL_UNIFORM_BUFFER,            /* 12 */
476 };
477 
478 /** Constructor.
479  *
480  * @param context CTS context.
481  **/
Buffer(deqp::Context & context)482 Buffer::Buffer(deqp::Context &context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
483 {
484 }
485 
486 /** Destructor
487  *
488  **/
~Buffer()489 Buffer::~Buffer()
490 {
491     Release();
492 }
493 
494 /** Initialize buffer instance
495  *
496  * @param target Buffer target
497  * @param usage  Buffer usage enum
498  * @param size   <size> parameter
499  * @param data   <data> parameter
500  **/
InitData(glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)501 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid *data)
502 {
503     /* Delete previous buffer instance */
504     Release();
505 
506     m_target = target;
507 
508     const Functions &gl = m_context.getRenderContext().getFunctions();
509 
510     Generate(gl, m_id);
511     Bind(gl, m_id, m_target);
512     Data(gl, m_target, usage, size, data);
513 }
514 
515 /** Initialize buffer instance
516  *
517  * @param target Buffer target
518  * @param usage  Buffer usage enum
519  * @param size   <size> parameter
520  * @param data   <data> parameter
521  **/
InitStorage(glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)522 void Buffer::InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid *data)
523 {
524     /* Delete previous buffer instance */
525     Release();
526 
527     m_target = target;
528 
529     const Functions &gl = m_context.getRenderContext().getFunctions();
530 
531     Generate(gl, m_id);
532     Bind(gl, m_id, m_target);
533     Storage(gl, m_target, flags, size, data);
534 }
535 
536 /** Release buffer instance
537  *
538  **/
Release()539 void Buffer::Release()
540 {
541     if (m_invalid_id != m_id)
542     {
543         const Functions &gl = m_context.getRenderContext().getFunctions();
544 
545         gl.deleteBuffers(1, &m_id);
546         m_id = m_invalid_id;
547     }
548 }
549 
550 /** Binds buffer to its target
551  *
552  **/
Bind() const553 void Buffer::Bind() const
554 {
555     const Functions &gl = m_context.getRenderContext().getFunctions();
556 
557     Bind(gl, m_id, m_target);
558 }
559 
560 /** Binds indexed buffer
561  *
562  * @param index <index> parameter
563  **/
BindBase(glw::GLuint index) const564 void Buffer::BindBase(glw::GLuint index) const
565 {
566     const Functions &gl = m_context.getRenderContext().getFunctions();
567 
568     BindBase(gl, m_id, m_target, index);
569 }
570 
571 /** Binds range of buffer
572  *
573  * @param index  <index> parameter
574  * @param offset <offset> parameter
575  * @param size   <size> parameter
576  **/
BindRange(glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size) const577 void Buffer::BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const
578 {
579     const Functions &gl = m_context.getRenderContext().getFunctions();
580 
581     BindRange(gl, m_id, m_target, index, offset, size);
582 }
583 
584 /** Maps contents of buffer into CPU space
585  *
586  * @param access Requested access
587  *
588  * @return Pointer to memory region available for CPU
589  **/
MapRange(glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)590 Buffer::MoveMapOwner Buffer::MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access)
591 {
592     const Functions &gl = m_context.getRenderContext().getFunctions();
593 
594     Bind(gl, m_id, m_target);
595 
596     void *data = MapRange(gl, m_target, offset, length, access);
597 
598     MoveMapOwner map(this, data);
599 
600     return map;
601 }
602 
603 /** Unmaps contents of buffer
604  *
605  **/
UnMap()606 void Buffer::UnMap()
607 {
608     const Functions &gl = m_context.getRenderContext().getFunctions();
609 
610     UnMap(gl, m_target);
611 }
612 
613 /** Loads entry points for direct state access extension
614  *
615  * @param context CTS context
616  **/
LoadExtDirectStateAccess(deqp::Context & context)617 void Buffer::LoadExtDirectStateAccess(deqp::Context &context)
618 {
619     FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
620 
621     switch (support)
622     {
623     case FUNCTIONALITY_SUPPORT_NONE:
624         /* Nothing to be done */
625         break;
626     case FUNCTIONALITY_SUPPORT_CORE:
627     case FUNCTIONALITY_SUPPORT_EXTENSION:
628         break;
629     default:
630         TCU_FAIL("Invalid enum");
631     }
632 }
633 
634 /** Bind buffer to given target
635  *
636  * @param gl     GL functions
637  * @param id     Id of buffer
638  * @param target Buffer target
639  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)640 void Buffer::Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target)
641 {
642     gl.bindBuffer(target, id);
643     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
644 }
645 
646 /** Binds indexed buffer
647  *
648  * @param gl     GL functions
649  * @param id     Id of buffer
650  * @param target Buffer target
651  * @param index  <index> parameter
652  **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)653 void Buffer::BindBase(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
654 {
655     gl.bindBufferBase(target, index, id);
656     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
657 }
658 
659 /** Binds buffer range
660  *
661  * @param gl     GL functions
662  * @param id     Id of buffer
663  * @param target Buffer target
664  * @param index  <index> parameter
665  * @param offset <offset> parameter
666  * @param size   <size> parameter
667  **/
BindRange(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)668 void Buffer::BindRange(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
669                        glw::GLintptr offset, glw::GLsizeiptr size)
670 {
671     gl.bindBufferRange(target, index, id, offset, size);
672     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
673 }
674 
675 /** Allocate memory for buffer and sends initial content
676  *
677  * @param gl     GL functions
678  * @param target Buffer target
679  * @param usage  Buffer usage enum
680  * @param size   <size> parameter
681  * @param data   <data> parameter
682  **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)683 void Buffer::Data(const glw::Functions &gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
684                   const glw::GLvoid *data)
685 {
686     gl.bufferData(target, size, data, usage);
687     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
688 }
689 
690 /** Generate buffer
691  *
692  * @param gl     GL functions
693  * @param out_id Id of buffer
694  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)695 void Buffer::Generate(const glw::Functions &gl, glw::GLuint &out_id)
696 {
697     GLuint id = m_invalid_id;
698 
699     gl.genBuffers(1, &id);
700     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
701 
702     if (m_invalid_id == id)
703     {
704         TCU_FAIL("Got invalid id");
705     }
706 
707     out_id = id;
708 }
709 
710 /** Query parameter of named buffer
711  *
712  * @param gl     GL functions
713  * @param buffer Buffer name
714  * @param pname  Parameter name
715  * @param data   Storage for queried results
716  **/
GetNamedParameter(const glw::Functions & gl,glw::GLuint buffer,glw::GLenum pname,glw::GLint * data)717 void Buffer::GetNamedParameter(const glw::Functions &gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint *data)
718 {
719     gl.getNamedBufferParameteriv(buffer, pname, data);
720     GLU_EXPECT_NO_ERROR(gl.getError(), "GetNameBufferParameteriv");
721 }
722 
723 /** Query parameter of bound buffer
724  *
725  * @param gl     GL functions
726  * @param Target Buffer target
727  * @param pname  Parameter name
728  * @param data   Storage for queried results
729  **/
GetParameter(const glw::Functions & gl,glw::GLenum target,glw::GLenum value,glw::GLint * data)730 void Buffer::GetParameter(const glw::Functions &gl, glw::GLenum target, glw::GLenum value, glw::GLint *data)
731 {
732     gl.getBufferParameteriv(target, value, data);
733     GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferParameteriv");
734 }
735 
736 /** Get contents of buffer's region
737  *
738  * @param gl     GL functions
739  * @param target Buffer target
740  * @param offset Offset in buffer
741  * @param size   <size> parameter
742  * @param data   <data> parameter
743  **/
GetSubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)744 void Buffer::GetSubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
745                         glw::GLvoid *data)
746 {
747     gl.getBufferSubData(target, offset, size, data);
748     GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferSubData");
749 }
750 
751 /** Maps buffer content
752  *
753  * @param gl     GL functions
754  * @param target Buffer target
755  * @param access Access rights for mapped region
756  *
757  * @return Mapped memory
758  **/
Map(const glw::Functions & gl,glw::GLenum target,glw::GLenum access)759 void *Buffer::Map(const glw::Functions &gl, glw::GLenum target, glw::GLenum access)
760 {
761     void *result = gl.mapBuffer(target, access);
762     GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
763 
764     return result;
765 }
766 
767 /** Maps buffer content
768  *
769  * @param gl     GL functions
770  * @param target Buffer target
771  * @param access Access rights for mapped region
772  *
773  * @return Mapped memory
774  **/
MapRange(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)775 void *Buffer::MapRange(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
776                        glw::GLenum access)
777 {
778     void *result = gl.mapBufferRange(target, offset, length, access);
779     GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
780 
781     return result;
782 }
783 
784 /** Allocate immutable memory for buffer and sends initial content
785  *
786  * @param gl     GL functions
787  * @param target Buffer target
788  * @param flags  Buffer flags
789  * @param size   <size> parameter
790  * @param data   <data> parameter
791  **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)792 void Buffer::Storage(const glw::Functions &gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
793                      const glw::GLvoid *data)
794 {
795     gl.bufferStorage(target, size, data, flags);
796     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
797 }
798 
799 /** Update range of buffer
800  *
801  * @param gl     GL functions
802  * @param target Buffer target
803  * @param offset Offset in buffer
804  * @param size   <size> parameter
805  * @param data   <data> parameter
806  **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)807 void Buffer::SubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
808                      glw::GLvoid *data)
809 {
810     gl.bufferSubData(target, offset, size, data);
811     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
812 }
813 
814 /** Unmaps buffer
815  *
816  * @param gl     GL functions
817  * @param target Buffer target
818  **/
UnMap(const glw::Functions & gl,glw::GLenum target)819 void Buffer::UnMap(const glw::Functions &gl, glw::GLenum target)
820 {
821     gl.unmapBuffer(target);
822     GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
823 }
824 
825 /** Constructor
826  * Takes ownership of mapped region
827  *
828  * @param buffer Mapped buffer
829  * @param data   Mapped data
830  **/
MapOwner(Buffer & buffer,glw::GLvoid * data)831 Buffer::MapOwner::MapOwner(Buffer &buffer, glw::GLvoid *data) : m_data(data), m_buffer(&buffer)
832 {
833     /* Nothing to be done */
834 }
835 
MapOwner(const Buffer::MoveMapOwner & moveOwner)836 Buffer::MapOwner::MapOwner(const Buffer::MoveMapOwner &moveOwner) : m_data(moveOwner.data), m_buffer(moveOwner.buffer)
837 {
838 }
839 
840 /** Move constructor
841  * Transfer ownership of mapped region.
842  *
843  * @param map_owner Map owner
844  **/
MapOwner(MapOwner & map_owner)845 Buffer::MapOwner::MapOwner(MapOwner &map_owner) : m_data(map_owner.m_data), m_buffer(map_owner.m_buffer)
846 {
847     map_owner.m_data   = 0;
848     map_owner.m_buffer = 0;
849 }
850 
851 /** Destructor
852  * Unmaps buffer
853  **/
~MapOwner()854 Buffer::MapOwner::~MapOwner()
855 {
856     m_data = 0;
857     if (0 != m_buffer)
858     {
859         m_buffer->Bind();
860         m_buffer->UnMap();
861         m_buffer = 0;
862     }
863 }
864 
865 /* Framebuffer constants */
866 const GLuint Framebuffer::m_invalid_id = -1;
867 
868 /** Constructor.
869  *
870  * @param context CTS context.
871  **/
Framebuffer(deqp::Context & context)872 Framebuffer::Framebuffer(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
873 {
874     /* Nothing to done here */
875 }
876 
877 /** Destructor
878  *
879  **/
~Framebuffer()880 Framebuffer::~Framebuffer()
881 {
882     Release();
883 }
884 
885 /** Release texture instance
886  *
887  **/
Release()888 void Framebuffer::Release()
889 {
890     if (m_invalid_id != m_id)
891     {
892         const Functions &gl = m_context.getRenderContext().getFunctions();
893 
894         gl.deleteFramebuffers(1, &m_id);
895         m_id = m_invalid_id;
896     }
897 }
898 
899 /** Attach texture to specified attachment
900  *
901  * @param gl         GL functions
902  * @param target     Framebuffer target
903  * @param attachment Attachment
904  * @param texture_id Texture id
905  * @param width      Texture width
906  * @param height     Texture height
907  **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)908 void Framebuffer::AttachTexture(const glw::Functions &gl, glw::GLenum target, glw::GLenum attachment,
909                                 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height)
910 {
911     gl.framebufferTexture(target, attachment, texture_id, 0 /* level */);
912     GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
913 
914     gl.viewport(0 /* x */, 0 /* y */, width, height);
915     GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
916 }
917 
918 /** Binds framebuffer to DRAW_FRAMEBUFFER
919  *
920  * @param gl     GL functions
921  * @param target Framebuffer target
922  * @param id     ID of framebuffer
923  **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)924 void Framebuffer::Bind(const glw::Functions &gl, glw::GLenum target, glw::GLuint id)
925 {
926     gl.bindFramebuffer(target, id);
927     GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
928 }
929 
930 /** Generate framebuffer
931  *
932  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)933 void Framebuffer::Generate(const glw::Functions &gl, glw::GLuint &out_id)
934 {
935     GLuint id = m_invalid_id;
936 
937     gl.genFramebuffers(1, &id);
938     GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
939 
940     if (m_invalid_id == id)
941     {
942         TCU_FAIL("Invalid id");
943     }
944 
945     out_id = id;
946 }
947 
948 /* Program constants */
949 const GLuint Program::m_invalid_id = 0;
950 
951 /** Constructor.
952  *
953  * @param context CTS context.
954  **/
Program(deqp::Context & context)955 Program::Program(deqp::Context &context)
956     : m_id(m_invalid_id)
957     , m_compute(context)
958     , m_fragment(context)
959     , m_geometry(context)
960     , m_tess_ctrl(context)
961     , m_tess_eval(context)
962     , m_vertex(context)
963     , m_context(context)
964 {
965     /* Nothing to be done here */
966 }
967 
968 /** Destructor
969  *
970  **/
~Program()971 Program::~Program()
972 {
973     Release();
974 }
975 
976 /** Initialize program instance
977  *
978  * @param compute_shader                Compute shader source code
979  * @param fragment_shader               Fragment shader source code
980  * @param geometry_shader               Geometry shader source code
981  * @param tesselation_control_shader    Tesselation control shader source code
982  * @param tesselation_evaluation_shader Tesselation evaluation shader source code
983  * @param vertex_shader                 Vertex shader source code
984  **/
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)985 void Program::Init(const std::string &compute_shader, const std::string &fragment_shader,
986                    const std::string &geometry_shader, const std::string &tesselation_control_shader,
987                    const std::string &tesselation_evaluation_shader, const std::string &vertex_shader)
988 {
989     /* Delete previous program */
990     Release();
991 
992     /* GL entry points */
993     const Functions &gl = m_context.getRenderContext().getFunctions();
994 
995     /* Initialize shaders */
996     m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
997     m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
998     m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
999     m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
1000     m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
1001     m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
1002 
1003     /* Create program, set up transform feedback and attach shaders */
1004     Create(gl, m_id);
1005     Attach(gl, m_id, m_compute.m_id);
1006     Attach(gl, m_id, m_fragment.m_id);
1007     Attach(gl, m_id, m_geometry.m_id);
1008     Attach(gl, m_id, m_tess_ctrl.m_id);
1009     Attach(gl, m_id, m_tess_eval.m_id);
1010     Attach(gl, m_id, m_vertex.m_id);
1011 
1012     /* Link program */
1013     Link(gl, m_id);
1014 }
1015 
1016 /** Release program instance
1017  *
1018  **/
Release()1019 void Program::Release()
1020 {
1021     const Functions &gl = m_context.getRenderContext().getFunctions();
1022 
1023     if (m_invalid_id != m_id)
1024     {
1025         Use(gl, m_invalid_id);
1026 
1027         gl.deleteProgram(m_id);
1028         m_id = m_invalid_id;
1029     }
1030 
1031     m_compute.Release();
1032     m_fragment.Release();
1033     m_geometry.Release();
1034     m_tess_ctrl.Release();
1035     m_tess_eval.Release();
1036     m_vertex.Release();
1037 }
1038 
1039 /** Attach shader to program
1040  *
1041  * @param gl         GL functions
1042  * @param program_id Id of program
1043  * @param shader_id  Id of shader
1044  **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)1045 void Program::Attach(const glw::Functions &gl, glw::GLuint program_id, glw::GLuint shader_id)
1046 {
1047     /* Quick checks */
1048     if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
1049     {
1050         return;
1051     }
1052 
1053     gl.attachShader(program_id, shader_id);
1054     GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
1055 }
1056 
1057 /** Create program instance
1058  *
1059  * @param gl     GL functions
1060  * @param out_id Id of program
1061  **/
Create(const glw::Functions & gl,glw::GLuint & out_id)1062 void Program::Create(const glw::Functions &gl, glw::GLuint &out_id)
1063 {
1064     const GLuint id = gl.createProgram();
1065     GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
1066 
1067     if (m_invalid_id == id)
1068     {
1069         TCU_FAIL("Failed to create program");
1070     }
1071 
1072     out_id = id;
1073 }
1074 
1075 /** Link program
1076  *
1077  * @param gl GL functions
1078  * @param id Id of program
1079  **/
Link(const glw::Functions & gl,glw::GLuint id)1080 void Program::Link(const glw::Functions &gl, glw::GLuint id)
1081 {
1082     GLint status = GL_FALSE;
1083 
1084     gl.linkProgram(id);
1085     GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
1086 
1087     /* Get link status */
1088     gl.getProgramiv(id, GL_LINK_STATUS, &status);
1089     GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1090 
1091     /* Log link error */
1092     if (GL_TRUE != status)
1093     {
1094         glw::GLint length = 0;
1095         std::string message;
1096 
1097         /* Get error log length */
1098         gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
1099         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1100 
1101         message.resize(length, 0);
1102 
1103         /* Get error log */
1104         gl.getProgramInfoLog(id, length, 0, &message[0]);
1105         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
1106 
1107         TCU_FAIL(message.c_str());
1108     }
1109 }
1110 
1111 /** Use program
1112  *
1113  * @param gl GL functions
1114  * @param id Id of program
1115  **/
Use(const glw::Functions & gl,glw::GLuint id)1116 void Program::Use(const glw::Functions &gl, glw::GLuint id)
1117 {
1118     gl.useProgram(id);
1119     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1120 }
1121 
1122 /* Shader's constants */
1123 const GLuint Shader::m_invalid_id = 0;
1124 
1125 /** Constructor.
1126  *
1127  * @param context CTS context.
1128  **/
Shader(deqp::Context & context)1129 Shader::Shader(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1130 {
1131     /* Nothing to be done here */
1132 }
1133 
1134 /** Destructor
1135  *
1136  **/
~Shader()1137 Shader::~Shader()
1138 {
1139     Release();
1140 }
1141 
1142 /** Initialize shader instance
1143  *
1144  * @param stage  Shader stage
1145  * @param source Source code
1146  **/
Init(glw::GLenum stage,const std::string & source)1147 void Shader::Init(glw::GLenum stage, const std::string &source)
1148 {
1149     if (true == source.empty())
1150     {
1151         /* No source == no shader */
1152         return;
1153     }
1154 
1155     /* Delete any previous shader */
1156     Release();
1157 
1158     /* Create, set source and compile */
1159     const Functions &gl = m_context.getRenderContext().getFunctions();
1160 
1161     Create(gl, stage, m_id);
1162     Source(gl, m_id, source);
1163 
1164     Compile(gl, m_id);
1165 }
1166 
1167 /** Release shader instance
1168  *
1169  **/
Release()1170 void Shader::Release()
1171 {
1172     if (m_invalid_id != m_id)
1173     {
1174         const Functions &gl = m_context.getRenderContext().getFunctions();
1175 
1176         gl.deleteShader(m_id);
1177         m_id = m_invalid_id;
1178     }
1179 }
1180 
1181 /** Compile shader
1182  *
1183  * @param gl GL functions
1184  * @param id Shader id
1185  **/
Compile(const glw::Functions & gl,glw::GLuint id)1186 void Shader::Compile(const glw::Functions &gl, glw::GLuint id)
1187 {
1188     GLint status = GL_FALSE;
1189 
1190     /* Compile */
1191     gl.compileShader(id);
1192     GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
1193 
1194     /* Get compilation status */
1195     gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
1196     GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1197 
1198     /* Log compilation error */
1199     if (GL_TRUE != status)
1200     {
1201         glw::GLint length = 0;
1202         std::string message;
1203 
1204         /* Error log length */
1205         gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
1206         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1207 
1208         /* Prepare storage */
1209         message.resize(length, 0);
1210 
1211         /* Get error log */
1212         gl.getShaderInfoLog(id, length, 0, &message[0]);
1213         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
1214 
1215         TCU_FAIL(message.c_str());
1216     }
1217 }
1218 
1219 /** Create shader
1220  *
1221  * @param gl     GL functions
1222  * @param stage  Shader stage
1223  * @param out_id Shader id
1224  **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)1225 void Shader::Create(const glw::Functions &gl, glw::GLenum stage, glw::GLuint &out_id)
1226 {
1227     const GLuint id = gl.createShader(stage);
1228     GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
1229 
1230     if (m_invalid_id == id)
1231     {
1232         TCU_FAIL("Failed to create shader");
1233     }
1234 
1235     out_id = id;
1236 }
1237 
1238 /** Set shader's source code
1239  *
1240  * @param gl     GL functions
1241  * @param id     Shader id
1242  * @param source Shader source code
1243  **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)1244 void Shader::Source(const glw::Functions &gl, glw::GLuint id, const std::string &source)
1245 {
1246     const GLchar *code = source.c_str();
1247 
1248     gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
1249     GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
1250 }
1251 
1252 /* Texture static fields */
1253 
1254 FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
1255 
1256 /* Texture constants */
1257 const GLuint Texture::m_invalid_id = -1;
1258 
1259 /** Constructor.
1260  *
1261  * @param context CTS context.
1262  **/
Texture(deqp::Context & context)1263 Texture::Texture(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1264 {
1265     /* Nothing to done here */
1266 }
1267 
1268 /** Destructor
1269  *
1270  **/
~Texture()1271 Texture::~Texture()
1272 {
1273     Release();
1274 }
1275 
1276 /** Release texture instance
1277  *
1278  **/
Release()1279 void Texture::Release()
1280 {
1281     if (m_invalid_id != m_id)
1282     {
1283         const Functions &gl = m_context.getRenderContext().getFunctions();
1284 
1285         gl.deleteTextures(1, &m_id);
1286         m_id = m_invalid_id;
1287     }
1288 }
1289 
1290 /** Loads entry points for direct state access extension
1291  *
1292  * @param context CTS context
1293  **/
LoadExtDirectStateAccess(deqp::Context & context)1294 void Texture::LoadExtDirectStateAccess(deqp::Context &context)
1295 {
1296     FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
1297 
1298     switch (support)
1299     {
1300     case FUNCTIONALITY_SUPPORT_NONE:
1301         /* Nothing to be done */
1302         break;
1303     case FUNCTIONALITY_SUPPORT_CORE:
1304     case FUNCTIONALITY_SUPPORT_EXTENSION:
1305         break;
1306     default:
1307         TCU_FAIL("Invalid enum");
1308     }
1309 }
1310 
1311 /** Bind texture to target
1312  *
1313  * @param gl       GL functions
1314  * @param id       Id of texture
1315  * @param tex_type Type of texture
1316  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1317 void Texture::Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target)
1318 {
1319     gl.bindTexture(target, id);
1320     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1321 }
1322 
1323 /** Set contents of compressed texture
1324  *
1325  * @param gl              GL functions
1326  * @param target          Texture target
1327  * @param level           Mipmap level
1328  * @param internal_format Format of data
1329  * @param width           Width of texture
1330  * @param height          Height of texture
1331  * @param depth           Depth of texture
1332  * @param image_size      Size of data
1333  * @param data            Buffer with image data
1334  **/
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)1335 void Texture::CompressedImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level,
1336                               glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1337                               glw::GLsizei image_size, const glw::GLvoid *data)
1338 {
1339     switch (target)
1340     {
1341     case GL_TEXTURE_1D:
1342         gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1343         GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1344         break;
1345     case GL_TEXTURE_1D_ARRAY:
1346     case GL_TEXTURE_2D:
1347     case GL_TEXTURE_RECTANGLE:
1348         gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1349         GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1350         break;
1351     case GL_TEXTURE_CUBE_MAP:
1352         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1353                                 image_size, data);
1354         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1355                                 image_size, data);
1356         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1357                                 image_size, data);
1358         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1359                                 image_size, data);
1360         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1361                                 image_size, data);
1362         gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1363                                 image_size, data);
1364         GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1365         break;
1366     case GL_TEXTURE_3D:
1367     case GL_TEXTURE_2D_ARRAY:
1368         gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1369         GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1370         break;
1371     default:
1372         TCU_FAIL("Invliad enum");
1373     }
1374 }
1375 
1376 /** Generate texture instance
1377  *
1378  * @param gl     GL functions
1379  * @param out_id Id of texture
1380  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1381 void Texture::Generate(const glw::Functions &gl, glw::GLuint &out_id)
1382 {
1383     GLuint id = m_invalid_id;
1384 
1385     gl.genTextures(1, &id);
1386     GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1387 
1388     if (m_invalid_id == id)
1389     {
1390         TCU_FAIL("Invalid id");
1391     }
1392 
1393     out_id = id;
1394 }
1395 
1396 /** Get texture data
1397  *
1398  * @param gl       GL functions
1399  * @param target   Texture target
1400  * @param format   Format of data
1401  * @param type     Type of data
1402  * @param out_data Buffer for data
1403  **/
GetData(const glw::Functions & gl,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1404 void Texture::GetData(const glw::Functions &gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
1405                       glw::GLvoid *out_data)
1406 {
1407     gl.getTexImage(target, 0 /* level */, format, type, out_data);
1408     GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1409 }
1410 
1411 /** Generate texture instance
1412  *
1413  * @param gl     GL functions
1414  * @param target Texture target
1415  * @param level  Mipmap level
1416  * @param pname  Parameter to query
1417  * @param param  Result of query
1418  **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1419 void Texture::GetLevelParameter(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1420                                 glw::GLint *param)
1421 {
1422     gl.getTexLevelParameteriv(target, level, pname, param);
1423     GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1424 }
1425 
1426 /** Set contents of texture
1427  *
1428  * @param gl              GL functions
1429  * @param target          Texture target
1430  * @param level           Mipmap level
1431  * @param internal_format Format of data
1432  * @param width           Width of texture
1433  * @param height          Height of texture
1434  * @param depth           Depth of texture
1435  * @param format          Format of data
1436  * @param type            Type of data
1437  * @param data            Buffer with image data
1438  **/
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)1439 void Texture::Image(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1440                     glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1441                     const glw::GLvoid *data)
1442 {
1443     switch (target)
1444     {
1445     case GL_TEXTURE_1D:
1446         gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1447         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1448         break;
1449     case GL_TEXTURE_1D_ARRAY:
1450     case GL_TEXTURE_2D:
1451     case GL_TEXTURE_RECTANGLE:
1452         gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1453         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1454         break;
1455     case GL_TEXTURE_CUBE_MAP:
1456         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1457                       type, data);
1458         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1459                       type, data);
1460         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1461                       type, data);
1462         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1463                       type, data);
1464         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1465                       type, data);
1466         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1467                       type, data);
1468         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1469         break;
1470     case GL_TEXTURE_3D:
1471     case GL_TEXTURE_2D_ARRAY:
1472         gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1473         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1474         break;
1475     default:
1476         TCU_FAIL("Invliad enum");
1477     }
1478 }
1479 
1480 /** Allocate storage for texture
1481  *
1482  * @param gl              GL functions
1483  * @param target          Texture target
1484  * @param levels          Number of levels
1485  * @param internal_format Internal format of texture
1486  * @param width           Width of texture
1487  * @param height          Height of texture
1488  * @param depth           Depth of texture
1489  **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth)1490 void Texture::Storage(const glw::Functions &gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1491                       glw::GLuint width, glw::GLuint height, glw::GLuint depth)
1492 {
1493     switch (target)
1494     {
1495     case GL_TEXTURE_1D:
1496         gl.texStorage1D(target, levels, internal_format, width);
1497         GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1498         break;
1499     case GL_TEXTURE_1D_ARRAY:
1500     case GL_TEXTURE_2D:
1501     case GL_TEXTURE_RECTANGLE:
1502     case GL_TEXTURE_CUBE_MAP:
1503         gl.texStorage2D(target, levels, internal_format, width, height);
1504         GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1505         break;
1506     case GL_TEXTURE_3D:
1507     case GL_TEXTURE_2D_ARRAY:
1508         gl.texStorage3D(target, levels, internal_format, width, height, depth);
1509         GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1510         break;
1511     default:
1512         TCU_FAIL("Invliad enum");
1513     }
1514 }
1515 
1516 /** Set contents of texture
1517  *
1518  * @param gl              GL functions
1519  * @param target          Texture target
1520  * @param level           Mipmap level
1521  * @param x               X offset
1522  * @param y               Y offset
1523  * @param z               Z offset
1524  * @param width           Width of texture
1525  * @param height          Height of texture
1526  * @param depth           Depth of texture
1527  * @param format          Format of data
1528  * @param type            Type of data
1529  * @param pixels          Buffer with image data
1530  **/
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)1531 void Texture::SubImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1532                        glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1533                        glw::GLenum type, const glw::GLvoid *pixels)
1534 {
1535     switch (target)
1536     {
1537     case GL_TEXTURE_1D:
1538         gl.texSubImage1D(target, level, x, width, format, type, pixels);
1539         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1540         break;
1541     case GL_TEXTURE_1D_ARRAY:
1542     case GL_TEXTURE_2D:
1543     case GL_TEXTURE_RECTANGLE:
1544         gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1545         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1546         break;
1547     case GL_TEXTURE_CUBE_MAP:
1548         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1549         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1550         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1551         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1552         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1553         gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1554         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1555         break;
1556     case GL_TEXTURE_3D:
1557     case GL_TEXTURE_2D_ARRAY:
1558         gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1559         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1560         break;
1561     default:
1562         TCU_FAIL("Invliad enum");
1563     }
1564 }
1565 
1566 /* VertexArray constants */
1567 const GLuint VertexArray::m_invalid_id = -1;
1568 
1569 /** Constructor.
1570  *
1571  * @param context CTS context.
1572  **/
VertexArray(deqp::Context & context)1573 VertexArray::VertexArray(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1574 {
1575 }
1576 
1577 /** Destructor
1578  *
1579  **/
~VertexArray()1580 VertexArray::~VertexArray()
1581 {
1582     Release();
1583 }
1584 
1585 /** Release vertex array object instance
1586  *
1587  **/
Release()1588 void VertexArray::Release()
1589 {
1590     if (m_invalid_id != m_id)
1591     {
1592         const Functions &gl = m_context.getRenderContext().getFunctions();
1593 
1594         Bind(gl, 0);
1595 
1596         gl.deleteVertexArrays(1, &m_id);
1597 
1598         m_id = m_invalid_id;
1599     }
1600 }
1601 
1602 /** Binds Vertex array object
1603  *
1604  * @param gl GL functions
1605  * @param id ID of vertex array object
1606  **/
Bind(const glw::Functions & gl,glw::GLuint id)1607 void VertexArray::Bind(const glw::Functions &gl, glw::GLuint id)
1608 {
1609     gl.bindVertexArray(id);
1610     GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
1611 }
1612 
1613 /** Generates Vertex array object
1614  *
1615  * @param gl     GL functions
1616  * @param out_id ID of vertex array object
1617  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1618 void VertexArray::Generate(const glw::Functions &gl, glw::GLuint &out_id)
1619 {
1620     GLuint id = m_invalid_id;
1621 
1622     gl.genVertexArrays(1, &id);
1623     GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1624 
1625     if (m_invalid_id == id)
1626     {
1627         TCU_FAIL("Invalid id");
1628     }
1629 
1630     out_id = id;
1631 }
1632 
1633 /** Constructor
1634  *
1635  * @param context Test context
1636  **/
ErrorsTest(deqp::Context & context)1637 ErrorsTest::ErrorsTest(deqp::Context &context)
1638     : TestCase(context, "errors", "Test if errors are generated as specified")
1639 {
1640     /* Nothing to be done here */
1641 }
1642 
1643 /** Execute test
1644  *
1645  * @return tcu::TestNode::STOP otherwise
1646  **/
iterate()1647 tcu::TestNode::IterateResult ErrorsTest::iterate()
1648 {
1649     const Functions &gl = m_context.getRenderContext().getFunctions();
1650 
1651     bool test_result = true;
1652 
1653     Buffer::LoadExtDirectStateAccess(m_context);
1654 
1655     // No GL45 or GL_ARB_direct_state_access support
1656     if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
1657     {
1658         m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
1659         return tcu::TestNode::STOP;
1660     }
1661 
1662     /*
1663      * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to
1664      * <target>; Check all targets;
1665      */
1666     for (GLuint i = 0; i < Buffer::m_n_targets; ++i)
1667     {
1668         const GLenum target = Buffer::m_targets[i];
1669         std::string message = "BufferStorage was executed for id 0, target: ";
1670 
1671         message.append(glu::getBufferTargetStr(target).toString().c_str());
1672 
1673         Buffer::Bind(gl, 0 /* id */, target);
1674         gl.bufferStorage(target, 0 /* size */, 0 /* data */, GL_DYNAMIC_STORAGE_BIT /* flags */);
1675 
1676         verifyError(GL_INVALID_OPERATION, message.c_str(), test_result);
1677     }
1678 
1679     /*
1680      * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and
1681      * BufferData if buffer already have immutable store;
1682      */
1683     {
1684         static const GLsizeiptr data_size = 32;
1685         static GLubyte data[data_size];
1686 
1687         Buffer buffer(m_context);
1688         buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1689 
1690         /* NamedBufferStorage */
1691         if (0 != gl.namedBufferStorage)
1692         {
1693             gl.namedBufferStorage(buffer.m_id, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1694             verifyError(GL_INVALID_OPERATION, "NamedBufferStorage was executed for id with immutable storage",
1695                         test_result);
1696         }
1697 
1698         /* BufferStorage */
1699         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1700 
1701         gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1702         verifyError(GL_INVALID_OPERATION, "BufferStorage was executed for target with immutable storage", test_result);
1703 
1704         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1705     }
1706 
1707     /*
1708      * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1709      * <size> is less or equal to zero;
1710      */
1711     {
1712         static const GLsizeiptr data_size = 32;
1713         static GLubyte data[data_size];
1714 
1715         Buffer buffer(m_context);
1716         gl.createBuffers(1, &buffer.m_id);
1717 
1718         /* NamedBufferStorage */
1719         if (0 != gl.namedBufferStorage)
1720         {
1721             gl.namedBufferStorage(buffer.m_id, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1722             verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == 0", test_result);
1723 
1724             gl.namedBufferStorage(buffer.m_id, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1725             verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == -16", test_result);
1726         }
1727 
1728         /* BufferStorage */
1729         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1730 
1731         gl.bufferStorage(GL_ARRAY_BUFFER, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1732         verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == 0", test_result);
1733 
1734         gl.bufferStorage(GL_ARRAY_BUFFER, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1735         verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == -16", test_result);
1736 
1737         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1738     }
1739 
1740     /*
1741      * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when
1742      * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor
1743      * MAP_WRITE_BIT;
1744      */
1745     {
1746         static const GLsizeiptr data_size = 32;
1747         static GLubyte data[data_size];
1748 
1749         Buffer buffer(m_context);
1750         gl.createBuffers(1, &buffer.m_id);
1751 
1752         /* NamedBufferStorage */
1753         if (0 != gl.namedBufferStorage)
1754         {
1755             gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_PERSISTENT_BIT);
1756             verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT",
1757                         test_result);
1758         }
1759 
1760         /* BufferStorage */
1761         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1762 
1763         gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_PERSISTENT_BIT);
1764         verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", test_result);
1765 
1766         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1767     }
1768 
1769     /*
1770      * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1771      * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT;
1772      */
1773     {
1774         static const GLsizeiptr data_size = 32;
1775         static GLubyte data[data_size];
1776 
1777         Buffer buffer(m_context);
1778         gl.createBuffers(1, &buffer.m_id);
1779 
1780         /* NamedBufferStorage */
1781         if (0 != gl.namedBufferStorage)
1782         {
1783             gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_COHERENT_BIT);
1784             verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_COHERENT_BIT",
1785                         test_result);
1786         }
1787 
1788         /* BufferStorage */
1789         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1790 
1791         gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_COHERENT_BIT);
1792         verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_COHERENT_BIT", test_result);
1793 
1794         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1795     }
1796 
1797     /*
1798      * - INVALID_OPERATION is generated by MapBufferRange if any of:
1799      *   * MAP_COHERENT_BIT,
1800      *   * MAP_PERSISTENT_BIT,
1801      *   * MAP_READ_BIT,
1802      *   * MAP_WRITE_BIT
1803      * is included in <access> and not in buffer's storage flags;
1804      */
1805     {
1806         static const GLsizeiptr data_size = 32;
1807         static GLubyte data[data_size];
1808 
1809         Buffer buffer(m_context);
1810         buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1811 
1812         /* MapNamedBufferRange */
1813         if (0 != gl.mapNamedBufferRange)
1814         {
1815             gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1816             verifyError(GL_INVALID_OPERATION,
1817                         "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, "
1818                         "storage flags == GL_DYNAMIC_STORAGE_BIT",
1819                         test_result);
1820 
1821             gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1822             verifyError(GL_INVALID_OPERATION,
1823                         "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, "
1824                         "storage flags == GL_DYNAMIC_STORAGE_BIT",
1825                         test_result);
1826 
1827             gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1828             verifyError(GL_INVALID_OPERATION,
1829                         "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, "
1830                         "storage flags == GL_DYNAMIC_STORAGE_BIT",
1831                         test_result);
1832 
1833             gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1834             verifyError(GL_INVALID_OPERATION,
1835                         "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, "
1836                         "storage flags == GL_DYNAMIC_STORAGE_BIT",
1837                         test_result);
1838         }
1839 
1840         /* BufferStorage */
1841         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1842 
1843         gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1844         verifyError(
1845             GL_INVALID_OPERATION,
1846             "MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1847             test_result);
1848 
1849         gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1850         verifyError(
1851             GL_INVALID_OPERATION,
1852             "MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1853             test_result);
1854 
1855         gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1856         verifyError(
1857             GL_INVALID_OPERATION,
1858             "MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1859             test_result);
1860 
1861         gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1862         verifyError(
1863             GL_INVALID_OPERATION,
1864             "MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1865             test_result);
1866 
1867         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1868     }
1869 
1870     /*
1871      * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData
1872      * when buffer has immutable store but its flags does not include
1873      * DYNAMIC_STORAGE.
1874      */
1875     {
1876         static const GLsizeiptr data_size = 32;
1877         static GLubyte data[data_size];
1878 
1879         Buffer buffer(m_context);
1880         buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size,
1881                            data);
1882 
1883         /* NamedBufferSubData */
1884         if (0 != gl.namedBufferSubData)
1885         {
1886             gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data);
1887             verifyError(GL_INVALID_OPERATION,
1888                         "NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result);
1889         }
1890 
1891         /* BufferStorage */
1892         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1893 
1894         gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data);
1895         verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT",
1896                     test_result);
1897 
1898         Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1899     }
1900 
1901     /* Set result */
1902     if (true == test_result)
1903     {
1904         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1905     }
1906     else
1907     {
1908         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1909     }
1910 
1911     /* Done */
1912     return tcu::TestNode::STOP;
1913 }
1914 
1915 /** Verifies that expected error was generated
1916  *
1917  * @param expected_error  Expected error
1918  * @param error_message   Message that will be logged in case of wrong error
1919  * @param out_test_result Set to false if worng error was generated, not modified otherwise
1920  **/
verifyError(glw::GLenum expected_error,const glw::GLchar * error_message,bool & out_test_result)1921 void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar *error_message, bool &out_test_result)
1922 {
1923     const Functions &gl = m_context.getRenderContext().getFunctions();
1924 
1925     const GLenum error = gl.getError();
1926 
1927     if (error != expected_error)
1928     {
1929         out_test_result = false;
1930 
1931         m_context.getTestContext().getLog()
1932             << tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error)
1933             << ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message
1934             << tcu::TestLog::EndMessage;
1935     }
1936 }
1937 
1938 /** Constructor
1939  *
1940  * @param context Test context
1941  **/
GetBufferParameterTest(deqp::Context & context)1942 GetBufferParameterTest::GetBufferParameterTest(deqp::Context &context)
1943     : TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers")
1944 {
1945     static const GLenum s_mapping_bits[] = {0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT};
1946     static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]);
1947 
1948     GLenum flags = 0;
1949 
1950     for (GLuint dynamic = 0; dynamic < 2; ++dynamic)
1951     {
1952         flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT;
1953 
1954         for (GLuint client = 0; client < 2; ++client)
1955         {
1956             flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT;
1957 
1958             /* No "map" bits */
1959             if (0 != flags)
1960             {
1961                 m_test_cases.push_back(testCase(flags, 0));
1962             }
1963 
1964             for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx)
1965             {
1966                 const GLenum flag_mapping_bits  = s_mapping_bits[flag_idx];
1967                 const GLenum flags_with_mapping = flags | flag_mapping_bits;
1968 
1969                 for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx)
1970                 {
1971                     const GLenum access = s_mapping_bits[access_idx];
1972 
1973                     m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT));
1974                     m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1975                     m_test_cases.push_back(
1976                         testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT));
1977                     m_test_cases.push_back(
1978                         testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1979                     m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
1980                                                     access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
1981                 }
1982             }
1983         }
1984     }
1985 }
1986 
1987 /** Execute test
1988  *
1989  * @return tcu::TestNode::STOP otherwise
1990  **/
iterate()1991 tcu::TestNode::IterateResult GetBufferParameterTest::iterate()
1992 {
1993     static const GLsizeiptr data_size = 32;
1994     static GLubyte data[data_size];
1995 
1996     Buffer::LoadExtDirectStateAccess(m_context);
1997 
1998     // No GL45 or GL_ARB_direct_state_access support
1999     if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2000     {
2001         m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2002         return tcu::TestNode::STOP;
2003     }
2004 
2005     const Functions &gl = m_context.getRenderContext().getFunctions();
2006 
2007     bool test_result = true;
2008 
2009     for (GLuint i = 0; i < m_test_cases.size(); ++i)
2010     {
2011         const testCase &test_case = m_test_cases[i];
2012         const GLenum access       = test_case.m_access;
2013         const GLenum flags        = test_case.m_flags;
2014 
2015         GLint queried_flags     = -1;
2016         GLint queried_immutable = -1;
2017         GLint queried_size      = -1;
2018 
2019         Buffer buffer(m_context);
2020 
2021         buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data);
2022         Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
2023 
2024         if (0 != gl.getNamedBufferParameteriv)
2025         {
2026             Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2027             Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2028             Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size);
2029 
2030             if (queried_flags != (GLint)flags)
2031             {
2032                 test_result = false;
2033                 m_context.getTestContext().getLog()
2034                     << tcu::TestLog::Message
2035                     << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2036                     << " expected: " << flags << tcu::TestLog::EndMessage;
2037             }
2038         }
2039 
2040         if (queried_flags != (GLint)flags)
2041         {
2042             test_result = false;
2043             m_context.getTestContext().getLog()
2044                 << tcu::TestLog::Message
2045                 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2046                 << " expected: " << flags << tcu::TestLog::EndMessage;
2047         }
2048 
2049         if (queried_immutable != GL_TRUE)
2050         {
2051             test_result = false;
2052             m_context.getTestContext().getLog()
2053                 << tcu::TestLog::Message
2054                 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: "
2055                 << queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2056         }
2057 
2058         if (queried_size != data_size)
2059         {
2060             test_result = false;
2061             m_context.getTestContext().getLog()
2062                 << tcu::TestLog::Message
2063                 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2064                 << " expected: " << data_size << tcu::TestLog::EndMessage;
2065         }
2066 
2067         queried_flags     = -1;
2068         queried_immutable = -1;
2069         queried_size      = -1;
2070 
2071         Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2072         Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2073         Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size);
2074 
2075         if (queried_flags != (GLint)flags)
2076         {
2077             test_result = false;
2078             m_context.getTestContext().getLog()
2079                 << tcu::TestLog::Message
2080                 << "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2081                 << " expected: " << flags << tcu::TestLog::EndMessage;
2082         }
2083 
2084         if (queried_immutable != GL_TRUE)
2085         {
2086             test_result = false;
2087             m_context.getTestContext().getLog()
2088                 << tcu::TestLog::Message
2089                 << "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable
2090                 << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2091         }
2092 
2093         if (queried_size != data_size)
2094         {
2095             test_result = false;
2096             m_context.getTestContext().getLog()
2097                 << tcu::TestLog::Message
2098                 << "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2099                 << " expected: " << data_size << tcu::TestLog::EndMessage;
2100         }
2101 
2102         if (0 != access)
2103         {
2104             GLint queried_access = -1;
2105 
2106             Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access));
2107 
2108             if (0 != gl.getNamedBufferParameteriv)
2109             {
2110                 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2111             }
2112 
2113             if (queried_access != (GLint)access)
2114             {
2115                 test_result = false;
2116                 m_context.getTestContext().getLog()
2117                     << tcu::TestLog::Message
2118                     << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2119                     << " expected: " << access << tcu::TestLog::EndMessage;
2120             }
2121 
2122             queried_access = -1;
2123 
2124             Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2125 
2126             if (queried_access != (GLint)access)
2127             {
2128                 test_result = false;
2129                 m_context.getTestContext().getLog()
2130                     << tcu::TestLog::Message
2131                     << "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2132                     << " expected: " << access << tcu::TestLog::EndMessage;
2133             }
2134         }
2135 
2136         Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER);
2137     }
2138 
2139     /* Set result */
2140     if (true == test_result)
2141     {
2142         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2143     }
2144     else
2145     {
2146         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2147     }
2148 
2149     /* Done */
2150     return tcu::TestNode::STOP;
2151 }
2152 
2153 /** Constructor
2154  *
2155  * @param context Test context
2156  **/
testCase(glw::GLenum flags,glw::GLenum access)2157 GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access)
2158 {
2159 }
2160 
2161 /** Constructor
2162  *
2163  * @param context Test context
2164  **/
DynamicStorageTest(deqp::Context & context)2165 DynamicStorageTest::DynamicStorageTest(deqp::Context &context)
2166     : TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected")
2167 {
2168     /* Nothing to be done here */
2169 }
2170 
2171 /** Execute test
2172  *
2173  * @return tcu::TestNode::STOP otherwise
2174  **/
iterate()2175 tcu::TestNode::IterateResult DynamicStorageTest::iterate()
2176 {
2177     static const size_t data_size = 64;
2178 
2179     const Functions &gl = m_context.getRenderContext().getFunctions();
2180 
2181     bool test_result = true;
2182 
2183     /*
2184      * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to
2185      * COPY_READ_BUFFER;
2186      * - prepare 64 bytes immutable buffer filled with value 2; Do not set
2187      * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER;
2188      * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2189      * filled with value 3; INVLIAD_OPERATION error should be generated;
2190      * - inspect contents of buffer to verify it is filled with 2;
2191      * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to
2192      * COPY_WRITE_BUFFER; No error should be generated;
2193      * - inspect contents of buffer to verify it is filled with 1;
2194      */
2195     {
2196         /* Prepare buffers */
2197         GLubyte read_data[data_size];
2198         GLubyte temp_data[data_size];
2199         GLubyte update_data[data_size];
2200         GLubyte write_data[data_size];
2201 
2202         for (size_t i = 0; i < data_size; ++i)
2203         {
2204             read_data[i]   = 1;
2205             temp_data[i]   = 0;
2206             update_data[i] = 3;
2207             write_data[i]  = 2;
2208         }
2209 
2210         Buffer read_buffer(m_context);
2211         Buffer write_buffer(m_context);
2212 
2213         read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data);
2214         write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data);
2215 
2216         /* Check bufferSubData */
2217         write_buffer.Bind();
2218         gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2219 
2220         GLenum error = gl.getError();
2221         if (GL_INVALID_OPERATION != error)
2222         {
2223             test_result = false;
2224 
2225             m_context.getTestContext().getLog()
2226                 << tcu::TestLog::Message
2227                 << "Invalid error was generated. BufferSubData was executed on store without "
2228                    "DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: "
2229                 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2230         }
2231 
2232         Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2233 
2234         if (0 != memcmp(temp_data, write_data, data_size))
2235         {
2236             test_result = false;
2237 
2238             m_context.getTestContext().getLog()
2239                 << tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT."
2240                 << tcu::TestLog::EndMessage;
2241         }
2242 
2243         /* Check copyBufferSubData */
2244         read_buffer.Bind();
2245         gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */,
2246                              data_size);
2247         GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData");
2248 
2249         Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2250 
2251         if (0 != memcmp(temp_data, read_data, data_size))
2252         {
2253             test_result = false;
2254 
2255             m_context.getTestContext().getLog()
2256                 << tcu::TestLog::Message << "CopyBufferSubData stored invalid contents in write target buffer."
2257                 << tcu::TestLog::EndMessage;
2258         }
2259     }
2260 
2261     /*
2262      * - delete buffer and create new one; This time <flags> should contain
2263      * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER;
2264      * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2265      * filled with value 3; No error should be generated;
2266      * - inspect contents of buffer to verify it is filled with 3;
2267      */
2268     {
2269         /* Prepare buffers */
2270         GLubyte temp_data[data_size];
2271         GLubyte update_data[data_size];
2272         GLubyte write_data[data_size];
2273 
2274         for (size_t i = 0; i < data_size; ++i)
2275         {
2276             temp_data[i]   = 0;
2277             update_data[i] = 3;
2278             write_data[i]  = 2;
2279         }
2280 
2281         Buffer write_buffer(m_context);
2282 
2283         write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data);
2284 
2285         /* Check bufferSubData */
2286         write_buffer.Bind();
2287         gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2288         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
2289 
2290         Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2291 
2292         if (0 != memcmp(temp_data, update_data, data_size))
2293         {
2294             test_result = false;
2295 
2296             m_context.getTestContext().getLog()
2297                 << tcu::TestLog::Message << "BufferSubData stored invalid contents in write target buffer."
2298                 << tcu::TestLog::EndMessage;
2299         }
2300     }
2301 
2302     /* Set result */
2303     if (true == test_result)
2304     {
2305         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2306     }
2307     else
2308     {
2309         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2310     }
2311 
2312     /* Done */
2313     return tcu::TestNode::STOP;
2314 }
2315 
2316 /** Constructor
2317  *
2318  * @param context Test context
2319  **/
MapPersistentBufferSubDataTest(deqp::Context & context)2320 MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context &context)
2321     : TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer")
2322 {
2323     /* Nothing to be done here */
2324 }
2325 
2326 /** Execute test
2327  *
2328  * @return tcu::TestNode::STOP otherwise
2329  **/
iterate()2330 tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate()
2331 {
2332     static const size_t data_size              = 64;
2333     static const GLintptr mapped_region_offset = 16;
2334     static const GLsizeiptr mapped_region_size = 16;
2335     static const testCase test_cases[]         = {
2336         {0, 16, false},  /* before mapped region */
2337         {32, 16, false}, /* after mapped region  */
2338         {8, 16, true},   /* at the beginning     */
2339         {24, 16, true},  /* at the end           */
2340         {12, 8, true},   /* in the middle        */
2341     };
2342     static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
2343 
2344     const Functions &gl = m_context.getRenderContext().getFunctions();
2345 
2346     bool test_result = true;
2347 
2348     /* Storage for data */
2349     GLubyte incrementing_data[data_size];
2350 
2351     /* Prepare data */
2352     for (size_t i = 0; i < data_size; ++i)
2353     {
2354         incrementing_data[i] = (glw::GLubyte)i;
2355     }
2356 
2357     /* Load DSA */
2358     Buffer::LoadExtDirectStateAccess(m_context);
2359 
2360     // No GL45 or GL_ARB_direct_state_access support
2361     if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2362     {
2363         m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2364         return tcu::TestNode::STOP;
2365     }
2366 
2367     /* Prepare buffer */
2368     Buffer buffer(m_context);
2369     buffer.InitStorage(GL_ARRAY_BUFFER,
2370                        GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2371                        0 /* data */);
2372     buffer.Bind();
2373 
2374     /*
2375      * - execute tested operation, to update whole buffer with incrementing values
2376      * starting from 0; No error should be generated;
2377      */
2378     gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data);
2379     GLenum error = gl.getError();
2380 
2381     if (GL_NO_ERROR != error)
2382     {
2383         test_result = false;
2384 
2385         m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: "
2386                                             << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2387     }
2388 
2389     if (0 != gl.namedBufferSubData)
2390     {
2391         gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2392         error = gl.getError();
2393     }
2394 
2395     gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2396     error = gl.getError();
2397 
2398     if (GL_NO_ERROR != error)
2399     {
2400         test_result = false;
2401 
2402         m_context.getTestContext().getLog()
2403             << tcu::TestLog::Message
2404             << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2405             << tcu::TestLog::EndMessage;
2406     }
2407 
2408     /*
2409      * - map buffer contents with MapBufferRange; <access> should contain
2410      * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset>
2411      * and <size>;
2412      * - mapped region should contain values from 16 to 31;
2413      * - execute tested operation, to update portions of buffer specified below;
2414      * No error should be generated;
2415      */
2416     {
2417         const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size,
2418                                                    GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2419 
2420         if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size))
2421         {
2422             test_result = false;
2423 
2424             m_context.getTestContext().getLog()
2425                 << tcu::TestLog::Message << "Mapped region contains unexpected data" << tcu::TestLog::EndMessage;
2426         }
2427 
2428         for (size_t i = 0; i < n_test_cases; ++i)
2429         {
2430             const GLintptr offset = test_cases[i].m_offset;
2431             const GLsizeiptr size = test_cases[i].m_size;
2432 
2433             gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2434             error = gl.getError();
2435 
2436             if (GL_NO_ERROR != error)
2437             {
2438                 test_result = false;
2439 
2440                 m_context.getTestContext().getLog()
2441                     << tcu::TestLog::Message
2442                     << "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2443                     << tcu::TestLog::EndMessage;
2444             }
2445 
2446             if (0 != gl.namedBufferSubData)
2447             {
2448                 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2449                 error = gl.getError();
2450             }
2451 
2452             if (GL_NO_ERROR != error)
2453             {
2454                 test_result = false;
2455 
2456                 m_context.getTestContext().getLog()
2457                     << tcu::TestLog::Message
2458                     << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2459                     << tcu::TestLog::EndMessage;
2460             }
2461         }
2462     }
2463 
2464     /*
2465      * - unmap buffer;
2466      * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2467      * - execute tested operation to update regions specified below; It is expected
2468      * that INVALID_OPERATION will be generated for cases that cross mapped region;
2469      * No error should be generated for other cases.
2470      */
2471     {
2472         Buffer::MapOwner tmp(
2473             buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2474 
2475         for (size_t i = 0; i < n_test_cases; ++i)
2476         {
2477             const GLintptr offset        = test_cases[i].m_offset;
2478             const GLsizeiptr size        = test_cases[i].m_size;
2479             const bool is_error_expected = test_cases[i].m_cross_mapped_region;
2480             const GLenum expected_error  = (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR;
2481 
2482             gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2483             error = gl.getError();
2484 
2485             if (expected_error != error)
2486             {
2487                 test_result = false;
2488 
2489                 m_context.getTestContext().getLog()
2490                     << tcu::TestLog::Message
2491                     << "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2492                     << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2493                     << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2494                     << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2495             }
2496 
2497             if (0 != gl.namedBufferSubData)
2498             {
2499                 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2500                 error = gl.getError();
2501             }
2502 
2503             if (expected_error != error)
2504             {
2505                 test_result = false;
2506 
2507                 m_context.getTestContext().getLog()
2508                     << tcu::TestLog::Message
2509                     << "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2510                     << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2511                     << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2512                     << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2513             }
2514         }
2515     }
2516 
2517     /* Set result */
2518     if (true == test_result)
2519     {
2520         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2521     }
2522     else
2523     {
2524         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2525     }
2526 
2527     /* Done */
2528     return tcu::TestNode::STOP;
2529 }
2530 
2531 /** Constructor
2532  *
2533  * @param context Test context
2534  **/
MapPersistentTextureTest(deqp::Context & context)2535 MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context &context)
2536     : TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer")
2537     , m_compressed_image_size(0)
2538     , m_compressed_internal_format(0)
2539 {
2540     /* Nothing to be done here */
2541 }
2542 
2543 /** Execute test
2544  *
2545  * @return tcu::TestNode::STOP otherwise
2546  **/
iterate()2547 tcu::TestNode::IterateResult MapPersistentTextureTest::iterate()
2548 {
2549     static const size_t data_size = 256;
2550 
2551     const Functions &gl = m_context.getRenderContext().getFunctions();
2552 
2553     bool test_result = true;
2554 
2555     /* Storage for data */
2556     GLubyte data[data_size];
2557 
2558     /* Prepare data */
2559     for (size_t i = 0; i < data_size; ++i)
2560     {
2561         data[i] = (glw::GLubyte)i;
2562     }
2563 
2564     /* Load DSA */
2565     Buffer::LoadExtDirectStateAccess(m_context);
2566     Texture::LoadExtDirectStateAccess(m_context);
2567 
2568     /* Get info about compressed image */
2569     getCompressedInfo();
2570 
2571     /* Prepare buffer */
2572     Buffer buffer(m_context);
2573     buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2574                        data);
2575     Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2576 
2577     /*
2578      * - prepare texture in a way that is relevant for tested operation;
2579      * - execute tested operation, no error should be generated;
2580      * - delete texture and prepare next one;
2581      */
2582     for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2583     {
2584         const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2585 
2586         bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2587 
2588         if (false == result)
2589         {
2590             test_result = false;
2591 
2592             m_context.getTestContext().getLog()
2593                 << tcu::TestLog::Message << "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped"
2594                 << tcu::TestLog::EndMessage;
2595         }
2596     }
2597 
2598     /*
2599      * - map buffer contents with MapBufferRange, <access> should contain
2600      * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2601      * - execute tested operation, no error should be generated;
2602      */
2603     for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2604     {
2605         const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2606 
2607         {
2608             Buffer::MapOwner tmp(
2609                 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2610         }
2611         Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2612 
2613         bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2614 
2615         if (false == result)
2616         {
2617             test_result = false;
2618 
2619             m_context.getTestContext().getLog()
2620                 << tcu::TestLog::Message << "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped"
2621                 << tcu::TestLog::EndMessage;
2622         }
2623     }
2624 
2625     /* Set result */
2626     if (true == test_result)
2627     {
2628         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2629     }
2630     else
2631     {
2632         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2633     }
2634 
2635     /* Done */
2636     return tcu::TestNode::STOP;
2637 }
2638 
2639 /** Return name of operation
2640  *
2641  * @param operation Operation which name will be returned
2642  *
2643  * @return Name of operation or 0 in case of invalid enum
2644  **/
getOperationName(TESTED_OPERATION operation)2645 const char *MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation)
2646 {
2647     const char *name = 0;
2648 
2649     switch (operation)
2650     {
2651     case OP_COMPRESSED_TEX_IMAGE:
2652         name = "CompressedTexImage";
2653         break;
2654     case OP_COMPRESSED_TEX_SUB_IMAGE:
2655         name = "CompressedTexSubImage";
2656         break;
2657     case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2658         name = "CompressedTextureSubImage";
2659         break;
2660     case OP_TEX_IMAGE:
2661         name = "TexImage";
2662         break;
2663     case OP_TEX_SUB_IMAGE:
2664         name = "TexSubImage";
2665         break;
2666     default:
2667         TCU_FAIL("Invalid enum");
2668     }
2669 
2670     return name;
2671 }
2672 
2673 /** Check format and size of compressed image
2674  *
2675  **/
getCompressedInfo()2676 void MapPersistentTextureTest::getCompressedInfo()
2677 {
2678     const Functions &gl = m_context.getRenderContext().getFunctions();
2679 
2680     /* Texture creation */
2681     Texture texture(m_context);
2682     Texture::Generate(gl, texture.m_id);
2683     Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2684     Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE,
2685                    0); // glspec 4.5 pg 216
2686 
2687     /* Queries */
2688     Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
2689                                &m_compressed_image_size);
2690     Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT,
2691                                &m_compressed_internal_format);
2692 }
2693 
2694 /** Verifies results of tested operation
2695  *
2696  * @param operation      Operation to be tested
2697  * @param buffer         Buffer that will be used as GL_PIXEL_UNPACK_BUFFER
2698  * @param expected_error Expected error
2699  *
2700  * @return false in case of any error, true otherwise
2701  **/
verifyTestedOperation(TESTED_OPERATION operation,Buffer & buffer,glw::GLenum expected_error)2702 bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer &buffer,
2703                                                      glw::GLenum expected_error)
2704 {
2705     const Functions &gl = m_context.getRenderContext().getFunctions();
2706 
2707     bool result = true;
2708 
2709     GLenum error = GL_NO_ERROR;
2710     Texture texture(m_context);
2711 
2712     /* Prepare texture */
2713     Texture::Generate(gl, texture.m_id);
2714     Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2715 
2716     switch (operation)
2717     {
2718     case OP_COMPRESSED_TEX_IMAGE:
2719     case OP_TEX_IMAGE:
2720         break;
2721     case OP_COMPRESSED_TEX_SUB_IMAGE:
2722     case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2723         Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2724                                  8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */,
2725                                  0 /* empty image */);
2726         break;
2727     case OP_TEX_SUB_IMAGE:
2728         Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED,
2729                        GL_UNSIGNED_BYTE, 0 /* empty image */);
2730         break;
2731     default:
2732         TCU_FAIL("Invalid enum");
2733     }
2734 
2735     /* Bind buffer to PIXEL_UNPACK */
2736     Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER);
2737 
2738     /* Execute operation */
2739     switch (operation)
2740     {
2741     case OP_COMPRESSED_TEX_IMAGE:
2742         gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2743                                 8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */,
2744                                 0 /* offset to pixel unpack buffer */);
2745         error = gl.getError();
2746         break;
2747     case OP_COMPRESSED_TEX_SUB_IMAGE:
2748         gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */,
2749                                    m_compressed_internal_format, m_compressed_image_size,
2750                                    0 /* offset to pixel unpack buffer */);
2751         error = gl.getError();
2752         break;
2753     case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2754         if (0 != gl.compressedTextureSubImage2D)
2755         {
2756             gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */,
2757                                            8 /* height */, m_compressed_internal_format, m_compressed_image_size,
2758                                            0 /* offset to pixel unpack buffer */);
2759             error = gl.getError();
2760         }
2761         else
2762         {
2763             /* Not supported, ignore */
2764             error = expected_error;
2765         }
2766         break;
2767     case OP_TEX_IMAGE:
2768         gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED,
2769                       GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2770         error = gl.getError();
2771         break;
2772     case OP_TEX_SUB_IMAGE:
2773         gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED,
2774                          GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2775         error = gl.getError();
2776         break;
2777     default:
2778         TCU_FAIL("Invalid enum");
2779     }
2780 
2781     /* Unbind buffer */
2782     Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2783 
2784     /* Check result */
2785     if (expected_error != error)
2786     {
2787         result = false;
2788 
2789         m_context.getTestContext().getLog()
2790             << tcu::TestLog::Message << getOperationName(operation)
2791             << " generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2792             << ", expected: " << glu::getErrorStr(expected_error).toString().c_str() << tcu::TestLog::EndMessage;
2793     }
2794 
2795     /* Done */
2796     return result;
2797 }
2798 
2799 /** Constructor
2800  *
2801  * @param context Test context
2802  **/
MapPersistentReadPixelsTest(deqp::Context & context)2803 MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context &context)
2804     : TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer")
2805 {
2806     /* Nothing to be done here */
2807 }
2808 
2809 /** Execute test
2810  *
2811  * @return tcu::TestNode::STOP otherwise
2812  **/
iterate()2813 tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate()
2814 {
2815     static const GLuint height    = 8;
2816     static const GLuint width     = 8;
2817     static const size_t data_size = width * height;
2818 
2819     const Functions &gl = m_context.getRenderContext().getFunctions();
2820 
2821     bool test_result = true;
2822 
2823     /* Prepare data */
2824     GLubyte initial_texture_data[data_size];
2825     GLubyte updated_texture_data[data_size];
2826 
2827     for (size_t i = 0; i < data_size; ++i)
2828     {
2829         initial_texture_data[i] = (glw::GLubyte)i;
2830         updated_texture_data[i] = (glw::GLubyte)(data_size - i);
2831     }
2832 
2833     /* Prepare GL objects */
2834     Buffer buffer(m_context);
2835     Framebuffer framebuffer(m_context);
2836     Texture texture(m_context);
2837 
2838     buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2839                        0 /* data */);
2840 
2841     Texture::Generate(gl, texture.m_id);
2842     Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2843     Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */);
2844     Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
2845                       GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data);
2846 
2847     Framebuffer::Generate(gl, framebuffer.m_id);
2848     Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id);
2849     Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
2850 
2851     /*
2852      * - execute ReadPixels to transfer texture contents to buffer, no error should
2853      * be generated;
2854      */
2855     buffer.Bind();
2856     gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2857                   0 /* offset in PIXEL_PACK_BUFFER */);
2858     GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer");
2859 
2860     /*
2861      * - update contents of texture with different image;
2862      * - map buffer contents with MapBufferRange, <access> should contain
2863      * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2864      * - execute ReadPixels to transfer texture contents to buffer, no error should
2865      * be generated;
2866      * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish;
2867      * - inspect contents of mapped buffer, to verify that latest data transfer was
2868      * successful;
2869      * - unmap buffer
2870      */
2871     {
2872         Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
2873                           0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data);
2874 
2875         const Buffer::MapOwner map(
2876             buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2877 
2878         buffer.Bind();
2879         gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2880                       0 /* offset in PIXEL_PACK_BUFFER */);
2881         GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer");
2882 
2883         gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
2884         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2885 
2886         gl.finish();
2887         GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
2888 
2889         if (0 != memcmp(updated_texture_data, map.m_data, data_size))
2890         {
2891             test_result = false;
2892 
2893             m_context.getTestContext().getLog()
2894                 << tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels"
2895                 << tcu::TestLog::EndMessage;
2896         }
2897     }
2898 
2899     /*
2900      * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2901      * - execute ReadPixels to transfer texture contents to buffer,
2902      * INVALID_OPERATION error should be generated.
2903      */
2904     {
2905         Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2906 
2907         buffer.Bind();
2908         gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2909                       0 /* offset in PIXEL_PACK_BUFFER */);
2910         GLenum error = gl.getError();
2911 
2912         if (GL_INVALID_OPERATION != error)
2913         {
2914             test_result = false;
2915 
2916             m_context.getTestContext().getLog()
2917                 << tcu::TestLog::Message
2918                 << "Wrong error was generated by ReadPixels. Expected INVALID_OPERATION as "
2919                    "PIXEL_PACK buffer is mapped. Got: "
2920                 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2921         }
2922     }
2923 
2924     /* Set result */
2925     if (true == test_result)
2926     {
2927         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2928     }
2929     else
2930     {
2931         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2932     }
2933 
2934     /* Done */
2935     return tcu::TestNode::STOP;
2936 }
2937 
2938 /** Constructor
2939  *
2940  * @param context Test context
2941  **/
MapPersistentDispatchTest(deqp::Context & context)2942 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context &context)
2943     : TestCase(context, "map_persistent_dispatch", "test dispatch operation against mapped buffer")
2944 {
2945     /* Nothing to be done here */
2946 }
2947 
2948 /** Constructor
2949  *
2950  * @param context          Test context
2951  * @param test_name        Test name
2952  * @param test_description Test description
2953  **/
MapPersistentDispatchTest(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)2954 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context &context, const GLchar *test_name,
2955                                                      const GLchar *test_description)
2956     : TestCase(context, test_name, test_description)
2957 {
2958     /* Nothing to be done here */
2959 }
2960 
2961 /** Execute test
2962  *
2963  * @return tcu::TestNode::STOP otherwise
2964  **/
iterate()2965 tcu::TestNode::IterateResult MapPersistentDispatchTest::iterate()
2966 {
2967     static const GLchar *compute_shader     = "#version 430 core\n"
2968                                               "\n"
2969                                               "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2970                                               "\n"
2971                                               "layout (binding = 0, std430) buffer DestinationData {\n"
2972                                               "    uint values[];\n"
2973                                               "} destination;\n"
2974                                               "\n"
2975                                               "layout (binding = 1, std430) buffer SourceData {\n"
2976                                               "    uint values[];\n"
2977                                               "} source;\n"
2978                                               "\n"
2979                                               "void main()\n"
2980                                               "{\n"
2981                                               "    uint index = gl_GlobalInvocationID.x;\n"
2982                                               "    uint sum   = 0u;\n"
2983                                               "\n"
2984                                               "    for (uint i = 0u; i <= index; ++i)\n"
2985                                               "    {\n"
2986                                               "        sum += source.values[i];\n"
2987                                               "    }\n"
2988                                               "\n"
2989                                               "    destination.values[index] = sum;\n"
2990                                               "}\n"
2991                                               "\n";
2992     static const GLuint data_size           = 16;
2993     static const GLuint destination_binding = 0;
2994     static const GLuint source_binding      = 1;
2995 
2996     const Functions &gl = m_context.getRenderContext().getFunctions();
2997 
2998     bool test_result = true;
2999 
3000     /* Prepare data */
3001     GLuint destination_data[data_size];
3002     GLuint modified_source_data[data_size];
3003     GLuint modified_sum_data[data_size];
3004     GLuint source_data[data_size];
3005     GLuint sum_data[data_size];
3006 
3007     GLuint modified_sum = 0;
3008     GLuint sum          = 0;
3009 
3010     for (GLuint i = 0; i < data_size; ++i)
3011     {
3012         destination_data[i]     = 0;
3013         modified_source_data[i] = data_size - i;
3014         source_data[i]          = i;
3015 
3016         modified_sum += modified_source_data[i];
3017         sum += source_data[i];
3018 
3019         modified_sum_data[i] = modified_sum;
3020         sum_data[i]          = sum;
3021     }
3022 
3023     /* Prepare buffers */
3024     Buffer destination(m_context);
3025     Buffer source(m_context);
3026 
3027     destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3028                             data_size * sizeof(GLuint), destination_data);
3029 
3030     source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3031                        data_size * sizeof(GLuint), source_data);
3032 
3033     /* Prepare program */
3034     Program program(m_context);
3035     program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3036 
3037     /*
3038      * - bind buffers to SHADER_STORAGE_BUFFER;
3039      * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3040      *   * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3041      *   * MAP_WRITE_BIT flag shall be set for source;
3042      *   * MAP_READ_BIT flag shall be set for destination;
3043      * - dispatch program for 16x1x1 groups;
3044      * - modify contents of source buffer via mapped memory;
3045      * - execute Finish;
3046      * - inspect contents of destination buffer via mapped memory; It is expected
3047      * that it will contain results based on original content of source buffer;
3048      * - dispatch program for 16x1x1 groups;
3049      * - execute Finish;
3050      * - inspect contents of destination buffer via mapped memory; It is expected
3051      * that it will contain results based on modified content of source buffer.
3052      */
3053     {
3054         /* Set program */
3055         Program::Use(gl, program.m_id);
3056 
3057         /* Map buffers */
3058         destination.Bind();
3059         const Buffer::MapOwner destination_map(destination.MapRange(
3060             0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3061 
3062         source.Bind();
3063         const Buffer::MapOwner source_map(
3064             source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3065                             GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3066 
3067         /* Clear binding point */
3068         Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3069 
3070         /* Bind buffers */
3071         Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3072         Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3073 
3074         /* Execute program for 16x1x1 groups */
3075         gl.dispatchCompute(16, 1, 1);
3076         GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3077 
3078         /* Make sure that program executed */
3079         gl.finish();
3080         GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3081 
3082         if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3083         {
3084             test_result = false;
3085 
3086             m_context.getTestContext().getLog()
3087                 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3088                 << tcu::TestLog::EndMessage;
3089         }
3090 
3091         /* Modify source buffer via mapped area */
3092         memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3093 
3094         /* Execute program for 16x1x1 groups */
3095         gl.dispatchCompute(16, 1, 1);
3096         GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3097 
3098         /* Make sure that program executed */
3099         gl.finish();
3100         GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3101 
3102         if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3103         {
3104             test_result = false;
3105 
3106             m_context.getTestContext().getLog()
3107                 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3108                 << tcu::TestLog::EndMessage;
3109         }
3110     }
3111 
3112     /* Set result */
3113     if (true == test_result)
3114     {
3115         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3116     }
3117     else
3118     {
3119         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3120     }
3121 
3122     /* Done */
3123     return tcu::TestNode::STOP;
3124 }
3125 
3126 /** Constructor
3127  *
3128  * @param context Test context
3129  **/
MapPersistentFlushTest(deqp::Context & context)3130 MapPersistentFlushTest::MapPersistentFlushTest(deqp::Context &context)
3131     : TestCase(context, "map_persistent_flush", "Test mapped buffer against flushing")
3132 {
3133     /* Nothing to be done here */
3134 }
3135 
3136 /** Execute test
3137  *
3138  * @return tcu::TestNode::STOP otherwise
3139  **/
iterate()3140 tcu::TestNode::IterateResult MapPersistentFlushTest::iterate()
3141 {
3142     static const GLchar *compute_shader     = "#version 430 core\n"
3143                                               "\n"
3144                                               "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3145                                               "\n"
3146                                               "layout (binding = 0, std430) buffer DestinationData {\n"
3147                                               "    uint values[];\n"
3148                                               "} destination;\n"
3149                                               "\n"
3150                                               "layout (binding = 1, std430) buffer SourceData {\n"
3151                                               "    uint values[];\n"
3152                                               "} source;\n"
3153                                               "\n"
3154                                               "void main()\n"
3155                                               "{\n"
3156                                               "    uint index = gl_GlobalInvocationID.x;\n"
3157                                               "    uint sum   = 0u;\n"
3158                                               "\n"
3159                                               "    for (uint i = 0u; i <= index; ++i)\n"
3160                                               "    {\n"
3161                                               "        sum += source.values[i];\n"
3162                                               "    }\n"
3163                                               "\n"
3164                                               "    destination.values[index] = sum;\n"
3165                                               "}\n"
3166                                               "\n";
3167     static const GLuint data_size           = 16;
3168     static const GLuint destination_binding = 0;
3169     static const GLuint source_binding      = 1;
3170 
3171     const Functions &gl = m_context.getRenderContext().getFunctions();
3172 
3173     bool test_result = true;
3174 
3175     /* Prepare data */
3176     GLuint destination_data[data_size];
3177     GLuint modified_source_data[data_size];
3178     GLuint modified_sum_data[data_size];
3179     GLuint source_data[data_size];
3180     GLuint sum_data[data_size];
3181 
3182     GLuint modified_sum = 0;
3183     GLuint sum          = 0;
3184 
3185     for (GLuint i = 0; i < data_size; ++i)
3186     {
3187         destination_data[i]     = 0;
3188         modified_source_data[i] = data_size - i;
3189         source_data[i]          = i;
3190 
3191         modified_sum += modified_source_data[i];
3192         sum += source_data[i];
3193 
3194         modified_sum_data[i] = modified_sum;
3195         sum_data[i]          = sum;
3196     }
3197 
3198     /* Prepare buffers */
3199     Buffer destination(m_context);
3200     Buffer source(m_context);
3201 
3202     destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3203                             data_size * sizeof(GLuint), destination_data);
3204 
3205     source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3206                        data_size * sizeof(GLuint), source_data);
3207 
3208     /* Prepare program */
3209     Program program(m_context);
3210     program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3211 
3212     /*
3213      * - bind buffers to SHADER_STORAGE_BUFFER;
3214      * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3215      *   * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3216      *   * MAP_WRITE_BIT flag shall be set for source;
3217      *   * MAP_READ_BIT flag shall be set for destination;
3218      * - dispatch program for 16x1x1 groups;
3219      * - modify contents of source buffer via mapped memory;
3220      * - execute Finish;
3221      * - inspect contents of destination buffer via mapped memory; It is expected
3222      * that it will contain results based on original content of source buffer;
3223      * - dispatch program for 16x1x1 groups;
3224      * - execute Finish;
3225      * - inspect contents of destination buffer via mapped memory; It is expected
3226      * that it will contain results based on modified content of source buffer.
3227      */
3228     {
3229         /* Set program */
3230         Program::Use(gl, program.m_id);
3231 
3232         /* Map buffers */
3233         destination.Bind();
3234         const Buffer::MapOwner destination_map(destination.MapRange(
3235             0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3236 
3237         source.Bind();
3238         const Buffer::MapOwner source_map(
3239             source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3240                             GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3241 
3242         /* Clear binding point */
3243         Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3244 
3245         /* Bind buffers */
3246         Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3247         Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3248 
3249         /* Execute program for 16x1x1 groups */
3250         gl.dispatchCompute(16, 1, 1);
3251         GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3252 
3253         /* Make sure that program executed */
3254         gl.finish();
3255         GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3256 
3257         if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3258         {
3259             test_result = false;
3260 
3261             m_context.getTestContext().getLog()
3262                 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3263                 << tcu::TestLog::EndMessage;
3264         }
3265 
3266         /* Modify source buffer via mapped area */
3267         memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3268 
3269         /*
3270          * - apply FlushMappedBufferRange to ensure that modifications of source buffer
3271          * are visible to server.
3272          */
3273         source.Bind();
3274         gl.flushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /* offset */, data_size * sizeof(GLuint));
3275         GLU_EXPECT_NO_ERROR(gl.getError(), "FlushMappedBufferRange");
3276 
3277         /* Clear binding point */
3278         Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3279 
3280         /* Execute program for 16x1x1 groups */
3281         gl.dispatchCompute(16, 1, 1);
3282         GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3283 
3284         /* Make sure that program executed */
3285         gl.finish();
3286         GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3287 
3288         if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3289         {
3290             test_result = false;
3291 
3292             m_context.getTestContext().getLog()
3293                 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3294                 << tcu::TestLog::EndMessage;
3295         }
3296     }
3297 
3298     /* Set result */
3299     if (true == test_result)
3300     {
3301         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3302     }
3303     else
3304     {
3305         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3306     }
3307 
3308     /* Done */
3309     return tcu::TestNode::STOP;
3310 }
3311 
3312 /** Constructor
3313  *
3314  * @param context Test context
3315  **/
MapPersistentDrawTest(deqp::Context & context)3316 MapPersistentDrawTest::MapPersistentDrawTest(deqp::Context &context)
3317     : TestCase(context, "map_persistent_draw", "Test draw operation against mapped buffer")
3318 {
3319     /* Nothing to be done here */
3320 }
3321 
3322 /** Execute test
3323  *
3324  * @return tcu::TestNode::STOP otherwise
3325  **/
iterate()3326 tcu::TestNode::IterateResult MapPersistentDrawTest::iterate()
3327 {
3328     /*
3329      *   * fragment shader should pass value of "gs_fs_color" varying to red
3330      *   channel of output color;
3331      */
3332     static const GLchar *fragment_shader = "#version 440 core\n"
3333                                            "\n"
3334                                            "in  float gs_fs_color;\n"
3335                                            "out vec4  fs_out_color;\n"
3336                                            "\n"
3337                                            "void main()\n"
3338                                            "{\n"
3339                                            "    fs_out_color = vec4(gs_fs_color, 0, 0, 1);\n"
3340                                            "}\n"
3341                                            "\n";
3342 
3343     /*
3344      *   * geometry shader should:
3345      *     - define single uniform buffer array "rectangles" with unspecified size;
3346      *     Rectangles should have two vec2 fields: position and size;
3347      *     - define a separate atomic_uint "atom_color" per input point;
3348      *     - increment "atom_color" once per input point;
3349      *     - output a quad that is placed at rectangles[vs_gs_index].position and
3350      *     has size equal rectangles[vs_gs_index].size;
3351      *     - define output float varying "gs_fs_color" equal to "atom_color" / 255;
3352      */
3353     static const GLchar *geometry_shader =
3354         "#version 440 core\n"
3355         "\n"
3356         "layout(points)                           in;\n"
3357         "layout(triangle_strip, max_vertices = 4) out;\n"
3358         "\n"
3359         "struct Rectangle {\n"
3360         "    vec2 position;\n"
3361         "    vec2 size;\n"
3362         "};\n"
3363         "\n"
3364         "layout (std140, binding = 0) uniform Rectangles {\n"
3365         "    Rectangle rectangle[2];\n"
3366         "} rectangles;\n"
3367         "\n"
3368         "layout (binding = 0) uniform atomic_uint atom_color[2];\n"
3369         "layout (binding = 0) uniform atomic_uint invocation_hit_count[2];\n"
3370         "\n"
3371         "in  uint  vs_gs_index[];\n"
3372         "out float gs_fs_color;\n"
3373         "\n"
3374         "void main()\n"
3375         "{\n"
3376         "    if (atomicCounterIncrement(invocation_hit_count[gl_PrimitiveIDIn]) == 0)\n"
3377         "    {\n"
3378         "        atomicCounterIncrement(atom_color[gl_PrimitiveIDIn]);\n"
3379         "    }\n"
3380         "    memoryBarrierAtomicCounter();\n"
3381         "    const uint atom_color_value = atomicCounter(atom_color[gl_PrimitiveIDIn]);"
3382         "    //const uint  atom_color_value = vs_gs_index[0];\n"
3383         "    const float color            = float(atom_color_value) / 255.0;\n"
3384         "    //const float color            = rectangles.rectangle[1].size.x;\n"
3385         "\n"
3386         "    const float left   = rectangles.rectangle[vs_gs_index[0]].position.x;\n"
3387         "    const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n"
3388         "    const float right  = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n"
3389         "    const float top    = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n"
3390         "\n"
3391         "    //const float left   = rectangles.rectangle[0].position.x;\n"
3392         "    //const float bottom = rectangles.rectangle[0].position.y;\n"
3393         "    //const float right  = rectangles.rectangle[0].size.x + left;\n"
3394         "    //const float top    = rectangles.rectangle[0].size.y + bottom;\n"
3395         "\n"
3396         "    gs_fs_color = color;\n"
3397         "    gl_Position  = vec4(left, bottom, 0, 1);\n"
3398         "    EmitVertex();\n"
3399         "\n"
3400         "    gs_fs_color = color;\n"
3401         "    gl_Position  = vec4(left, top, 0, 1);\n"
3402         "    EmitVertex();\n"
3403         "\n"
3404         "    gs_fs_color = color;\n"
3405         "    gl_Position  = vec4(right, bottom, 0, 1);\n"
3406         "    EmitVertex();\n"
3407         "\n"
3408         "    gs_fs_color = color;\n"
3409         "    gl_Position  = vec4(right, top, 0, 1);\n"
3410         "    EmitVertex();\n"
3411         "}\n"
3412         "\n";
3413 
3414     /*
3415      *   * vertex shader should output single varying "vs_gs_index" of type uint,
3416      *   equal to gl_VertexID;
3417      */
3418     static const GLchar *vertex_shader = "#version 440 core\n"
3419                                          "\n"
3420                                          "out uint vs_gs_index;\n"
3421                                          "\n"
3422                                          "void main()\n"
3423                                          "{\n"
3424                                          "    vs_gs_index = gl_VertexID;\n"
3425                                          "}\n"
3426                                          "\n";
3427 
3428     static const GLuint atom_binding         = 0;
3429     static const size_t atom_data_size       = 4 * sizeof(GLuint);
3430     static const GLuint expected_atom_first  = 2;
3431     static const GLuint expected_atom_second = 6;
3432     static const GLuint expected_pixel       = 0xff000004;
3433     static const GLuint height               = 16;
3434     static const GLuint n_rectangles         = 2;
3435     static const GLuint pixel_size           = 4 * sizeof(GLubyte);
3436     static const GLuint rectangles_binding   = 0;
3437     static const size_t rectangle_size       = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */
3438     static const size_t rectangles_data_size = n_rectangles * rectangle_size;
3439     static const GLuint width                = 16;
3440     static const GLuint line_size            = width * pixel_size;
3441     static const GLuint pixel_offset         = 8 * line_size + 7 * pixel_size;
3442     static const size_t texture_data_size    = height * line_size;
3443 
3444     const Functions &gl = m_context.getRenderContext().getFunctions();
3445 
3446     bool test_result = true;
3447 
3448     /* Prepare data */
3449     GLuint atom_first_data[4]  = {1, 1, 0, 0};
3450     GLuint atom_second_data[4] = {5, 5, 0, 0};
3451     GLubyte rectangles_first_data[rectangles_data_size];
3452     GLubyte rectangles_second_data[rectangles_data_size];
3453     GLubyte texture_data[texture_data_size];
3454 
3455     {
3456         GLfloat *ptr = (GLfloat *)rectangles_first_data;
3457 
3458         /* First.position*/
3459         ptr[0] = -0.5f;
3460         ptr[1] = -0.5f;
3461 
3462         /* First.size*/
3463         ptr[2] = 1.0f;
3464         ptr[3] = 1.0f;
3465 
3466         /* Second.position*/
3467         ptr[4 + 0] = -0.75f;
3468         ptr[4 + 1] = -0.75f;
3469 
3470         /* Second.size*/
3471         ptr[4 + 2] = 1.5f;
3472         ptr[4 + 3] = 1.5f;
3473     }
3474 
3475     {
3476         GLfloat *ptr = (GLfloat *)rectangles_second_data;
3477 
3478         /* First.position*/
3479         ptr[0] = -1.0f;
3480         ptr[1] = -1.0f;
3481 
3482         /* First.size*/
3483         ptr[2] = 0.5f;
3484         ptr[3] = 0.5f;
3485 
3486         /* Second.position*/
3487         ptr[4 + 0] = 0.5f;
3488         ptr[4 + 1] = 0.5f;
3489 
3490         /* Second.size*/
3491         ptr[4 + 2] = 0.5f;
3492         ptr[4 + 3] = 0.5f;
3493     }
3494 
3495     /* Prepare buffers */
3496     Buffer atom(m_context);
3497     Buffer rectangles(m_context);
3498 
3499     atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
3500                      atom_data_size, 0);
3501 
3502     rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0);
3503 
3504     /* Prepare framebuffer */
3505     Framebuffer framebuffer(m_context);
3506     Texture texture(m_context);
3507 
3508     Texture::Generate(gl, texture.m_id);
3509     Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
3510     Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */);
3511 
3512     Framebuffer::Generate(gl, framebuffer.m_id);
3513     Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
3514     Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
3515 
3516     /* Prepare VAO */
3517     VertexArray vao(m_context);
3518 
3519     VertexArray::Generate(gl, vao.m_id);
3520     VertexArray::Bind(gl, vao.m_id);
3521 
3522     /* Prepare program */
3523     Program program(m_context);
3524     program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader);
3525     Program::Use(gl, program.m_id);
3526 
3527     /*
3528      * - make persistent mapping of both buffers for reads and writes;
3529      * - modify "rectangles" buffer via mapped memory with the following two sets
3530      *   * position [-0.5,-0.5], size [1.0,1.0],
3531      *   * position [-0.25,-0.25], size [1.5,1.5];
3532      * - modify "atom_color" buffer via mapped memory to value 1;
3533      * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3534      * - enable blending with functions ONE for both source and destination;
3535      * - execute DrawArrays for two vertices;
3536      * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3537      * - inspect contents of:
3538      *   * texture - to verify that pixel at 8,8 is filled with RGBA8(4,0,0,0),
3539      *   * "atom_color" - to verify that it is equal to 2;
3540      * - modify "rectangles" buffer via mapped memory with the following two sets
3541      *   * position [-1.0,-1.0], size [0.5,0.5],
3542      *   * position [0.5,0.5], size [0.5,0.5];
3543      * - modify "atom_color" buffer via mapped memory to value 5;
3544      * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3545      * - execute DrawArrays for two vertices;
3546      * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3547      * - inspect contents of:
3548      *   * texture - to verify that pixel at 8,8 is filled with RGBA8(4,0,0,0),
3549      *   * "atom_color" - to verify that it is equal to 6;
3550      *
3551      *  Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile.
3552      */
3553     {
3554         /* Choose specification */
3555         const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3556 
3557         /* Map buffers */
3558         atom.Bind();
3559         const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size,
3560                                                       GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
3561                                                           (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3562 
3563         rectangles.Bind();
3564         const Buffer::MapOwner rectangles_map(
3565             rectangles.MapRange(0 /* offset */, rectangles_data_size,
3566                                 GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3567 
3568         /* Clear binding points */
3569         Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER);
3570         Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER);
3571 
3572         /* Bind buffers */
3573         Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding);
3574         Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding);
3575 
3576         /* Set up blending */
3577         gl.enable(GL_BLEND);
3578         gl.blendFunc(GL_ONE, GL_ONE);
3579 
3580         /* Modify buffers */
3581         memcpy(atom_map.m_data, atom_first_data, atom_data_size);
3582         memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size);
3583 
3584         /* Execute barrier or flush content. */
3585         if (is_gl_45)
3586         {
3587             gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3588             GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3589 
3590             gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3591             GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3592         }
3593         else
3594         {
3595             gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3596             GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3597         }
3598 
3599         /* Clear drawbuffer */
3600         GLint clear_color[4] = {0, 0, 0, 0};
3601         gl.clearBufferiv(GL_COLOR, 0, clear_color);
3602 
3603         /* Execute program for 2 vertices */
3604         gl.drawArrays(GL_POINTS, 0, 2);
3605         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3606 
3607         /* Execute barrier */
3608         gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3609         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3610 
3611         /* Inspect texture */
3612         Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3613         if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3614         {
3615             test_result = false;
3616 
3617             m_context.getTestContext().getLog()
3618                 << tcu::TestLog::Message << "Contents of framebuffer does not correspond with expected results"
3619                 << tcu::TestLog::EndMessage;
3620             tcu::ConstPixelBufferAccess img(
3621                 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3622                 1 /* depth */, texture_data);
3623             m_context.getTestContext().getLog()
3624                 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img);
3625         }
3626 
3627         /* Inspect atom */
3628         if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint)))
3629         {
3630             test_result = false;
3631 
3632             m_context.getTestContext().getLog()
3633                 << tcu::TestLog::Message << "Contents of ATOMIC_COUNTER buffer are invalid."
3634                 << tcu::TestLog::EndMessage;
3635         }
3636 
3637         /* Modify buffers */
3638         memcpy(atom_map.m_data, atom_second_data, atom_data_size);
3639         memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size);
3640 
3641         /* Execute barrier or flush content. */
3642         if (is_gl_45)
3643         {
3644             gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3645             GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3646 
3647             gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3648             GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3649         }
3650         else
3651         {
3652             gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3653             GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3654         }
3655 
3656         /* Execute program for 2 vertices */
3657         gl.drawArrays(GL_POINTS, 0, 2);
3658         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3659 
3660         /* Execute barrier */
3661         gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3662         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3663 
3664         /* Inspect texture */
3665         Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3666         if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3667         {
3668             test_result = false;
3669 
3670             m_context.getTestContext().getLog()
3671                 << tcu::TestLog::Message << "Contents of framebuffer does not correspond with expected results"
3672                 << tcu::TestLog::EndMessage;
3673             tcu::ConstPixelBufferAccess img(
3674                 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3675                 1 /* depth */, texture_data);
3676             m_context.getTestContext().getLog()
3677                 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img);
3678         }
3679 
3680         /* Inspect atom */
3681         if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint)))
3682         {
3683             test_result = false;
3684 
3685             m_context.getTestContext().getLog()
3686                 << tcu::TestLog::Message << "Contents of ATOMIC_COUNTER buffer are invalid."
3687                 << tcu::TestLog::EndMessage;
3688         }
3689     }
3690 
3691     /* Set result */
3692     if (true == test_result)
3693     {
3694         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3695     }
3696     else
3697     {
3698         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3699     }
3700 
3701     /* Done */
3702     return tcu::TestNode::STOP;
3703 }
3704 } // namespace BufferStorage
3705 
3706 /** Constructor.
3707  *
3708  *  @param context Rendering context.
3709  **/
BufferStorageTests(deqp::Context & context)3710 BufferStorageTests::BufferStorageTests(deqp::Context &context)
3711     : TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality")
3712 {
3713     /* Left blank on purpose */
3714 }
3715 
3716 /** Initializes a texture_storage_multisample test group.
3717  *
3718  **/
init(void)3719 void BufferStorageTests::init(void)
3720 {
3721     addChild(new BufferStorage::ErrorsTest(m_context));
3722     addChild(new BufferStorage::GetBufferParameterTest(m_context));
3723     addChild(new BufferStorage::DynamicStorageTest(m_context));
3724     addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context));
3725     addChild(new BufferStorage::MapPersistentTextureTest(m_context));
3726     addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context));
3727     addChild(new BufferStorage::MapPersistentDispatchTest(m_context));
3728     addChild(new BufferStorage::MapPersistentFlushTest(m_context));
3729     addChild(new BufferStorage::MapPersistentDrawTest(m_context));
3730 }
3731 } // namespace gl4cts
3732