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 break;
632 }
633 }
634
635 /** Bind buffer to given target
636 *
637 * @param gl GL functions
638 * @param id Id of buffer
639 * @param target Buffer target
640 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)641 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
642 {
643 gl.bindBuffer(target, id);
644 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
645 }
646
647 /** Binds indexed buffer
648 *
649 * @param gl GL functions
650 * @param id Id of buffer
651 * @param target Buffer target
652 * @param index <index> parameter
653 **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)654 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
655 {
656 gl.bindBufferBase(target, index, id);
657 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
658 }
659
660 /** Binds buffer range
661 *
662 * @param gl GL functions
663 * @param id Id of buffer
664 * @param target Buffer target
665 * @param index <index> parameter
666 * @param offset <offset> parameter
667 * @param size <size> parameter
668 **/
BindRange(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)669 void Buffer::BindRange(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
670 glw::GLintptr offset, glw::GLsizeiptr size)
671 {
672 gl.bindBufferRange(target, index, id, offset, size);
673 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
674 }
675
676 /** Allocate memory for buffer and sends initial content
677 *
678 * @param gl GL functions
679 * @param target Buffer target
680 * @param usage Buffer usage enum
681 * @param size <size> parameter
682 * @param data <data> parameter
683 **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)684 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
685 const glw::GLvoid* data)
686 {
687 gl.bufferData(target, size, data, usage);
688 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
689 }
690
691 /** Generate buffer
692 *
693 * @param gl GL functions
694 * @param out_id Id of buffer
695 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)696 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
697 {
698 GLuint id = m_invalid_id;
699
700 gl.genBuffers(1, &id);
701 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
702
703 if (m_invalid_id == id)
704 {
705 TCU_FAIL("Got invalid id");
706 }
707
708 out_id = id;
709 }
710
711 /** Query parameter of named buffer
712 *
713 * @param gl GL functions
714 * @param buffer Buffer name
715 * @param pname Parameter name
716 * @param data Storage for queried results
717 **/
GetNamedParameter(const glw::Functions & gl,glw::GLuint buffer,glw::GLenum pname,glw::GLint * data)718 void Buffer::GetNamedParameter(const glw::Functions& gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint* data)
719 {
720 gl.getNamedBufferParameteriv(buffer, pname, data);
721 GLU_EXPECT_NO_ERROR(gl.getError(), "GetNameBufferParameteriv");
722 }
723
724 /** Query parameter of bound buffer
725 *
726 * @param gl GL functions
727 * @param Target Buffer target
728 * @param pname Parameter name
729 * @param data Storage for queried results
730 **/
GetParameter(const glw::Functions & gl,glw::GLenum target,glw::GLenum value,glw::GLint * data)731 void Buffer::GetParameter(const glw::Functions& gl, glw::GLenum target, glw::GLenum value, glw::GLint* data)
732 {
733 gl.getBufferParameteriv(target, value, data);
734 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferParameteriv");
735 }
736
737 /** Get contents of buffer's region
738 *
739 * @param gl GL functions
740 * @param target Buffer target
741 * @param offset Offset in buffer
742 * @param size <size> parameter
743 * @param data <data> parameter
744 **/
GetSubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)745 void Buffer::GetSubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
746 glw::GLvoid* data)
747 {
748 gl.getBufferSubData(target, offset, size, data);
749 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferSubData");
750 }
751
752 /** Maps buffer content
753 *
754 * @param gl GL functions
755 * @param target Buffer target
756 * @param access Access rights for mapped region
757 *
758 * @return Mapped memory
759 **/
Map(const glw::Functions & gl,glw::GLenum target,glw::GLenum access)760 void* Buffer::Map(const glw::Functions& gl, glw::GLenum target, glw::GLenum access)
761 {
762 void* result = gl.mapBuffer(target, access);
763 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
764
765 return result;
766 }
767
768 /** Maps buffer content
769 *
770 * @param gl GL functions
771 * @param target Buffer target
772 * @param access Access rights for mapped region
773 *
774 * @return Mapped memory
775 **/
MapRange(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)776 void* Buffer::MapRange(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
777 glw::GLenum access)
778 {
779 void* result = gl.mapBufferRange(target, offset, length, access);
780 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
781
782 return result;
783 }
784
785 /** Allocate immutable memory for buffer and sends initial content
786 *
787 * @param gl GL functions
788 * @param target Buffer target
789 * @param flags Buffer flags
790 * @param size <size> parameter
791 * @param data <data> parameter
792 **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)793 void Buffer::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
794 const glw::GLvoid* data)
795 {
796 gl.bufferStorage(target, size, data, flags);
797 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
798 }
799
800 /** Update range of buffer
801 *
802 * @param gl GL functions
803 * @param target Buffer target
804 * @param offset Offset in buffer
805 * @param size <size> parameter
806 * @param data <data> parameter
807 **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)808 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
809 glw::GLvoid* data)
810 {
811 gl.bufferSubData(target, offset, size, data);
812 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
813 }
814
815 /** Unmaps buffer
816 *
817 * @param gl GL functions
818 * @param target Buffer target
819 **/
UnMap(const glw::Functions & gl,glw::GLenum target)820 void Buffer::UnMap(const glw::Functions& gl, glw::GLenum target)
821 {
822 gl.unmapBuffer(target);
823 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
824 }
825
826 /** Constructor
827 * Takes ownership of mapped region
828 *
829 * @param buffer Mapped buffer
830 * @param data Mapped data
831 **/
MapOwner(Buffer & buffer,glw::GLvoid * data)832 Buffer::MapOwner::MapOwner(Buffer& buffer, glw::GLvoid* data) : m_data(data), m_buffer(&buffer)
833 {
834 /* Nothing to be done */
835 }
836
MapOwner(const Buffer::MoveMapOwner & moveOwner)837 Buffer::MapOwner::MapOwner(const Buffer::MoveMapOwner& moveOwner) : m_data(moveOwner.data), m_buffer(moveOwner.buffer)
838 {
839 }
840
841 /** Move constructor
842 * Transfer ownership of mapped region.
843 *
844 * @param map_owner Map owner
845 **/
MapOwner(MapOwner & map_owner)846 Buffer::MapOwner::MapOwner(MapOwner& map_owner) : m_data(map_owner.m_data), m_buffer(map_owner.m_buffer)
847 {
848 map_owner.m_data = 0;
849 map_owner.m_buffer = 0;
850 }
851
852 /** Destructor
853 * Unmaps buffer
854 **/
~MapOwner()855 Buffer::MapOwner::~MapOwner()
856 {
857 m_data = 0;
858 if (0 != m_buffer)
859 {
860 m_buffer->Bind();
861 m_buffer->UnMap();
862 m_buffer = 0;
863 }
864 }
865
866 /* Framebuffer constants */
867 const GLuint Framebuffer::m_invalid_id = -1;
868
869 /** Constructor.
870 *
871 * @param context CTS context.
872 **/
Framebuffer(deqp::Context & context)873 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
874 {
875 /* Nothing to done here */
876 }
877
878 /** Destructor
879 *
880 **/
~Framebuffer()881 Framebuffer::~Framebuffer()
882 {
883 Release();
884 }
885
886 /** Release texture instance
887 *
888 **/
Release()889 void Framebuffer::Release()
890 {
891 if (m_invalid_id != m_id)
892 {
893 const Functions& gl = m_context.getRenderContext().getFunctions();
894
895 gl.deleteFramebuffers(1, &m_id);
896 m_id = m_invalid_id;
897 }
898 }
899
900 /** Attach texture to specified attachment
901 *
902 * @param gl GL functions
903 * @param target Framebuffer target
904 * @param attachment Attachment
905 * @param texture_id Texture id
906 * @param width Texture width
907 * @param height Texture height
908 **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)909 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
910 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height)
911 {
912 gl.framebufferTexture(target, attachment, texture_id, 0 /* level */);
913 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
914
915 gl.viewport(0 /* x */, 0 /* y */, width, height);
916 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
917 }
918
919 /** Binds framebuffer to DRAW_FRAMEBUFFER
920 *
921 * @param gl GL functions
922 * @param target Framebuffer target
923 * @param id ID of framebuffer
924 **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)925 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
926 {
927 gl.bindFramebuffer(target, id);
928 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
929 }
930
931 /** Generate framebuffer
932 *
933 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)934 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
935 {
936 GLuint id = m_invalid_id;
937
938 gl.genFramebuffers(1, &id);
939 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
940
941 if (m_invalid_id == id)
942 {
943 TCU_FAIL("Invalid id");
944 }
945
946 out_id = id;
947 }
948
949 /* Program constants */
950 const GLuint Program::m_invalid_id = 0;
951
952 /** Constructor.
953 *
954 * @param context CTS context.
955 **/
Program(deqp::Context & context)956 Program::Program(deqp::Context& context)
957 : m_id(m_invalid_id)
958 , m_compute(context)
959 , m_fragment(context)
960 , m_geometry(context)
961 , m_tess_ctrl(context)
962 , m_tess_eval(context)
963 , m_vertex(context)
964 , m_context(context)
965 {
966 /* Nothing to be done here */
967 }
968
969 /** Destructor
970 *
971 **/
~Program()972 Program::~Program()
973 {
974 Release();
975 }
976
977 /** Initialize program instance
978 *
979 * @param compute_shader Compute shader source code
980 * @param fragment_shader Fragment shader source code
981 * @param geometry_shader Geometry shader source code
982 * @param tesselation_control_shader Tesselation control shader source code
983 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
984 * @param vertex_shader Vertex shader source code
985 **/
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)986 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
987 const std::string& geometry_shader, const std::string& tesselation_control_shader,
988 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
989 {
990 /* Delete previous program */
991 Release();
992
993 /* GL entry points */
994 const Functions& gl = m_context.getRenderContext().getFunctions();
995
996 /* Initialize shaders */
997 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
998 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
999 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
1000 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
1001 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
1002 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
1003
1004 /* Create program, set up transform feedback and attach shaders */
1005 Create(gl, m_id);
1006 Attach(gl, m_id, m_compute.m_id);
1007 Attach(gl, m_id, m_fragment.m_id);
1008 Attach(gl, m_id, m_geometry.m_id);
1009 Attach(gl, m_id, m_tess_ctrl.m_id);
1010 Attach(gl, m_id, m_tess_eval.m_id);
1011 Attach(gl, m_id, m_vertex.m_id);
1012
1013 /* Link program */
1014 Link(gl, m_id);
1015 }
1016
1017 /** Release program instance
1018 *
1019 **/
Release()1020 void Program::Release()
1021 {
1022 const Functions& gl = m_context.getRenderContext().getFunctions();
1023
1024 if (m_invalid_id != m_id)
1025 {
1026 Use(gl, m_invalid_id);
1027
1028 gl.deleteProgram(m_id);
1029 m_id = m_invalid_id;
1030 }
1031
1032 m_compute.Release();
1033 m_fragment.Release();
1034 m_geometry.Release();
1035 m_tess_ctrl.Release();
1036 m_tess_eval.Release();
1037 m_vertex.Release();
1038 }
1039
1040 /** Attach shader to program
1041 *
1042 * @param gl GL functions
1043 * @param program_id Id of program
1044 * @param shader_id Id of shader
1045 **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)1046 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
1047 {
1048 /* Sanity checks */
1049 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
1050 {
1051 return;
1052 }
1053
1054 gl.attachShader(program_id, shader_id);
1055 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
1056 }
1057
1058 /** Create program instance
1059 *
1060 * @param gl GL functions
1061 * @param out_id Id of program
1062 **/
Create(const glw::Functions & gl,glw::GLuint & out_id)1063 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
1064 {
1065 const GLuint id = gl.createProgram();
1066 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
1067
1068 if (m_invalid_id == id)
1069 {
1070 TCU_FAIL("Failed to create program");
1071 }
1072
1073 out_id = id;
1074 }
1075
1076 /** Link program
1077 *
1078 * @param gl GL functions
1079 * @param id Id of program
1080 **/
Link(const glw::Functions & gl,glw::GLuint id)1081 void Program::Link(const glw::Functions& gl, glw::GLuint id)
1082 {
1083 GLint status = GL_FALSE;
1084
1085 gl.linkProgram(id);
1086 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
1087
1088 /* Get link status */
1089 gl.getProgramiv(id, GL_LINK_STATUS, &status);
1090 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1091
1092 /* Log link error */
1093 if (GL_TRUE != status)
1094 {
1095 glw::GLint length = 0;
1096 std::string message;
1097
1098 /* Get error log length */
1099 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
1100 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1101
1102 message.resize(length, 0);
1103
1104 /* Get error log */
1105 gl.getProgramInfoLog(id, length, 0, &message[0]);
1106 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
1107
1108 TCU_FAIL(message.c_str());
1109 }
1110 }
1111
1112 /** Use program
1113 *
1114 * @param gl GL functions
1115 * @param id Id of program
1116 **/
Use(const glw::Functions & gl,glw::GLuint id)1117 void Program::Use(const glw::Functions& gl, glw::GLuint id)
1118 {
1119 gl.useProgram(id);
1120 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1121 }
1122
1123 /* Shader's constants */
1124 const GLuint Shader::m_invalid_id = 0;
1125
1126 /** Constructor.
1127 *
1128 * @param context CTS context.
1129 **/
Shader(deqp::Context & context)1130 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1131 {
1132 /* Nothing to be done here */
1133 }
1134
1135 /** Destructor
1136 *
1137 **/
~Shader()1138 Shader::~Shader()
1139 {
1140 Release();
1141 }
1142
1143 /** Initialize shader instance
1144 *
1145 * @param stage Shader stage
1146 * @param source Source code
1147 **/
Init(glw::GLenum stage,const std::string & source)1148 void Shader::Init(glw::GLenum stage, const std::string& source)
1149 {
1150 if (true == source.empty())
1151 {
1152 /* No source == no shader */
1153 return;
1154 }
1155
1156 /* Delete any previous shader */
1157 Release();
1158
1159 /* Create, set source and compile */
1160 const Functions& gl = m_context.getRenderContext().getFunctions();
1161
1162 Create(gl, stage, m_id);
1163 Source(gl, m_id, source);
1164
1165 Compile(gl, m_id);
1166 }
1167
1168 /** Release shader instance
1169 *
1170 **/
Release()1171 void Shader::Release()
1172 {
1173 if (m_invalid_id != m_id)
1174 {
1175 const Functions& gl = m_context.getRenderContext().getFunctions();
1176
1177 gl.deleteShader(m_id);
1178 m_id = m_invalid_id;
1179 }
1180 }
1181
1182 /** Compile shader
1183 *
1184 * @param gl GL functions
1185 * @param id Shader id
1186 **/
Compile(const glw::Functions & gl,glw::GLuint id)1187 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
1188 {
1189 GLint status = GL_FALSE;
1190
1191 /* Compile */
1192 gl.compileShader(id);
1193 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
1194
1195 /* Get compilation status */
1196 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
1197 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1198
1199 /* Log compilation error */
1200 if (GL_TRUE != status)
1201 {
1202 glw::GLint length = 0;
1203 std::string message;
1204
1205 /* Error log length */
1206 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
1207 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1208
1209 /* Prepare storage */
1210 message.resize(length, 0);
1211
1212 /* Get error log */
1213 gl.getShaderInfoLog(id, length, 0, &message[0]);
1214 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
1215
1216 TCU_FAIL(message.c_str());
1217 }
1218 }
1219
1220 /** Create shader
1221 *
1222 * @param gl GL functions
1223 * @param stage Shader stage
1224 * @param out_id Shader id
1225 **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)1226 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
1227 {
1228 const GLuint id = gl.createShader(stage);
1229 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
1230
1231 if (m_invalid_id == id)
1232 {
1233 TCU_FAIL("Failed to create shader");
1234 }
1235
1236 out_id = id;
1237 }
1238
1239 /** Set shader's source code
1240 *
1241 * @param gl GL functions
1242 * @param id Shader id
1243 * @param source Shader source code
1244 **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)1245 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
1246 {
1247 const GLchar* code = source.c_str();
1248
1249 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
1250 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
1251 }
1252
1253 /* Texture static fields */
1254
1255 FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
1256
1257 /* Texture constants */
1258 const GLuint Texture::m_invalid_id = -1;
1259
1260 /** Constructor.
1261 *
1262 * @param context CTS context.
1263 **/
Texture(deqp::Context & context)1264 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1265 {
1266 /* Nothing to done here */
1267 }
1268
1269 /** Destructor
1270 *
1271 **/
~Texture()1272 Texture::~Texture()
1273 {
1274 Release();
1275 }
1276
1277 /** Release texture instance
1278 *
1279 **/
Release()1280 void Texture::Release()
1281 {
1282 if (m_invalid_id != m_id)
1283 {
1284 const Functions& gl = m_context.getRenderContext().getFunctions();
1285
1286 gl.deleteTextures(1, &m_id);
1287 m_id = m_invalid_id;
1288 }
1289 }
1290
1291 /** Loads entry points for direct state access extension
1292 *
1293 * @param context CTS context
1294 **/
LoadExtDirectStateAccess(deqp::Context & context)1295 void Texture::LoadExtDirectStateAccess(deqp::Context& context)
1296 {
1297 FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
1298
1299 switch (support)
1300 {
1301 case FUNCTIONALITY_SUPPORT_NONE:
1302 /* Nothing to be done */
1303 break;
1304 case FUNCTIONALITY_SUPPORT_CORE:
1305 case FUNCTIONALITY_SUPPORT_EXTENSION:
1306 break;
1307 default:
1308 TCU_FAIL("Invalid enum");
1309 break;
1310 }
1311 }
1312
1313 /** Bind texture to target
1314 *
1315 * @param gl GL functions
1316 * @param id Id of texture
1317 * @param tex_type Type of texture
1318 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1319 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
1320 {
1321 gl.bindTexture(target, id);
1322 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1323 }
1324
1325 /** Set contents of compressed texture
1326 *
1327 * @param gl GL functions
1328 * @param target Texture target
1329 * @param level Mipmap level
1330 * @param internal_format Format of data
1331 * @param width Width of texture
1332 * @param height Height of texture
1333 * @param depth Depth of texture
1334 * @param image_size Size of data
1335 * @param data Buffer with image data
1336 **/
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)1337 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
1338 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1339 glw::GLsizei image_size, const glw::GLvoid* data)
1340 {
1341 switch (target)
1342 {
1343 case GL_TEXTURE_1D:
1344 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1345 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1346 break;
1347 case GL_TEXTURE_1D_ARRAY:
1348 case GL_TEXTURE_2D:
1349 case GL_TEXTURE_RECTANGLE:
1350 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1351 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1352 break;
1353 case GL_TEXTURE_CUBE_MAP:
1354 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1355 image_size, data);
1356 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1357 image_size, data);
1358 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1359 image_size, data);
1360 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1361 image_size, data);
1362 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1363 image_size, data);
1364 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1365 image_size, data);
1366 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1367 break;
1368 case GL_TEXTURE_3D:
1369 case GL_TEXTURE_2D_ARRAY:
1370 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1371 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1372 break;
1373 default:
1374 TCU_FAIL("Invliad enum");
1375 break;
1376 }
1377 }
1378
1379 /** Generate texture instance
1380 *
1381 * @param gl GL functions
1382 * @param out_id Id of texture
1383 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1384 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1385 {
1386 GLuint id = m_invalid_id;
1387
1388 gl.genTextures(1, &id);
1389 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1390
1391 if (m_invalid_id == id)
1392 {
1393 TCU_FAIL("Invalid id");
1394 }
1395
1396 out_id = id;
1397 }
1398
1399 /** Get texture data
1400 *
1401 * @param gl GL functions
1402 * @param target Texture target
1403 * @param format Format of data
1404 * @param type Type of data
1405 * @param out_data Buffer for data
1406 **/
GetData(const glw::Functions & gl,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1407 void Texture::GetData(const glw::Functions& gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
1408 glw::GLvoid* out_data)
1409 {
1410 gl.getTexImage(target, 0 /* level */, format, type, out_data);
1411 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1412 }
1413
1414 /** Generate texture instance
1415 *
1416 * @param gl GL functions
1417 * @param target Texture target
1418 * @param level Mipmap level
1419 * @param pname Parameter to query
1420 * @param param Result of query
1421 **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1422 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1423 glw::GLint* param)
1424 {
1425 gl.getTexLevelParameteriv(target, level, pname, param);
1426 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1427 }
1428
1429 /** Set contents of texture
1430 *
1431 * @param gl GL functions
1432 * @param target Texture target
1433 * @param level Mipmap level
1434 * @param internal_format Format of data
1435 * @param width Width of texture
1436 * @param height Height of texture
1437 * @param depth Depth of texture
1438 * @param format Format of data
1439 * @param type Type of data
1440 * @param data Buffer with image data
1441 **/
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)1442 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1443 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1444 const glw::GLvoid* data)
1445 {
1446 switch (target)
1447 {
1448 case GL_TEXTURE_1D:
1449 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1450 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1451 break;
1452 case GL_TEXTURE_1D_ARRAY:
1453 case GL_TEXTURE_2D:
1454 case GL_TEXTURE_RECTANGLE:
1455 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1456 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1457 break;
1458 case GL_TEXTURE_CUBE_MAP:
1459 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1460 type, data);
1461 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1462 type, data);
1463 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1464 type, data);
1465 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1466 type, data);
1467 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1468 type, data);
1469 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1470 type, data);
1471 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1472 break;
1473 case GL_TEXTURE_3D:
1474 case GL_TEXTURE_2D_ARRAY:
1475 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1476 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1477 break;
1478 default:
1479 TCU_FAIL("Invliad enum");
1480 break;
1481 }
1482 }
1483
1484 /** Allocate storage for texture
1485 *
1486 * @param gl GL functions
1487 * @param target Texture target
1488 * @param levels Number of levels
1489 * @param internal_format Internal format of texture
1490 * @param width Width of texture
1491 * @param height Height of texture
1492 * @param depth Depth of texture
1493 **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth)1494 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1495 glw::GLuint width, glw::GLuint height, glw::GLuint depth)
1496 {
1497 switch (target)
1498 {
1499 case GL_TEXTURE_1D:
1500 gl.texStorage1D(target, levels, internal_format, width);
1501 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1502 break;
1503 case GL_TEXTURE_1D_ARRAY:
1504 case GL_TEXTURE_2D:
1505 case GL_TEXTURE_RECTANGLE:
1506 case GL_TEXTURE_CUBE_MAP:
1507 gl.texStorage2D(target, levels, internal_format, width, height);
1508 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1509 break;
1510 case GL_TEXTURE_3D:
1511 case GL_TEXTURE_2D_ARRAY:
1512 gl.texStorage3D(target, levels, internal_format, width, height, depth);
1513 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1514 break;
1515 default:
1516 TCU_FAIL("Invliad enum");
1517 break;
1518 }
1519 }
1520
1521 /** Set contents of texture
1522 *
1523 * @param gl GL functions
1524 * @param target Texture target
1525 * @param level Mipmap level
1526 * @param x X offset
1527 * @param y Y offset
1528 * @param z Z offset
1529 * @param width Width of texture
1530 * @param height Height of texture
1531 * @param depth Depth of texture
1532 * @param format Format of data
1533 * @param type Type of data
1534 * @param pixels Buffer with image data
1535 **/
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)1536 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1537 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1538 glw::GLenum type, const glw::GLvoid* pixels)
1539 {
1540 switch (target)
1541 {
1542 case GL_TEXTURE_1D:
1543 gl.texSubImage1D(target, level, x, width, format, type, pixels);
1544 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1545 break;
1546 case GL_TEXTURE_1D_ARRAY:
1547 case GL_TEXTURE_2D:
1548 case GL_TEXTURE_RECTANGLE:
1549 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1550 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1551 break;
1552 case GL_TEXTURE_CUBE_MAP:
1553 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1554 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1555 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1556 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1557 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1558 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1559 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1560 break;
1561 case GL_TEXTURE_3D:
1562 case GL_TEXTURE_2D_ARRAY:
1563 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1564 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1565 break;
1566 default:
1567 TCU_FAIL("Invliad enum");
1568 break;
1569 }
1570 }
1571
1572 /* VertexArray constants */
1573 const GLuint VertexArray::m_invalid_id = -1;
1574
1575 /** Constructor.
1576 *
1577 * @param context CTS context.
1578 **/
VertexArray(deqp::Context & context)1579 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
1580 {
1581 }
1582
1583 /** Destructor
1584 *
1585 **/
~VertexArray()1586 VertexArray::~VertexArray()
1587 {
1588 Release();
1589 }
1590
1591 /** Release vertex array object instance
1592 *
1593 **/
Release()1594 void VertexArray::Release()
1595 {
1596 if (m_invalid_id != m_id)
1597 {
1598 const Functions& gl = m_context.getRenderContext().getFunctions();
1599
1600 Bind(gl, 0);
1601
1602 gl.deleteVertexArrays(1, &m_id);
1603
1604 m_id = m_invalid_id;
1605 }
1606 }
1607
1608 /** Binds Vertex array object
1609 *
1610 * @param gl GL functions
1611 * @param id ID of vertex array object
1612 **/
Bind(const glw::Functions & gl,glw::GLuint id)1613 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
1614 {
1615 gl.bindVertexArray(id);
1616 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
1617 }
1618
1619 /** Generates Vertex array object
1620 *
1621 * @param gl GL functions
1622 * @param out_id ID of vertex array object
1623 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1624 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1625 {
1626 GLuint id = m_invalid_id;
1627
1628 gl.genVertexArrays(1, &id);
1629 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1630
1631 if (m_invalid_id == id)
1632 {
1633 TCU_FAIL("Invalid id");
1634 }
1635
1636 out_id = id;
1637 }
1638
1639 /** Constructor
1640 *
1641 * @param context Test context
1642 **/
ErrorsTest(deqp::Context & context)1643 ErrorsTest::ErrorsTest(deqp::Context& context)
1644 : TestCase(context, "errors", "Test if errors are generated as specified")
1645 {
1646 /* Nothing to be done here */
1647 }
1648
1649 /** Execute test
1650 *
1651 * @return tcu::TestNode::STOP otherwise
1652 **/
iterate()1653 tcu::TestNode::IterateResult ErrorsTest::iterate()
1654 {
1655 const Functions& gl = m_context.getRenderContext().getFunctions();
1656
1657 bool test_result = true;
1658
1659 Buffer::LoadExtDirectStateAccess(m_context);
1660
1661 // No GL45 or GL_ARB_direct_state_access support
1662 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
1663 {
1664 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
1665 return tcu::TestNode::STOP;
1666 }
1667
1668 /*
1669 * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to
1670 * <target>; Check all targets;
1671 */
1672 for (GLuint i = 0; i < Buffer::m_n_targets; ++i)
1673 {
1674 const GLenum target = Buffer::m_targets[i];
1675 std::string message = "BufferStorage was executed for id 0, target: ";
1676
1677 message.append(glu::getBufferTargetStr(target).toString().c_str());
1678
1679 Buffer::Bind(gl, 0 /* id */, target);
1680 gl.bufferStorage(target, 0 /* size */, 0 /* data */, GL_DYNAMIC_STORAGE_BIT /* flags */);
1681
1682 verifyError(GL_INVALID_OPERATION, message.c_str(), test_result);
1683 }
1684
1685 /*
1686 * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and
1687 * BufferData if buffer already have immutable store;
1688 */
1689 {
1690 static const GLsizeiptr data_size = 32;
1691 static GLubyte data[data_size];
1692
1693 Buffer buffer(m_context);
1694 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1695
1696 /* NamedBufferStorage */
1697 if (0 != gl.namedBufferStorage)
1698 {
1699 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1700 verifyError(GL_INVALID_OPERATION, "NamedBufferStorage was executed for id with immutable storage",
1701 test_result);
1702 }
1703
1704 /* BufferStorage */
1705 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1706
1707 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1708 verifyError(GL_INVALID_OPERATION, "BufferStorage was executed for target with immutable storage", test_result);
1709
1710 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1711 }
1712
1713 /*
1714 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1715 * <size> is less or equal to zero;
1716 */
1717 {
1718 static const GLsizeiptr data_size = 32;
1719 static GLubyte data[data_size];
1720
1721 Buffer buffer(m_context);
1722 gl.createBuffers(1, &buffer.m_id);
1723
1724 /* NamedBufferStorage */
1725 if (0 != gl.namedBufferStorage)
1726 {
1727 gl.namedBufferStorage(buffer.m_id, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1728 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == 0", test_result);
1729
1730 gl.namedBufferStorage(buffer.m_id, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1731 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == -16", test_result);
1732 }
1733
1734 /* BufferStorage */
1735 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1736
1737 gl.bufferStorage(GL_ARRAY_BUFFER, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1738 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == 0", test_result);
1739
1740 gl.bufferStorage(GL_ARRAY_BUFFER, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1741 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == -16", test_result);
1742
1743 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1744 }
1745
1746 /*
1747 * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when
1748 * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor
1749 * MAP_WRITE_BIT;
1750 */
1751 {
1752 static const GLsizeiptr data_size = 32;
1753 static GLubyte data[data_size];
1754
1755 Buffer buffer(m_context);
1756 gl.createBuffers(1, &buffer.m_id);
1757
1758 /* NamedBufferStorage */
1759 if (0 != gl.namedBufferStorage)
1760 {
1761 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_PERSISTENT_BIT);
1762 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT",
1763 test_result);
1764 }
1765
1766 /* BufferStorage */
1767 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1768
1769 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_PERSISTENT_BIT);
1770 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", test_result);
1771
1772 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1773 }
1774
1775 /*
1776 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1777 * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT;
1778 */
1779 {
1780 static const GLsizeiptr data_size = 32;
1781 static GLubyte data[data_size];
1782
1783 Buffer buffer(m_context);
1784 gl.createBuffers(1, &buffer.m_id);
1785
1786 /* NamedBufferStorage */
1787 if (0 != gl.namedBufferStorage)
1788 {
1789 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_COHERENT_BIT);
1790 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_COHERENT_BIT",
1791 test_result);
1792 }
1793
1794 /* BufferStorage */
1795 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1796
1797 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_COHERENT_BIT);
1798 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_COHERENT_BIT", test_result);
1799
1800 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1801 }
1802
1803 /*
1804 * - INVALID_OPERATION is generated by MapBufferRange if any of:
1805 * * MAP_COHERENT_BIT,
1806 * * MAP_PERSISTENT_BIT,
1807 * * MAP_READ_BIT,
1808 * * MAP_WRITE_BIT
1809 * is included in <access> and not in buffer's storage flags;
1810 */
1811 {
1812 static const GLsizeiptr data_size = 32;
1813 static GLubyte data[data_size];
1814
1815 Buffer buffer(m_context);
1816 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1817
1818 /* MapNamedBufferRange */
1819 if (0 != gl.mapNamedBufferRange)
1820 {
1821 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1822 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, "
1823 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1824 test_result);
1825
1826 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1827 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, "
1828 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1829 test_result);
1830
1831 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1832 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, "
1833 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1834 test_result);
1835
1836 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1837 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, "
1838 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1839 test_result);
1840 }
1841
1842 /* BufferStorage */
1843 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1844
1845 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1846 verifyError(
1847 GL_INVALID_OPERATION,
1848 "MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1849 test_result);
1850
1851 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1852 verifyError(
1853 GL_INVALID_OPERATION,
1854 "MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1855 test_result);
1856
1857 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1858 verifyError(
1859 GL_INVALID_OPERATION,
1860 "MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1861 test_result);
1862
1863 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1864 verifyError(
1865 GL_INVALID_OPERATION,
1866 "MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1867 test_result);
1868
1869 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1870 }
1871
1872 /*
1873 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData
1874 * when buffer has immutable store but its flags does not include
1875 * DYNAMIC_STORAGE.
1876 */
1877 {
1878 static const GLsizeiptr data_size = 32;
1879 static GLubyte data[data_size];
1880
1881 Buffer buffer(m_context);
1882 buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size,
1883 data);
1884
1885 /* NamedBufferSubData */
1886 if (0 != gl.namedBufferSubData)
1887 {
1888 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data);
1889 verifyError(GL_INVALID_OPERATION,
1890 "NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result);
1891 }
1892
1893 /* BufferStorage */
1894 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1895
1896 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data);
1897 verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT",
1898 test_result);
1899
1900 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1901 }
1902
1903 /* Set result */
1904 if (true == test_result)
1905 {
1906 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1907 }
1908 else
1909 {
1910 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1911 }
1912
1913 /* Done */
1914 return tcu::TestNode::STOP;
1915 }
1916
1917 /** Verifies that expected error was generated
1918 *
1919 * @param expected_error Expected error
1920 * @param error_message Message that will be logged in case of wrong error
1921 * @param out_test_result Set to false if worng error was generated, not modified otherwise
1922 **/
verifyError(glw::GLenum expected_error,const glw::GLchar * error_message,bool & out_test_result)1923 void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result)
1924 {
1925 const Functions& gl = m_context.getRenderContext().getFunctions();
1926
1927 const GLenum error = gl.getError();
1928
1929 if (error != expected_error)
1930 {
1931 out_test_result = false;
1932
1933 m_context.getTestContext().getLog()
1934 << tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error)
1935 << ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message
1936 << tcu::TestLog::EndMessage;
1937 }
1938 }
1939
1940 /** Constructor
1941 *
1942 * @param context Test context
1943 **/
GetBufferParameterTest(deqp::Context & context)1944 GetBufferParameterTest::GetBufferParameterTest(deqp::Context& context)
1945 : TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers")
1946 {
1947 static const GLenum s_mapping_bits[] = { 0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT };
1948 static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]);
1949
1950 GLenum flags = 0;
1951
1952 for (GLuint dynamic = 0; dynamic < 2; ++dynamic)
1953 {
1954 flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT;
1955
1956 for (GLuint client = 0; client < 2; ++client)
1957 {
1958 flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT;
1959
1960 /* No "map" bits */
1961 if (0 != flags)
1962 {
1963 m_test_cases.push_back(testCase(flags, 0));
1964 }
1965
1966 for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx)
1967 {
1968 const GLenum flag_mapping_bits = s_mapping_bits[flag_idx];
1969 const GLenum flags_with_mapping = flags | flag_mapping_bits;
1970
1971 for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx)
1972 {
1973 const GLenum access = s_mapping_bits[access_idx];
1974
1975 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT));
1976 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1977 m_test_cases.push_back(
1978 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT));
1979 m_test_cases.push_back(
1980 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1981 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
1982 access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
1983 }
1984 }
1985 }
1986 }
1987 }
1988
1989 /** Execute test
1990 *
1991 * @return tcu::TestNode::STOP otherwise
1992 **/
iterate()1993 tcu::TestNode::IterateResult GetBufferParameterTest::iterate()
1994 {
1995 static const GLsizeiptr data_size = 32;
1996 static GLubyte data[data_size];
1997
1998 Buffer::LoadExtDirectStateAccess(m_context);
1999
2000 // No GL45 or GL_ARB_direct_state_access support
2001 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2002 {
2003 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2004 return tcu::TestNode::STOP;
2005 }
2006
2007 const Functions& gl = m_context.getRenderContext().getFunctions();
2008
2009 bool test_result = true;
2010
2011 for (GLuint i = 0; i < m_test_cases.size(); ++i)
2012 {
2013 const testCase& test_case = m_test_cases[i];
2014 const GLenum access = test_case.m_access;
2015 const GLenum flags = test_case.m_flags;
2016
2017 GLint queried_flags = -1;
2018 GLint queried_immutable = -1;
2019 GLint queried_size = -1;
2020
2021 Buffer buffer(m_context);
2022
2023 buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data);
2024 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
2025
2026 if (0 != gl.getNamedBufferParameteriv)
2027 {
2028 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2029 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2030 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size);
2031
2032 if (queried_flags != (GLint)flags)
2033 {
2034 test_result = false;
2035 m_context.getTestContext().getLog()
2036 << tcu::TestLog::Message
2037 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2038 << " expected: " << flags << tcu::TestLog::EndMessage;
2039 }
2040 }
2041
2042 if (queried_flags != (GLint)flags)
2043 {
2044 test_result = false;
2045 m_context.getTestContext().getLog()
2046 << tcu::TestLog::Message
2047 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2048 << " expected: " << flags << tcu::TestLog::EndMessage;
2049 }
2050
2051 if (queried_immutable != GL_TRUE)
2052 {
2053 test_result = false;
2054 m_context.getTestContext().getLog()
2055 << tcu::TestLog::Message
2056 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: "
2057 << queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2058 }
2059
2060 if (queried_size != data_size)
2061 {
2062 test_result = false;
2063 m_context.getTestContext().getLog()
2064 << tcu::TestLog::Message
2065 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2066 << " expected: " << data_size << tcu::TestLog::EndMessage;
2067 }
2068
2069 queried_flags = -1;
2070 queried_immutable = -1;
2071 queried_size = -1;
2072
2073 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2074 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2075 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size);
2076
2077 if (queried_flags != (GLint)flags)
2078 {
2079 test_result = false;
2080 m_context.getTestContext().getLog()
2081 << tcu::TestLog::Message
2082 << "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2083 << " expected: " << flags << tcu::TestLog::EndMessage;
2084 }
2085
2086 if (queried_immutable != GL_TRUE)
2087 {
2088 test_result = false;
2089 m_context.getTestContext().getLog()
2090 << tcu::TestLog::Message
2091 << "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable
2092 << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2093 }
2094
2095 if (queried_size != data_size)
2096 {
2097 test_result = false;
2098 m_context.getTestContext().getLog()
2099 << tcu::TestLog::Message
2100 << "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2101 << " expected: " << data_size << tcu::TestLog::EndMessage;
2102 }
2103
2104 if (0 != access)
2105 {
2106 GLint queried_access = -1;
2107
2108 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access));
2109
2110 if (0 != gl.getNamedBufferParameteriv)
2111 {
2112 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2113 }
2114
2115 if (queried_access != (GLint)access)
2116 {
2117 test_result = false;
2118 m_context.getTestContext().getLog()
2119 << tcu::TestLog::Message
2120 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2121 << " expected: " << access << tcu::TestLog::EndMessage;
2122 }
2123
2124 queried_access = -1;
2125
2126 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2127
2128 if (queried_access != (GLint)access)
2129 {
2130 test_result = false;
2131 m_context.getTestContext().getLog()
2132 << tcu::TestLog::Message
2133 << "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2134 << " expected: " << access << tcu::TestLog::EndMessage;
2135 }
2136 }
2137
2138 Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER);
2139 }
2140
2141 /* Set result */
2142 if (true == test_result)
2143 {
2144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2145 }
2146 else
2147 {
2148 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2149 }
2150
2151 /* Done */
2152 return tcu::TestNode::STOP;
2153 }
2154
2155 /** Constructor
2156 *
2157 * @param context Test context
2158 **/
testCase(glw::GLenum flags,glw::GLenum access)2159 GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access)
2160 {
2161 }
2162
2163 /** Constructor
2164 *
2165 * @param context Test context
2166 **/
DynamicStorageTest(deqp::Context & context)2167 DynamicStorageTest::DynamicStorageTest(deqp::Context& context)
2168 : TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected")
2169 {
2170 /* Nothing to be done here */
2171 }
2172
2173 /** Execute test
2174 *
2175 * @return tcu::TestNode::STOP otherwise
2176 **/
iterate()2177 tcu::TestNode::IterateResult DynamicStorageTest::iterate()
2178 {
2179 static const size_t data_size = 64;
2180
2181 const Functions& gl = m_context.getRenderContext().getFunctions();
2182
2183 bool test_result = true;
2184
2185 /*
2186 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to
2187 * COPY_READ_BUFFER;
2188 * - prepare 64 bytes immutable buffer filled with value 2; Do not set
2189 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER;
2190 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2191 * filled with value 3; INVLIAD_OPERATION error should be generated;
2192 * - inspect contents of buffer to verify it is filled with 2;
2193 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to
2194 * COPY_WRITE_BUFFER; No error should be generated;
2195 * - inspect contents of buffer to verify it is filled with 1;
2196 */
2197 {
2198 /* Prepare buffers */
2199 GLubyte read_data[data_size];
2200 GLubyte temp_data[data_size];
2201 GLubyte update_data[data_size];
2202 GLubyte write_data[data_size];
2203
2204 for (size_t i = 0; i < data_size; ++i)
2205 {
2206 read_data[i] = 1;
2207 temp_data[i] = 0;
2208 update_data[i] = 3;
2209 write_data[i] = 2;
2210 }
2211
2212 Buffer read_buffer(m_context);
2213 Buffer write_buffer(m_context);
2214
2215 read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data);
2216 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data);
2217
2218 /* Check bufferSubData */
2219 write_buffer.Bind();
2220 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2221
2222 GLenum error = gl.getError();
2223 if (GL_INVALID_OPERATION != error)
2224 {
2225 test_result = false;
2226
2227 m_context.getTestContext().getLog()
2228 << tcu::TestLog::Message << "Invalid error was generated. BufferSubData was executed on store without "
2229 "DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: "
2230 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2231 }
2232
2233 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2234
2235 if (0 != memcmp(temp_data, write_data, data_size))
2236 {
2237 test_result = false;
2238
2239 m_context.getTestContext().getLog()
2240 << tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT."
2241 << tcu::TestLog::EndMessage;
2242 }
2243
2244 /* Check copyBufferSubData */
2245 read_buffer.Bind();
2246 gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */,
2247 data_size);
2248 GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData");
2249
2250 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2251
2252 if (0 != memcmp(temp_data, read_data, data_size))
2253 {
2254 test_result = false;
2255
2256 m_context.getTestContext().getLog() << tcu::TestLog::Message
2257 << "CopyBufferSubData stored invalid contents in write target buffer."
2258 << tcu::TestLog::EndMessage;
2259 }
2260 }
2261
2262 /*
2263 * - delete buffer and create new one; This time <flags> should contain
2264 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER;
2265 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2266 * filled with value 3; No error should be generated;
2267 * - inspect contents of buffer to verify it is filled with 3;
2268 */
2269 {
2270 /* Prepare buffers */
2271 GLubyte temp_data[data_size];
2272 GLubyte update_data[data_size];
2273 GLubyte write_data[data_size];
2274
2275 for (size_t i = 0; i < data_size; ++i)
2276 {
2277 temp_data[i] = 0;
2278 update_data[i] = 3;
2279 write_data[i] = 2;
2280 }
2281
2282 Buffer write_buffer(m_context);
2283
2284 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data);
2285
2286 /* Check bufferSubData */
2287 write_buffer.Bind();
2288 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2289 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
2290
2291 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2292
2293 if (0 != memcmp(temp_data, update_data, data_size))
2294 {
2295 test_result = false;
2296
2297 m_context.getTestContext().getLog() << tcu::TestLog::Message
2298 << "BufferSubData stored invalid contents in write target buffer."
2299 << tcu::TestLog::EndMessage;
2300 }
2301 }
2302
2303 /* Set result */
2304 if (true == test_result)
2305 {
2306 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2307 }
2308 else
2309 {
2310 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2311 }
2312
2313 /* Done */
2314 return tcu::TestNode::STOP;
2315 }
2316
2317 /** Constructor
2318 *
2319 * @param context Test context
2320 **/
MapPersistentBufferSubDataTest(deqp::Context & context)2321 MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context& context)
2322 : TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer")
2323 {
2324 /* Nothing to be done here */
2325 }
2326
2327 /** Execute test
2328 *
2329 * @return tcu::TestNode::STOP otherwise
2330 **/
iterate()2331 tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate()
2332 {
2333 static const size_t data_size = 64;
2334 static const GLintptr mapped_region_offset = 16;
2335 static const GLsizeiptr mapped_region_size = 16;
2336 static const testCase test_cases[] = {
2337 { 0, 16, false }, /* before mapped region */
2338 { 32, 16, false }, /* after mapped region */
2339 { 8, 16, true }, /* at the beginning */
2340 { 24, 16, true }, /* at the end */
2341 { 12, 8, true }, /* in the middle */
2342 };
2343 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
2344
2345 const Functions& gl = m_context.getRenderContext().getFunctions();
2346
2347 bool test_result = true;
2348
2349 /* Storage for data */
2350 GLubyte incrementing_data[data_size];
2351
2352 /* Prepare data */
2353 for (size_t i = 0; i < data_size; ++i)
2354 {
2355 incrementing_data[i] = (glw::GLubyte)i;
2356 }
2357
2358 /* Load DSA */
2359 Buffer::LoadExtDirectStateAccess(m_context);
2360
2361 // No GL45 or GL_ARB_direct_state_access support
2362 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2363 {
2364 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2365 return tcu::TestNode::STOP;
2366 }
2367
2368 /* Prepare buffer */
2369 Buffer buffer(m_context);
2370 buffer.InitStorage(GL_ARRAY_BUFFER,
2371 GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2372 0 /* data */);
2373 buffer.Bind();
2374
2375 /*
2376 * - execute tested operation, to update whole buffer with incrementing values
2377 * starting from 0; No error should be generated;
2378 */
2379 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data);
2380 GLenum error = gl.getError();
2381
2382 if (GL_NO_ERROR != error)
2383 {
2384 test_result = false;
2385
2386 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: "
2387 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2388 }
2389
2390 if (0 != gl.namedBufferSubData)
2391 {
2392 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2393 error = gl.getError();
2394 }
2395
2396 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2397 error = gl.getError();
2398
2399 if (GL_NO_ERROR != error)
2400 {
2401 test_result = false;
2402
2403 m_context.getTestContext().getLog()
2404 << tcu::TestLog::Message
2405 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2406 << tcu::TestLog::EndMessage;
2407 }
2408
2409 /*
2410 * - map buffer contents with MapBufferRange; <access> should contain
2411 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset>
2412 * and <size>;
2413 * - mapped region should contain values from 16 to 31;
2414 * - execute tested operation, to update portions of buffer specified below;
2415 * No error should be generated;
2416 */
2417 {
2418 const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size,
2419 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2420
2421 if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size))
2422 {
2423 test_result = false;
2424
2425 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Mapped region contains unexpected data"
2426 << tcu::TestLog::EndMessage;
2427 }
2428
2429 for (size_t i = 0; i < n_test_cases; ++i)
2430 {
2431 const GLintptr offset = test_cases[i].m_offset;
2432 const GLsizeiptr size = test_cases[i].m_size;
2433
2434 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2435 error = gl.getError();
2436
2437 if (GL_NO_ERROR != error)
2438 {
2439 test_result = false;
2440
2441 m_context.getTestContext().getLog()
2442 << tcu::TestLog::Message
2443 << "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2444 << tcu::TestLog::EndMessage;
2445 }
2446
2447 if (0 != gl.namedBufferSubData)
2448 {
2449 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2450 error = gl.getError();
2451 }
2452
2453 if (GL_NO_ERROR != error)
2454 {
2455 test_result = false;
2456
2457 m_context.getTestContext().getLog()
2458 << tcu::TestLog::Message
2459 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2460 << tcu::TestLog::EndMessage;
2461 }
2462 }
2463 }
2464
2465 /*
2466 * - unmap buffer;
2467 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2468 * - execute tested operation to update regions specified below; It is expected
2469 * that INVALID_OPERATION will be generated for cases that cross mapped region;
2470 * No error should be generated for other cases.
2471 */
2472 {
2473 Buffer::MapOwner tmp(
2474 buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2475
2476 for (size_t i = 0; i < n_test_cases; ++i)
2477 {
2478 const GLintptr offset = test_cases[i].m_offset;
2479 const GLsizeiptr size = test_cases[i].m_size;
2480 const bool is_error_expected = test_cases[i].m_cross_mapped_region;
2481 const GLenum expected_error = (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR;
2482
2483 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2484 error = gl.getError();
2485
2486 if (expected_error != error)
2487 {
2488 test_result = false;
2489
2490 m_context.getTestContext().getLog()
2491 << tcu::TestLog::Message
2492 << "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2493 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2494 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2495 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2496 }
2497
2498 if (0 != gl.namedBufferSubData)
2499 {
2500 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2501 error = gl.getError();
2502 }
2503
2504 if (expected_error != error)
2505 {
2506 test_result = false;
2507
2508 m_context.getTestContext().getLog()
2509 << tcu::TestLog::Message
2510 << "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2511 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2512 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2513 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2514 }
2515 }
2516 }
2517
2518 /* Set result */
2519 if (true == test_result)
2520 {
2521 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2522 }
2523 else
2524 {
2525 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2526 }
2527
2528 /* Done */
2529 return tcu::TestNode::STOP;
2530 }
2531
2532 /** Constructor
2533 *
2534 * @param context Test context
2535 **/
MapPersistentTextureTest(deqp::Context & context)2536 MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context& context)
2537 : TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer")
2538 , m_compressed_image_size(0)
2539 , m_compressed_internal_format(0)
2540 {
2541 /* Nothing to be done here */
2542 }
2543
2544 /** Execute test
2545 *
2546 * @return tcu::TestNode::STOP otherwise
2547 **/
iterate()2548 tcu::TestNode::IterateResult MapPersistentTextureTest::iterate()
2549 {
2550 static const size_t data_size = 256;
2551
2552 const Functions& gl = m_context.getRenderContext().getFunctions();
2553
2554 bool test_result = true;
2555
2556 /* Storage for data */
2557 GLubyte data[data_size];
2558
2559 /* Prepare data */
2560 for (size_t i = 0; i < data_size; ++i)
2561 {
2562 data[i] = (glw::GLubyte)i;
2563 }
2564
2565 /* Load DSA */
2566 Buffer::LoadExtDirectStateAccess(m_context);
2567 Texture::LoadExtDirectStateAccess(m_context);
2568
2569 /* Get info about compressed image */
2570 getCompressedInfo();
2571
2572 /* Prepare buffer */
2573 Buffer buffer(m_context);
2574 buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2575 data);
2576 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2577
2578 /*
2579 * - prepare texture in a way that is relevant for tested operation;
2580 * - execute tested operation, no error should be generated;
2581 * - delete texture and prepare next one;
2582 */
2583 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2584 {
2585 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2586
2587 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2588
2589 if (false == result)
2590 {
2591 test_result = false;
2592
2593 m_context.getTestContext().getLog() << tcu::TestLog::Message
2594 << "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped"
2595 << tcu::TestLog::EndMessage;
2596 }
2597 }
2598
2599 /*
2600 * - map buffer contents with MapBufferRange, <access> should contain
2601 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2602 * - execute tested operation, no error should be generated;
2603 */
2604 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2605 {
2606 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2607
2608 {
2609 Buffer::MapOwner tmp(
2610 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2611 }
2612 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2613
2614 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2615
2616 if (false == result)
2617 {
2618 test_result = false;
2619
2620 m_context.getTestContext().getLog() << tcu::TestLog::Message
2621 << "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped"
2622 << tcu::TestLog::EndMessage;
2623 }
2624 }
2625
2626 /* Set result */
2627 if (true == test_result)
2628 {
2629 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2630 }
2631 else
2632 {
2633 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2634 }
2635
2636 /* Done */
2637 return tcu::TestNode::STOP;
2638 }
2639
2640 /** Return name of operation
2641 *
2642 * @param operation Operation which name will be returned
2643 *
2644 * @return Name of operation or 0 in case of invalid enum
2645 **/
getOperationName(TESTED_OPERATION operation)2646 const char* MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation)
2647 {
2648 const char* name = 0;
2649
2650 switch (operation)
2651 {
2652 case OP_COMPRESSED_TEX_IMAGE:
2653 name = "CompressedTexImage";
2654 break;
2655 case OP_COMPRESSED_TEX_SUB_IMAGE:
2656 name = "CompressedTexSubImage";
2657 break;
2658 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2659 name = "CompressedTextureSubImage";
2660 break;
2661 case OP_TEX_IMAGE:
2662 name = "TexImage";
2663 break;
2664 case OP_TEX_SUB_IMAGE:
2665 name = "TexSubImage";
2666 break;
2667 default:
2668 TCU_FAIL("Invalid enum");
2669 }
2670
2671 return name;
2672 }
2673
2674 /** Check format and size of compressed image
2675 *
2676 **/
getCompressedInfo()2677 void MapPersistentTextureTest::getCompressedInfo()
2678 {
2679 const Functions& gl = m_context.getRenderContext().getFunctions();
2680
2681 /* Texture creation */
2682 Texture texture(m_context);
2683 Texture::Generate(gl, texture.m_id);
2684 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2685 Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE,
2686 0); // glspec 4.5 pg 216
2687
2688 /* Queries */
2689 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
2690 &m_compressed_image_size);
2691 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT,
2692 &m_compressed_internal_format);
2693 }
2694
2695 /** Verifies results of tested operation
2696 *
2697 * @param operation Operation to be tested
2698 * @param buffer Buffer that will be used as GL_PIXEL_UNPACK_BUFFER
2699 * @param expected_error Expected error
2700 *
2701 * @return false in case of any error, true otherwise
2702 **/
verifyTestedOperation(TESTED_OPERATION operation,Buffer & buffer,glw::GLenum expected_error)2703 bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer,
2704 glw::GLenum expected_error)
2705 {
2706 const Functions& gl = m_context.getRenderContext().getFunctions();
2707
2708 bool result = true;
2709
2710 GLenum error = GL_NO_ERROR;
2711 Texture texture(m_context);
2712
2713 /* Prepare texture */
2714 Texture::Generate(gl, texture.m_id);
2715 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2716
2717 switch (operation)
2718 {
2719 case OP_COMPRESSED_TEX_IMAGE:
2720 case OP_TEX_IMAGE:
2721 break;
2722 case OP_COMPRESSED_TEX_SUB_IMAGE:
2723 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2724 Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2725 8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */,
2726 0 /* empty image */);
2727 break;
2728 case OP_TEX_SUB_IMAGE:
2729 Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED,
2730 GL_UNSIGNED_BYTE, 0 /* empty image */);
2731 break;
2732 default:
2733 TCU_FAIL("Invalid enum");
2734 }
2735
2736 /* Bind buffer to PIXEL_UNPACK */
2737 Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER);
2738
2739 /* Execute operation */
2740 switch (operation)
2741 {
2742 case OP_COMPRESSED_TEX_IMAGE:
2743 gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2744 8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */,
2745 0 /* offset to pixel unpack buffer */);
2746 error = gl.getError();
2747 break;
2748 case OP_COMPRESSED_TEX_SUB_IMAGE:
2749 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */,
2750 m_compressed_internal_format, m_compressed_image_size,
2751 0 /* offset to pixel unpack buffer */);
2752 error = gl.getError();
2753 break;
2754 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2755 if (0 != gl.compressedTextureSubImage2D)
2756 {
2757 gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */,
2758 8 /* height */, m_compressed_internal_format, m_compressed_image_size,
2759 0 /* offset to pixel unpack buffer */);
2760 error = gl.getError();
2761 }
2762 else
2763 {
2764 /* Not supported, ignore */
2765 error = expected_error;
2766 }
2767 break;
2768 case OP_TEX_IMAGE:
2769 gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED,
2770 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2771 error = gl.getError();
2772 break;
2773 case OP_TEX_SUB_IMAGE:
2774 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED,
2775 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2776 error = gl.getError();
2777 break;
2778 default:
2779 TCU_FAIL("Invalid enum");
2780 }
2781
2782 /* Unbind buffer */
2783 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2784
2785 /* Check result */
2786 if (expected_error != error)
2787 {
2788 result = false;
2789
2790 m_context.getTestContext().getLog() << tcu::TestLog::Message << getOperationName(operation)
2791 << " generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2792 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2793 << tcu::TestLog::EndMessage;
2794 }
2795
2796 /* Done */
2797 return result;
2798 }
2799
2800 /** Constructor
2801 *
2802 * @param context Test context
2803 **/
MapPersistentReadPixelsTest(deqp::Context & context)2804 MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context& context)
2805 : TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer")
2806 {
2807 /* Nothing to be done here */
2808 }
2809
2810 /** Execute test
2811 *
2812 * @return tcu::TestNode::STOP otherwise
2813 **/
iterate()2814 tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate()
2815 {
2816 static const GLuint height = 8;
2817 static const GLuint width = 8;
2818 static const size_t data_size = width * height;
2819
2820 const Functions& gl = m_context.getRenderContext().getFunctions();
2821
2822 bool test_result = true;
2823
2824 /* Prepare data */
2825 GLubyte initial_texture_data[data_size];
2826 GLubyte updated_texture_data[data_size];
2827
2828 for (size_t i = 0; i < data_size; ++i)
2829 {
2830 initial_texture_data[i] = (glw::GLubyte)i;
2831 updated_texture_data[i] = (glw::GLubyte)(data_size - i);
2832 }
2833
2834 /* Prepare GL objects */
2835 Buffer buffer(m_context);
2836 Framebuffer framebuffer(m_context);
2837 Texture texture(m_context);
2838
2839 buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2840 0 /* data */);
2841
2842 Texture::Generate(gl, texture.m_id);
2843 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2844 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */);
2845 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
2846 GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data);
2847
2848 Framebuffer::Generate(gl, framebuffer.m_id);
2849 Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id);
2850 Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
2851
2852 /*
2853 * - execute ReadPixels to transfer texture contents to buffer, no error should
2854 * be generated;
2855 */
2856 buffer.Bind();
2857 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2858 0 /* offset in PIXEL_PACK_BUFFER */);
2859 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer");
2860
2861 /*
2862 * - update contents of texture with different image;
2863 * - map buffer contents with MapBufferRange, <access> should contain
2864 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2865 * - execute ReadPixels to transfer texture contents to buffer, no error should
2866 * be generated;
2867 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish;
2868 * - inspect contents of mapped buffer, to verify that latest data transfer was
2869 * successful;
2870 * - unmap buffer
2871 */
2872 {
2873 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
2874 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data);
2875
2876 const Buffer::MapOwner map(
2877 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2878
2879 buffer.Bind();
2880 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2881 0 /* offset in PIXEL_PACK_BUFFER */);
2882 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer");
2883
2884 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
2885 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2886
2887 gl.finish();
2888 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
2889
2890 if (0 != memcmp(updated_texture_data, map.m_data, data_size))
2891 {
2892 test_result = false;
2893
2894 m_context.getTestContext().getLog()
2895 << tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels"
2896 << tcu::TestLog::EndMessage;
2897 }
2898 }
2899
2900 /*
2901 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2902 * - execute ReadPixels to transfer texture contents to buffer,
2903 * INVALID_OPERATION error should be generated.
2904 */
2905 {
2906 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2907
2908 buffer.Bind();
2909 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2910 0 /* offset in PIXEL_PACK_BUFFER */);
2911 GLenum error = gl.getError();
2912
2913 if (GL_INVALID_OPERATION != error)
2914 {
2915 test_result = false;
2916
2917 m_context.getTestContext().getLog()
2918 << tcu::TestLog::Message << "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() << tcu::TestLog::Message
3087 << "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() << tcu::TestLog::Message
3107 << "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() << tcu::TestLog::Message
3262 << "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() << tcu::TestLog::Message
3293 << "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 single atomic_uint "atom_color";
3348 * - increment "atom_color" once per execution;
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;\n"
3369 "\n"
3370 "in uint vs_gs_index[];\n"
3371 "out float gs_fs_color;\n"
3372 "\n"
3373 "void main()\n"
3374 "{\n"
3375 " const uint atom_color_value = atomicCounterIncrement(atom_color);\n"
3376 " //const uint atom_color_value = vs_gs_index[0];\n"
3377 " const float color = float(atom_color_value) / 255.0;\n"
3378 " //const float color = rectangles.rectangle[1].size.x;\n"
3379 "\n"
3380 " const float left = rectangles.rectangle[vs_gs_index[0]].position.x;\n"
3381 " const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n"
3382 " const float right = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n"
3383 " const float top = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n"
3384 "\n"
3385 " //const float left = rectangles.rectangle[0].position.x;\n"
3386 " //const float bottom = rectangles.rectangle[0].position.y;\n"
3387 " //const float right = rectangles.rectangle[0].size.x + left;\n"
3388 " //const float top = rectangles.rectangle[0].size.y + bottom;\n"
3389 "\n"
3390 " gs_fs_color = color;\n"
3391 " gl_Position = vec4(left, bottom, 0, 1);\n"
3392 " EmitVertex();\n"
3393 "\n"
3394 " gs_fs_color = color;\n"
3395 " gl_Position = vec4(left, top, 0, 1);\n"
3396 " EmitVertex();\n"
3397 "\n"
3398 " gs_fs_color = color;\n"
3399 " gl_Position = vec4(right, bottom, 0, 1);\n"
3400 " EmitVertex();\n"
3401 "\n"
3402 " gs_fs_color = color;\n"
3403 " gl_Position = vec4(right, top, 0, 1);\n"
3404 " EmitVertex();\n"
3405 "}\n"
3406 "\n";
3407
3408 /*
3409 * * vertex shader should output single varying "vs_gs_index" of type uint,
3410 * equal to gl_VertexID;
3411 */
3412 static const GLchar* vertex_shader = "#version 440 core\n"
3413 "\n"
3414 "out uint vs_gs_index;\n"
3415 "\n"
3416 "void main()\n"
3417 "{\n"
3418 " vs_gs_index = gl_VertexID;\n"
3419 "}\n"
3420 "\n";
3421
3422 static const GLuint atom_binding = 0;
3423 static const size_t atom_data_size = 1 * sizeof(GLuint);
3424 static const GLuint expected_atom_first = 3;
3425 static const GLuint expected_atom_second = 7;
3426 static const GLuint expected_pixel = 0xff000003;
3427 static const GLuint height = 16;
3428 static const GLuint n_rectangles = 2;
3429 static const GLuint pixel_size = 4 * sizeof(GLubyte);
3430 static const GLuint rectangles_binding = 0;
3431 static const size_t rectangle_size = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */
3432 static const size_t rectangles_data_size = n_rectangles * rectangle_size;
3433 static const GLuint width = 16;
3434 static const GLuint line_size = width * pixel_size;
3435 static const GLuint pixel_offset = 8 * line_size + 7 * pixel_size;
3436 static const size_t texture_data_size = height * line_size;
3437
3438 const Functions& gl = m_context.getRenderContext().getFunctions();
3439
3440 bool test_result = true;
3441
3442 /* Prepare data */
3443 GLuint atom_first_data[1];
3444 GLuint atom_second_data[1];
3445 GLubyte rectangles_first_data[rectangles_data_size];
3446 GLubyte rectangles_second_data[rectangles_data_size];
3447 GLubyte texture_data[texture_data_size];
3448
3449 atom_first_data[0] = 1;
3450 atom_second_data[0] = 5;
3451
3452 {
3453 GLfloat* ptr = (GLfloat*)rectangles_first_data;
3454
3455 /* First.position*/
3456 ptr[0] = -0.5f;
3457 ptr[1] = -0.5f;
3458
3459 /* First.size*/
3460 ptr[2] = 1.0f;
3461 ptr[3] = 1.0f;
3462
3463 /* Second.position*/
3464 ptr[4 + 0] = -0.75f;
3465 ptr[4 + 1] = -0.75f;
3466
3467 /* Second.size*/
3468 ptr[4 + 2] = 1.5f;
3469 ptr[4 + 3] = 1.5f;
3470 }
3471
3472 {
3473 GLfloat* ptr = (GLfloat*)rectangles_second_data;
3474
3475 /* First.position*/
3476 ptr[0] = -1.0f;
3477 ptr[1] = -1.0f;
3478
3479 /* First.size*/
3480 ptr[2] = 0.5f;
3481 ptr[3] = 0.5f;
3482
3483 /* Second.position*/
3484 ptr[4 + 0] = 0.5f;
3485 ptr[4 + 1] = 0.5f;
3486
3487 /* Second.size*/
3488 ptr[4 + 2] = 0.5f;
3489 ptr[4 + 3] = 0.5f;
3490 }
3491
3492 /* Prepare buffers */
3493 Buffer atom(m_context);
3494 Buffer rectangles(m_context);
3495
3496 atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
3497 atom_data_size, 0);
3498
3499 rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0);
3500
3501 /* Prepare framebuffer */
3502 Framebuffer framebuffer(m_context);
3503 Texture texture(m_context);
3504
3505 Texture::Generate(gl, texture.m_id);
3506 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
3507 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */);
3508
3509 Framebuffer::Generate(gl, framebuffer.m_id);
3510 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
3511 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
3512
3513 /* Prepare VAO */
3514 VertexArray vao(m_context);
3515
3516 VertexArray::Generate(gl, vao.m_id);
3517 VertexArray::Bind(gl, vao.m_id);
3518
3519 /* Prepare program */
3520 Program program(m_context);
3521 program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader);
3522 Program::Use(gl, program.m_id);
3523
3524 /*
3525 * - make persistent mapping of both buffers for reads and writes;
3526 * - modify "rectangles" buffer via mapped memory with the following two sets
3527 * * position [-0.5,-0.5], size [1.0,1.0],
3528 * * position [-0.25,-0.25], size [1.5,1.5];
3529 * - modify "atom_color" buffer via mapped memory to value 1;
3530 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3531 * - enable blending with functions ONE for both source and destination;
3532 * - execute DrawArrays for two vertices;
3533 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3534 * - inspect contents of:
3535 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3536 * * "atom_color" - to verify that it is equal to 3;
3537 * - modify "rectangles" buffer via mapped memory with the following two sets
3538 * * position [-1.0,-1.0], size [0.5,0.5],
3539 * * position [0.5,0.5], size [0.5,0.5];
3540 * - modify "atom_color" buffer via mapped memory to value 5;
3541 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3542 * - execute DrawArrays for two vertices;
3543 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3544 * - inspect contents of:
3545 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3546 * * "atom_color" - to verify that it is equal to 7;
3547 *
3548 * Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile.
3549 */
3550 {
3551 /* Choose specification */
3552 const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3553
3554 /* Map buffers */
3555 atom.Bind();
3556 const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size,
3557 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
3558 (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3559
3560 rectangles.Bind();
3561 const Buffer::MapOwner rectangles_map(
3562 rectangles.MapRange(0 /* offset */, rectangles_data_size,
3563 GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3564
3565 /* Clear binding points */
3566 Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER);
3567 Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER);
3568
3569 /* Bind buffers */
3570 Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding);
3571 Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding);
3572
3573 /* Set up blending */
3574 gl.enable(GL_BLEND);
3575 gl.blendFunc(GL_ONE, GL_ONE);
3576
3577 /* Modify buffers */
3578 memcpy(atom_map.m_data, atom_first_data, atom_data_size);
3579 memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size);
3580
3581 /* Execute barrier or flush content. */
3582 if (is_gl_45)
3583 {
3584 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3585 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3586
3587 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3588 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3589 }
3590 else
3591 {
3592 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3593 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3594 }
3595
3596 /* Clear drawbuffer */
3597 GLint clear_color[4] = { 0, 0, 0, 0 };
3598 gl.clearBufferiv(GL_COLOR, 0, clear_color);
3599
3600 /* Execute program for 2 vertices */
3601 gl.drawArrays(GL_POINTS, 0, 2);
3602 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3603
3604 /* Execute barrier */
3605 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3606 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3607
3608 /* Inspect texture */
3609 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3610 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3611 {
3612 test_result = false;
3613
3614 m_context.getTestContext().getLog() << tcu::TestLog::Message
3615 << "Contents of framebuffer does not correspond with expected results"
3616 << tcu::TestLog::EndMessage;
3617 tcu::ConstPixelBufferAccess img(
3618 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3619 1 /* depth */, texture_data);
3620 m_context.getTestContext().getLog()
3621 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img);
3622 }
3623
3624 /* Inspect atom */
3625 if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint)))
3626 {
3627 test_result = false;
3628
3629 m_context.getTestContext().getLog() << tcu::TestLog::Message
3630 << "Contents of ATOMIC_COUNTER buffer are invalid."
3631 << tcu::TestLog::EndMessage;
3632 }
3633
3634 /* Modify buffers */
3635 memcpy(atom_map.m_data, atom_second_data, atom_data_size);
3636 memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size);
3637
3638 /* Execute barrier or flush content. */
3639 if (is_gl_45)
3640 {
3641 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3642 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3643
3644 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3645 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3646 }
3647 else
3648 {
3649 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3650 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3651 }
3652
3653 /* Execute program for 2 vertices */
3654 gl.drawArrays(GL_POINTS, 0, 2);
3655 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3656
3657 /* Execute barrier */
3658 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3659 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3660
3661 /* Inspect texture */
3662 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3663 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3664 {
3665 test_result = false;
3666
3667 m_context.getTestContext().getLog() << tcu::TestLog::Message
3668 << "Contents of framebuffer does not correspond with expected results"
3669 << tcu::TestLog::EndMessage;
3670 tcu::ConstPixelBufferAccess img(
3671 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3672 1 /* depth */, texture_data);
3673 m_context.getTestContext().getLog()
3674 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img);
3675 }
3676
3677 /* Inspect atom */
3678 if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint)))
3679 {
3680 test_result = false;
3681
3682 m_context.getTestContext().getLog() << tcu::TestLog::Message
3683 << "Contents of ATOMIC_COUNTER buffer are invalid."
3684 << tcu::TestLog::EndMessage;
3685 }
3686 }
3687
3688 /* Set result */
3689 if (true == test_result)
3690 {
3691 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3692 }
3693 else
3694 {
3695 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3696 }
3697
3698 /* Done */
3699 return tcu::TestNode::STOP;
3700 }
3701 } /* BufferStorage */
3702
3703 /** Constructor.
3704 *
3705 * @param context Rendering context.
3706 **/
BufferStorageTests(deqp::Context & context)3707 BufferStorageTests::BufferStorageTests(deqp::Context& context)
3708 : TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality")
3709 {
3710 /* Left blank on purpose */
3711 }
3712
3713 /** Initializes a texture_storage_multisample test group.
3714 *
3715 **/
init(void)3716 void BufferStorageTests::init(void)
3717 {
3718 addChild(new BufferStorage::ErrorsTest(m_context));
3719 addChild(new BufferStorage::GetBufferParameterTest(m_context));
3720 addChild(new BufferStorage::DynamicStorageTest(m_context));
3721 addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context));
3722 addChild(new BufferStorage::MapPersistentTextureTest(m_context));
3723 addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context));
3724 addChild(new BufferStorage::MapPersistentDispatchTest(m_context));
3725 addChild(new BufferStorage::MapPersistentFlushTest(m_context));
3726 addChild(new BufferStorage::MapPersistentDrawTest(m_context));
3727 }
3728 } /* gl4cts namespace */
3729