1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite 3e5c31af7Sopenharmony_ci * ----------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2015-2016 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci */ /*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief 22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci/** 25e5c31af7Sopenharmony_ci */ /*! 26e5c31af7Sopenharmony_ci * \file gl4cSparseBufferTests.cpp 27e5c31af7Sopenharmony_ci * \brief Conformance tests for the GL_ARB_sparse_buffer functionality. 28e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/ 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "gl4cSparseBufferTests.hpp" 31e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 32e5c31af7Sopenharmony_ci#include "gluDefs.hpp" 33e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 34e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 35e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci#include <string.h> 38e5c31af7Sopenharmony_ci#include <vector> 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_ci#ifndef GL_SPARSE_BUFFER_PAGE_SIZE_ARB 41e5c31af7Sopenharmony_ci#define GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8 42e5c31af7Sopenharmony_ci#endif 43e5c31af7Sopenharmony_ci#ifndef GL_SPARSE_STORAGE_BIT_ARB 44e5c31af7Sopenharmony_ci#define GL_SPARSE_STORAGE_BIT_ARB 0x0400 45e5c31af7Sopenharmony_ci#endif 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_cinamespace gl4cts 48e5c31af7Sopenharmony_ci{ 49e5c31af7Sopenharmony_ci/** Rounds up the provided offset so that it is aligned to the specified value (eg. page size). 50e5c31af7Sopenharmony_ci * In other words, the result value meets the following requirements: 51e5c31af7Sopenharmony_ci * 52e5c31af7Sopenharmony_ci * 1) result value % input value = 0 53e5c31af7Sopenharmony_ci * 2) result value >= offset 54e5c31af7Sopenharmony_ci * 3) (result value - offset) < input value 55e5c31af7Sopenharmony_ci * 56e5c31af7Sopenharmony_ci * @param offset Offset to be used for the rounding operation. 57e5c31af7Sopenharmony_ci * @param value Value to align the offset to. 58e5c31af7Sopenharmony_ci * 59e5c31af7Sopenharmony_ci * @return Result value. 60e5c31af7Sopenharmony_ci **/ 61e5c31af7Sopenharmony_ciunsigned int SparseBufferTestUtilities::alignOffset(const unsigned int& offset, const unsigned int& value) 62e5c31af7Sopenharmony_ci{ 63e5c31af7Sopenharmony_ci return offset + (value - offset % value) % value; 64e5c31af7Sopenharmony_ci} 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_ci/** Builds a compute program object, using the user-specified CS code snippets. 67e5c31af7Sopenharmony_ci * 68e5c31af7Sopenharmony_ci * @param gl DEQP CTS GL functions container. 69e5c31af7Sopenharmony_ci * @param cs_body_parts Code snippets to use for the compute shader. Must hold exactly 70e5c31af7Sopenharmony_ci * @param n_cs_body_parts null-terminated text strings. 71e5c31af7Sopenharmony_ci * @param n_cs_body_parts Number of code snippets accessible via @param cs_body_parts. 72e5c31af7Sopenharmony_ci * 73e5c31af7Sopenharmony_ci * @return Result PO id if program has been linked successfully, 0 otherwise. 74e5c31af7Sopenharmony_ci **/ 75e5c31af7Sopenharmony_ciglw::GLuint SparseBufferTestUtilities::createComputeProgram(const glw::Functions& gl, const char** cs_body_parts, 76e5c31af7Sopenharmony_ci unsigned int n_cs_body_parts) 77e5c31af7Sopenharmony_ci{ 78e5c31af7Sopenharmony_ci glw::GLint compile_status = GL_FALSE; 79e5c31af7Sopenharmony_ci glw::GLuint cs_id = 0; 80e5c31af7Sopenharmony_ci glw::GLint link_status = GL_FALSE; 81e5c31af7Sopenharmony_ci glw::GLuint po_id = 0; 82e5c31af7Sopenharmony_ci bool result = true; 83e5c31af7Sopenharmony_ci 84e5c31af7Sopenharmony_ci if (n_cs_body_parts > 0) 85e5c31af7Sopenharmony_ci { 86e5c31af7Sopenharmony_ci cs_id = gl.createShader(GL_COMPUTE_SHADER); 87e5c31af7Sopenharmony_ci } 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci po_id = gl.createProgram(); 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() / glCreateShader() call(s) failed."); 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_ci if (n_cs_body_parts > 0) 94e5c31af7Sopenharmony_ci { 95e5c31af7Sopenharmony_ci gl.attachShader(po_id, cs_id); 96e5c31af7Sopenharmony_ci } 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci if (n_cs_body_parts > 0) 101e5c31af7Sopenharmony_ci { 102e5c31af7Sopenharmony_ci gl.shaderSource(cs_id, n_cs_body_parts, cs_body_parts, NULL); /* length */ 103e5c31af7Sopenharmony_ci } 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci gl.compileShader(cs_id); 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci gl.getShaderiv(cs_id, GL_COMPILE_STATUS, &compile_status); 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci char temp[1024]; 116e5c31af7Sopenharmony_ci gl.getShaderInfoLog(cs_id, 1024, NULL, temp); 117e5c31af7Sopenharmony_ci 118e5c31af7Sopenharmony_ci if (GL_TRUE != compile_status) 119e5c31af7Sopenharmony_ci { 120e5c31af7Sopenharmony_ci result = false; 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci goto end; 123e5c31af7Sopenharmony_ci } 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ci gl.linkProgram(po_id); 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci if (GL_TRUE != link_status) 134e5c31af7Sopenharmony_ci { 135e5c31af7Sopenharmony_ci result = false; 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci goto end; 138e5c31af7Sopenharmony_ci } 139e5c31af7Sopenharmony_ci 140e5c31af7Sopenharmony_ciend: 141e5c31af7Sopenharmony_ci if (cs_id != 0) 142e5c31af7Sopenharmony_ci { 143e5c31af7Sopenharmony_ci gl.deleteShader(cs_id); 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci cs_id = 0; 146e5c31af7Sopenharmony_ci } 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci if (!result) 149e5c31af7Sopenharmony_ci { 150e5c31af7Sopenharmony_ci if (po_id != 0) 151e5c31af7Sopenharmony_ci { 152e5c31af7Sopenharmony_ci gl.deleteProgram(po_id); 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci po_id = 0; 155e5c31af7Sopenharmony_ci } 156e5c31af7Sopenharmony_ci } /* if (!result) */ 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci return po_id; 159e5c31af7Sopenharmony_ci} 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci/** Builds a program object, using the user-specified code snippets. Can optionally configure 162e5c31af7Sopenharmony_ci * the PO to use pre-defined attribute locations & transform feed-back varyings. 163e5c31af7Sopenharmony_ci * 164e5c31af7Sopenharmony_ci * @param gl DEQP CTS GL functions container. 165e5c31af7Sopenharmony_ci * @param fs_body_parts Code snippets to use for the fragment shader. Must hold exactly 166e5c31af7Sopenharmony_ci * @param n_fs_body_parts null-terminated text strings. May only 167e5c31af7Sopenharmony_ci * be NULL if @param n_fs_body_parts is 0. 168e5c31af7Sopenharmony_ci * @param n_fs_body_parts See @param fs_body_parts definitions. 169e5c31af7Sopenharmony_ci * @param vs_body_parts Code snippets to use for the vertex shader. Must hold exactly 170e5c31af7Sopenharmony_ci * @param n_vs_body_parts null-terminated text strings. May only 171e5c31af7Sopenharmony_ci * be NULL if @param n_vs_body_parts is 0. 172e5c31af7Sopenharmony_ci * @param n_vs_body_parts See @param vs_body_parts definitions. 173e5c31af7Sopenharmony_ci * @param attribute_names Null-terminated attribute names to pass to the 174e5c31af7Sopenharmony_ci * glBindAttribLocation() call. 175e5c31af7Sopenharmony_ci * May only be NULL if @param n_attribute_properties is 0. 176e5c31af7Sopenharmony_ci * @param attribute_locations Attribute locations to pass to the glBindAttribLocation() call. 177e5c31af7Sopenharmony_ci * May only be NULL if @param n_attribute_properties is 0. 178e5c31af7Sopenharmony_ci * @param n_attribute_properties See @param attribute_names and @param attribute_locations definitions. 179e5c31af7Sopenharmony_ci * @param tf_varyings Transform-feedback varying names to use for the 180e5c31af7Sopenharmony_ci * glTransformFeedbackVaryings() call. May only be NULL if 181e5c31af7Sopenharmony_ci * @param n_tf_varyings is 0. 182e5c31af7Sopenharmony_ci * @param n_tf_varyings See @param tf_varyings definition. 183e5c31af7Sopenharmony_ci * @param tf_varying_mode Transform feedback mode to use for the 184e5c31af7Sopenharmony_ci * glTransformFeedbackVaryings() call. Only used if @param n_tf_varyings 185e5c31af7Sopenharmony_ci * is 0. 186e5c31af7Sopenharmony_ci * 187e5c31af7Sopenharmony_ci * @return Result PO id if program has been linked successfully, 0 otherwise. 188e5c31af7Sopenharmony_ci **/ 189e5c31af7Sopenharmony_ciglw::GLuint SparseBufferTestUtilities::createProgram(const glw::Functions& gl, const char** fs_body_parts, 190e5c31af7Sopenharmony_ci unsigned int n_fs_body_parts, const char** vs_body_parts, 191e5c31af7Sopenharmony_ci unsigned int n_vs_body_parts, const char** attribute_names, 192e5c31af7Sopenharmony_ci const unsigned int* attribute_locations, 193e5c31af7Sopenharmony_ci unsigned int n_attribute_properties, 194e5c31af7Sopenharmony_ci const glw::GLchar* const* tf_varyings, unsigned int n_tf_varyings, 195e5c31af7Sopenharmony_ci glw::GLenum tf_varying_mode) 196e5c31af7Sopenharmony_ci{ 197e5c31af7Sopenharmony_ci glw::GLint compile_status = GL_FALSE; 198e5c31af7Sopenharmony_ci glw::GLuint fs_id = 0; 199e5c31af7Sopenharmony_ci glw::GLint link_status = GL_FALSE; 200e5c31af7Sopenharmony_ci glw::GLuint po_id = 0; 201e5c31af7Sopenharmony_ci bool result = true; 202e5c31af7Sopenharmony_ci glw::GLuint vs_id = 0; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci if (n_fs_body_parts > 0) 205e5c31af7Sopenharmony_ci { 206e5c31af7Sopenharmony_ci fs_id = gl.createShader(GL_FRAGMENT_SHADER); 207e5c31af7Sopenharmony_ci } 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_ci po_id = gl.createProgram(); 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ci if (n_vs_body_parts > 0) 212e5c31af7Sopenharmony_ci { 213e5c31af7Sopenharmony_ci vs_id = gl.createShader(GL_VERTEX_SHADER); 214e5c31af7Sopenharmony_ci } 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() / glCreateShader() call(s) failed."); 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci if (n_fs_body_parts > 0) 219e5c31af7Sopenharmony_ci { 220e5c31af7Sopenharmony_ci gl.attachShader(po_id, fs_id); 221e5c31af7Sopenharmony_ci } 222e5c31af7Sopenharmony_ci 223e5c31af7Sopenharmony_ci if (n_vs_body_parts > 0) 224e5c31af7Sopenharmony_ci { 225e5c31af7Sopenharmony_ci gl.attachShader(po_id, vs_id); 226e5c31af7Sopenharmony_ci } 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ci if (n_fs_body_parts > 0) 231e5c31af7Sopenharmony_ci { 232e5c31af7Sopenharmony_ci gl.shaderSource(fs_id, n_fs_body_parts, fs_body_parts, NULL); /* length */ 233e5c31af7Sopenharmony_ci } 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci if (n_vs_body_parts > 0) 236e5c31af7Sopenharmony_ci { 237e5c31af7Sopenharmony_ci gl.shaderSource(vs_id, n_vs_body_parts, vs_body_parts, NULL); /* length */ 238e5c31af7Sopenharmony_ci } 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); 241e5c31af7Sopenharmony_ci 242e5c31af7Sopenharmony_ci const glw::GLuint so_ids[] = { fs_id, vs_id }; 243e5c31af7Sopenharmony_ci const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]); 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id) 246e5c31af7Sopenharmony_ci { 247e5c31af7Sopenharmony_ci if (so_ids[n_so_id] != 0) 248e5c31af7Sopenharmony_ci { 249e5c31af7Sopenharmony_ci gl.compileShader(so_ids[n_so_id]); 250e5c31af7Sopenharmony_ci 251e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_ci gl.getShaderiv(so_ids[n_so_id], GL_COMPILE_STATUS, &compile_status); 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci char temp[1024]; 258e5c31af7Sopenharmony_ci gl.getShaderInfoLog(so_ids[n_so_id], 1024, NULL, temp); 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci if (GL_TRUE != compile_status) 261e5c31af7Sopenharmony_ci { 262e5c31af7Sopenharmony_ci result = false; 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci goto end; 265e5c31af7Sopenharmony_ci } 266e5c31af7Sopenharmony_ci } /* if (so_ids[n_so_id] != 0) */ 267e5c31af7Sopenharmony_ci } /* for (all shader object IDs) */ 268e5c31af7Sopenharmony_ci 269e5c31af7Sopenharmony_ci for (unsigned int n_attribute = 0; n_attribute < n_attribute_properties; ++n_attribute) 270e5c31af7Sopenharmony_ci { 271e5c31af7Sopenharmony_ci gl.bindAttribLocation(po_id, attribute_locations[n_attribute], attribute_names[n_attribute]); 272e5c31af7Sopenharmony_ci 273e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation() call failed."); 274e5c31af7Sopenharmony_ci } /* for (all attributes to configure) */ 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci if (n_tf_varyings != 0) 277e5c31af7Sopenharmony_ci { 278e5c31af7Sopenharmony_ci gl.transformFeedbackVaryings(po_id, n_tf_varyings, tf_varyings, tf_varying_mode); 279e5c31af7Sopenharmony_ci 280e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 281e5c31af7Sopenharmony_ci } /* if (n_tf_varyings != 0) */ 282e5c31af7Sopenharmony_ci 283e5c31af7Sopenharmony_ci gl.linkProgram(po_id); 284e5c31af7Sopenharmony_ci 285e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 286e5c31af7Sopenharmony_ci 287e5c31af7Sopenharmony_ci gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 290e5c31af7Sopenharmony_ci 291e5c31af7Sopenharmony_ci if (GL_TRUE != link_status) 292e5c31af7Sopenharmony_ci { 293e5c31af7Sopenharmony_ci result = false; 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci goto end; 296e5c31af7Sopenharmony_ci } 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_ciend: 299e5c31af7Sopenharmony_ci if (fs_id != 0) 300e5c31af7Sopenharmony_ci { 301e5c31af7Sopenharmony_ci gl.deleteShader(fs_id); 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci fs_id = 0; 304e5c31af7Sopenharmony_ci } 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ci if (vs_id != 0) 307e5c31af7Sopenharmony_ci { 308e5c31af7Sopenharmony_ci gl.deleteShader(vs_id); 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci vs_id = 0; 311e5c31af7Sopenharmony_ci } 312e5c31af7Sopenharmony_ci 313e5c31af7Sopenharmony_ci if (!result) 314e5c31af7Sopenharmony_ci { 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci if (po_id != 0) 317e5c31af7Sopenharmony_ci { 318e5c31af7Sopenharmony_ci gl.deleteProgram(po_id); 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci po_id = 0; 321e5c31af7Sopenharmony_ci } 322e5c31af7Sopenharmony_ci } /* if (!result) */ 323e5c31af7Sopenharmony_ci 324e5c31af7Sopenharmony_ci return po_id; 325e5c31af7Sopenharmony_ci} 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci/** Returns a string with textual representation of the @param flags bitfield 328e5c31af7Sopenharmony_ci * holding bits applicable to the @param flags argument of glBufferStorage() 329e5c31af7Sopenharmony_ci * calls. 330e5c31af7Sopenharmony_ci * 331e5c31af7Sopenharmony_ci * @param flags Flags argument, as supported by the @param flags argument of 332e5c31af7Sopenharmony_ci * glBufferStorage() entry-point. 333e5c31af7Sopenharmony_ci * 334e5c31af7Sopenharmony_ci * @return Described string. 335e5c31af7Sopenharmony_ci **/ 336e5c31af7Sopenharmony_cistd::string SparseBufferTestUtilities::getSparseBOFlagsString(glw::GLenum flags) 337e5c31af7Sopenharmony_ci{ 338e5c31af7Sopenharmony_ci unsigned int n_flags_added = 0; 339e5c31af7Sopenharmony_ci std::stringstream result_sstream; 340e5c31af7Sopenharmony_ci 341e5c31af7Sopenharmony_ci if ((flags & GL_CLIENT_STORAGE_BIT) != 0) 342e5c31af7Sopenharmony_ci { 343e5c31af7Sopenharmony_ci result_sstream << "GL_CLIENT_STORAGE_BIT"; 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ci ++n_flags_added; 346e5c31af7Sopenharmony_ci } 347e5c31af7Sopenharmony_ci 348e5c31af7Sopenharmony_ci if ((flags & GL_DYNAMIC_STORAGE_BIT) != 0) 349e5c31af7Sopenharmony_ci { 350e5c31af7Sopenharmony_ci result_sstream << ((n_flags_added) ? " | " : "") << "GL_DYNAMIC_STORAGE_BIT"; 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci ++n_flags_added; 353e5c31af7Sopenharmony_ci } 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci if ((flags & GL_MAP_COHERENT_BIT) != 0) 356e5c31af7Sopenharmony_ci { 357e5c31af7Sopenharmony_ci result_sstream << ((n_flags_added) ? " | " : "") << "GL_MAP_COHERENT_BIT"; 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci ++n_flags_added; 360e5c31af7Sopenharmony_ci } 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci if ((flags & GL_MAP_PERSISTENT_BIT) != 0) 363e5c31af7Sopenharmony_ci { 364e5c31af7Sopenharmony_ci result_sstream << ((n_flags_added) ? " | " : "") << "GL_MAP_PERSISTENT_BIT"; 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_ci ++n_flags_added; 367e5c31af7Sopenharmony_ci } 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_ci if ((flags & GL_SPARSE_STORAGE_BIT_ARB) != 0) 370e5c31af7Sopenharmony_ci { 371e5c31af7Sopenharmony_ci result_sstream << ((n_flags_added) ? " | " : "") << "GL_SPARSE_STORAGE_BIT"; 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci ++n_flags_added; 374e5c31af7Sopenharmony_ci } 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_ci return result_sstream.str(); 377e5c31af7Sopenharmony_ci} 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_ci/** Constructor. 380e5c31af7Sopenharmony_ci * 381e5c31af7Sopenharmony_ci * @param context Rendering context 382e5c31af7Sopenharmony_ci * @param name Test name 383e5c31af7Sopenharmony_ci * @param description Test description 384e5c31af7Sopenharmony_ci */ 385e5c31af7Sopenharmony_ciNegativeTests::NegativeTests(deqp::Context& context) 386e5c31af7Sopenharmony_ci : TestCase(context, "NegativeTests", "Implements all negative tests described in CTS_ARB_sparse_buffer") 387e5c31af7Sopenharmony_ci , m_helper_bo_id(0) 388e5c31af7Sopenharmony_ci , m_immutable_bo_id(0) 389e5c31af7Sopenharmony_ci , m_immutable_bo_size(1024768) 390e5c31af7Sopenharmony_ci , m_sparse_bo_id(0) 391e5c31af7Sopenharmony_ci{ 392e5c31af7Sopenharmony_ci /* Left blank intentionally */ 393e5c31af7Sopenharmony_ci} 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci/** Stub deinit method. */ 396e5c31af7Sopenharmony_civoid NegativeTests::deinit() 397e5c31af7Sopenharmony_ci{ 398e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_ci if (m_helper_bo_id != 0) 401e5c31af7Sopenharmony_ci { 402e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_helper_bo_id); 403e5c31af7Sopenharmony_ci 404e5c31af7Sopenharmony_ci m_helper_bo_id = 0; 405e5c31af7Sopenharmony_ci } 406e5c31af7Sopenharmony_ci 407e5c31af7Sopenharmony_ci if (m_immutable_bo_id != 0) 408e5c31af7Sopenharmony_ci { 409e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_immutable_bo_id); 410e5c31af7Sopenharmony_ci 411e5c31af7Sopenharmony_ci m_immutable_bo_id = 0; 412e5c31af7Sopenharmony_ci } 413e5c31af7Sopenharmony_ci 414e5c31af7Sopenharmony_ci if (m_sparse_bo_id != 0) 415e5c31af7Sopenharmony_ci { 416e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_sparse_bo_id); 417e5c31af7Sopenharmony_ci 418e5c31af7Sopenharmony_ci m_sparse_bo_id = 0; 419e5c31af7Sopenharmony_ci } 420e5c31af7Sopenharmony_ci} 421e5c31af7Sopenharmony_ci 422e5c31af7Sopenharmony_ci/** Stub init method */ 423e5c31af7Sopenharmony_civoid NegativeTests::init() 424e5c31af7Sopenharmony_ci{ 425e5c31af7Sopenharmony_ci /* Nothing to do here */ 426e5c31af7Sopenharmony_ci} 427e5c31af7Sopenharmony_ci 428e5c31af7Sopenharmony_ci/** Executes test iteration. 429e5c31af7Sopenharmony_ci * 430e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 431e5c31af7Sopenharmony_ci */ 432e5c31af7Sopenharmony_citcu::TestNode::IterateResult NegativeTests::iterate() 433e5c31af7Sopenharmony_ci{ 434e5c31af7Sopenharmony_ci glw::GLvoid* data_ptr = DE_NULL; 435e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 436e5c31af7Sopenharmony_ci glw::GLint page_size = 0; 437e5c31af7Sopenharmony_ci bool result = true; 438e5c31af7Sopenharmony_ci 439e5c31af7Sopenharmony_ci /* Only execute if the implementation supports the GL_ARB_sparse_buffer extension */ 440e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_buffer")) 441e5c31af7Sopenharmony_ci { 442e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_sparse_buffer is not supported"); 443e5c31af7Sopenharmony_ci } 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci /* Set up */ 446e5c31af7Sopenharmony_ci gl.getIntegerv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size); 447e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed."); 448e5c31af7Sopenharmony_ci 449e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_helper_bo_id); 450e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_immutable_bo_id); 451e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_sparse_bo_id); 452e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed."); 453e5c31af7Sopenharmony_ci 454e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo_id); 455e5c31af7Sopenharmony_ci gl.bindBuffer(GL_COPY_READ_BUFFER, m_immutable_bo_id); 456e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_helper_bo_id); 457e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 458e5c31af7Sopenharmony_ci 459e5c31af7Sopenharmony_ci gl.bufferStorage(GL_ARRAY_BUFFER, page_size * 3, /* size as per test spec */ 460e5c31af7Sopenharmony_ci DE_NULL, /* data */ 461e5c31af7Sopenharmony_ci GL_SPARSE_STORAGE_BIT_ARB); 462e5c31af7Sopenharmony_ci gl.bufferStorage(GL_COPY_READ_BUFFER, m_immutable_bo_size, /* size */ 463e5c31af7Sopenharmony_ci DE_NULL, /* data */ 464e5c31af7Sopenharmony_ci 0); 465e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage() call(s) failed."); 466e5c31af7Sopenharmony_ci 467e5c31af7Sopenharmony_ci /** * Verify glBufferPageCommitmentARB() returns GL_INVALID_ENUM if <target> is 468e5c31af7Sopenharmony_ci * set to GL_INTERLEAVED_ATTRIBS. */ 469e5c31af7Sopenharmony_ci glw::GLint error_code = GL_NO_ERROR; 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_INTERLEAVED_ATTRIBS, 0, /* offset */ 472e5c31af7Sopenharmony_ci page_size, GL_TRUE); /* commit */ 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci error_code = gl.getError(); 475e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_ENUM) 476e5c31af7Sopenharmony_ci { 477e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 478e5c31af7Sopenharmony_ci << "Invalid <target> value passed to a glBufferPageCommitmentARB() call" 479e5c31af7Sopenharmony_ci " did not generate a GL_INVALID_ENUM error." 480e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci result = false; 483e5c31af7Sopenharmony_ci } 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_ci /* * Verify glBufferStorage() throws a GL_INVALID_VALUE error if <flags> is 486e5c31af7Sopenharmony_ci * set to (GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_READ_BIT) or 487e5c31af7Sopenharmony_ci * (GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_WRITE_BIT). */ 488e5c31af7Sopenharmony_ci gl.bufferStorage(GL_ELEMENT_ARRAY_BUFFER, page_size * 3, /* size */ 489e5c31af7Sopenharmony_ci DE_NULL, /* data */ 490e5c31af7Sopenharmony_ci GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_READ_BIT); 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ci error_code = gl.getError(); 493e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 494e5c31af7Sopenharmony_ci { 495e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 496e5c31af7Sopenharmony_ci << "Invalid <flags> value set to GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_READ_BIT " 497e5c31af7Sopenharmony_ci "did not generate a GL_INVALID_VALUE error." 498e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci result = false; 501e5c31af7Sopenharmony_ci } 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci gl.bufferStorage(GL_ELEMENT_ARRAY_BUFFER, page_size * 3, /* size */ 504e5c31af7Sopenharmony_ci DE_NULL, /* data */ 505e5c31af7Sopenharmony_ci GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_WRITE_BIT); 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_ci error_code = gl.getError(); 508e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 509e5c31af7Sopenharmony_ci { 510e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 511e5c31af7Sopenharmony_ci << "Invalid <flags> value set to GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_WRITE_BIT " 512e5c31af7Sopenharmony_ci "did not generate a GL_INVALID_VALUE error." 513e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 514e5c31af7Sopenharmony_ci 515e5c31af7Sopenharmony_ci result = false; 516e5c31af7Sopenharmony_ci } 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() generates a GL_INVALID_OPERATION error if 519e5c31af7Sopenharmony_ci * it is called for an immutable BO, which has not been initialized with the 520e5c31af7Sopenharmony_ci * GL_SPARSE_STORAGE_BIT_ARB flag. */ 521e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_COPY_READ_BUFFER, 0, /* offset */ 522e5c31af7Sopenharmony_ci page_size, GL_TRUE); /* commit */ 523e5c31af7Sopenharmony_ci 524e5c31af7Sopenharmony_ci error_code = gl.getError(); 525e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_OPERATION) 526e5c31af7Sopenharmony_ci { 527e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error code generated by glBufferPageCommitmentARB() " 528e5c31af7Sopenharmony_ci " issued against an immutable, non-sparse buffer object." 529e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_ci result = false; 532e5c31af7Sopenharmony_ci } 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() issues a GL_INVALID_VALUE error if <offset> 535e5c31af7Sopenharmony_ci * is set to (0.5 * GL_SPARSE_BUFFER_PAGE_SIZE_ARB). Skip if the constant's value 536e5c31af7Sopenharmony_ci * is equal to 1. */ 537e5c31af7Sopenharmony_ci if (page_size != 1) 538e5c31af7Sopenharmony_ci { 539e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, page_size / 2, /* offset */ 540e5c31af7Sopenharmony_ci page_size, GL_TRUE); /* commit */ 541e5c31af7Sopenharmony_ci 542e5c31af7Sopenharmony_ci error_code = gl.getError(); 543e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 544e5c31af7Sopenharmony_ci { 545e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 546e5c31af7Sopenharmony_ci << "Invalid error code generated by glBufferPageCommitmentARB() " 547e5c31af7Sopenharmony_ci "whose <offset> value was set to (page size / 2)." 548e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 549e5c31af7Sopenharmony_ci 550e5c31af7Sopenharmony_ci result = false; 551e5c31af7Sopenharmony_ci } 552e5c31af7Sopenharmony_ci } /* if (page_size != 1) */ 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() emits a GL_INVALID_VALUE error if <size> 555e5c31af7Sopenharmony_ci * is set to (0.5 * GL_SPARSE_BUFFER_PAGE_SIZE_ARB). Skip if the constant's value 556e5c31af7Sopenharmony_ci * is equal to 1. */ 557e5c31af7Sopenharmony_ci if (page_size != 1) 558e5c31af7Sopenharmony_ci { 559e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 560e5c31af7Sopenharmony_ci page_size / 2, GL_TRUE); /* commit */ 561e5c31af7Sopenharmony_ci 562e5c31af7Sopenharmony_ci error_code = gl.getError(); 563e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 564e5c31af7Sopenharmony_ci { 565e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 566e5c31af7Sopenharmony_ci << "Invalid error code generated by glBufferPageCommitmentARB() " 567e5c31af7Sopenharmony_ci "whose <size> value was set to (page size / 2)." 568e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 569e5c31af7Sopenharmony_ci 570e5c31af7Sopenharmony_ci result = false; 571e5c31af7Sopenharmony_ci } 572e5c31af7Sopenharmony_ci } /* if (page_size != 1) */ 573e5c31af7Sopenharmony_ci 574e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if <offset> is 575e5c31af7Sopenharmony_ci * set to -1, but all other arguments are valid. */ 576e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, -1, /* offset */ 577e5c31af7Sopenharmony_ci page_size, GL_TRUE); /* commit */ 578e5c31af7Sopenharmony_ci 579e5c31af7Sopenharmony_ci error_code = gl.getError(); 580e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 581e5c31af7Sopenharmony_ci { 582e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error code generated by glBufferPageCommitmentARB() " 583e5c31af7Sopenharmony_ci "whose <offset> argument was set to -1." 584e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 585e5c31af7Sopenharmony_ci 586e5c31af7Sopenharmony_ci result = false; 587e5c31af7Sopenharmony_ci } 588e5c31af7Sopenharmony_ci 589e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if <size> is 590e5c31af7Sopenharmony_ci * set to -1, but all other arguments are valid. */ 591e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 592e5c31af7Sopenharmony_ci -1, /* size */ 593e5c31af7Sopenharmony_ci GL_TRUE); /* commit */ 594e5c31af7Sopenharmony_ci 595e5c31af7Sopenharmony_ci error_code = gl.getError(); 596e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 597e5c31af7Sopenharmony_ci { 598e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error code generated by glBufferPageCommitmentARB() " 599e5c31af7Sopenharmony_ci "whose <size> argument was set to -1." 600e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 601e5c31af7Sopenharmony_ci 602e5c31af7Sopenharmony_ci result = false; 603e5c31af7Sopenharmony_ci } 604e5c31af7Sopenharmony_ci 605e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if BO's size is 606e5c31af7Sopenharmony_ci * GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3, but the <offset> is set to 0 and <size> 607e5c31af7Sopenharmony_ci * argument used for the call is set to GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 4. */ 608e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 609e5c31af7Sopenharmony_ci page_size * 4, /* size */ 610e5c31af7Sopenharmony_ci GL_TRUE); 611e5c31af7Sopenharmony_ci 612e5c31af7Sopenharmony_ci error_code = gl.getError(); 613e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 614e5c31af7Sopenharmony_ci { 615e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 616e5c31af7Sopenharmony_ci << "Invalid error code generated by glBufferPageCommitmentARB() " 617e5c31af7Sopenharmony_ci "whose <offset> was set to 0 and <size> was set to (page size * 4), " 618e5c31af7Sopenharmony_ci "when the buffer storage size had been configured to be (page size * 3)." 619e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci result = false; 622e5c31af7Sopenharmony_ci } 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci /* * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if BO's size is 625e5c31af7Sopenharmony_ci * GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3, but the <offset> is set to 626e5c31af7Sopenharmony_ci * GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 1 and <size> argument used for the call 627e5c31af7Sopenharmony_ci * is set to GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3. */ 628e5c31af7Sopenharmony_ci gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, page_size * 1, /* offset */ 629e5c31af7Sopenharmony_ci page_size * 3, /* size */ 630e5c31af7Sopenharmony_ci GL_TRUE); 631e5c31af7Sopenharmony_ci 632e5c31af7Sopenharmony_ci error_code = gl.getError(); 633e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_VALUE) 634e5c31af7Sopenharmony_ci { 635e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 636e5c31af7Sopenharmony_ci << "Invalid error code generated by glBufferPageCommitmentARB() " 637e5c31af7Sopenharmony_ci "whose <offset> was set to (page size) and <size> was set to (page size * 3), " 638e5c31af7Sopenharmony_ci "when the buffer storage size had been configured to be (page size * 3)." 639e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 640e5c31af7Sopenharmony_ci 641e5c31af7Sopenharmony_ci result = false; 642e5c31af7Sopenharmony_ci } 643e5c31af7Sopenharmony_ci 644e5c31af7Sopenharmony_ci /* * Verify that calling glMapBuffer() or glMapBufferRange() against a sparse 645e5c31af7Sopenharmony_ci * buffer generates a GL_INVALID_OPERATION error. */ 646e5c31af7Sopenharmony_ci data_ptr = gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 647e5c31af7Sopenharmony_ci 648e5c31af7Sopenharmony_ci if (data_ptr != DE_NULL) 649e5c31af7Sopenharmony_ci { 650e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 651e5c31af7Sopenharmony_ci << "Non-NULL pointer returned by an invalid glMapBuffer() call, issued " 652e5c31af7Sopenharmony_ci "against a sparse buffer object" 653e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_ci result = false; 656e5c31af7Sopenharmony_ci } 657e5c31af7Sopenharmony_ci 658e5c31af7Sopenharmony_ci error_code = gl.getError(); 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_OPERATION) 661e5c31af7Sopenharmony_ci { 662e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 663e5c31af7Sopenharmony_ci << "Invalid error code generated by glMapBuffer() call, issued against " 664e5c31af7Sopenharmony_ci "a sparse buffer object" 665e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 666e5c31af7Sopenharmony_ci 667e5c31af7Sopenharmony_ci result = false; 668e5c31af7Sopenharmony_ci } 669e5c31af7Sopenharmony_ci 670e5c31af7Sopenharmony_ci data_ptr = gl.mapBufferRange(GL_ARRAY_BUFFER, 0, /* offset */ 671e5c31af7Sopenharmony_ci page_size, /* length */ 672e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci if (data_ptr != DE_NULL) 675e5c31af7Sopenharmony_ci { 676e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 677e5c31af7Sopenharmony_ci << "Non-NULL pointer returned by an invalid glMapBufferRange() call, issued " 678e5c31af7Sopenharmony_ci "against a sparse buffer object" 679e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 680e5c31af7Sopenharmony_ci 681e5c31af7Sopenharmony_ci result = false; 682e5c31af7Sopenharmony_ci } 683e5c31af7Sopenharmony_ci 684e5c31af7Sopenharmony_ci error_code = gl.getError(); 685e5c31af7Sopenharmony_ci 686e5c31af7Sopenharmony_ci if (error_code != GL_INVALID_OPERATION) 687e5c31af7Sopenharmony_ci { 688e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 689e5c31af7Sopenharmony_ci << "Invalid error code generated by glMapBufferRange() call, issued against " 690e5c31af7Sopenharmony_ci "a sparse buffer object" 691e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci result = false; 694e5c31af7Sopenharmony_ci } 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); 697e5c31af7Sopenharmony_ci 698e5c31af7Sopenharmony_ci return STOP; 699e5c31af7Sopenharmony_ci} 700e5c31af7Sopenharmony_ci 701e5c31af7Sopenharmony_ci/** Constructor. 702e5c31af7Sopenharmony_ci * 703e5c31af7Sopenharmony_ci * @param context Rendering context 704e5c31af7Sopenharmony_ci * @param name Test name 705e5c31af7Sopenharmony_ci * @param description Test description 706e5c31af7Sopenharmony_ci */ 707e5c31af7Sopenharmony_ciPageSizeGetterTest::PageSizeGetterTest(deqp::Context& context) 708e5c31af7Sopenharmony_ci : TestCase(context, "PageSizeGetterTest", 709e5c31af7Sopenharmony_ci "Verifies GL_SPARSE_BUFFER_PAGE_SIZE_ARB pname is recognized by the getter functions") 710e5c31af7Sopenharmony_ci{ 711e5c31af7Sopenharmony_ci /* Left blank intentionally */ 712e5c31af7Sopenharmony_ci} 713e5c31af7Sopenharmony_ci 714e5c31af7Sopenharmony_ci/** Stub deinit method. */ 715e5c31af7Sopenharmony_civoid PageSizeGetterTest::deinit() 716e5c31af7Sopenharmony_ci{ 717e5c31af7Sopenharmony_ci /* Nothing to be done here */ 718e5c31af7Sopenharmony_ci} 719e5c31af7Sopenharmony_ci 720e5c31af7Sopenharmony_ci/** Stub init method */ 721e5c31af7Sopenharmony_civoid PageSizeGetterTest::init() 722e5c31af7Sopenharmony_ci{ 723e5c31af7Sopenharmony_ci /* Nothing to do here */ 724e5c31af7Sopenharmony_ci} 725e5c31af7Sopenharmony_ci 726e5c31af7Sopenharmony_ci/** Executes test iteration. 727e5c31af7Sopenharmony_ci * 728e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 729e5c31af7Sopenharmony_ci */ 730e5c31af7Sopenharmony_citcu::TestNode::IterateResult PageSizeGetterTest::iterate() 731e5c31af7Sopenharmony_ci{ 732e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 733e5c31af7Sopenharmony_ci glw::GLboolean page_size_bool = false; 734e5c31af7Sopenharmony_ci glw::GLdouble page_size_double = 0.0; 735e5c31af7Sopenharmony_ci glw::GLfloat page_size_float = 0.0f; 736e5c31af7Sopenharmony_ci glw::GLint page_size_int = 0; 737e5c31af7Sopenharmony_ci glw::GLint64 page_size_int64 = 0; 738e5c31af7Sopenharmony_ci bool result = true; 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ci /* Only execute if the implementation supports the GL_ARB_sparse_buffer extension */ 741e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_buffer")) 742e5c31af7Sopenharmony_ci { 743e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_sparse_buffer is not supported"); 744e5c31af7Sopenharmony_ci } 745e5c31af7Sopenharmony_ci 746e5c31af7Sopenharmony_ci /* glGetIntegerv() */ 747e5c31af7Sopenharmony_ci gl.getIntegerv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size_int); 748e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed"); 749e5c31af7Sopenharmony_ci 750e5c31af7Sopenharmony_ci if (page_size_int < 1 || page_size_int > 65536) 751e5c31af7Sopenharmony_ci { 752e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Page size reported by the implementation (" << page_size_int 753e5c31af7Sopenharmony_ci << ")" 754e5c31af7Sopenharmony_ci " by glGetIntegerv() is out of the allowed range." 755e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 756e5c31af7Sopenharmony_ci 757e5c31af7Sopenharmony_ci result = false; 758e5c31af7Sopenharmony_ci } 759e5c31af7Sopenharmony_ci 760e5c31af7Sopenharmony_ci /* glGetBooleanv() */ 761e5c31af7Sopenharmony_ci gl.getBooleanv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size_bool); 762e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed"); 763e5c31af7Sopenharmony_ci 764e5c31af7Sopenharmony_ci if (!page_size_bool) 765e5c31af7Sopenharmony_ci { 766e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid page size reported by glGetBooleanv()" 767e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 768e5c31af7Sopenharmony_ci 769e5c31af7Sopenharmony_ci result = false; 770e5c31af7Sopenharmony_ci } 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci /* glGetDoublev() */ 773e5c31af7Sopenharmony_ci gl.getDoublev(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size_double); 774e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed"); 775e5c31af7Sopenharmony_ci 776e5c31af7Sopenharmony_ci if (de::abs(page_size_double - page_size_int) > 1e-5) 777e5c31af7Sopenharmony_ci { 778e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid page size reported by glGetDoublev()" 779e5c31af7Sopenharmony_ci " (reported value: " 780e5c31af7Sopenharmony_ci << page_size_double << ", expected value: " << page_size_int << ")" 781e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 782e5c31af7Sopenharmony_ci 783e5c31af7Sopenharmony_ci result = false; 784e5c31af7Sopenharmony_ci } 785e5c31af7Sopenharmony_ci 786e5c31af7Sopenharmony_ci /* glGetFloatv() */ 787e5c31af7Sopenharmony_ci gl.getFloatv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size_float); 788e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed"); 789e5c31af7Sopenharmony_ci 790e5c31af7Sopenharmony_ci if (de::abs(page_size_float - static_cast<float>(page_size_int)) > 1e-5f) 791e5c31af7Sopenharmony_ci { 792e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid page size reported by glGetFloatv()" 793e5c31af7Sopenharmony_ci " (reported value: " 794e5c31af7Sopenharmony_ci << page_size_float << ", expected value: " << page_size_int << ")" 795e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 796e5c31af7Sopenharmony_ci 797e5c31af7Sopenharmony_ci result = false; 798e5c31af7Sopenharmony_ci } 799e5c31af7Sopenharmony_ci 800e5c31af7Sopenharmony_ci /* glGetInteger64v() */ 801e5c31af7Sopenharmony_ci gl.getInteger64v(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size_int64); 802e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed"); 803e5c31af7Sopenharmony_ci 804e5c31af7Sopenharmony_ci if (page_size_int64 != page_size_int) 805e5c31af7Sopenharmony_ci { 806e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid page size reported by glGetInteger64v()" 807e5c31af7Sopenharmony_ci " (reported value: " 808e5c31af7Sopenharmony_ci << page_size_int64 << ", expected value: " << page_size_int << ")" 809e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 810e5c31af7Sopenharmony_ci 811e5c31af7Sopenharmony_ci result = false; 812e5c31af7Sopenharmony_ci } 813e5c31af7Sopenharmony_ci 814e5c31af7Sopenharmony_ci m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); 815e5c31af7Sopenharmony_ci 816e5c31af7Sopenharmony_ci return STOP; 817e5c31af7Sopenharmony_ci} 818e5c31af7Sopenharmony_ci 819e5c31af7Sopenharmony_ci/** Constructor. 820e5c31af7Sopenharmony_ci * 821e5c31af7Sopenharmony_ci * @param gl GL entry-points container 822e5c31af7Sopenharmony_ci * @param testContext CTS test context 823e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 824e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 825e5c31af7Sopenharmony_ci * @param all_pages_committed true to run the test with all data memory pages committed, 826e5c31af7Sopenharmony_ci * false to leave some of them without an actual memory backing. 827e5c31af7Sopenharmony_ci */ 828e5c31af7Sopenharmony_ciAtomicCounterBufferStorageTestCase::AtomicCounterBufferStorageTestCase(const glw::Functions& gl, 829e5c31af7Sopenharmony_ci tcu::TestContext& testContext, 830e5c31af7Sopenharmony_ci glw::GLint page_size, bool all_pages_committed) 831e5c31af7Sopenharmony_ci : m_all_pages_committed(all_pages_committed) 832e5c31af7Sopenharmony_ci , m_gl(gl) 833e5c31af7Sopenharmony_ci , m_gl_atomic_counter_uniform_array_stride(0) 834e5c31af7Sopenharmony_ci , m_gl_max_vertex_atomic_counters_value(0) 835e5c31af7Sopenharmony_ci , m_helper_bo(0) 836e5c31af7Sopenharmony_ci , m_helper_bo_size(0) 837e5c31af7Sopenharmony_ci , m_helper_bo_size_rounded(0) 838e5c31af7Sopenharmony_ci , m_n_draw_calls(3) /* as per test spec */ 839e5c31af7Sopenharmony_ci , m_page_size(page_size) 840e5c31af7Sopenharmony_ci , m_po(0) 841e5c31af7Sopenharmony_ci , m_sparse_bo(0) 842e5c31af7Sopenharmony_ci , m_sparse_bo_data_size(0) 843e5c31af7Sopenharmony_ci , m_sparse_bo_data_size_rounded(0) 844e5c31af7Sopenharmony_ci , m_sparse_bo_data_start_offset(0) 845e5c31af7Sopenharmony_ci , m_sparse_bo_data_start_offset_rounded(0) 846e5c31af7Sopenharmony_ci , m_testCtx(testContext) 847e5c31af7Sopenharmony_ci , m_vao(0) 848e5c31af7Sopenharmony_ci{ 849e5c31af7Sopenharmony_ci /* Left blank intentionally */ 850e5c31af7Sopenharmony_ci} 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 853e5c31af7Sopenharmony_ci * 854e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 855e5c31af7Sopenharmony_ci */ 856e5c31af7Sopenharmony_civoid AtomicCounterBufferStorageTestCase::deinitTestCaseGlobal() 857e5c31af7Sopenharmony_ci{ 858e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 859e5c31af7Sopenharmony_ci { 860e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 861e5c31af7Sopenharmony_ci 862e5c31af7Sopenharmony_ci m_helper_bo = 0; 863e5c31af7Sopenharmony_ci } 864e5c31af7Sopenharmony_ci 865e5c31af7Sopenharmony_ci if (m_po != 0) 866e5c31af7Sopenharmony_ci { 867e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci m_po = 0; 870e5c31af7Sopenharmony_ci } 871e5c31af7Sopenharmony_ci 872e5c31af7Sopenharmony_ci if (m_vao != 0) 873e5c31af7Sopenharmony_ci { 874e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 875e5c31af7Sopenharmony_ci 876e5c31af7Sopenharmony_ci m_vao = 0; 877e5c31af7Sopenharmony_ci } 878e5c31af7Sopenharmony_ci} 879e5c31af7Sopenharmony_ci 880e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 881e5c31af7Sopenharmony_civoid AtomicCounterBufferStorageTestCase::deinitTestCaseIteration() 882e5c31af7Sopenharmony_ci{ 883e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 884e5c31af7Sopenharmony_ci { 885e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 886e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 887e5c31af7Sopenharmony_ci 888e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, m_sparse_bo_data_start_offset_rounded, /* offset */ 889e5c31af7Sopenharmony_ci m_sparse_bo_data_size_rounded, GL_FALSE); /* commit */ 890e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_ci m_sparse_bo = 0; 893e5c31af7Sopenharmony_ci } 894e5c31af7Sopenharmony_ci} 895e5c31af7Sopenharmony_ci 896e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 897e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 898e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 899e5c31af7Sopenharmony_ci * 900e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 901e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 902e5c31af7Sopenharmony_ci * 903e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 904e5c31af7Sopenharmony_ci */ 905e5c31af7Sopenharmony_cibool AtomicCounterBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 906e5c31af7Sopenharmony_ci{ 907e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 908e5c31af7Sopenharmony_ci static const unsigned char data_zero = 0; 909e5c31af7Sopenharmony_ci bool result = true; 910e5c31af7Sopenharmony_ci 911e5c31af7Sopenharmony_ci /* Only execute if GL_MAX_VERTEX_ATOMIC_COUNTERS is > 0 */ 912e5c31af7Sopenharmony_ci if (m_gl_max_vertex_atomic_counters_value == 0) 913e5c31af7Sopenharmony_ci { 914e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "G_MAX_VERTEX_ATOMIC_COUNTERS is 0. Skipping the test." 915e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 916e5c31af7Sopenharmony_ci 917e5c31af7Sopenharmony_ci goto end; 918e5c31af7Sopenharmony_ci } 919e5c31af7Sopenharmony_ci 920e5c31af7Sopenharmony_ci /* Bind the test program object */ 921e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 922e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 923e5c31af7Sopenharmony_ci 924e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_sparse_bo); 925e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ci /* Try using both ranged and non-ranged AC bindings. 928e5c31af7Sopenharmony_ci * 929e5c31af7Sopenharmony_ci * NOTE: It only makes sense to perform glBindBufferBase() test if all AC pages are 930e5c31af7Sopenharmony_ci * committed 931e5c31af7Sopenharmony_ci */ 932e5c31af7Sopenharmony_ci for (unsigned int n_binding_type = (m_all_pages_committed) ? 0 : 1; 933e5c31af7Sopenharmony_ci n_binding_type < 2; /* glBindBufferBase(), glBindBufferRange() */ 934e5c31af7Sopenharmony_ci ++n_binding_type) 935e5c31af7Sopenharmony_ci { 936e5c31af7Sopenharmony_ci bool result_local = true; 937e5c31af7Sopenharmony_ci 938e5c31af7Sopenharmony_ci if (n_binding_type == 0) 939e5c31af7Sopenharmony_ci { 940e5c31af7Sopenharmony_ci m_gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, /* index */ 941e5c31af7Sopenharmony_ci m_sparse_bo); 942e5c31af7Sopenharmony_ci 943e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase() call failed."); 944e5c31af7Sopenharmony_ci } 945e5c31af7Sopenharmony_ci else 946e5c31af7Sopenharmony_ci { 947e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, /* index */ 948e5c31af7Sopenharmony_ci m_sparse_bo, m_sparse_bo_data_start_offset, m_helper_bo_size); 949e5c31af7Sopenharmony_ci 950e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferRange() call failed."); 951e5c31af7Sopenharmony_ci } 952e5c31af7Sopenharmony_ci 953e5c31af7Sopenharmony_ci /* Zero out the sparse buffer's contents */ 954e5c31af7Sopenharmony_ci m_gl.clearBufferData(GL_ATOMIC_COUNTER_BUFFER, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &data_zero); 955e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferData() call failed."); 956e5c31af7Sopenharmony_ci 957e5c31af7Sopenharmony_ci /* Run the test */ 958e5c31af7Sopenharmony_ci m_gl.drawArraysInstanced(GL_POINTS, 0, /* first */ 959e5c31af7Sopenharmony_ci m_gl_max_vertex_atomic_counters_value, /* count */ 960e5c31af7Sopenharmony_ci m_n_draw_calls); 961e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArraysInstanced() call failed"); 962e5c31af7Sopenharmony_ci 963e5c31af7Sopenharmony_ci /* Retrieve the atomic counter values */ 964e5c31af7Sopenharmony_ci const glw::GLuint* ac_data = NULL; 965e5c31af7Sopenharmony_ci const unsigned int n_expected_written_values = 966e5c31af7Sopenharmony_ci (m_all_pages_committed) ? m_gl_max_vertex_atomic_counters_value : m_gl_max_vertex_atomic_counters_value / 2; 967e5c31af7Sopenharmony_ci 968e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_sparse_bo); 969e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_helper_bo); 970e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffeR() call failed"); 971e5c31af7Sopenharmony_ci 972e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 973e5c31af7Sopenharmony_ci (n_binding_type == 0) ? 0 : m_sparse_bo_data_start_offset, 0, /* writeOffset */ 974e5c31af7Sopenharmony_ci m_sparse_bo_data_size); 975e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 976e5c31af7Sopenharmony_ci 977e5c31af7Sopenharmony_ci ac_data = (const glw::GLuint*)m_gl.mapBufferRange(GL_COPY_WRITE_BUFFER, 0, /* offset */ 978e5c31af7Sopenharmony_ci m_sparse_bo_data_size, GL_MAP_READ_BIT); 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 981e5c31af7Sopenharmony_ci 982e5c31af7Sopenharmony_ci for (unsigned int n_counter = 0; n_counter < n_expected_written_values && result_local; ++n_counter) 983e5c31af7Sopenharmony_ci { 984e5c31af7Sopenharmony_ci const unsigned int expected_value = m_n_draw_calls; 985e5c31af7Sopenharmony_ci const unsigned int retrieved_value = 986e5c31af7Sopenharmony_ci *((unsigned int*)((unsigned char*)ac_data + m_gl_atomic_counter_uniform_array_stride * n_counter)); 987e5c31af7Sopenharmony_ci 988e5c31af7Sopenharmony_ci if (expected_value != retrieved_value) 989e5c31af7Sopenharmony_ci { 990e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid atomic counter value " 991e5c31af7Sopenharmony_ci "[" 992e5c31af7Sopenharmony_ci << retrieved_value << "]" 993e5c31af7Sopenharmony_ci " instead of the expected value " 994e5c31af7Sopenharmony_ci "[" 995e5c31af7Sopenharmony_ci << expected_value << "]" 996e5c31af7Sopenharmony_ci " at index " 997e5c31af7Sopenharmony_ci << n_counter << " when using " 998e5c31af7Sopenharmony_ci << ((n_binding_type == 0) ? "glBindBufferBase()" : "glBindBufferRange()") 999e5c31af7Sopenharmony_ci << " for AC binding configuration" << tcu::TestLog::EndMessage; 1000e5c31af7Sopenharmony_ci 1001e5c31af7Sopenharmony_ci result_local = false; 1002e5c31af7Sopenharmony_ci } /* if (expected_value != retrieved_value) */ 1003e5c31af7Sopenharmony_ci } /* for (all draw calls that need to be executed) */ 1004e5c31af7Sopenharmony_ci 1005e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_WRITE_BUFFER); 1006e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 1007e5c31af7Sopenharmony_ci 1008e5c31af7Sopenharmony_ci result &= result_local; 1009e5c31af7Sopenharmony_ci } /* for (both binding types) */ 1010e5c31af7Sopenharmony_ci 1011e5c31af7Sopenharmony_ciend: 1012e5c31af7Sopenharmony_ci return result; 1013e5c31af7Sopenharmony_ci} 1014e5c31af7Sopenharmony_ci 1015e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 1016e5c31af7Sopenharmony_ci * 1017e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1018e5c31af7Sopenharmony_ci */ 1019e5c31af7Sopenharmony_cibool AtomicCounterBufferStorageTestCase::initTestCaseGlobal() 1020e5c31af7Sopenharmony_ci{ 1021e5c31af7Sopenharmony_ci const glw::GLuint ac_uniform_index = 0; /* only one uniform is defined in the VS below */ 1022e5c31af7Sopenharmony_ci std::stringstream n_counters_sstream; 1023e5c31af7Sopenharmony_ci std::string n_counters_string; 1024e5c31af7Sopenharmony_ci bool result = true; 1025e5c31af7Sopenharmony_ci 1026e5c31af7Sopenharmony_ci static const char* vs_body_preamble = "#version 430 core\n" 1027e5c31af7Sopenharmony_ci "\n"; 1028e5c31af7Sopenharmony_ci 1029e5c31af7Sopenharmony_ci static const char* vs_body_core = "layout(binding = 0) uniform atomic_uint counters[N_COUNTERS];\n" 1030e5c31af7Sopenharmony_ci "\n" 1031e5c31af7Sopenharmony_ci "void main()\n" 1032e5c31af7Sopenharmony_ci "{\n" 1033e5c31af7Sopenharmony_ci " for (uint n = 0; n < N_COUNTERS; ++n)\n" 1034e5c31af7Sopenharmony_ci " {\n" 1035e5c31af7Sopenharmony_ci " if (n == gl_VertexID)\n" 1036e5c31af7Sopenharmony_ci " {\n" 1037e5c31af7Sopenharmony_ci " atomicCounterIncrement(counters[n]);\n" 1038e5c31af7Sopenharmony_ci " }\n" 1039e5c31af7Sopenharmony_ci " }\n" 1040e5c31af7Sopenharmony_ci "\n" 1041e5c31af7Sopenharmony_ci " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 1042e5c31af7Sopenharmony_ci "}\n"; 1043e5c31af7Sopenharmony_ci const char* vs_body_parts[] = { vs_body_preamble, DE_NULL, /* will be set to n_counters_string.c_str() */ 1044e5c31af7Sopenharmony_ci vs_body_core }; 1045e5c31af7Sopenharmony_ci const unsigned int n_vs_body_parts = sizeof(vs_body_parts) / sizeof(vs_body_parts[0]); 1046e5c31af7Sopenharmony_ci 1047e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_VERTEX_ATOMIC_COUNTERS value. The test will only be executed if it's >= 1 */ 1048e5c31af7Sopenharmony_ci m_gl.getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &m_gl_max_vertex_atomic_counters_value); 1049e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetIntegerv() call failed."); 1050e5c31af7Sopenharmony_ci 1051e5c31af7Sopenharmony_ci if (m_gl_max_vertex_atomic_counters_value == 0) 1052e5c31af7Sopenharmony_ci { 1053e5c31af7Sopenharmony_ci goto end; 1054e5c31af7Sopenharmony_ci } 1055e5c31af7Sopenharmony_ci 1056e5c31af7Sopenharmony_ci /* Form the N_COUNTERS declaration string */ 1057e5c31af7Sopenharmony_ci n_counters_sstream << "#define N_COUNTERS " << m_gl_max_vertex_atomic_counters_value << "\n"; 1058e5c31af7Sopenharmony_ci n_counters_string = n_counters_sstream.str(); 1059e5c31af7Sopenharmony_ci 1060e5c31af7Sopenharmony_ci vs_body_parts[1] = n_counters_string.c_str(); 1061e5c31af7Sopenharmony_ci 1062e5c31af7Sopenharmony_ci /* Set up the program object */ 1063e5c31af7Sopenharmony_ci DE_ASSERT(m_po == 0); 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci m_po = 1066e5c31af7Sopenharmony_ci SparseBufferTestUtilities::createProgram(m_gl, DE_NULL, /* fs_body_parts */ 1067e5c31af7Sopenharmony_ci 0, /* n_fs_body_parts */ 1068e5c31af7Sopenharmony_ci vs_body_parts, n_vs_body_parts, DE_NULL, /* attribute_names */ 1069e5c31af7Sopenharmony_ci DE_NULL, /* attribute_locations */ 1070e5c31af7Sopenharmony_ci 0); /* n_attribute_properties */ 1071e5c31af7Sopenharmony_ci 1072e5c31af7Sopenharmony_ci if (m_po == 0) 1073e5c31af7Sopenharmony_ci { 1074e5c31af7Sopenharmony_ci result = false; 1075e5c31af7Sopenharmony_ci 1076e5c31af7Sopenharmony_ci goto end; 1077e5c31af7Sopenharmony_ci } 1078e5c31af7Sopenharmony_ci 1079e5c31af7Sopenharmony_ci /* Helper BO will be used to hold the atomic counter buffer data. 1080e5c31af7Sopenharmony_ci * Determine how much space will be needed. 1081e5c31af7Sopenharmony_ci * 1082e5c31af7Sopenharmony_ci * Min max for the GL constant value is 0. Bail out if that's the 1083e5c31af7Sopenharmony_ci * value we are returned - it is pointless to execute the test in 1084e5c31af7Sopenharmony_ci * such environment. 1085e5c31af7Sopenharmony_ci */ 1086e5c31af7Sopenharmony_ci m_gl.getActiveUniformsiv(m_po, 1, /* uniformCount */ 1087e5c31af7Sopenharmony_ci &ac_uniform_index, GL_UNIFORM_ARRAY_STRIDE, &m_gl_atomic_counter_uniform_array_stride); 1088e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetActiveUniformsiv() call failed."); 1089e5c31af7Sopenharmony_ci 1090e5c31af7Sopenharmony_ci DE_ASSERT(m_gl_atomic_counter_uniform_array_stride >= (int)sizeof(unsigned int)); 1091e5c31af7Sopenharmony_ci 1092e5c31af7Sopenharmony_ci m_helper_bo_size = m_gl_atomic_counter_uniform_array_stride * m_gl_max_vertex_atomic_counters_value; 1093e5c31af7Sopenharmony_ci m_helper_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_helper_bo_size, m_page_size); 1094e5c31af7Sopenharmony_ci 1095e5c31af7Sopenharmony_ci /* Set up the helper BO */ 1096e5c31af7Sopenharmony_ci DE_ASSERT(m_helper_bo == 0); 1097e5c31af7Sopenharmony_ci 1098e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 1099e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 1100e5c31af7Sopenharmony_ci 1101e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 1102e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1103e5c31af7Sopenharmony_ci 1104e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_helper_bo_size_rounded, DE_NULL, GL_MAP_READ_BIT); /* flags */ 1105e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 1106e5c31af7Sopenharmony_ci 1107e5c31af7Sopenharmony_ci /* Set up the vertex array object */ 1108e5c31af7Sopenharmony_ci DE_ASSERT(m_vao == 0); 1109e5c31af7Sopenharmony_ci 1110e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 1111e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 1112e5c31af7Sopenharmony_ci 1113e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 1114e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 1115e5c31af7Sopenharmony_ci 1116e5c31af7Sopenharmony_ciend: 1117e5c31af7Sopenharmony_ci return result; 1118e5c31af7Sopenharmony_ci} 1119e5c31af7Sopenharmony_ci 1120e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 1121e5c31af7Sopenharmony_ci * 1122e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 1123e5c31af7Sopenharmony_ci * to release these objects. 1124e5c31af7Sopenharmony_ci **/ 1125e5c31af7Sopenharmony_cibool AtomicCounterBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 1126e5c31af7Sopenharmony_ci{ 1127e5c31af7Sopenharmony_ci bool result = true; 1128e5c31af7Sopenharmony_ci 1129e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 1130e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 1131e5c31af7Sopenharmony_ci 1132e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 1133e5c31af7Sopenharmony_ci 1134e5c31af7Sopenharmony_ci /* Set up the sparse bufffer. */ 1135e5c31af7Sopenharmony_ci int sparse_bo_data_size = 0; 1136e5c31af7Sopenharmony_ci 1137e5c31af7Sopenharmony_ci DE_ASSERT(m_helper_bo_size_rounded != 0); 1138e5c31af7Sopenharmony_ci 1139e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 1140e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1141e5c31af7Sopenharmony_ci 1142e5c31af7Sopenharmony_ci if (m_all_pages_committed) 1143e5c31af7Sopenharmony_ci { 1144e5c31af7Sopenharmony_ci /* Commit all required pages */ 1145e5c31af7Sopenharmony_ci sparse_bo_data_size = m_helper_bo_size_rounded; 1146e5c31af7Sopenharmony_ci } 1147e5c31af7Sopenharmony_ci else 1148e5c31af7Sopenharmony_ci { 1149e5c31af7Sopenharmony_ci /* Only commit the first half of the required pages */ 1150e5c31af7Sopenharmony_ci DE_ASSERT((m_helper_bo_size_rounded % m_page_size) == 0); 1151e5c31af7Sopenharmony_ci 1152e5c31af7Sopenharmony_ci sparse_bo_data_size = (m_helper_bo_size_rounded / m_page_size) * m_page_size / 2; 1153e5c31af7Sopenharmony_ci } 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci /* NOTE: We need to ensure that the memory region assigned to the atomic counter buffer spans 1156e5c31af7Sopenharmony_ci * at least through two separate pages. 1157e5c31af7Sopenharmony_ci * 1158e5c31af7Sopenharmony_ci * Since we align up, we need to move one page backward and then apply the alignment function 1159e5c31af7Sopenharmony_ci * to determine the start page index. 1160e5c31af7Sopenharmony_ci */ 1161e5c31af7Sopenharmony_ci const int sparse_bo_data_start_offset = m_page_size - m_helper_bo_size_rounded / 2; 1162e5c31af7Sopenharmony_ci int sparse_bo_data_start_offset_minus_page = sparse_bo_data_start_offset - m_page_size; 1163e5c31af7Sopenharmony_ci 1164e5c31af7Sopenharmony_ci if (sparse_bo_data_start_offset_minus_page < 0) 1165e5c31af7Sopenharmony_ci { 1166e5c31af7Sopenharmony_ci sparse_bo_data_start_offset_minus_page = 0; 1167e5c31af7Sopenharmony_ci } 1168e5c31af7Sopenharmony_ci 1169e5c31af7Sopenharmony_ci m_sparse_bo_data_start_offset = sparse_bo_data_start_offset; 1170e5c31af7Sopenharmony_ci m_sparse_bo_data_start_offset_rounded = 1171e5c31af7Sopenharmony_ci SparseBufferTestUtilities::alignOffset(sparse_bo_data_start_offset_minus_page, m_page_size); 1172e5c31af7Sopenharmony_ci m_sparse_bo_data_size = sparse_bo_data_size; 1173e5c31af7Sopenharmony_ci m_sparse_bo_data_size_rounded = 1174e5c31af7Sopenharmony_ci SparseBufferTestUtilities::alignOffset(m_sparse_bo_data_start_offset + sparse_bo_data_size, m_page_size); 1175e5c31af7Sopenharmony_ci 1176e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_data_size_rounded % m_page_size) == 0); 1177e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_data_start_offset_rounded % m_page_size) == 0); 1178e5c31af7Sopenharmony_ci 1179e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, m_sparse_bo_data_start_offset_rounded, m_sparse_bo_data_size_rounded, 1180e5c31af7Sopenharmony_ci GL_TRUE); /* commit */ 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1183e5c31af7Sopenharmony_ci 1184e5c31af7Sopenharmony_ci return result; 1185e5c31af7Sopenharmony_ci} 1186e5c31af7Sopenharmony_ci 1187e5c31af7Sopenharmony_ci/** Constructor. 1188e5c31af7Sopenharmony_ci * 1189e5c31af7Sopenharmony_ci * @param gl GL entry-points container 1190e5c31af7Sopenharmony_ci * @param context CTS rendering context 1191e5c31af7Sopenharmony_ci * @param testContext CTS test context 1192e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 1193e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 1194e5c31af7Sopenharmony_ci */ 1195e5c31af7Sopenharmony_ciBufferTextureStorageTestCase::BufferTextureStorageTestCase(const glw::Functions& gl, deqp::Context& context, 1196e5c31af7Sopenharmony_ci tcu::TestContext& testContext, glw::GLint page_size) 1197e5c31af7Sopenharmony_ci : m_gl(gl) 1198e5c31af7Sopenharmony_ci , m_helper_bo(0) 1199e5c31af7Sopenharmony_ci , m_helper_bo_data(DE_NULL) 1200e5c31af7Sopenharmony_ci , m_helper_bo_data_size(0) 1201e5c31af7Sopenharmony_ci , m_is_texture_buffer_range_supported(false) 1202e5c31af7Sopenharmony_ci , m_page_size(page_size) 1203e5c31af7Sopenharmony_ci , m_po(0) 1204e5c31af7Sopenharmony_ci , m_po_local_wg_size(1024) 1205e5c31af7Sopenharmony_ci , m_sparse_bo(0) 1206e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 1207e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 1208e5c31af7Sopenharmony_ci , m_ssbo(0) 1209e5c31af7Sopenharmony_ci , m_ssbo_zero_data(DE_NULL) 1210e5c31af7Sopenharmony_ci , m_ssbo_zero_data_size(0) 1211e5c31af7Sopenharmony_ci , m_testCtx(testContext) 1212e5c31af7Sopenharmony_ci , m_to(0) 1213e5c31af7Sopenharmony_ci , m_to_width(65536) /* min max for GL_MAX_TEXTURE_BUFFER_SIZE_ARB */ 1214e5c31af7Sopenharmony_ci{ 1215e5c31af7Sopenharmony_ci const glu::ContextInfo& context_info = context.getContextInfo(); 1216e5c31af7Sopenharmony_ci glu::RenderContext& render_context = context.getRenderContext(); 1217e5c31af7Sopenharmony_ci 1218e5c31af7Sopenharmony_ci if (glu::contextSupports(render_context.getType(), glu::ApiType::core(4, 3)) || 1219e5c31af7Sopenharmony_ci context_info.isExtensionSupported("GL_ARB_texture_buffer_range")) 1220e5c31af7Sopenharmony_ci { 1221e5c31af7Sopenharmony_ci m_is_texture_buffer_range_supported = true; 1222e5c31af7Sopenharmony_ci } 1223e5c31af7Sopenharmony_ci} 1224e5c31af7Sopenharmony_ci 1225e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 1226e5c31af7Sopenharmony_ci * 1227e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1228e5c31af7Sopenharmony_ci */ 1229e5c31af7Sopenharmony_civoid BufferTextureStorageTestCase::deinitTestCaseGlobal() 1230e5c31af7Sopenharmony_ci{ 1231e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 1232e5c31af7Sopenharmony_ci { 1233e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 1234e5c31af7Sopenharmony_ci 1235e5c31af7Sopenharmony_ci m_helper_bo = 0; 1236e5c31af7Sopenharmony_ci } 1237e5c31af7Sopenharmony_ci 1238e5c31af7Sopenharmony_ci if (m_helper_bo_data != DE_NULL) 1239e5c31af7Sopenharmony_ci { 1240e5c31af7Sopenharmony_ci delete[] m_helper_bo_data; 1241e5c31af7Sopenharmony_ci 1242e5c31af7Sopenharmony_ci m_helper_bo_data = DE_NULL; 1243e5c31af7Sopenharmony_ci } 1244e5c31af7Sopenharmony_ci 1245e5c31af7Sopenharmony_ci if (m_po != 0) 1246e5c31af7Sopenharmony_ci { 1247e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 1248e5c31af7Sopenharmony_ci 1249e5c31af7Sopenharmony_ci m_po = 0; 1250e5c31af7Sopenharmony_ci } 1251e5c31af7Sopenharmony_ci 1252e5c31af7Sopenharmony_ci if (m_ssbo != 0) 1253e5c31af7Sopenharmony_ci { 1254e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_ssbo); 1255e5c31af7Sopenharmony_ci 1256e5c31af7Sopenharmony_ci m_ssbo = 0; 1257e5c31af7Sopenharmony_ci } 1258e5c31af7Sopenharmony_ci 1259e5c31af7Sopenharmony_ci if (m_ssbo_zero_data != DE_NULL) 1260e5c31af7Sopenharmony_ci { 1261e5c31af7Sopenharmony_ci delete[] m_ssbo_zero_data; 1262e5c31af7Sopenharmony_ci 1263e5c31af7Sopenharmony_ci m_ssbo_zero_data = DE_NULL; 1264e5c31af7Sopenharmony_ci } 1265e5c31af7Sopenharmony_ci 1266e5c31af7Sopenharmony_ci if (m_to != 0) 1267e5c31af7Sopenharmony_ci { 1268e5c31af7Sopenharmony_ci m_gl.deleteTextures(1, &m_to); 1269e5c31af7Sopenharmony_ci 1270e5c31af7Sopenharmony_ci m_to = 0; 1271e5c31af7Sopenharmony_ci } 1272e5c31af7Sopenharmony_ci} 1273e5c31af7Sopenharmony_ci 1274e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 1275e5c31af7Sopenharmony_civoid BufferTextureStorageTestCase::deinitTestCaseIteration() 1276e5c31af7Sopenharmony_ci{ 1277e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 1278e5c31af7Sopenharmony_ci { 1279e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 1280e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1281e5c31af7Sopenharmony_ci 1282e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 1283e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 1284e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1285e5c31af7Sopenharmony_ci 1286e5c31af7Sopenharmony_ci m_sparse_bo = 0; 1287e5c31af7Sopenharmony_ci } 1288e5c31af7Sopenharmony_ci} 1289e5c31af7Sopenharmony_ci 1290e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 1291e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 1292e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 1293e5c31af7Sopenharmony_ci * 1294e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 1295e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 1296e5c31af7Sopenharmony_ci * 1297e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 1298e5c31af7Sopenharmony_ci */ 1299e5c31af7Sopenharmony_cibool BufferTextureStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 1300e5c31af7Sopenharmony_ci{ 1301e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 1302e5c31af7Sopenharmony_ci bool result = true; 1303e5c31af7Sopenharmony_ci 1304e5c31af7Sopenharmony_ci /* Bind the program object */ 1305e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 1306e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 1307e5c31af7Sopenharmony_ci 1308e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo); 1309e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1310e5c31af7Sopenharmony_ci 1311e5c31af7Sopenharmony_ci m_gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, /* index */ 1312e5c31af7Sopenharmony_ci m_ssbo); 1313e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase() call failed."); 1314e5c31af7Sopenharmony_ci 1315e5c31af7Sopenharmony_ci /* Set up bindings for the copy ops */ 1316e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 1317e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bo); 1318e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 1319e5c31af7Sopenharmony_ci 1320e5c31af7Sopenharmony_ci /* Run the test in two iterations: 1321e5c31af7Sopenharmony_ci * 1322e5c31af7Sopenharmony_ci * a) All required pages are committed. 1323e5c31af7Sopenharmony_ci * b) Only half of the pages are committed. */ 1324e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2; ++n_iteration) 1325e5c31af7Sopenharmony_ci { 1326e5c31af7Sopenharmony_ci 1327e5c31af7Sopenharmony_ci /* Test glTexBuffer() and glTexBufferRange() separately. */ 1328e5c31af7Sopenharmony_ci for (int n_entry_point = 0; n_entry_point < (m_is_texture_buffer_range_supported ? 2 : 1); ++n_entry_point) 1329e5c31af7Sopenharmony_ci { 1330e5c31af7Sopenharmony_ci bool result_local = true; 1331e5c31af7Sopenharmony_ci 1332e5c31af7Sopenharmony_ci /* Set up the sparse buffer's memory backing. */ 1333e5c31af7Sopenharmony_ci const unsigned int tbo_commit_start_offset = (n_iteration == 0) ? 0 : m_sparse_bo_size_rounded / 2; 1334e5c31af7Sopenharmony_ci const unsigned int tbo_commit_size = 1335e5c31af7Sopenharmony_ci (n_iteration == 0) ? m_sparse_bo_size_rounded : m_sparse_bo_size_rounded / 2; 1336e5c31af7Sopenharmony_ci 1337e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_TEXTURE_BUFFER, m_sparse_bo); 1338e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1339e5c31af7Sopenharmony_ci 1340e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_TEXTURE_BUFFER, tbo_commit_start_offset, tbo_commit_size, 1341e5c31af7Sopenharmony_ci GL_TRUE); /* commit */ 1342e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1343e5c31af7Sopenharmony_ci 1344e5c31af7Sopenharmony_ci /* Set up the buffer texture's backing */ 1345e5c31af7Sopenharmony_ci if (n_entry_point == 0) 1346e5c31af7Sopenharmony_ci { 1347e5c31af7Sopenharmony_ci m_gl.texBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, m_sparse_bo); 1348e5c31af7Sopenharmony_ci 1349e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexBuffer() call failed."); 1350e5c31af7Sopenharmony_ci } 1351e5c31af7Sopenharmony_ci else 1352e5c31af7Sopenharmony_ci { 1353e5c31af7Sopenharmony_ci m_gl.texBufferRange(GL_TEXTURE_BUFFER, GL_RGBA8, m_sparse_bo, 0, /* offset */ 1354e5c31af7Sopenharmony_ci m_sparse_bo_size); 1355e5c31af7Sopenharmony_ci 1356e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexBufferRange() call failed."); 1357e5c31af7Sopenharmony_ci } 1358e5c31af7Sopenharmony_ci 1359e5c31af7Sopenharmony_ci /* Set up the sparse buffer's data storage */ 1360e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 1361e5c31af7Sopenharmony_ci 0, /* writeOffset */ 1362e5c31af7Sopenharmony_ci m_helper_bo_data_size); 1363e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 1364e5c31af7Sopenharmony_ci 1365e5c31af7Sopenharmony_ci /* Run the compute program */ 1366e5c31af7Sopenharmony_ci DE_ASSERT((m_to_width % m_po_local_wg_size) == 0); 1367e5c31af7Sopenharmony_ci 1368e5c31af7Sopenharmony_ci m_gl.dispatchCompute(m_to_width / m_po_local_wg_size, 1, /* num_groups_y */ 1369e5c31af7Sopenharmony_ci 1); /* num_groups_z */ 1370e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDispatchCompute() call failed."); 1371e5c31af7Sopenharmony_ci 1372e5c31af7Sopenharmony_ci /* Flush the caches */ 1373e5c31af7Sopenharmony_ci m_gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1374e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMemoryBarrier() call failed."); 1375e5c31af7Sopenharmony_ci 1376e5c31af7Sopenharmony_ci /* Map the SSBO into process space, so we can check if the texture buffer's 1377e5c31af7Sopenharmony_ci * contents was found valid by the compute shader */ 1378e5c31af7Sopenharmony_ci unsigned int current_tb_offset = 0; 1379e5c31af7Sopenharmony_ci const unsigned int* ssbo_data_ptr = 1380e5c31af7Sopenharmony_ci (const unsigned int*)m_gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 1381e5c31af7Sopenharmony_ci 1382e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer() call failed."); 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_ci for (unsigned int n_texel = 0; n_texel < m_to_width && result_local; 1385e5c31af7Sopenharmony_ci ++n_texel, current_tb_offset += 4 /* rgba */) 1386e5c31af7Sopenharmony_ci { 1387e5c31af7Sopenharmony_ci /* NOTE: Since the CS uses std140 layout, we need to move by 4 ints for 1388e5c31af7Sopenharmony_ci * each result value */ 1389e5c31af7Sopenharmony_ci if (current_tb_offset >= tbo_commit_start_offset && 1390e5c31af7Sopenharmony_ci current_tb_offset < (tbo_commit_start_offset + tbo_commit_size) && ssbo_data_ptr[n_texel * 4] != 1) 1391e5c31af7Sopenharmony_ci { 1392e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "A texel read from the texture buffer at index " 1393e5c31af7Sopenharmony_ci "[" 1394e5c31af7Sopenharmony_ci << n_texel << "]" 1395e5c31af7Sopenharmony_ci " was marked as invalid by the CS invocation." 1396e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1397e5c31af7Sopenharmony_ci 1398e5c31af7Sopenharmony_ci result_local = false; 1399e5c31af7Sopenharmony_ci } /* if (ssbo_data_ptr[n_texel] != 1) */ 1400e5c31af7Sopenharmony_ci } /* for (all result values) */ 1401e5c31af7Sopenharmony_ci 1402e5c31af7Sopenharmony_ci result &= result_local; 1403e5c31af7Sopenharmony_ci 1404e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1405e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 1406e5c31af7Sopenharmony_ci 1407e5c31af7Sopenharmony_ci /* Remove the physical backing from the sparse buffer */ 1408e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_TEXTURE_BUFFER, 0, /* offset */ 1409e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 1410e5c31af7Sopenharmony_ci 1411e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1412e5c31af7Sopenharmony_ci 1413e5c31af7Sopenharmony_ci /* Reset SSBO's contents */ 1414e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_SHADER_STORAGE_BUFFER, 0, /* offset */ 1415e5c31af7Sopenharmony_ci m_ssbo_zero_data_size, m_ssbo_zero_data); 1416e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 1417e5c31af7Sopenharmony_ci } /* for (both entry-points) */ 1418e5c31af7Sopenharmony_ci } /* for (both iterations) */ 1419e5c31af7Sopenharmony_ci 1420e5c31af7Sopenharmony_ci return result; 1421e5c31af7Sopenharmony_ci} 1422e5c31af7Sopenharmony_ci 1423e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 1424e5c31af7Sopenharmony_ci * 1425e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1426e5c31af7Sopenharmony_ci */ 1427e5c31af7Sopenharmony_cibool BufferTextureStorageTestCase::initTestCaseGlobal() 1428e5c31af7Sopenharmony_ci{ 1429e5c31af7Sopenharmony_ci /* Set up the test program */ 1430e5c31af7Sopenharmony_ci static const char* cs_body = 1431e5c31af7Sopenharmony_ci "#version 430 core\n" 1432e5c31af7Sopenharmony_ci "\n" 1433e5c31af7Sopenharmony_ci "layout(local_size_x = 1024) in;\n" 1434e5c31af7Sopenharmony_ci "\n" 1435e5c31af7Sopenharmony_ci "layout(std140, binding = 0) buffer data\n" 1436e5c31af7Sopenharmony_ci "{\n" 1437e5c31af7Sopenharmony_ci " restrict writeonly int result[];\n" 1438e5c31af7Sopenharmony_ci "};\n" 1439e5c31af7Sopenharmony_ci "\n" 1440e5c31af7Sopenharmony_ci "uniform samplerBuffer input_texture;\n" 1441e5c31af7Sopenharmony_ci "\n" 1442e5c31af7Sopenharmony_ci "void main()\n" 1443e5c31af7Sopenharmony_ci "{\n" 1444e5c31af7Sopenharmony_ci " uint texel_index = gl_GlobalInvocationID.x;\n" 1445e5c31af7Sopenharmony_ci "\n" 1446e5c31af7Sopenharmony_ci " if (texel_index < 65536)\n" 1447e5c31af7Sopenharmony_ci " {\n" 1448e5c31af7Sopenharmony_ci " vec4 expected_texel_data = vec4 (float((texel_index) % 255) / 255.0,\n" 1449e5c31af7Sopenharmony_ci " float((texel_index + 35) % 255) / 255.0,\n" 1450e5c31af7Sopenharmony_ci " float((texel_index + 78) % 255) / 255.0,\n" 1451e5c31af7Sopenharmony_ci " float((texel_index + 131) % 255) / 255.0);\n" 1452e5c31af7Sopenharmony_ci " vec4 texel_data = texelFetch(input_texture, int(texel_index) );\n" 1453e5c31af7Sopenharmony_ci "\n" 1454e5c31af7Sopenharmony_ci " if (abs(texel_data.r - expected_texel_data.r) > 1.0 / 255.0 ||\n" 1455e5c31af7Sopenharmony_ci " abs(texel_data.g - expected_texel_data.g) > 1.0 / 255.0 ||\n" 1456e5c31af7Sopenharmony_ci " abs(texel_data.b - expected_texel_data.b) > 1.0 / 255.0 ||\n" 1457e5c31af7Sopenharmony_ci " abs(texel_data.a - expected_texel_data.a) > 1.0 / 255.0)\n" 1458e5c31af7Sopenharmony_ci " {\n" 1459e5c31af7Sopenharmony_ci " result[texel_index] = 0;\n" 1460e5c31af7Sopenharmony_ci " }\n" 1461e5c31af7Sopenharmony_ci " else\n" 1462e5c31af7Sopenharmony_ci " {\n" 1463e5c31af7Sopenharmony_ci " result[texel_index] = 1;\n" 1464e5c31af7Sopenharmony_ci " }\n" 1465e5c31af7Sopenharmony_ci " }\n" 1466e5c31af7Sopenharmony_ci "}\n"; 1467e5c31af7Sopenharmony_ci 1468e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createComputeProgram(m_gl, &cs_body, 1); /* n_cs_body_parts */ 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci /* Set up a data buffer we will use to initialize the SSBO with default data. 1471e5c31af7Sopenharmony_ci * 1472e5c31af7Sopenharmony_ci * CS uses a std140 layout for the SSBO, so we need to add the additional padding. 1473e5c31af7Sopenharmony_ci */ 1474e5c31af7Sopenharmony_ci m_ssbo_zero_data_size = static_cast<unsigned int>(4 * sizeof(int) * m_to_width); 1475e5c31af7Sopenharmony_ci m_ssbo_zero_data = new unsigned char[m_ssbo_zero_data_size]; 1476e5c31af7Sopenharmony_ci 1477e5c31af7Sopenharmony_ci memset(m_ssbo_zero_data, 0, m_ssbo_zero_data_size); 1478e5c31af7Sopenharmony_ci 1479e5c31af7Sopenharmony_ci /* Set up the SSBO */ 1480e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_ssbo); 1481e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 1482e5c31af7Sopenharmony_ci 1483e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo); 1484e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1485e5c31af7Sopenharmony_ci 1486e5c31af7Sopenharmony_ci m_gl.bufferData(GL_SHADER_STORAGE_BUFFER, m_ssbo_zero_data_size, m_ssbo_zero_data, GL_STATIC_DRAW); 1487e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData() call failed."); 1488e5c31af7Sopenharmony_ci 1489e5c31af7Sopenharmony_ci /* During execution, we will need to use a helper buffer object. The BO will hold 1490e5c31af7Sopenharmony_ci * data we will be copying into the sparse buffer object for each iteration. 1491e5c31af7Sopenharmony_ci * 1492e5c31af7Sopenharmony_ci * Create an array to hold the helper buffer's data and fill it with info that 1493e5c31af7Sopenharmony_ci * the compute shader is going to be expecting */ 1494e5c31af7Sopenharmony_ci unsigned char* helper_bo_data_traveller_ptr = NULL; 1495e5c31af7Sopenharmony_ci 1496e5c31af7Sopenharmony_ci m_helper_bo_data_size = m_to_width * 4; /* rgba */ 1497e5c31af7Sopenharmony_ci m_helper_bo_data = new unsigned char[m_helper_bo_data_size]; 1498e5c31af7Sopenharmony_ci 1499e5c31af7Sopenharmony_ci helper_bo_data_traveller_ptr = m_helper_bo_data; 1500e5c31af7Sopenharmony_ci 1501e5c31af7Sopenharmony_ci for (unsigned int n_texel = 0; n_texel < m_to_width; ++n_texel) 1502e5c31af7Sopenharmony_ci { 1503e5c31af7Sopenharmony_ci /* Red */ 1504e5c31af7Sopenharmony_ci *helper_bo_data_traveller_ptr = static_cast<unsigned char>(n_texel % 255); 1505e5c31af7Sopenharmony_ci ++helper_bo_data_traveller_ptr; 1506e5c31af7Sopenharmony_ci 1507e5c31af7Sopenharmony_ci /* Green */ 1508e5c31af7Sopenharmony_ci *helper_bo_data_traveller_ptr = static_cast<unsigned char>((n_texel + 35) % 255); 1509e5c31af7Sopenharmony_ci ++helper_bo_data_traveller_ptr; 1510e5c31af7Sopenharmony_ci 1511e5c31af7Sopenharmony_ci /* Blue */ 1512e5c31af7Sopenharmony_ci *helper_bo_data_traveller_ptr = static_cast<unsigned char>((n_texel + 78) % 255); 1513e5c31af7Sopenharmony_ci ++helper_bo_data_traveller_ptr; 1514e5c31af7Sopenharmony_ci 1515e5c31af7Sopenharmony_ci /* Alpha */ 1516e5c31af7Sopenharmony_ci *helper_bo_data_traveller_ptr = static_cast<unsigned char>((n_texel + 131) % 255); 1517e5c31af7Sopenharmony_ci ++helper_bo_data_traveller_ptr; 1518e5c31af7Sopenharmony_ci } /* for (all texels to be accessible via the buffer texture) */ 1519e5c31af7Sopenharmony_ci 1520e5c31af7Sopenharmony_ci /* Set up the helper buffer object which we are going to use to copy data into 1521e5c31af7Sopenharmony_ci * the sparse buffer object. */ 1522e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 1523e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 1524e5c31af7Sopenharmony_ci 1525e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 1526e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1527e5c31af7Sopenharmony_ci 1528e5c31af7Sopenharmony_ci m_gl.bufferData(GL_COPY_READ_BUFFER, m_helper_bo_data_size, m_helper_bo_data, GL_STATIC_DRAW); 1529e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData() call failed."); 1530e5c31af7Sopenharmony_ci 1531e5c31af7Sopenharmony_ci /* Set up the texture buffer object. We will attach the actual buffer storage 1532e5c31af7Sopenharmony_ci * in execute() */ 1533e5c31af7Sopenharmony_ci m_gl.genTextures(1, &m_to); 1534e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures() call failed."); 1535e5c31af7Sopenharmony_ci 1536e5c31af7Sopenharmony_ci m_gl.bindTexture(GL_TEXTURE_BUFFER, m_to); 1537e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture() call failed."); 1538e5c31af7Sopenharmony_ci 1539e5c31af7Sopenharmony_ci /* Determine the number of bytes both the helper and the sparse buffer 1540e5c31af7Sopenharmony_ci * object need to be able to hold, at maximum */ 1541e5c31af7Sopenharmony_ci m_sparse_bo_size = static_cast<unsigned int>(m_to_width * sizeof(int)); 1542e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 1543e5c31af7Sopenharmony_ci 1544e5c31af7Sopenharmony_ci return true; 1545e5c31af7Sopenharmony_ci} 1546e5c31af7Sopenharmony_ci 1547e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 1548e5c31af7Sopenharmony_ci * 1549e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 1550e5c31af7Sopenharmony_ci * to release these objects. 1551e5c31af7Sopenharmony_ci **/ 1552e5c31af7Sopenharmony_cibool BufferTextureStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 1553e5c31af7Sopenharmony_ci{ 1554e5c31af7Sopenharmony_ci bool result = true; 1555e5c31af7Sopenharmony_ci 1556e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 1557e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 1558e5c31af7Sopenharmony_ci 1559e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 1560e5c31af7Sopenharmony_ci 1561e5c31af7Sopenharmony_ci return result; 1562e5c31af7Sopenharmony_ci} 1563e5c31af7Sopenharmony_ci 1564e5c31af7Sopenharmony_ci/** Constructor. 1565e5c31af7Sopenharmony_ci * 1566e5c31af7Sopenharmony_ci * @param gl GL entry-points container 1567e5c31af7Sopenharmony_ci * @param testContext CTS test context 1568e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 1569e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 1570e5c31af7Sopenharmony_ci */ 1571e5c31af7Sopenharmony_ciClearOpsBufferStorageTestCase::ClearOpsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 1572e5c31af7Sopenharmony_ci glw::GLint page_size) 1573e5c31af7Sopenharmony_ci : m_gl(gl) 1574e5c31af7Sopenharmony_ci , m_helper_bo(0) 1575e5c31af7Sopenharmony_ci , m_initial_data(DE_NULL) 1576e5c31af7Sopenharmony_ci , m_n_pages_to_use(16) 1577e5c31af7Sopenharmony_ci , m_page_size(page_size) 1578e5c31af7Sopenharmony_ci , m_sparse_bo(0) 1579e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 1580e5c31af7Sopenharmony_ci , m_testCtx(testContext) 1581e5c31af7Sopenharmony_ci{ 1582e5c31af7Sopenharmony_ci /* Left blank intentionally */ 1583e5c31af7Sopenharmony_ci} 1584e5c31af7Sopenharmony_ci 1585e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 1586e5c31af7Sopenharmony_ci * 1587e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1588e5c31af7Sopenharmony_ci */ 1589e5c31af7Sopenharmony_civoid ClearOpsBufferStorageTestCase::deinitTestCaseGlobal() 1590e5c31af7Sopenharmony_ci{ 1591e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 1592e5c31af7Sopenharmony_ci { 1593e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 1594e5c31af7Sopenharmony_ci 1595e5c31af7Sopenharmony_ci m_helper_bo = 0; 1596e5c31af7Sopenharmony_ci } 1597e5c31af7Sopenharmony_ci 1598e5c31af7Sopenharmony_ci if (m_initial_data != DE_NULL) 1599e5c31af7Sopenharmony_ci { 1600e5c31af7Sopenharmony_ci delete[] m_initial_data; 1601e5c31af7Sopenharmony_ci 1602e5c31af7Sopenharmony_ci m_initial_data = DE_NULL; 1603e5c31af7Sopenharmony_ci } 1604e5c31af7Sopenharmony_ci} 1605e5c31af7Sopenharmony_ci 1606e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 1607e5c31af7Sopenharmony_civoid ClearOpsBufferStorageTestCase::deinitTestCaseIteration() 1608e5c31af7Sopenharmony_ci{ 1609e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 1610e5c31af7Sopenharmony_ci { 1611e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 1612e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1613e5c31af7Sopenharmony_ci 1614e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 1615e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 1616e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1617e5c31af7Sopenharmony_ci 1618e5c31af7Sopenharmony_ci m_sparse_bo = 0; 1619e5c31af7Sopenharmony_ci } 1620e5c31af7Sopenharmony_ci} 1621e5c31af7Sopenharmony_ci 1622e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 1623e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 1624e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 1625e5c31af7Sopenharmony_ci * 1626e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 1627e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 1628e5c31af7Sopenharmony_ci * 1629e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 1630e5c31af7Sopenharmony_ci */ 1631e5c31af7Sopenharmony_cibool ClearOpsBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 1632e5c31af7Sopenharmony_ci{ 1633e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 1634e5c31af7Sopenharmony_ci bool result = true; 1635e5c31af7Sopenharmony_ci const unsigned int data_rgba8 = 0x12345678; 1636e5c31af7Sopenharmony_ci 1637e5c31af7Sopenharmony_ci for (unsigned int n_clear_op_type = 0; n_clear_op_type < 2; /* glClearBufferData(), glClearBufferSubData() */ 1638e5c31af7Sopenharmony_ci ++n_clear_op_type) 1639e5c31af7Sopenharmony_ci { 1640e5c31af7Sopenharmony_ci const bool use_clear_buffer_data_call = (n_clear_op_type == 0); 1641e5c31af7Sopenharmony_ci 1642e5c31af7Sopenharmony_ci /* We will run the test case in two iterations: 1643e5c31af7Sopenharmony_ci * 1644e5c31af7Sopenharmony_ci * 1) All pages will have a physical backing. 1645e5c31af7Sopenharmony_ci * 2) Half of the pages will have a physical backing. 1646e5c31af7Sopenharmony_ci */ 1647e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2; ++n_iteration) 1648e5c31af7Sopenharmony_ci { 1649e5c31af7Sopenharmony_ci /* By default, for each iteration all sparse buffer pages are commited. 1650e5c31af7Sopenharmony_ci * 1651e5c31af7Sopenharmony_ci * For the last iteration, we need to de-commit the latter half before 1652e5c31af7Sopenharmony_ci * proceeding with the test. 1653e5c31af7Sopenharmony_ci */ 1654e5c31af7Sopenharmony_ci const bool all_pages_committed = (n_iteration == 0); 1655e5c31af7Sopenharmony_ci 1656e5c31af7Sopenharmony_ci if (!all_pages_committed) 1657e5c31af7Sopenharmony_ci { 1658e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 1659e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1660e5c31af7Sopenharmony_ci 1661e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, m_sparse_bo_size_rounded / 2, /* offset */ 1662e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded / 2, /* size */ 1663e5c31af7Sopenharmony_ci GL_TRUE); /* commit */ 1664e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1665e5c31af7Sopenharmony_ci } 1666e5c31af7Sopenharmony_ci 1667e5c31af7Sopenharmony_ci /* Set up the sparse buffer contents */ 1668e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_helper_bo); 1669e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1670e5c31af7Sopenharmony_ci 1671e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */ 1672e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, m_initial_data); 1673e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 1674e5c31af7Sopenharmony_ci 1675e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 1676e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bo); 1677e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 1678e5c31af7Sopenharmony_ci 1679e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, /* readTarget */ 1680e5c31af7Sopenharmony_ci GL_COPY_WRITE_BUFFER, /* writeTarget */ 1681e5c31af7Sopenharmony_ci 0, /* readOffset */ 1682e5c31af7Sopenharmony_ci 0, /* writeOffset */ 1683e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded); 1684e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 1685e5c31af7Sopenharmony_ci 1686e5c31af7Sopenharmony_ci /* Issue the clear call */ 1687e5c31af7Sopenharmony_ci unsigned int clear_region_size = 0; 1688e5c31af7Sopenharmony_ci unsigned int clear_region_start_offset = 0; 1689e5c31af7Sopenharmony_ci 1690e5c31af7Sopenharmony_ci if (use_clear_buffer_data_call) 1691e5c31af7Sopenharmony_ci { 1692e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size_rounded % sizeof(unsigned int)) == 0); 1693e5c31af7Sopenharmony_ci 1694e5c31af7Sopenharmony_ci clear_region_size = m_sparse_bo_size_rounded; 1695e5c31af7Sopenharmony_ci clear_region_start_offset = 0; 1696e5c31af7Sopenharmony_ci 1697e5c31af7Sopenharmony_ci m_gl.clearBufferData(GL_COPY_WRITE_BUFFER, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &data_rgba8); 1698e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferData() call failed."); 1699e5c31af7Sopenharmony_ci } 1700e5c31af7Sopenharmony_ci else 1701e5c31af7Sopenharmony_ci { 1702e5c31af7Sopenharmony_ci DE_ASSERT(((m_sparse_bo_size_rounded / 2) % sizeof(unsigned int)) == 0); 1703e5c31af7Sopenharmony_ci DE_ASSERT(((m_sparse_bo_size_rounded) % sizeof(unsigned int)) == 0); 1704e5c31af7Sopenharmony_ci 1705e5c31af7Sopenharmony_ci clear_region_size = m_sparse_bo_size_rounded / 2; 1706e5c31af7Sopenharmony_ci clear_region_start_offset = m_sparse_bo_size_rounded / 2; 1707e5c31af7Sopenharmony_ci 1708e5c31af7Sopenharmony_ci m_gl.clearBufferSubData(GL_COPY_WRITE_BUFFER, GL_RGBA8, clear_region_start_offset, clear_region_size, 1709e5c31af7Sopenharmony_ci GL_RGBA, GL_UNSIGNED_BYTE, &data_rgba8); 1710e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferSubData() call failed."); 1711e5c31af7Sopenharmony_ci } 1712e5c31af7Sopenharmony_ci 1713e5c31af7Sopenharmony_ci /* Retrieve the modified buffer's contents */ 1714e5c31af7Sopenharmony_ci const unsigned char* result_data = NULL; 1715e5c31af7Sopenharmony_ci 1716e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_WRITE_BUFFER, /* readTarget */ 1717e5c31af7Sopenharmony_ci GL_COPY_READ_BUFFER, /* writeTarget */ 1718e5c31af7Sopenharmony_ci 0, /* readOffset */ 1719e5c31af7Sopenharmony_ci 0, /* writeOffset */ 1720e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded); 1721e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 1722e5c31af7Sopenharmony_ci 1723e5c31af7Sopenharmony_ci result_data = (unsigned char*)m_gl.mapBufferRange(GL_COPY_READ_BUFFER, 0, /* offset */ 1724e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_MAP_READ_BIT); 1725e5c31af7Sopenharmony_ci 1726e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 1727e5c31af7Sopenharmony_ci 1728e5c31af7Sopenharmony_ci /* Verify the result data: unmodified region */ 1729e5c31af7Sopenharmony_ci bool result_local = true; 1730e5c31af7Sopenharmony_ci const unsigned int unmodified_region_size = (use_clear_buffer_data_call) ? 0 : clear_region_start_offset; 1731e5c31af7Sopenharmony_ci const unsigned int unmodified_region_start_offset = 0; 1732e5c31af7Sopenharmony_ci 1733e5c31af7Sopenharmony_ci for (unsigned int n_current_byte = unmodified_region_start_offset; 1734e5c31af7Sopenharmony_ci (n_current_byte < unmodified_region_start_offset + unmodified_region_size) && result_local; 1735e5c31af7Sopenharmony_ci ++n_current_byte) 1736e5c31af7Sopenharmony_ci { 1737e5c31af7Sopenharmony_ci const unsigned int current_initial_data_offset = n_current_byte - unmodified_region_start_offset; 1738e5c31af7Sopenharmony_ci const unsigned char expected_value = m_initial_data[current_initial_data_offset]; 1739e5c31af7Sopenharmony_ci const unsigned char found_value = result_data[n_current_byte]; 1740e5c31af7Sopenharmony_ci 1741e5c31af7Sopenharmony_ci if (expected_value != found_value) 1742e5c31af7Sopenharmony_ci { 1743e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 1744e5c31af7Sopenharmony_ci << "Unmodified buffer object region has invalid contents. Expected byte " 1745e5c31af7Sopenharmony_ci << "[" << (int)expected_value << "]" 1746e5c31af7Sopenharmony_ci ", found byte:" 1747e5c31af7Sopenharmony_ci "[" 1748e5c31af7Sopenharmony_ci << (int)found_value << "]" 1749e5c31af7Sopenharmony_ci " at index " 1750e5c31af7Sopenharmony_ci "[" 1751e5c31af7Sopenharmony_ci << n_current_byte << "]; " 1752e5c31af7Sopenharmony_ci "call type:" 1753e5c31af7Sopenharmony_ci "[" 1754e5c31af7Sopenharmony_ci << ((use_clear_buffer_data_call) ? "glClearBufferData()" : 1755e5c31af7Sopenharmony_ci "glClearBufferSubData()") 1756e5c31af7Sopenharmony_ci << "]" 1757e5c31af7Sopenharmony_ci ", all required pages committed?:" 1758e5c31af7Sopenharmony_ci "[" 1759e5c31af7Sopenharmony_ci << ((all_pages_committed) ? "yes" : "no") << "]" << tcu::TestLog::EndMessage; 1760e5c31af7Sopenharmony_ci 1761e5c31af7Sopenharmony_ci result_local = false; 1762e5c31af7Sopenharmony_ci break; 1763e5c31af7Sopenharmony_ci } 1764e5c31af7Sopenharmony_ci } 1765e5c31af7Sopenharmony_ci 1766e5c31af7Sopenharmony_ci result &= result_local; 1767e5c31af7Sopenharmony_ci result_local = true; 1768e5c31af7Sopenharmony_ci 1769e5c31af7Sopenharmony_ci /* Verify the result data: modified region (clamped to the memory region 1770e5c31af7Sopenharmony_ci * with actual physical backing) */ 1771e5c31af7Sopenharmony_ci const unsigned int modified_region_size = (all_pages_committed) ? clear_region_size : 0; 1772e5c31af7Sopenharmony_ci const unsigned int modified_region_start_offset = clear_region_start_offset; 1773e5c31af7Sopenharmony_ci 1774e5c31af7Sopenharmony_ci for (unsigned int n_current_byte = modified_region_start_offset; 1775e5c31af7Sopenharmony_ci (n_current_byte < modified_region_start_offset + modified_region_size) && result_local; 1776e5c31af7Sopenharmony_ci ++n_current_byte) 1777e5c31af7Sopenharmony_ci { 1778e5c31af7Sopenharmony_ci const unsigned char component_offset = n_current_byte % 4; 1779e5c31af7Sopenharmony_ci const unsigned char expected_value = 1780e5c31af7Sopenharmony_ci static_cast<unsigned char>((data_rgba8 & (0xFFu << (component_offset * 8))) >> (component_offset * 8)); 1781e5c31af7Sopenharmony_ci const unsigned char found_value = result_data[n_current_byte]; 1782e5c31af7Sopenharmony_ci 1783e5c31af7Sopenharmony_ci if (expected_value != found_value) 1784e5c31af7Sopenharmony_ci { 1785e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 1786e5c31af7Sopenharmony_ci << "Modified buffer object region has invalid contents. Expected byte " 1787e5c31af7Sopenharmony_ci << "[" << (int)expected_value << "]" 1788e5c31af7Sopenharmony_ci ", found byte:" 1789e5c31af7Sopenharmony_ci "[" 1790e5c31af7Sopenharmony_ci << (int)found_value << "]" 1791e5c31af7Sopenharmony_ci " at index " 1792e5c31af7Sopenharmony_ci "[" 1793e5c31af7Sopenharmony_ci << n_current_byte << "]; " 1794e5c31af7Sopenharmony_ci "call type:" 1795e5c31af7Sopenharmony_ci "[" 1796e5c31af7Sopenharmony_ci << ((use_clear_buffer_data_call) ? "glClearBufferData()" : 1797e5c31af7Sopenharmony_ci "glClearBufferSubData()") 1798e5c31af7Sopenharmony_ci << "]" 1799e5c31af7Sopenharmony_ci ", all required pages committed?:" 1800e5c31af7Sopenharmony_ci "[" 1801e5c31af7Sopenharmony_ci << ((all_pages_committed) ? "yes" : "no") << "]" << tcu::TestLog::EndMessage; 1802e5c31af7Sopenharmony_ci 1803e5c31af7Sopenharmony_ci result_local = false; 1804e5c31af7Sopenharmony_ci break; 1805e5c31af7Sopenharmony_ci } 1806e5c31af7Sopenharmony_ci } 1807e5c31af7Sopenharmony_ci 1808e5c31af7Sopenharmony_ci result &= result_local; 1809e5c31af7Sopenharmony_ci 1810e5c31af7Sopenharmony_ci /* Unmap the storage before proceeding */ 1811e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_READ_BUFFER); 1812e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 1813e5c31af7Sopenharmony_ci } /* for (both iterations) */ 1814e5c31af7Sopenharmony_ci } /* for (both clear types) */ 1815e5c31af7Sopenharmony_ci 1816e5c31af7Sopenharmony_ci return result; 1817e5c31af7Sopenharmony_ci} 1818e5c31af7Sopenharmony_ci 1819e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 1820e5c31af7Sopenharmony_ci * 1821e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1822e5c31af7Sopenharmony_ci */ 1823e5c31af7Sopenharmony_cibool ClearOpsBufferStorageTestCase::initTestCaseGlobal() 1824e5c31af7Sopenharmony_ci{ 1825e5c31af7Sopenharmony_ci unsigned int n_bytes_filled = 0; 1826e5c31af7Sopenharmony_ci const unsigned int n_bytes_needed = m_n_pages_to_use * m_page_size; 1827e5c31af7Sopenharmony_ci 1828e5c31af7Sopenharmony_ci /* Determine the number of bytes both the helper and the sparse buffer 1829e5c31af7Sopenharmony_ci * object need to be able to hold, at maximum */ 1830e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(n_bytes_needed, m_page_size); 1831e5c31af7Sopenharmony_ci 1832e5c31af7Sopenharmony_ci /* Set up the helper BO */ 1833e5c31af7Sopenharmony_ci DE_ASSERT(m_helper_bo == 0); 1834e5c31af7Sopenharmony_ci 1835e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 1836e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 1837e5c31af7Sopenharmony_ci 1838e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 1839e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1840e5c31af7Sopenharmony_ci 1841e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_sparse_bo_size_rounded, DE_NULL, 1842e5c31af7Sopenharmony_ci GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT); /* flags */ 1843e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 1844e5c31af7Sopenharmony_ci 1845e5c31af7Sopenharmony_ci /* Set up a client-side data buffer we will use to fill the sparse BO with data, 1846e5c31af7Sopenharmony_ci * to be later cleared with the clear ops */ 1847e5c31af7Sopenharmony_ci DE_ASSERT(m_initial_data == DE_NULL); 1848e5c31af7Sopenharmony_ci 1849e5c31af7Sopenharmony_ci m_initial_data = new unsigned char[m_sparse_bo_size_rounded]; 1850e5c31af7Sopenharmony_ci 1851e5c31af7Sopenharmony_ci while (n_bytes_filled < m_sparse_bo_size_rounded) 1852e5c31af7Sopenharmony_ci { 1853e5c31af7Sopenharmony_ci m_initial_data[n_bytes_filled] = static_cast<unsigned char>(n_bytes_filled % 256); 1854e5c31af7Sopenharmony_ci 1855e5c31af7Sopenharmony_ci ++n_bytes_filled; 1856e5c31af7Sopenharmony_ci } 1857e5c31af7Sopenharmony_ci 1858e5c31af7Sopenharmony_ci return true; 1859e5c31af7Sopenharmony_ci} 1860e5c31af7Sopenharmony_ci 1861e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 1862e5c31af7Sopenharmony_ci * 1863e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 1864e5c31af7Sopenharmony_ci * to release these objects. 1865e5c31af7Sopenharmony_ci **/ 1866e5c31af7Sopenharmony_cibool ClearOpsBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 1867e5c31af7Sopenharmony_ci{ 1868e5c31af7Sopenharmony_ci bool result = true; 1869e5c31af7Sopenharmony_ci 1870e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 1871e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 1872e5c31af7Sopenharmony_ci 1873e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 1874e5c31af7Sopenharmony_ci 1875e5c31af7Sopenharmony_ci /* Set up the sparse bufffer. */ 1876e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 1877e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1878e5c31af7Sopenharmony_ci 1879e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 1880e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 1881e5c31af7Sopenharmony_ci 1882e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1883e5c31af7Sopenharmony_ci 1884e5c31af7Sopenharmony_ci return result; 1885e5c31af7Sopenharmony_ci} 1886e5c31af7Sopenharmony_ci 1887e5c31af7Sopenharmony_ci/** Constructor. 1888e5c31af7Sopenharmony_ci * 1889e5c31af7Sopenharmony_ci * @param gl GL entry-points container 1890e5c31af7Sopenharmony_ci * @param testContext CTS test context 1891e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 1892e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 1893e5c31af7Sopenharmony_ci */ 1894e5c31af7Sopenharmony_ciCopyOpsBufferStorageTestCase::CopyOpsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 1895e5c31af7Sopenharmony_ci glw::GLint page_size) 1896e5c31af7Sopenharmony_ci : m_gl(gl) 1897e5c31af7Sopenharmony_ci , m_helper_bo(0) 1898e5c31af7Sopenharmony_ci , m_immutable_bo(0) 1899e5c31af7Sopenharmony_ci , m_page_size(page_size) 1900e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 1901e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 1902e5c31af7Sopenharmony_ci , m_testCtx(testContext) 1903e5c31af7Sopenharmony_ci{ 1904e5c31af7Sopenharmony_ci m_ref_data[0] = DE_NULL; 1905e5c31af7Sopenharmony_ci m_ref_data[1] = DE_NULL; 1906e5c31af7Sopenharmony_ci m_ref_data[2] = DE_NULL; 1907e5c31af7Sopenharmony_ci m_sparse_bos[0] = 0; 1908e5c31af7Sopenharmony_ci m_sparse_bos[1] = 0; 1909e5c31af7Sopenharmony_ci} 1910e5c31af7Sopenharmony_ci 1911e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 1912e5c31af7Sopenharmony_ci * 1913e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 1914e5c31af7Sopenharmony_ci */ 1915e5c31af7Sopenharmony_ci 1916e5c31af7Sopenharmony_civoid CopyOpsBufferStorageTestCase::deinitTestCaseGlobal() 1917e5c31af7Sopenharmony_ci{ 1918e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 1919e5c31af7Sopenharmony_ci { 1920e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 1921e5c31af7Sopenharmony_ci 1922e5c31af7Sopenharmony_ci m_helper_bo = 0; 1923e5c31af7Sopenharmony_ci } 1924e5c31af7Sopenharmony_ci 1925e5c31af7Sopenharmony_ci if (m_immutable_bo != 0) 1926e5c31af7Sopenharmony_ci { 1927e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_immutable_bo); 1928e5c31af7Sopenharmony_ci 1929e5c31af7Sopenharmony_ci m_immutable_bo = 0; 1930e5c31af7Sopenharmony_ci } 1931e5c31af7Sopenharmony_ci 1932e5c31af7Sopenharmony_ci for (unsigned int n_ref_data_buffer = 0; n_ref_data_buffer < sizeof(m_ref_data) / sizeof(m_ref_data[0]); 1933e5c31af7Sopenharmony_ci ++n_ref_data_buffer) 1934e5c31af7Sopenharmony_ci { 1935e5c31af7Sopenharmony_ci if (m_ref_data[n_ref_data_buffer] != DE_NULL) 1936e5c31af7Sopenharmony_ci { 1937e5c31af7Sopenharmony_ci delete[] m_ref_data[n_ref_data_buffer]; 1938e5c31af7Sopenharmony_ci 1939e5c31af7Sopenharmony_ci m_ref_data[n_ref_data_buffer] = DE_NULL; 1940e5c31af7Sopenharmony_ci } 1941e5c31af7Sopenharmony_ci } 1942e5c31af7Sopenharmony_ci 1943e5c31af7Sopenharmony_ci /* Only release the test case-owned BO */ 1944e5c31af7Sopenharmony_ci if (m_sparse_bos[1] != 0) 1945e5c31af7Sopenharmony_ci { 1946e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, m_sparse_bos + 1); 1947e5c31af7Sopenharmony_ci 1948e5c31af7Sopenharmony_ci m_sparse_bos[1] = 0; 1949e5c31af7Sopenharmony_ci } 1950e5c31af7Sopenharmony_ci} 1951e5c31af7Sopenharmony_ci 1952e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 1953e5c31af7Sopenharmony_civoid CopyOpsBufferStorageTestCase::deinitTestCaseIteration() 1954e5c31af7Sopenharmony_ci{ 1955e5c31af7Sopenharmony_ci for (unsigned int n_sparse_bo = 0; n_sparse_bo < sizeof(m_sparse_bos) / sizeof(m_sparse_bos[0]); ++n_sparse_bo) 1956e5c31af7Sopenharmony_ci { 1957e5c31af7Sopenharmony_ci const glw::GLuint sparse_bo_id = m_sparse_bos[n_sparse_bo]; 1958e5c31af7Sopenharmony_ci 1959e5c31af7Sopenharmony_ci if (sparse_bo_id != 0) 1960e5c31af7Sopenharmony_ci { 1961e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, sparse_bo_id); 1962e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 1963e5c31af7Sopenharmony_ci 1964e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 1965e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 1966e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 1967e5c31af7Sopenharmony_ci } /* if (sparse_bo_id != 0) */ 1968e5c31af7Sopenharmony_ci } /* for (both BOs) */ 1969e5c31af7Sopenharmony_ci} 1970e5c31af7Sopenharmony_ci 1971e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 1972e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 1973e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 1974e5c31af7Sopenharmony_ci * 1975e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 1976e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 1977e5c31af7Sopenharmony_ci * 1978e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 1979e5c31af7Sopenharmony_ci */ 1980e5c31af7Sopenharmony_cibool CopyOpsBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 1981e5c31af7Sopenharmony_ci{ 1982e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 1983e5c31af7Sopenharmony_ci bool result = true; 1984e5c31af7Sopenharmony_ci 1985e5c31af7Sopenharmony_ci /* Iterate over all test cases */ 1986e5c31af7Sopenharmony_ci DE_ASSERT(m_immutable_bo != 0); 1987e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bos[0] != 0); 1988e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bos[1] != 0); 1989e5c31af7Sopenharmony_ci 1990e5c31af7Sopenharmony_ci for (_test_cases_const_iterator test_iterator = m_test_cases.begin(); test_iterator != m_test_cases.end(); 1991e5c31af7Sopenharmony_ci ++test_iterator) 1992e5c31af7Sopenharmony_ci { 1993e5c31af7Sopenharmony_ci bool result_local = true; 1994e5c31af7Sopenharmony_ci const _test_case& test_case = *test_iterator; 1995e5c31af7Sopenharmony_ci const glw::GLuint dst_bo_id = 1996e5c31af7Sopenharmony_ci test_case.dst_bo_is_sparse ? m_sparse_bos[test_case.dst_bo_sparse_id] : m_immutable_bo; 1997e5c31af7Sopenharmony_ci const glw::GLuint src_bo_id = 1998e5c31af7Sopenharmony_ci test_case.src_bo_is_sparse ? m_sparse_bos[test_case.src_bo_sparse_id] : m_immutable_bo; 1999e5c31af7Sopenharmony_ci 2000e5c31af7Sopenharmony_ci /* Initialize immutable BO data (if used) */ 2001e5c31af7Sopenharmony_ci if (dst_bo_id == m_immutable_bo || src_bo_id == m_immutable_bo) 2002e5c31af7Sopenharmony_ci { 2003e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_immutable_bo); 2004e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2005e5c31af7Sopenharmony_ci 2006e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */ 2007e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, m_ref_data[0]); 2008e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 2009e5c31af7Sopenharmony_ci } 2010e5c31af7Sopenharmony_ci 2011e5c31af7Sopenharmony_ci /* Initialize sparse BO data storage */ 2012e5c31af7Sopenharmony_ci for (unsigned int n_sparse_bo = 0; n_sparse_bo < sizeof(m_sparse_bos) / sizeof(m_sparse_bos[0]); ++n_sparse_bo) 2013e5c31af7Sopenharmony_ci { 2014e5c31af7Sopenharmony_ci const bool is_dst_bo = (dst_bo_id == m_sparse_bos[n_sparse_bo]); 2015e5c31af7Sopenharmony_ci const bool is_src_bo = (src_bo_id == m_sparse_bos[n_sparse_bo]); 2016e5c31af7Sopenharmony_ci 2017e5c31af7Sopenharmony_ci if (!is_dst_bo && !is_src_bo) 2018e5c31af7Sopenharmony_ci continue; 2019e5c31af7Sopenharmony_ci 2020e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 2021e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bos[n_sparse_bo]); 2022e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 2023e5c31af7Sopenharmony_ci 2024e5c31af7Sopenharmony_ci if (is_dst_bo) 2025e5c31af7Sopenharmony_ci { 2026e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_COPY_WRITE_BUFFER, test_case.dst_bo_commit_start_offset, 2027e5c31af7Sopenharmony_ci test_case.dst_bo_commit_size, GL_TRUE); /* commit */ 2028e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2029e5c31af7Sopenharmony_ci } 2030e5c31af7Sopenharmony_ci 2031e5c31af7Sopenharmony_ci if (is_src_bo) 2032e5c31af7Sopenharmony_ci { 2033e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_COPY_WRITE_BUFFER, test_case.src_bo_commit_start_offset, 2034e5c31af7Sopenharmony_ci test_case.src_bo_commit_size, GL_TRUE); /* commit */ 2035e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2036e5c31af7Sopenharmony_ci } 2037e5c31af7Sopenharmony_ci 2038e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_COPY_READ_BUFFER, 0, /* offset */ 2039e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, m_ref_data[1 + n_sparse_bo]); 2040e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 2041e5c31af7Sopenharmony_ci 2042e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 2043e5c31af7Sopenharmony_ci 0, /* writeOffset */ 2044e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded); 2045e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 2046e5c31af7Sopenharmony_ci } /* for (both sparse BOs) */ 2047e5c31af7Sopenharmony_ci 2048e5c31af7Sopenharmony_ci /* Set up the bindings */ 2049e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, src_bo_id); 2050e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, dst_bo_id); 2051e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2052e5c31af7Sopenharmony_ci 2053e5c31af7Sopenharmony_ci /* Issue the copy op */ 2054e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, test_case.src_bo_start_offset, 2055e5c31af7Sopenharmony_ci test_case.dst_bo_start_offset, test_case.n_bytes_to_copy); 2056e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 2057e5c31af7Sopenharmony_ci 2058e5c31af7Sopenharmony_ci /* Retrieve the destination buffer's contents. The BO used for the previous copy op might have 2059e5c31af7Sopenharmony_ci * been a sparse BO, so copy its storage to a helper immutable BO */ 2060e5c31af7Sopenharmony_ci const unsigned short* dst_bo_data_ptr = NULL; 2061e5c31af7Sopenharmony_ci 2062e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, dst_bo_id); 2063e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_helper_bo); 2064e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2065e5c31af7Sopenharmony_ci 2066e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 2067e5c31af7Sopenharmony_ci 0, /* writeOffset */ 2068e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded); 2069e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 2070e5c31af7Sopenharmony_ci 2071e5c31af7Sopenharmony_ci dst_bo_data_ptr = (const unsigned short*)m_gl.mapBufferRange(GL_COPY_WRITE_BUFFER, 0, /* offset */ 2072e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_MAP_READ_BIT); 2073e5c31af7Sopenharmony_ci 2074e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 2075e5c31af7Sopenharmony_ci 2076e5c31af7Sopenharmony_ci /* Verify the retrieved data: 2077e5c31af7Sopenharmony_ci * 2078e5c31af7Sopenharmony_ci * 1. Check the bytes which precede the copy op dst offset. These should be equal to 2079e5c31af7Sopenharmony_ci * the destination buffer's reference data within the committed memory region. 2080e5c31af7Sopenharmony_ci **/ 2081e5c31af7Sopenharmony_ci if (test_case.dst_bo_start_offset != 0 && test_case.dst_bo_commit_start_offset < test_case.dst_bo_start_offset) 2082e5c31af7Sopenharmony_ci { 2083e5c31af7Sopenharmony_ci DE_ASSERT(((test_case.dst_bo_start_offset - test_case.dst_bo_commit_start_offset) % sizeof(short)) == 0); 2084e5c31af7Sopenharmony_ci 2085e5c31af7Sopenharmony_ci const unsigned int n_valid_values = static_cast<unsigned int>( 2086e5c31af7Sopenharmony_ci (test_case.dst_bo_start_offset - test_case.dst_bo_commit_start_offset) / sizeof(short)); 2087e5c31af7Sopenharmony_ci 2088e5c31af7Sopenharmony_ci for (unsigned int n_value = 0; n_value < n_valid_values && result_local; ++n_value) 2089e5c31af7Sopenharmony_ci { 2090e5c31af7Sopenharmony_ci const int dst_data_offset = static_cast<int>(sizeof(short) * n_value); 2091e5c31af7Sopenharmony_ci 2092e5c31af7Sopenharmony_ci if (dst_data_offset >= test_case.dst_bo_commit_start_offset && 2093e5c31af7Sopenharmony_ci dst_data_offset < test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size) 2094e5c31af7Sopenharmony_ci { 2095e5c31af7Sopenharmony_ci const unsigned short expected_short_value = 2096e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)test_case.dst_bo_ref_data + dst_data_offset); 2097e5c31af7Sopenharmony_ci const unsigned short found_short_value = 2098e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)dst_bo_data_ptr + dst_data_offset); 2099e5c31af7Sopenharmony_ci 2100e5c31af7Sopenharmony_ci if (expected_short_value != found_short_value) 2101e5c31af7Sopenharmony_ci { 2102e5c31af7Sopenharmony_ci m_testCtx.getLog() 2103e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "Malformed data found in the copy op's destination BO, " 2104e5c31af7Sopenharmony_ci "preceding the region modified by the copy op. " 2105e5c31af7Sopenharmony_ci << "Destination BO id:" << dst_bo_id << " (" 2106e5c31af7Sopenharmony_ci << ((test_case.dst_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2107e5c31af7Sopenharmony_ci << ", commited region: " << test_case.dst_bo_commit_start_offset << ":" 2108e5c31af7Sopenharmony_ci << (test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size) 2109e5c31af7Sopenharmony_ci << ", copy region: " << test_case.dst_bo_start_offset << ":" 2110e5c31af7Sopenharmony_ci << (test_case.dst_bo_start_offset + test_case.n_bytes_to_copy) 2111e5c31af7Sopenharmony_ci << ". Source BO id:" << src_bo_id << " (" 2112e5c31af7Sopenharmony_ci << ((test_case.src_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2113e5c31af7Sopenharmony_ci << ", commited region: " << test_case.src_bo_commit_start_offset << ":" 2114e5c31af7Sopenharmony_ci << (test_case.src_bo_commit_start_offset + test_case.src_bo_commit_size) 2115e5c31af7Sopenharmony_ci << ", copy region: " << test_case.src_bo_start_offset << ":" 2116e5c31af7Sopenharmony_ci << (test_case.src_bo_start_offset + test_case.n_bytes_to_copy) << ". Expected value of " 2117e5c31af7Sopenharmony_ci << expected_short_value << ", found value of " << found_short_value 2118e5c31af7Sopenharmony_ci << " at dst data offset of " << dst_data_offset << "." << tcu::TestLog::EndMessage; 2119e5c31af7Sopenharmony_ci 2120e5c31af7Sopenharmony_ci result_local = false; 2121e5c31af7Sopenharmony_ci } 2122e5c31af7Sopenharmony_ci } 2123e5c31af7Sopenharmony_ci } /* for (all preceding values which should not have been affected by the copy op) */ 2124e5c31af7Sopenharmony_ci } /* if (copy op did not modify the beginning of the destination buffer storage) */ 2125e5c31af7Sopenharmony_ci 2126e5c31af7Sopenharmony_ci /* 2. Check if the data written to the destination buffer object is correct. */ 2127e5c31af7Sopenharmony_ci for (unsigned int n_copied_short_value = 0; 2128e5c31af7Sopenharmony_ci n_copied_short_value < test_case.n_bytes_to_copy / sizeof(short) && result_local; ++n_copied_short_value) 2129e5c31af7Sopenharmony_ci { 2130e5c31af7Sopenharmony_ci const int src_data_offset = 2131e5c31af7Sopenharmony_ci static_cast<unsigned int>(test_case.src_bo_start_offset + sizeof(short) * n_copied_short_value); 2132e5c31af7Sopenharmony_ci const int dst_data_offset = 2133e5c31af7Sopenharmony_ci static_cast<unsigned int>(test_case.dst_bo_start_offset + sizeof(short) * n_copied_short_value); 2134e5c31af7Sopenharmony_ci 2135e5c31af7Sopenharmony_ci if (dst_data_offset >= test_case.dst_bo_commit_start_offset && 2136e5c31af7Sopenharmony_ci dst_data_offset < test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size && 2137e5c31af7Sopenharmony_ci src_data_offset >= test_case.src_bo_commit_start_offset && 2138e5c31af7Sopenharmony_ci src_data_offset < test_case.src_bo_commit_start_offset + test_case.src_bo_commit_size) 2139e5c31af7Sopenharmony_ci { 2140e5c31af7Sopenharmony_ci const unsigned short expected_short_value = 2141e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)test_case.src_bo_ref_data + src_data_offset); 2142e5c31af7Sopenharmony_ci const unsigned short found_short_value = 2143e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)dst_bo_data_ptr + dst_data_offset); 2144e5c31af7Sopenharmony_ci 2145e5c31af7Sopenharmony_ci if (expected_short_value != found_short_value) 2146e5c31af7Sopenharmony_ci { 2147e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 2148e5c31af7Sopenharmony_ci << "Malformed data found in the copy op's destination BO. " 2149e5c31af7Sopenharmony_ci << "Destination BO id:" << dst_bo_id << " (" 2150e5c31af7Sopenharmony_ci << ((test_case.dst_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2151e5c31af7Sopenharmony_ci << ", commited region: " << test_case.dst_bo_commit_start_offset << ":" 2152e5c31af7Sopenharmony_ci << (test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size) 2153e5c31af7Sopenharmony_ci << ", copy region: " << test_case.dst_bo_start_offset << ":" 2154e5c31af7Sopenharmony_ci << (test_case.dst_bo_start_offset + test_case.n_bytes_to_copy) 2155e5c31af7Sopenharmony_ci << ". Source BO id:" << src_bo_id << " (" 2156e5c31af7Sopenharmony_ci << ((test_case.src_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2157e5c31af7Sopenharmony_ci << ", commited region: " << test_case.src_bo_commit_start_offset << ":" 2158e5c31af7Sopenharmony_ci << (test_case.src_bo_commit_start_offset + test_case.src_bo_commit_size) 2159e5c31af7Sopenharmony_ci << ", copy region: " << test_case.src_bo_start_offset << ":" 2160e5c31af7Sopenharmony_ci << (test_case.src_bo_start_offset + test_case.n_bytes_to_copy) 2161e5c31af7Sopenharmony_ci << ". Expected value of " << expected_short_value << ", found value of " 2162e5c31af7Sopenharmony_ci << found_short_value << " at dst data offset of " << dst_data_offset << "." 2163e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 2164e5c31af7Sopenharmony_ci 2165e5c31af7Sopenharmony_ci result_local = false; 2166e5c31af7Sopenharmony_ci } 2167e5c31af7Sopenharmony_ci } 2168e5c31af7Sopenharmony_ci } 2169e5c31af7Sopenharmony_ci 2170e5c31af7Sopenharmony_ci /* 3. Verify the remaining data in the committed part of the destination buffer object is left intact. */ 2171e5c31af7Sopenharmony_ci const unsigned int commit_region_end_offset = 2172e5c31af7Sopenharmony_ci test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size; 2173e5c31af7Sopenharmony_ci const unsigned int copy_region_end_offset = test_case.dst_bo_start_offset + test_case.n_bytes_to_copy; 2174e5c31af7Sopenharmony_ci 2175e5c31af7Sopenharmony_ci if (commit_region_end_offset > copy_region_end_offset) 2176e5c31af7Sopenharmony_ci { 2177e5c31af7Sopenharmony_ci DE_ASSERT(((commit_region_end_offset - copy_region_end_offset) % sizeof(short)) == 0); 2178e5c31af7Sopenharmony_ci 2179e5c31af7Sopenharmony_ci const unsigned int n_valid_values = 2180e5c31af7Sopenharmony_ci static_cast<unsigned int>((commit_region_end_offset - copy_region_end_offset) / sizeof(short)); 2181e5c31af7Sopenharmony_ci 2182e5c31af7Sopenharmony_ci for (unsigned int n_value = 0; n_value < n_valid_values && result_local; ++n_value) 2183e5c31af7Sopenharmony_ci { 2184e5c31af7Sopenharmony_ci const int dst_data_offset = static_cast<int>(copy_region_end_offset + sizeof(short) * n_value); 2185e5c31af7Sopenharmony_ci 2186e5c31af7Sopenharmony_ci if (dst_data_offset >= test_case.dst_bo_commit_start_offset && 2187e5c31af7Sopenharmony_ci dst_data_offset < test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size) 2188e5c31af7Sopenharmony_ci { 2189e5c31af7Sopenharmony_ci const unsigned short expected_short_value = 2190e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)test_case.dst_bo_ref_data + dst_data_offset); 2191e5c31af7Sopenharmony_ci const unsigned short found_short_value = 2192e5c31af7Sopenharmony_ci *(unsigned short*)((unsigned char*)dst_bo_data_ptr + dst_data_offset); 2193e5c31af7Sopenharmony_ci 2194e5c31af7Sopenharmony_ci if (expected_short_value != found_short_value) 2195e5c31af7Sopenharmony_ci { 2196e5c31af7Sopenharmony_ci m_testCtx.getLog() 2197e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "Malformed data found in the copy op's destination BO, " 2198e5c31af7Sopenharmony_ci "following the region modified by the copy op. " 2199e5c31af7Sopenharmony_ci << "Destination BO id:" << dst_bo_id << " (" 2200e5c31af7Sopenharmony_ci << ((test_case.dst_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2201e5c31af7Sopenharmony_ci << ", commited region: " << test_case.dst_bo_commit_start_offset << ":" 2202e5c31af7Sopenharmony_ci << (test_case.dst_bo_commit_start_offset + test_case.dst_bo_commit_size) 2203e5c31af7Sopenharmony_ci << ", copy region: " << test_case.dst_bo_start_offset << ":" 2204e5c31af7Sopenharmony_ci << (test_case.dst_bo_start_offset + test_case.n_bytes_to_copy) 2205e5c31af7Sopenharmony_ci << ". Source BO id:" << src_bo_id << " (" 2206e5c31af7Sopenharmony_ci << ((test_case.src_bo_is_sparse) ? "sparse buffer)" : "immutable buffer)") 2207e5c31af7Sopenharmony_ci << ", commited region: " << test_case.src_bo_commit_start_offset << ":" 2208e5c31af7Sopenharmony_ci << (test_case.src_bo_commit_start_offset + test_case.src_bo_commit_size) 2209e5c31af7Sopenharmony_ci << ", copy region: " << test_case.src_bo_start_offset << ":" 2210e5c31af7Sopenharmony_ci << (test_case.src_bo_start_offset + test_case.n_bytes_to_copy) << ". Expected value of " 2211e5c31af7Sopenharmony_ci << expected_short_value << ", found value of " << found_short_value 2212e5c31af7Sopenharmony_ci << " at dst data offset of " << dst_data_offset << "." << tcu::TestLog::EndMessage; 2213e5c31af7Sopenharmony_ci 2214e5c31af7Sopenharmony_ci result_local = false; 2215e5c31af7Sopenharmony_ci } 2216e5c31af7Sopenharmony_ci } 2217e5c31af7Sopenharmony_ci } /* for (all preceding values which should not have been affected by the copy op) */ 2218e5c31af7Sopenharmony_ci } /* if (copy op did not modify the beginning of the destination buffer storage) */ 2219e5c31af7Sopenharmony_ci 2220e5c31af7Sopenharmony_ci /* Unmap the buffer storage */ 2221e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_WRITE_BUFFER); 2222e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 2223e5c31af7Sopenharmony_ci 2224e5c31af7Sopenharmony_ci /* Clean up */ 2225e5c31af7Sopenharmony_ci for (unsigned int n_sparse_bo = 0; n_sparse_bo < sizeof(m_sparse_bos) / sizeof(m_sparse_bos[0]); ++n_sparse_bo) 2226e5c31af7Sopenharmony_ci { 2227e5c31af7Sopenharmony_ci const bool is_dst_bo = (dst_bo_id == m_sparse_bos[n_sparse_bo]); 2228e5c31af7Sopenharmony_ci const bool is_src_bo = (src_bo_id == m_sparse_bos[n_sparse_bo]); 2229e5c31af7Sopenharmony_ci 2230e5c31af7Sopenharmony_ci if (is_dst_bo || is_src_bo) 2231e5c31af7Sopenharmony_ci { 2232e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bos[n_sparse_bo]); 2233e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2234e5c31af7Sopenharmony_ci 2235e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 2236e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2237e5c31af7Sopenharmony_ci } 2238e5c31af7Sopenharmony_ci } 2239e5c31af7Sopenharmony_ci 2240e5c31af7Sopenharmony_ci result &= result_local; 2241e5c31af7Sopenharmony_ci } /* for (all test cases) */ 2242e5c31af7Sopenharmony_ci 2243e5c31af7Sopenharmony_ci return result; 2244e5c31af7Sopenharmony_ci} 2245e5c31af7Sopenharmony_ci 2246e5c31af7Sopenharmony_ci/** Allocates reference buffers, fills them with data and updates the m_ref_data array. */ 2247e5c31af7Sopenharmony_civoid CopyOpsBufferStorageTestCase::initReferenceData() 2248e5c31af7Sopenharmony_ci{ 2249e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo_size_rounded != 0); 2250e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size_rounded % 2) == 0); 2251e5c31af7Sopenharmony_ci DE_ASSERT(sizeof(short) == 2); 2252e5c31af7Sopenharmony_ci 2253e5c31af7Sopenharmony_ci for (unsigned int n_ref_data_buffer = 0; n_ref_data_buffer < sizeof(m_ref_data) / sizeof(m_ref_data[0]); 2254e5c31af7Sopenharmony_ci ++n_ref_data_buffer) 2255e5c31af7Sopenharmony_ci { 2256e5c31af7Sopenharmony_ci DE_ASSERT(m_ref_data[n_ref_data_buffer] == DE_NULL); 2257e5c31af7Sopenharmony_ci 2258e5c31af7Sopenharmony_ci m_ref_data[n_ref_data_buffer] = new unsigned short[m_sparse_bo_size_rounded / 2]; 2259e5c31af7Sopenharmony_ci 2260e5c31af7Sopenharmony_ci /* Write reference values. */ 2261e5c31af7Sopenharmony_ci for (unsigned int n_short_value = 0; n_short_value < m_sparse_bo_size_rounded / 2; ++n_short_value) 2262e5c31af7Sopenharmony_ci { 2263e5c31af7Sopenharmony_ci m_ref_data[n_ref_data_buffer][n_short_value] = 2264e5c31af7Sopenharmony_ci (unsigned short)((n_ref_data_buffer + 1) * (n_short_value + 1)); 2265e5c31af7Sopenharmony_ci } 2266e5c31af7Sopenharmony_ci } /* for (all reference data buffers) */ 2267e5c31af7Sopenharmony_ci} 2268e5c31af7Sopenharmony_ci 2269e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 2270e5c31af7Sopenharmony_ci * 2271e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2272e5c31af7Sopenharmony_ci */ 2273e5c31af7Sopenharmony_cibool CopyOpsBufferStorageTestCase::initTestCaseGlobal() 2274e5c31af7Sopenharmony_ci{ 2275e5c31af7Sopenharmony_ci m_sparse_bo_size = 2 * 3 * 4 * m_page_size; 2276e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 2277e5c31af7Sopenharmony_ci 2278e5c31af7Sopenharmony_ci initReferenceData(); 2279e5c31af7Sopenharmony_ci 2280e5c31af7Sopenharmony_ci /* Initialize the sparse buffer object */ 2281e5c31af7Sopenharmony_ci m_gl.genBuffers(1, m_sparse_bos + 1); 2282e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 2283e5c31af7Sopenharmony_ci 2284e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bos[1]); 2285e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2286e5c31af7Sopenharmony_ci 2287e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_ARRAY_BUFFER, m_sparse_bo_size_rounded, DE_NULL, /* data */ 2288e5c31af7Sopenharmony_ci GL_SPARSE_STORAGE_BIT_ARB); 2289e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 2290e5c31af7Sopenharmony_ci 2291e5c31af7Sopenharmony_ci /* Initialize the immutable buffer objects used by the test */ 2292e5c31af7Sopenharmony_ci for (unsigned int n_bo = 0; n_bo < 2; /* helper + immutable BO used for the copy ops */ 2293e5c31af7Sopenharmony_ci ++n_bo) 2294e5c31af7Sopenharmony_ci { 2295e5c31af7Sopenharmony_ci glw::GLuint* bo_id_ptr = (n_bo == 0) ? &m_helper_bo : &m_immutable_bo; 2296e5c31af7Sopenharmony_ci glw::GLenum flags = GL_DYNAMIC_STORAGE_BIT; 2297e5c31af7Sopenharmony_ci 2298e5c31af7Sopenharmony_ci if (n_bo == 0) 2299e5c31af7Sopenharmony_ci { 2300e5c31af7Sopenharmony_ci flags |= GL_MAP_READ_BIT; 2301e5c31af7Sopenharmony_ci } 2302e5c31af7Sopenharmony_ci 2303e5c31af7Sopenharmony_ci /* Initialize the immutable buffer object */ 2304e5c31af7Sopenharmony_ci m_gl.genBuffers(1, bo_id_ptr); 2305e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 2306e5c31af7Sopenharmony_ci 2307e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, *bo_id_ptr); 2308e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2309e5c31af7Sopenharmony_ci 2310e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_ARRAY_BUFFER, m_sparse_bo_size_rounded, m_ref_data[0], flags); 2311e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 2312e5c31af7Sopenharmony_ci } 2313e5c31af7Sopenharmony_ci 2314e5c31af7Sopenharmony_ci return true; 2315e5c31af7Sopenharmony_ci} 2316e5c31af7Sopenharmony_ci 2317e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 2318e5c31af7Sopenharmony_ci * 2319e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 2320e5c31af7Sopenharmony_ci * to release these objects. 2321e5c31af7Sopenharmony_ci **/ 2322e5c31af7Sopenharmony_cibool CopyOpsBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 2323e5c31af7Sopenharmony_ci{ 2324e5c31af7Sopenharmony_ci bool result = true; 2325e5c31af7Sopenharmony_ci 2326e5c31af7Sopenharmony_ci /* Remember the BO id */ 2327e5c31af7Sopenharmony_ci m_sparse_bos[0] = sparse_bo; 2328e5c31af7Sopenharmony_ci 2329e5c31af7Sopenharmony_ci /* Initialize test cases, if this is the first call to initTestCaseIteration() */ 2330e5c31af7Sopenharmony_ci if (m_test_cases.size() == 0) 2331e5c31af7Sopenharmony_ci { 2332e5c31af7Sopenharmony_ci initTestCases(); 2333e5c31af7Sopenharmony_ci } 2334e5c31af7Sopenharmony_ci 2335e5c31af7Sopenharmony_ci /* Make sure all pages of the provided sparse BO are de-committed before 2336e5c31af7Sopenharmony_ci * ::execute() is called. */ 2337e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bos[0]); 2338e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2339e5c31af7Sopenharmony_ci 2340e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 2341e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 2342e5c31af7Sopenharmony_ci 2343e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2344e5c31af7Sopenharmony_ci 2345e5c31af7Sopenharmony_ci return result; 2346e5c31af7Sopenharmony_ci} 2347e5c31af7Sopenharmony_ci 2348e5c31af7Sopenharmony_ci/** Fills m_test_cases with test case descriptors. Each such descriptor defines 2349e5c31af7Sopenharmony_ci * a single copy op use case. 2350e5c31af7Sopenharmony_ci * 2351e5c31af7Sopenharmony_ci * The descriptors are then iterated over in ::execute(), defining the testing 2352e5c31af7Sopenharmony_ci * behavior of the test copy ops buffer storage test case. 2353e5c31af7Sopenharmony_ci */ 2354e5c31af7Sopenharmony_civoid CopyOpsBufferStorageTestCase::initTestCases() 2355e5c31af7Sopenharmony_ci{ 2356e5c31af7Sopenharmony_ci /* We need to use the following destination & source BO configurations: 2357e5c31af7Sopenharmony_ci * 2358e5c31af7Sopenharmony_ci * Dst: sparse BO 1; Src: sparse BO 2 2359e5c31af7Sopenharmony_ci * Dst: sparse BO 1; Src: immutable BO 2360e5c31af7Sopenharmony_ci * Dst: immutable BO; Src: sparse BO 1 2361e5c31af7Sopenharmony_ci * Dst: sparse BO 1; Src: sparse BO 1 2362e5c31af7Sopenharmony_ci */ 2363e5c31af7Sopenharmony_ci unsigned int n_test_case = 0; 2364e5c31af7Sopenharmony_ci 2365e5c31af7Sopenharmony_ci for (unsigned int n_bo_configuration = 0; n_bo_configuration < 4; /* as per the comment */ 2366e5c31af7Sopenharmony_ci ++n_bo_configuration, ++n_test_case) 2367e5c31af7Sopenharmony_ci { 2368e5c31af7Sopenharmony_ci glw::GLuint dst_bo_sparse_id = 0; 2369e5c31af7Sopenharmony_ci bool dst_bo_is_sparse = false; 2370e5c31af7Sopenharmony_ci unsigned short* dst_bo_ref_data = DE_NULL; 2371e5c31af7Sopenharmony_ci glw::GLuint src_bo_sparse_id = 0; 2372e5c31af7Sopenharmony_ci bool src_bo_is_sparse = false; 2373e5c31af7Sopenharmony_ci unsigned short* src_bo_ref_data = DE_NULL; 2374e5c31af7Sopenharmony_ci 2375e5c31af7Sopenharmony_ci switch (n_bo_configuration) 2376e5c31af7Sopenharmony_ci { 2377e5c31af7Sopenharmony_ci case 0: 2378e5c31af7Sopenharmony_ci { 2379e5c31af7Sopenharmony_ci dst_bo_sparse_id = 0; 2380e5c31af7Sopenharmony_ci dst_bo_is_sparse = true; 2381e5c31af7Sopenharmony_ci dst_bo_ref_data = m_ref_data[1]; 2382e5c31af7Sopenharmony_ci src_bo_sparse_id = 1; 2383e5c31af7Sopenharmony_ci src_bo_is_sparse = true; 2384e5c31af7Sopenharmony_ci src_bo_ref_data = m_ref_data[2]; 2385e5c31af7Sopenharmony_ci 2386e5c31af7Sopenharmony_ci break; 2387e5c31af7Sopenharmony_ci } 2388e5c31af7Sopenharmony_ci 2389e5c31af7Sopenharmony_ci case 1: 2390e5c31af7Sopenharmony_ci { 2391e5c31af7Sopenharmony_ci dst_bo_sparse_id = 0; 2392e5c31af7Sopenharmony_ci dst_bo_is_sparse = true; 2393e5c31af7Sopenharmony_ci dst_bo_ref_data = m_ref_data[1]; 2394e5c31af7Sopenharmony_ci src_bo_is_sparse = false; 2395e5c31af7Sopenharmony_ci src_bo_ref_data = m_ref_data[0]; 2396e5c31af7Sopenharmony_ci 2397e5c31af7Sopenharmony_ci break; 2398e5c31af7Sopenharmony_ci } 2399e5c31af7Sopenharmony_ci 2400e5c31af7Sopenharmony_ci case 2: 2401e5c31af7Sopenharmony_ci { 2402e5c31af7Sopenharmony_ci dst_bo_is_sparse = false; 2403e5c31af7Sopenharmony_ci dst_bo_ref_data = m_ref_data[0]; 2404e5c31af7Sopenharmony_ci src_bo_sparse_id = 0; 2405e5c31af7Sopenharmony_ci src_bo_is_sparse = true; 2406e5c31af7Sopenharmony_ci src_bo_ref_data = m_ref_data[1]; 2407e5c31af7Sopenharmony_ci 2408e5c31af7Sopenharmony_ci break; 2409e5c31af7Sopenharmony_ci } 2410e5c31af7Sopenharmony_ci 2411e5c31af7Sopenharmony_ci case 3: 2412e5c31af7Sopenharmony_ci { 2413e5c31af7Sopenharmony_ci dst_bo_sparse_id = 0; 2414e5c31af7Sopenharmony_ci dst_bo_is_sparse = true; 2415e5c31af7Sopenharmony_ci dst_bo_ref_data = m_ref_data[1]; 2416e5c31af7Sopenharmony_ci src_bo_sparse_id = 0; 2417e5c31af7Sopenharmony_ci src_bo_is_sparse = true; 2418e5c31af7Sopenharmony_ci src_bo_ref_data = m_ref_data[1]; 2419e5c31af7Sopenharmony_ci 2420e5c31af7Sopenharmony_ci break; 2421e5c31af7Sopenharmony_ci } 2422e5c31af7Sopenharmony_ci 2423e5c31af7Sopenharmony_ci default: 2424e5c31af7Sopenharmony_ci { 2425e5c31af7Sopenharmony_ci TCU_FAIL("Invalid BO configuration index"); 2426e5c31af7Sopenharmony_ci } 2427e5c31af7Sopenharmony_ci } /* switch (n_bo_configuration) */ 2428e5c31af7Sopenharmony_ci 2429e5c31af7Sopenharmony_ci /* Need to test the copy operation in three different scenarios, 2430e5c31af7Sopenharmony_ci * in regard to the destination buffer: 2431e5c31af7Sopenharmony_ci * 2432e5c31af7Sopenharmony_ci * a) All pages of the destination region are committed. 2433e5c31af7Sopenharmony_ci * b) Half of the pages of the destination region are committed. 2434e5c31af7Sopenharmony_ci * c) None of the pages of the destination region are committed. 2435e5c31af7Sopenharmony_ci * 2436e5c31af7Sopenharmony_ci * Destination region spans from 0 to half of the memory we use 2437e5c31af7Sopenharmony_ci * for the testing purposes. 2438e5c31af7Sopenharmony_ci */ 2439e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size_rounded % m_page_size) == 0); 2440e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size_rounded % 2) == 0); 2441e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size_rounded % 4) == 0); 2442e5c31af7Sopenharmony_ci 2443e5c31af7Sopenharmony_ci for (unsigned int n_dst_region = 0; n_dst_region < 3; /* as per the comment */ 2444e5c31af7Sopenharmony_ci ++n_dst_region) 2445e5c31af7Sopenharmony_ci { 2446e5c31af7Sopenharmony_ci glw::GLuint dst_bo_commit_size = 0; 2447e5c31af7Sopenharmony_ci glw::GLuint dst_bo_commit_start_offset = 0; 2448e5c31af7Sopenharmony_ci 2449e5c31af7Sopenharmony_ci switch (n_dst_region) 2450e5c31af7Sopenharmony_ci { 2451e5c31af7Sopenharmony_ci case 0: 2452e5c31af7Sopenharmony_ci { 2453e5c31af7Sopenharmony_ci dst_bo_commit_start_offset = 0; 2454e5c31af7Sopenharmony_ci dst_bo_commit_size = m_sparse_bo_size_rounded / 2; 2455e5c31af7Sopenharmony_ci 2456e5c31af7Sopenharmony_ci break; 2457e5c31af7Sopenharmony_ci } 2458e5c31af7Sopenharmony_ci 2459e5c31af7Sopenharmony_ci case 1: 2460e5c31af7Sopenharmony_ci { 2461e5c31af7Sopenharmony_ci dst_bo_commit_start_offset = m_sparse_bo_size_rounded / 4; 2462e5c31af7Sopenharmony_ci dst_bo_commit_size = m_sparse_bo_size_rounded / 4; 2463e5c31af7Sopenharmony_ci 2464e5c31af7Sopenharmony_ci break; 2465e5c31af7Sopenharmony_ci } 2466e5c31af7Sopenharmony_ci 2467e5c31af7Sopenharmony_ci case 2: 2468e5c31af7Sopenharmony_ci { 2469e5c31af7Sopenharmony_ci dst_bo_commit_start_offset = 0; 2470e5c31af7Sopenharmony_ci dst_bo_commit_size = 0; 2471e5c31af7Sopenharmony_ci 2472e5c31af7Sopenharmony_ci break; 2473e5c31af7Sopenharmony_ci } 2474e5c31af7Sopenharmony_ci 2475e5c31af7Sopenharmony_ci default: 2476e5c31af7Sopenharmony_ci { 2477e5c31af7Sopenharmony_ci TCU_FAIL("Invalid destination region configuration index"); 2478e5c31af7Sopenharmony_ci } 2479e5c31af7Sopenharmony_ci } /* switch (n_dst_region) */ 2480e5c31af7Sopenharmony_ci 2481e5c31af7Sopenharmony_ci /* Same goes for the source region. 2482e5c31af7Sopenharmony_ci * 2483e5c31af7Sopenharmony_ci * Source region spans from m_sparse_bo_size_rounded / 2 to 2484e5c31af7Sopenharmony_ci * m_sparse_bo_size_rounded. 2485e5c31af7Sopenharmony_ci * 2486e5c31af7Sopenharmony_ci **/ 2487e5c31af7Sopenharmony_ci for (unsigned int n_src_region = 0; n_src_region < 3; /* as per the comment */ 2488e5c31af7Sopenharmony_ci ++n_src_region) 2489e5c31af7Sopenharmony_ci { 2490e5c31af7Sopenharmony_ci glw::GLuint src_bo_commit_size = 0; 2491e5c31af7Sopenharmony_ci glw::GLuint src_bo_commit_start_offset = 0; 2492e5c31af7Sopenharmony_ci 2493e5c31af7Sopenharmony_ci switch (n_src_region) 2494e5c31af7Sopenharmony_ci { 2495e5c31af7Sopenharmony_ci case 0: 2496e5c31af7Sopenharmony_ci { 2497e5c31af7Sopenharmony_ci src_bo_commit_start_offset = m_sparse_bo_size_rounded / 2; 2498e5c31af7Sopenharmony_ci src_bo_commit_size = m_sparse_bo_size_rounded / 2; 2499e5c31af7Sopenharmony_ci 2500e5c31af7Sopenharmony_ci break; 2501e5c31af7Sopenharmony_ci } 2502e5c31af7Sopenharmony_ci 2503e5c31af7Sopenharmony_ci case 1: 2504e5c31af7Sopenharmony_ci { 2505e5c31af7Sopenharmony_ci src_bo_commit_start_offset = 3 * m_sparse_bo_size_rounded / 4; 2506e5c31af7Sopenharmony_ci src_bo_commit_size = m_sparse_bo_size_rounded / 4; 2507e5c31af7Sopenharmony_ci 2508e5c31af7Sopenharmony_ci break; 2509e5c31af7Sopenharmony_ci } 2510e5c31af7Sopenharmony_ci 2511e5c31af7Sopenharmony_ci case 2: 2512e5c31af7Sopenharmony_ci { 2513e5c31af7Sopenharmony_ci src_bo_commit_start_offset = m_sparse_bo_size_rounded / 2; 2514e5c31af7Sopenharmony_ci src_bo_commit_size = 0; 2515e5c31af7Sopenharmony_ci 2516e5c31af7Sopenharmony_ci break; 2517e5c31af7Sopenharmony_ci } 2518e5c31af7Sopenharmony_ci 2519e5c31af7Sopenharmony_ci default: 2520e5c31af7Sopenharmony_ci { 2521e5c31af7Sopenharmony_ci TCU_FAIL("Invalid source region configuration index"); 2522e5c31af7Sopenharmony_ci } 2523e5c31af7Sopenharmony_ci } /* switch (n_src_region) */ 2524e5c31af7Sopenharmony_ci 2525e5c31af7Sopenharmony_ci /* Initialize the test case descriptor */ 2526e5c31af7Sopenharmony_ci _test_case test_case; 2527e5c31af7Sopenharmony_ci 2528e5c31af7Sopenharmony_ci test_case.dst_bo_commit_size = dst_bo_commit_size; 2529e5c31af7Sopenharmony_ci test_case.dst_bo_commit_start_offset = dst_bo_commit_start_offset; 2530e5c31af7Sopenharmony_ci test_case.dst_bo_sparse_id = dst_bo_sparse_id; 2531e5c31af7Sopenharmony_ci test_case.dst_bo_is_sparse = dst_bo_is_sparse; 2532e5c31af7Sopenharmony_ci test_case.dst_bo_ref_data = dst_bo_ref_data; 2533e5c31af7Sopenharmony_ci test_case.dst_bo_start_offset = static_cast<glw::GLint>(sizeof(short) * n_test_case); 2534e5c31af7Sopenharmony_ci test_case.n_bytes_to_copy = static_cast<glw::GLint>( 2535e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded / 2 - test_case.dst_bo_start_offset - sizeof(short) * n_test_case); 2536e5c31af7Sopenharmony_ci test_case.src_bo_commit_size = src_bo_commit_size; 2537e5c31af7Sopenharmony_ci test_case.src_bo_commit_start_offset = src_bo_commit_start_offset; 2538e5c31af7Sopenharmony_ci test_case.src_bo_sparse_id = src_bo_sparse_id; 2539e5c31af7Sopenharmony_ci test_case.src_bo_is_sparse = src_bo_is_sparse; 2540e5c31af7Sopenharmony_ci test_case.src_bo_ref_data = src_bo_ref_data; 2541e5c31af7Sopenharmony_ci test_case.src_bo_start_offset = m_sparse_bo_size_rounded / 2; 2542e5c31af7Sopenharmony_ci 2543e5c31af7Sopenharmony_ci DE_ASSERT(test_case.dst_bo_commit_size >= 0); 2544e5c31af7Sopenharmony_ci DE_ASSERT(test_case.dst_bo_commit_start_offset >= 0); 2545e5c31af7Sopenharmony_ci DE_ASSERT(test_case.dst_bo_ref_data != DE_NULL); 2546e5c31af7Sopenharmony_ci DE_ASSERT(test_case.dst_bo_start_offset >= 0); 2547e5c31af7Sopenharmony_ci DE_ASSERT(test_case.n_bytes_to_copy >= 0); 2548e5c31af7Sopenharmony_ci DE_ASSERT(test_case.src_bo_commit_size >= 0); 2549e5c31af7Sopenharmony_ci DE_ASSERT(test_case.src_bo_commit_start_offset >= 0); 2550e5c31af7Sopenharmony_ci DE_ASSERT(test_case.src_bo_ref_data != DE_NULL); 2551e5c31af7Sopenharmony_ci DE_ASSERT(test_case.src_bo_start_offset >= 0); 2552e5c31af7Sopenharmony_ci 2553e5c31af7Sopenharmony_ci m_test_cases.push_back(test_case); 2554e5c31af7Sopenharmony_ci } /* for (all source region commit configurations) */ 2555e5c31af7Sopenharmony_ci } /* for (all destination region commit configurations) */ 2556e5c31af7Sopenharmony_ci } /* for (all BO configurations which need to be tested) */ 2557e5c31af7Sopenharmony_ci} 2558e5c31af7Sopenharmony_ci 2559e5c31af7Sopenharmony_ci/** Constructor. 2560e5c31af7Sopenharmony_ci * 2561e5c31af7Sopenharmony_ci * @param gl GL entry-points container 2562e5c31af7Sopenharmony_ci * @param testContext CTS test context 2563e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 2564e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 2565e5c31af7Sopenharmony_ci */ 2566e5c31af7Sopenharmony_ciIndirectDispatchBufferStorageTestCase::IndirectDispatchBufferStorageTestCase(const glw::Functions& gl, 2567e5c31af7Sopenharmony_ci tcu::TestContext& testContext, 2568e5c31af7Sopenharmony_ci glw::GLint page_size) 2569e5c31af7Sopenharmony_ci : m_dispatch_draw_call_args_start_offset(-1) 2570e5c31af7Sopenharmony_ci , m_expected_ac_value(0) 2571e5c31af7Sopenharmony_ci , m_gl(gl) 2572e5c31af7Sopenharmony_ci , m_global_wg_size_x(2048) 2573e5c31af7Sopenharmony_ci , m_helper_bo(0) 2574e5c31af7Sopenharmony_ci , m_local_wg_size_x(1023) /* must stay in sync with the local work-groups's size hardcoded in m_po's body! */ 2575e5c31af7Sopenharmony_ci , m_page_size(page_size) 2576e5c31af7Sopenharmony_ci , m_po(0) 2577e5c31af7Sopenharmony_ci , m_sparse_bo(0) 2578e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 2579e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 2580e5c31af7Sopenharmony_ci , m_testCtx(testContext) 2581e5c31af7Sopenharmony_ci{ 2582e5c31af7Sopenharmony_ci /* Left blank intentionally */ 2583e5c31af7Sopenharmony_ci} 2584e5c31af7Sopenharmony_ci 2585e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 2586e5c31af7Sopenharmony_ci * 2587e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2588e5c31af7Sopenharmony_ci */ 2589e5c31af7Sopenharmony_civoid IndirectDispatchBufferStorageTestCase::deinitTestCaseGlobal() 2590e5c31af7Sopenharmony_ci{ 2591e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 2592e5c31af7Sopenharmony_ci { 2593e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 2594e5c31af7Sopenharmony_ci 2595e5c31af7Sopenharmony_ci m_helper_bo = 0; 2596e5c31af7Sopenharmony_ci } 2597e5c31af7Sopenharmony_ci 2598e5c31af7Sopenharmony_ci if (m_po != 0) 2599e5c31af7Sopenharmony_ci { 2600e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 2601e5c31af7Sopenharmony_ci 2602e5c31af7Sopenharmony_ci m_po = 0; 2603e5c31af7Sopenharmony_ci } 2604e5c31af7Sopenharmony_ci} 2605e5c31af7Sopenharmony_ci 2606e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 2607e5c31af7Sopenharmony_civoid IndirectDispatchBufferStorageTestCase::deinitTestCaseIteration() 2608e5c31af7Sopenharmony_ci{ 2609e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 2610e5c31af7Sopenharmony_ci { 2611e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 2612e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2613e5c31af7Sopenharmony_ci 2614e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 2615e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 2616e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2617e5c31af7Sopenharmony_ci 2618e5c31af7Sopenharmony_ci m_sparse_bo = 0; 2619e5c31af7Sopenharmony_ci } 2620e5c31af7Sopenharmony_ci} 2621e5c31af7Sopenharmony_ci 2622e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 2623e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 2624e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 2625e5c31af7Sopenharmony_ci * 2626e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 2627e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 2628e5c31af7Sopenharmony_ci * 2629e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 2630e5c31af7Sopenharmony_ci */ 2631e5c31af7Sopenharmony_cibool IndirectDispatchBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 2632e5c31af7Sopenharmony_ci{ 2633e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 2634e5c31af7Sopenharmony_ci bool result = true; 2635e5c31af7Sopenharmony_ci 2636e5c31af7Sopenharmony_ci /* Set up the buffer bindings */ 2637e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_helper_bo); 2638e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_sparse_bo); 2639e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed"); 2640e5c31af7Sopenharmony_ci 2641e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, /* index */ 2642e5c31af7Sopenharmony_ci m_helper_bo, 12, /* offset */ 2643e5c31af7Sopenharmony_ci 4); /* size */ 2644e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferRange() call failed."); 2645e5c31af7Sopenharmony_ci 2646e5c31af7Sopenharmony_ci /* Bind the compute program */ 2647e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 2648e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 2649e5c31af7Sopenharmony_ci 2650e5c31af7Sopenharmony_ci /* Zero out atomic counter value. */ 2651e5c31af7Sopenharmony_ci const unsigned int zero_ac_value = 0; 2652e5c31af7Sopenharmony_ci 2653e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 12, /* offset */ 2654e5c31af7Sopenharmony_ci 4, /* size */ 2655e5c31af7Sopenharmony_ci &zero_ac_value); 2656e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 2657e5c31af7Sopenharmony_ci 2658e5c31af7Sopenharmony_ci m_expected_ac_value = zero_ac_value; 2659e5c31af7Sopenharmony_ci 2660e5c31af7Sopenharmony_ci /* Run the test only in a configuration where all arguments are local in 2661e5c31af7Sopenharmony_ci * committed memory page(s): reading arguments from uncommitted pages means 2662e5c31af7Sopenharmony_ci * reading undefined data, which can result in huge dispatches that 2663e5c31af7Sopenharmony_ci * effectively hang the test. 2664e5c31af7Sopenharmony_ci */ 2665e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_DISPATCH_INDIRECT_BUFFER, 0, /* offset */ 2666e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 2667e5c31af7Sopenharmony_ci 2668e5c31af7Sopenharmony_ci m_expected_ac_value += m_global_wg_size_x * m_local_wg_size_x; 2669e5c31af7Sopenharmony_ci 2670e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call(s) failed."); 2671e5c31af7Sopenharmony_ci 2672e5c31af7Sopenharmony_ci /* Copy the indirect dispatch call args data from the helper BO to the sparse BO */ 2673e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 2674e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bo); 2675e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2676e5c31af7Sopenharmony_ci 2677e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 2678e5c31af7Sopenharmony_ci m_dispatch_draw_call_args_start_offset, sizeof(unsigned int) * 3); 2679e5c31af7Sopenharmony_ci 2680e5c31af7Sopenharmony_ci /* Run the program */ 2681e5c31af7Sopenharmony_ci m_gl.dispatchComputeIndirect(m_dispatch_draw_call_args_start_offset); 2682e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDispatchComputeIndirect() call failed."); 2683e5c31af7Sopenharmony_ci 2684e5c31af7Sopenharmony_ci /* Extract the AC value and verify it */ 2685e5c31af7Sopenharmony_ci const unsigned int* ac_data_ptr = 2686e5c31af7Sopenharmony_ci (const unsigned int*)m_gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 12, /* offset */ 2687e5c31af7Sopenharmony_ci 4, /* length */ 2688e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 2689e5c31af7Sopenharmony_ci 2690e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 2691e5c31af7Sopenharmony_ci 2692e5c31af7Sopenharmony_ci if (*ac_data_ptr != m_expected_ac_value && result) 2693e5c31af7Sopenharmony_ci { 2694e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid atomic counter value encountered. " 2695e5c31af7Sopenharmony_ci "Expected value: [" 2696e5c31af7Sopenharmony_ci << m_expected_ac_value << "]" 2697e5c31af7Sopenharmony_ci ", found:" 2698e5c31af7Sopenharmony_ci "[" 2699e5c31af7Sopenharmony_ci << *ac_data_ptr << "]." << tcu::TestLog::EndMessage; 2700e5c31af7Sopenharmony_ci 2701e5c31af7Sopenharmony_ci result = false; 2702e5c31af7Sopenharmony_ci } 2703e5c31af7Sopenharmony_ci 2704e5c31af7Sopenharmony_ci /* Unmap the buffer before we move on with the next iteration */ 2705e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 2706e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 2707e5c31af7Sopenharmony_ci 2708e5c31af7Sopenharmony_ci return result; 2709e5c31af7Sopenharmony_ci} 2710e5c31af7Sopenharmony_ci 2711e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 2712e5c31af7Sopenharmony_ci * 2713e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2714e5c31af7Sopenharmony_ci */ 2715e5c31af7Sopenharmony_cibool IndirectDispatchBufferStorageTestCase::initTestCaseGlobal() 2716e5c31af7Sopenharmony_ci{ 2717e5c31af7Sopenharmony_ci bool result = true; 2718e5c31af7Sopenharmony_ci 2719e5c31af7Sopenharmony_ci /* One of the cases the test case implementation needs to support is the scenario 2720e5c31af7Sopenharmony_ci * where the indirect call arguments are located on the boundary of two (or more) memory pages, 2721e5c31af7Sopenharmony_ci * and some of the pages are not committed. 2722e5c31af7Sopenharmony_ci * 2723e5c31af7Sopenharmony_ci * There are two scenarios which can happen: 2724e5c31af7Sopenharmony_ci * 2725e5c31af7Sopenharmony_ci * a) page size >= sizeof(uint) * 3: Allocate two pages, arg start offset: (page_size - 4) aligned to 4. 2726e5c31af7Sopenharmony_ci * The alignment is a must, since we'll be feeding the offset to an indirect dispatch call. 2727e5c31af7Sopenharmony_ci * b) page size < sizeof(uint) * 3: Allocate as many pages as needed, disable some of the pages. 2728e5c31af7Sopenharmony_ci * 2729e5c31af7Sopenharmony_ci * For code clarity, the two cases are handled by separate branches, although they could be easily 2730e5c31af7Sopenharmony_ci * merged. 2731e5c31af7Sopenharmony_ci */ 2732e5c31af7Sopenharmony_ci const int n_indirect_dispatch_call_arg_bytes = sizeof(unsigned int) * 3; 2733e5c31af7Sopenharmony_ci 2734e5c31af7Sopenharmony_ci if (m_page_size >= n_indirect_dispatch_call_arg_bytes) 2735e5c31af7Sopenharmony_ci { 2736e5c31af7Sopenharmony_ci /* Indirect dispatch call args must be aligned to 4 */ 2737e5c31af7Sopenharmony_ci DE_ASSERT(m_page_size >= 4); 2738e5c31af7Sopenharmony_ci 2739e5c31af7Sopenharmony_ci m_dispatch_draw_call_args_start_offset = SparseBufferTestUtilities::alignOffset(m_page_size - 4, 4); 2740e5c31af7Sopenharmony_ci m_sparse_bo_size = m_dispatch_draw_call_args_start_offset + n_indirect_dispatch_call_arg_bytes; 2741e5c31af7Sopenharmony_ci } 2742e5c31af7Sopenharmony_ci else 2743e5c31af7Sopenharmony_ci { 2744e5c31af7Sopenharmony_ci m_dispatch_draw_call_args_start_offset = 0; 2745e5c31af7Sopenharmony_ci m_sparse_bo_size = n_indirect_dispatch_call_arg_bytes; 2746e5c31af7Sopenharmony_ci } 2747e5c31af7Sopenharmony_ci 2748e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 2749e5c31af7Sopenharmony_ci 2750e5c31af7Sopenharmony_ci /* Set up the helper buffer object. Its structure is as follows: 2751e5c31af7Sopenharmony_ci * 2752e5c31af7Sopenharmony_ci * [ 0-11]: Indirect dispatch call args 2753e5c31af7Sopenharmony_ci * [12-15]: Atomic counter value storage 2754e5c31af7Sopenharmony_ci */ 2755e5c31af7Sopenharmony_ci unsigned int helper_bo_data[4] = { 0 }; 2756e5c31af7Sopenharmony_ci const unsigned int n_helper_bo_bytes = sizeof(helper_bo_data); 2757e5c31af7Sopenharmony_ci 2758e5c31af7Sopenharmony_ci helper_bo_data[0] = m_global_wg_size_x; /* num_groups_x */ 2759e5c31af7Sopenharmony_ci helper_bo_data[1] = 1; /* num_groups_y */ 2760e5c31af7Sopenharmony_ci helper_bo_data[2] = 1; /* num_groups_z */ 2761e5c31af7Sopenharmony_ci helper_bo_data[3] = 0; /* default atomic counter value */ 2762e5c31af7Sopenharmony_ci 2763e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 2764e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 2765e5c31af7Sopenharmony_ci 2766e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_helper_bo); 2767e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2768e5c31af7Sopenharmony_ci 2769e5c31af7Sopenharmony_ci m_gl.bufferData(GL_ARRAY_BUFFER, n_helper_bo_bytes, helper_bo_data, GL_STATIC_DRAW); 2770e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData() call failed."); 2771e5c31af7Sopenharmony_ci 2772e5c31af7Sopenharmony_ci /* Set up the test compute program object */ 2773e5c31af7Sopenharmony_ci static const char* cs_body = "#version 430 core\n" 2774e5c31af7Sopenharmony_ci "\n" 2775e5c31af7Sopenharmony_ci "layout(local_size_x = 1023) in;\n" 2776e5c31af7Sopenharmony_ci "layout(binding = 0, offset = 0) uniform atomic_uint ac;\n" 2777e5c31af7Sopenharmony_ci "\n" 2778e5c31af7Sopenharmony_ci "void main()\n" 2779e5c31af7Sopenharmony_ci "{\n" 2780e5c31af7Sopenharmony_ci " atomicCounterIncrement(ac);\n" 2781e5c31af7Sopenharmony_ci "}\n"; 2782e5c31af7Sopenharmony_ci 2783e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createComputeProgram(m_gl, &cs_body, 1); /* n_cs_body_parts */ 2784e5c31af7Sopenharmony_ci 2785e5c31af7Sopenharmony_ci result = (m_po != 0); 2786e5c31af7Sopenharmony_ci 2787e5c31af7Sopenharmony_ci return result; 2788e5c31af7Sopenharmony_ci} 2789e5c31af7Sopenharmony_ci 2790e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 2791e5c31af7Sopenharmony_ci * 2792e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 2793e5c31af7Sopenharmony_ci * to release these objects. 2794e5c31af7Sopenharmony_ci **/ 2795e5c31af7Sopenharmony_cibool IndirectDispatchBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 2796e5c31af7Sopenharmony_ci{ 2797e5c31af7Sopenharmony_ci bool result = true; 2798e5c31af7Sopenharmony_ci 2799e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 2800e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 2801e5c31af7Sopenharmony_ci 2802e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 2803e5c31af7Sopenharmony_ci 2804e5c31af7Sopenharmony_ci /* Set up the sparse bufffer. */ 2805e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 2806e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2807e5c31af7Sopenharmony_ci 2808e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 2809e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 2810e5c31af7Sopenharmony_ci 2811e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2812e5c31af7Sopenharmony_ci 2813e5c31af7Sopenharmony_ci return result; 2814e5c31af7Sopenharmony_ci} 2815e5c31af7Sopenharmony_ci 2816e5c31af7Sopenharmony_ci/** Constructor. 2817e5c31af7Sopenharmony_ci * 2818e5c31af7Sopenharmony_ci * @param gl GL entry-points container 2819e5c31af7Sopenharmony_ci * @param testContext CTS test context 2820e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 2821e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 2822e5c31af7Sopenharmony_ci */ 2823e5c31af7Sopenharmony_ciInvalidateBufferStorageTestCase::InvalidateBufferStorageTestCase(const glw::Functions& gl, 2824e5c31af7Sopenharmony_ci tcu::TestContext& testContext, glw::GLint page_size) 2825e5c31af7Sopenharmony_ci : m_gl(gl) 2826e5c31af7Sopenharmony_ci , m_n_pages_to_use(4) 2827e5c31af7Sopenharmony_ci , m_page_size(page_size) 2828e5c31af7Sopenharmony_ci , m_sparse_bo(0) 2829e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 2830e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 2831e5c31af7Sopenharmony_ci{ 2832e5c31af7Sopenharmony_ci (void)testContext; 2833e5c31af7Sopenharmony_ci DE_ASSERT((m_n_pages_to_use % 2) == 0); 2834e5c31af7Sopenharmony_ci} 2835e5c31af7Sopenharmony_ci 2836e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 2837e5c31af7Sopenharmony_ci * 2838e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2839e5c31af7Sopenharmony_ci */ 2840e5c31af7Sopenharmony_civoid InvalidateBufferStorageTestCase::deinitTestCaseGlobal() 2841e5c31af7Sopenharmony_ci{ 2842e5c31af7Sopenharmony_ci /* Stub */ 2843e5c31af7Sopenharmony_ci} 2844e5c31af7Sopenharmony_ci 2845e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 2846e5c31af7Sopenharmony_civoid InvalidateBufferStorageTestCase::deinitTestCaseIteration() 2847e5c31af7Sopenharmony_ci{ 2848e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 2849e5c31af7Sopenharmony_ci { 2850e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 2851e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2852e5c31af7Sopenharmony_ci 2853e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 2854e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 2855e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2856e5c31af7Sopenharmony_ci 2857e5c31af7Sopenharmony_ci m_sparse_bo = 0; 2858e5c31af7Sopenharmony_ci } 2859e5c31af7Sopenharmony_ci} 2860e5c31af7Sopenharmony_ci 2861e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 2862e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 2863e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 2864e5c31af7Sopenharmony_ci * 2865e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 2866e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 2867e5c31af7Sopenharmony_ci * 2868e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 2869e5c31af7Sopenharmony_ci */ 2870e5c31af7Sopenharmony_cibool InvalidateBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 2871e5c31af7Sopenharmony_ci{ 2872e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 2873e5c31af7Sopenharmony_ci bool result = true; 2874e5c31af7Sopenharmony_ci 2875e5c31af7Sopenharmony_ci /* Since we cannot really perform any validation related to whether buffer 2876e5c31af7Sopenharmony_ci * storage invalidation works corectly, all this test can really do is to verify 2877e5c31af7Sopenharmony_ci * if the implementation does not crash when both entry-points are used against 2878e5c31af7Sopenharmony_ci * a sparse buffer object. 2879e5c31af7Sopenharmony_ci */ 2880e5c31af7Sopenharmony_ci for (unsigned int n_entry_point = 0; n_entry_point < 2; /* glInvalidateBuffer(), glInvalidateBufferSubData() */ 2881e5c31af7Sopenharmony_ci ++n_entry_point) 2882e5c31af7Sopenharmony_ci { 2883e5c31af7Sopenharmony_ci const bool should_test_invalidate_buffer = (n_entry_point == 0); 2884e5c31af7Sopenharmony_ci 2885e5c31af7Sopenharmony_ci /* For glInvalidateBufferSubData(), we need to test two different ranges. */ 2886e5c31af7Sopenharmony_ci for (int n_iteration = 0; n_iteration < ((should_test_invalidate_buffer) ? 1 : 2); ++n_iteration) 2887e5c31af7Sopenharmony_ci { 2888e5c31af7Sopenharmony_ci if (should_test_invalidate_buffer) 2889e5c31af7Sopenharmony_ci { 2890e5c31af7Sopenharmony_ci m_gl.invalidateBufferData(m_sparse_bo); 2891e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glInvalidateBufferData() call failed."); 2892e5c31af7Sopenharmony_ci } 2893e5c31af7Sopenharmony_ci else 2894e5c31af7Sopenharmony_ci { 2895e5c31af7Sopenharmony_ci m_gl.invalidateBufferSubData(m_sparse_bo, 0, /* offset */ 2896e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded * ((n_iteration == 0) ? 1 : 2)); 2897e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glInvalidateBufferSubData() call failed."); 2898e5c31af7Sopenharmony_ci } 2899e5c31af7Sopenharmony_ci } /* for (all iterations) */ 2900e5c31af7Sopenharmony_ci } /* for (both entry-points) */ 2901e5c31af7Sopenharmony_ci 2902e5c31af7Sopenharmony_ci return result; 2903e5c31af7Sopenharmony_ci} 2904e5c31af7Sopenharmony_ci 2905e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 2906e5c31af7Sopenharmony_ci * 2907e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2908e5c31af7Sopenharmony_ci */ 2909e5c31af7Sopenharmony_cibool InvalidateBufferStorageTestCase::initTestCaseGlobal() 2910e5c31af7Sopenharmony_ci{ 2911e5c31af7Sopenharmony_ci const unsigned int n_bytes_needed = m_n_pages_to_use * m_page_size; 2912e5c31af7Sopenharmony_ci 2913e5c31af7Sopenharmony_ci /* Determine the number of bytes both the helper and the sparse buffer 2914e5c31af7Sopenharmony_ci * object need to be able to hold, at maximum */ 2915e5c31af7Sopenharmony_ci m_sparse_bo_size = n_bytes_needed; 2916e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(n_bytes_needed, m_page_size); 2917e5c31af7Sopenharmony_ci 2918e5c31af7Sopenharmony_ci return true; 2919e5c31af7Sopenharmony_ci} 2920e5c31af7Sopenharmony_ci 2921e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 2922e5c31af7Sopenharmony_ci * 2923e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 2924e5c31af7Sopenharmony_ci * to release these objects. 2925e5c31af7Sopenharmony_ci **/ 2926e5c31af7Sopenharmony_cibool InvalidateBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 2927e5c31af7Sopenharmony_ci{ 2928e5c31af7Sopenharmony_ci bool result = true; 2929e5c31af7Sopenharmony_ci 2930e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 2931e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 2932e5c31af7Sopenharmony_ci 2933e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 2934e5c31af7Sopenharmony_ci 2935e5c31af7Sopenharmony_ci /* Set up the sparse bufffer. */ 2936e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 2937e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 2938e5c31af7Sopenharmony_ci 2939e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 2940e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 2941e5c31af7Sopenharmony_ci 2942e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 2943e5c31af7Sopenharmony_ci 2944e5c31af7Sopenharmony_ci return result; 2945e5c31af7Sopenharmony_ci} 2946e5c31af7Sopenharmony_ci 2947e5c31af7Sopenharmony_ci/** Constructor. 2948e5c31af7Sopenharmony_ci * 2949e5c31af7Sopenharmony_ci * @param gl GL entry-points container 2950e5c31af7Sopenharmony_ci * @param testContext CTS test context 2951e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 2952e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 2953e5c31af7Sopenharmony_ci */ 2954e5c31af7Sopenharmony_ciPixelPackBufferStorageTestCase::PixelPackBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 2955e5c31af7Sopenharmony_ci glw::GLint page_size) 2956e5c31af7Sopenharmony_ci : m_color_rb(0) 2957e5c31af7Sopenharmony_ci , m_color_rb_height(1024) 2958e5c31af7Sopenharmony_ci , m_color_rb_width(1024) 2959e5c31af7Sopenharmony_ci , m_fbo(0) 2960e5c31af7Sopenharmony_ci , m_gl(gl) 2961e5c31af7Sopenharmony_ci , m_helper_bo(0) 2962e5c31af7Sopenharmony_ci , m_page_size(page_size) 2963e5c31af7Sopenharmony_ci , m_po(0) 2964e5c31af7Sopenharmony_ci , m_ref_data_ptr(DE_NULL) 2965e5c31af7Sopenharmony_ci , m_ref_data_size(0) 2966e5c31af7Sopenharmony_ci , m_sparse_bo(0) 2967e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 2968e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 2969e5c31af7Sopenharmony_ci , m_testCtx(testContext) 2970e5c31af7Sopenharmony_ci , m_vao(0) 2971e5c31af7Sopenharmony_ci{ 2972e5c31af7Sopenharmony_ci m_ref_data_size = m_color_rb_width * m_color_rb_height * 4; /* rgba */ 2973e5c31af7Sopenharmony_ci} 2974e5c31af7Sopenharmony_ci 2975e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 2976e5c31af7Sopenharmony_ci * 2977e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 2978e5c31af7Sopenharmony_ci */ 2979e5c31af7Sopenharmony_civoid PixelPackBufferStorageTestCase::deinitTestCaseGlobal() 2980e5c31af7Sopenharmony_ci{ 2981e5c31af7Sopenharmony_ci if (m_color_rb != 0) 2982e5c31af7Sopenharmony_ci { 2983e5c31af7Sopenharmony_ci m_gl.deleteRenderbuffers(1, &m_color_rb); 2984e5c31af7Sopenharmony_ci 2985e5c31af7Sopenharmony_ci m_color_rb = 0; 2986e5c31af7Sopenharmony_ci } 2987e5c31af7Sopenharmony_ci 2988e5c31af7Sopenharmony_ci if (m_fbo != 0) 2989e5c31af7Sopenharmony_ci { 2990e5c31af7Sopenharmony_ci m_gl.deleteFramebuffers(1, &m_fbo); 2991e5c31af7Sopenharmony_ci 2992e5c31af7Sopenharmony_ci m_fbo = 0; 2993e5c31af7Sopenharmony_ci } 2994e5c31af7Sopenharmony_ci 2995e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 2996e5c31af7Sopenharmony_ci { 2997e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 2998e5c31af7Sopenharmony_ci 2999e5c31af7Sopenharmony_ci m_helper_bo = 0; 3000e5c31af7Sopenharmony_ci } 3001e5c31af7Sopenharmony_ci 3002e5c31af7Sopenharmony_ci if (m_ref_data_ptr != DE_NULL) 3003e5c31af7Sopenharmony_ci { 3004e5c31af7Sopenharmony_ci delete[] m_ref_data_ptr; 3005e5c31af7Sopenharmony_ci 3006e5c31af7Sopenharmony_ci m_ref_data_ptr = DE_NULL; 3007e5c31af7Sopenharmony_ci } 3008e5c31af7Sopenharmony_ci 3009e5c31af7Sopenharmony_ci if (m_po != 0) 3010e5c31af7Sopenharmony_ci { 3011e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 3012e5c31af7Sopenharmony_ci 3013e5c31af7Sopenharmony_ci m_po = 0; 3014e5c31af7Sopenharmony_ci } 3015e5c31af7Sopenharmony_ci 3016e5c31af7Sopenharmony_ci if (m_vao != 0) 3017e5c31af7Sopenharmony_ci { 3018e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 3019e5c31af7Sopenharmony_ci 3020e5c31af7Sopenharmony_ci m_vao = 0; 3021e5c31af7Sopenharmony_ci } 3022e5c31af7Sopenharmony_ci} 3023e5c31af7Sopenharmony_ci 3024e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 3025e5c31af7Sopenharmony_civoid PixelPackBufferStorageTestCase::deinitTestCaseIteration() 3026e5c31af7Sopenharmony_ci{ 3027e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 3028e5c31af7Sopenharmony_ci { 3029e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 3030e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3031e5c31af7Sopenharmony_ci 3032e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 3033e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 3034e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3035e5c31af7Sopenharmony_ci 3036e5c31af7Sopenharmony_ci m_sparse_bo = 0; 3037e5c31af7Sopenharmony_ci } 3038e5c31af7Sopenharmony_ci} 3039e5c31af7Sopenharmony_ci 3040e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 3041e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 3042e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 3043e5c31af7Sopenharmony_ci * 3044e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 3045e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 3046e5c31af7Sopenharmony_ci * 3047e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 3048e5c31af7Sopenharmony_ci */ 3049e5c31af7Sopenharmony_cibool PixelPackBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 3050e5c31af7Sopenharmony_ci{ 3051e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 3052e5c31af7Sopenharmony_ci bool result = true; 3053e5c31af7Sopenharmony_ci 3054e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 3055e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_PACK_BUFFER, m_sparse_bo); 3056e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 3057e5c31af7Sopenharmony_ci 3058e5c31af7Sopenharmony_ci /* Run three separate iterations: 3059e5c31af7Sopenharmony_ci * 3060e5c31af7Sopenharmony_ci * a) All pages that are going to hold the texture data are committed. 3061e5c31af7Sopenharmony_ci * b) Use a zig-zag memory page commitment layout patern. 3062e5c31af7Sopenharmony_ci * b) No pages are committed. 3063e5c31af7Sopenharmony_ci */ 3064e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 3; ++n_iteration) 3065e5c31af7Sopenharmony_ci { 3066e5c31af7Sopenharmony_ci bool result_local = true; 3067e5c31af7Sopenharmony_ci 3068e5c31af7Sopenharmony_ci /* Set up the memory page commitment & the storage contents*/ 3069e5c31af7Sopenharmony_ci switch (n_iteration) 3070e5c31af7Sopenharmony_ci { 3071e5c31af7Sopenharmony_ci case 0: 3072e5c31af7Sopenharmony_ci { 3073e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_PACK_BUFFER, 0, /* offset */ 3074e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 3075e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3076e5c31af7Sopenharmony_ci 3077e5c31af7Sopenharmony_ci break; 3078e5c31af7Sopenharmony_ci } 3079e5c31af7Sopenharmony_ci 3080e5c31af7Sopenharmony_ci case 1: 3081e5c31af7Sopenharmony_ci { 3082e5c31af7Sopenharmony_ci const unsigned int n_pages = 1 + m_ref_data_size / m_page_size; 3083e5c31af7Sopenharmony_ci 3084e5c31af7Sopenharmony_ci DE_ASSERT((m_ref_data_size % m_page_size) == 0); 3085e5c31af7Sopenharmony_ci 3086e5c31af7Sopenharmony_ci for (unsigned int n_page = 0; n_page < n_pages; ++n_page) 3087e5c31af7Sopenharmony_ci { 3088e5c31af7Sopenharmony_ci const bool should_commit = ((n_page % 2) == 0); 3089e5c31af7Sopenharmony_ci 3090e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_PACK_BUFFER, m_page_size * n_page, m_page_size, 3091e5c31af7Sopenharmony_ci should_commit ? GL_TRUE : GL_FALSE); 3092e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3093e5c31af7Sopenharmony_ci } /* for (all relevant memory pages) */ 3094e5c31af7Sopenharmony_ci 3095e5c31af7Sopenharmony_ci break; 3096e5c31af7Sopenharmony_ci } 3097e5c31af7Sopenharmony_ci 3098e5c31af7Sopenharmony_ci case 2: 3099e5c31af7Sopenharmony_ci { 3100e5c31af7Sopenharmony_ci /* Do nothing - all pages already de-committed */ 3101e5c31af7Sopenharmony_ci break; 3102e5c31af7Sopenharmony_ci } 3103e5c31af7Sopenharmony_ci 3104e5c31af7Sopenharmony_ci default: 3105e5c31af7Sopenharmony_ci { 3106e5c31af7Sopenharmony_ci TCU_FAIL("Invalid iteration index"); 3107e5c31af7Sopenharmony_ci } 3108e5c31af7Sopenharmony_ci } /* switch (n_iteration) */ 3109e5c31af7Sopenharmony_ci 3110e5c31af7Sopenharmony_ci /* Draw full screen quad to generate the black-to-white gradient */ 3111e5c31af7Sopenharmony_ci const unsigned char* read_data_ptr = NULL; 3112e5c31af7Sopenharmony_ci 3113e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 3114e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 3115e5c31af7Sopenharmony_ci 3116e5c31af7Sopenharmony_ci m_gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */); 3117e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() call failed."); 3118e5c31af7Sopenharmony_ci 3119e5c31af7Sopenharmony_ci /* Read a framebuffer pixel data */ 3120e5c31af7Sopenharmony_ci m_gl.readPixels(0, /* x */ 3121e5c31af7Sopenharmony_ci 0, /* y */ 3122e5c31af7Sopenharmony_ci m_color_rb_width, m_color_rb_height, GL_RGBA, GL_UNSIGNED_BYTE, 0); /* pixels */ 3123e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glReadPixels() call failed."); 3124e5c31af7Sopenharmony_ci 3125e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_COPY_READ_BUFFER, 0, /* readOffset */ 3126e5c31af7Sopenharmony_ci 0, /* writeOffset */ 3127e5c31af7Sopenharmony_ci m_ref_data_size); 3128e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 3129e5c31af7Sopenharmony_ci 3130e5c31af7Sopenharmony_ci read_data_ptr = (unsigned char*)m_gl.mapBufferRange(GL_COPY_READ_BUFFER, 0, /* offset */ 3131e5c31af7Sopenharmony_ci m_ref_data_size, GL_MAP_READ_BIT); 3132e5c31af7Sopenharmony_ci 3133e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 3134e5c31af7Sopenharmony_ci 3135e5c31af7Sopenharmony_ci /* Verify the data */ 3136e5c31af7Sopenharmony_ci unsigned int n_current_tex_data_byte = 0; 3137e5c31af7Sopenharmony_ci const unsigned char* read_data_traveller_ptr = (const unsigned char*)read_data_ptr; 3138e5c31af7Sopenharmony_ci const unsigned char* reference_data_traveller_ptr = (const unsigned char*)m_ref_data_ptr; 3139e5c31af7Sopenharmony_ci 3140e5c31af7Sopenharmony_ci for (unsigned int y = 0; y < m_color_rb_height && result_local; ++y) 3141e5c31af7Sopenharmony_ci { 3142e5c31af7Sopenharmony_ci for (unsigned int x = 0; x < m_color_rb_width && result_local; ++x) 3143e5c31af7Sopenharmony_ci { 3144e5c31af7Sopenharmony_ci for (unsigned int n_component = 0; n_component < 4 /* rgba */ && result_local; ++n_component) 3145e5c31af7Sopenharmony_ci { 3146e5c31af7Sopenharmony_ci unsigned char expected_value = 0; 3147e5c31af7Sopenharmony_ci bool is_from_committed_page = true; 3148e5c31af7Sopenharmony_ci 3149e5c31af7Sopenharmony_ci if (n_iteration == 1) /* zig-zag */ 3150e5c31af7Sopenharmony_ci { 3151e5c31af7Sopenharmony_ci is_from_committed_page = ((n_current_tex_data_byte / m_page_size) % 2) == 0; 3152e5c31af7Sopenharmony_ci } 3153e5c31af7Sopenharmony_ci else if (n_iteration == 2) /* no pages committed */ 3154e5c31af7Sopenharmony_ci { 3155e5c31af7Sopenharmony_ci is_from_committed_page = false; 3156e5c31af7Sopenharmony_ci } 3157e5c31af7Sopenharmony_ci 3158e5c31af7Sopenharmony_ci if (is_from_committed_page) 3159e5c31af7Sopenharmony_ci { 3160e5c31af7Sopenharmony_ci expected_value = *reference_data_traveller_ptr; 3161e5c31af7Sopenharmony_ci } 3162e5c31af7Sopenharmony_ci 3163e5c31af7Sopenharmony_ci if (is_from_committed_page && de::abs(expected_value - *read_data_traveller_ptr) > 1) 3164e5c31af7Sopenharmony_ci { 3165e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel data (channel:" << n_component 3166e5c31af7Sopenharmony_ci << ")" 3167e5c31af7Sopenharmony_ci " found at X:" 3168e5c31af7Sopenharmony_ci << x << ", " 3169e5c31af7Sopenharmony_ci "Y:" 3170e5c31af7Sopenharmony_ci << y << ")." 3171e5c31af7Sopenharmony_ci " Expected value:" 3172e5c31af7Sopenharmony_ci << expected_value << "," 3173e5c31af7Sopenharmony_ci " found value:" 3174e5c31af7Sopenharmony_ci << *reference_data_traveller_ptr << tcu::TestLog::EndMessage; 3175e5c31af7Sopenharmony_ci 3176e5c31af7Sopenharmony_ci result_local = false; 3177e5c31af7Sopenharmony_ci } 3178e5c31af7Sopenharmony_ci 3179e5c31af7Sopenharmony_ci n_current_tex_data_byte++; 3180e5c31af7Sopenharmony_ci read_data_traveller_ptr++; 3181e5c31af7Sopenharmony_ci reference_data_traveller_ptr++; 3182e5c31af7Sopenharmony_ci } /* for (all components) */ 3183e5c31af7Sopenharmony_ci } /* for (all columns) */ 3184e5c31af7Sopenharmony_ci } /* for (all rows) */ 3185e5c31af7Sopenharmony_ci 3186e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_READ_BUFFER); 3187e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 3188e5c31af7Sopenharmony_ci 3189e5c31af7Sopenharmony_ci read_data_ptr = DE_NULL; 3190e5c31af7Sopenharmony_ci result &= result_local; 3191e5c31af7Sopenharmony_ci 3192e5c31af7Sopenharmony_ci /* Clean up */ 3193e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_PACK_BUFFER, 0, /* offset */ 3194e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 3195e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3196e5c31af7Sopenharmony_ci } /* for (three iterations) */ 3197e5c31af7Sopenharmony_ci 3198e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0); 3199e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3200e5c31af7Sopenharmony_ci 3201e5c31af7Sopenharmony_ci return result; 3202e5c31af7Sopenharmony_ci} 3203e5c31af7Sopenharmony_ci 3204e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 3205e5c31af7Sopenharmony_ci * 3206e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 3207e5c31af7Sopenharmony_ci */ 3208e5c31af7Sopenharmony_cibool PixelPackBufferStorageTestCase::initTestCaseGlobal() 3209e5c31af7Sopenharmony_ci{ 3210e5c31af7Sopenharmony_ci /* Determine vertex shader and fragment shader that will generate black-to-white gradient. */ 3211e5c31af7Sopenharmony_ci const char* gradient_fs_code = "#version 330 core\n" 3212e5c31af7Sopenharmony_ci "\n" 3213e5c31af7Sopenharmony_ci "out vec4 result;\n" 3214e5c31af7Sopenharmony_ci "\n" 3215e5c31af7Sopenharmony_ci "void main()\n" 3216e5c31af7Sopenharmony_ci "{\n" 3217e5c31af7Sopenharmony_ci " float c = 1.0 - (gl_FragCoord.y - 0.5) / 1023.0;\n" 3218e5c31af7Sopenharmony_ci " result = vec4(c);\n" 3219e5c31af7Sopenharmony_ci "}\n"; 3220e5c31af7Sopenharmony_ci 3221e5c31af7Sopenharmony_ci const char* gradient_vs_code = "#version 330\n" 3222e5c31af7Sopenharmony_ci "\n" 3223e5c31af7Sopenharmony_ci "void main()\n" 3224e5c31af7Sopenharmony_ci "{\n" 3225e5c31af7Sopenharmony_ci " switch (gl_VertexID)\n" 3226e5c31af7Sopenharmony_ci " {\n" 3227e5c31af7Sopenharmony_ci " case 0: gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); break;\n" 3228e5c31af7Sopenharmony_ci " case 1: gl_Position = vec4( 1.0, -1.0, 0.0, 1.0); break;\n" 3229e5c31af7Sopenharmony_ci " case 2: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break;\n" 3230e5c31af7Sopenharmony_ci " case 3: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break;\n" 3231e5c31af7Sopenharmony_ci " }\n" 3232e5c31af7Sopenharmony_ci "}\n"; 3233e5c31af7Sopenharmony_ci 3234e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createProgram(m_gl, &gradient_fs_code, 1, /* n_fs_body_parts */ 3235e5c31af7Sopenharmony_ci &gradient_vs_code, 1, /* n_vs_body_parts*/ 3236e5c31af7Sopenharmony_ci NULL, /* attribute_names */ 3237e5c31af7Sopenharmony_ci NULL, /* attribute_locations */ 3238e5c31af7Sopenharmony_ci GL_NONE, /* attribute_properties */ 3239e5c31af7Sopenharmony_ci 0, /* tf_varyings */ 3240e5c31af7Sopenharmony_ci 0, /* n_tf_varyings */ 3241e5c31af7Sopenharmony_ci 0); /* tf_varying_mode */ 3242e5c31af7Sopenharmony_ci if (m_po == 0) 3243e5c31af7Sopenharmony_ci { 3244e5c31af7Sopenharmony_ci TCU_FAIL("Failed to link the test program"); 3245e5c31af7Sopenharmony_ci } 3246e5c31af7Sopenharmony_ci 3247e5c31af7Sopenharmony_ci /* Generate and bind VAO */ 3248e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 3249e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 3250e5c31af7Sopenharmony_ci 3251e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 3252e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 3253e5c31af7Sopenharmony_ci 3254e5c31af7Sopenharmony_ci /* Generate and bind FBO */ 3255e5c31af7Sopenharmony_ci m_gl.genFramebuffers(1, &m_fbo); 3256e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers() call failed."); 3257e5c31af7Sopenharmony_ci 3258e5c31af7Sopenharmony_ci m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 3259e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer() call failed."); 3260e5c31af7Sopenharmony_ci 3261e5c31af7Sopenharmony_ci m_gl.readBuffer(GL_COLOR_ATTACHMENT0); 3262e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glReadBuffer() call failed."); 3263e5c31af7Sopenharmony_ci 3264e5c31af7Sopenharmony_ci /* Generate and bind RBO and attach it to FBO as a color attachment */ 3265e5c31af7Sopenharmony_ci m_gl.genRenderbuffers(1, &m_color_rb); 3266e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenRenderbuffers() call failed."); 3267e5c31af7Sopenharmony_ci 3268e5c31af7Sopenharmony_ci m_gl.bindRenderbuffer(GL_RENDERBUFFER, m_color_rb); 3269e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindRenderbuffer() call failed."); 3270e5c31af7Sopenharmony_ci 3271e5c31af7Sopenharmony_ci m_gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_color_rb_width, m_color_rb_height); 3272e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glRenderbufferStorage() call failed."); 3273e5c31af7Sopenharmony_ci 3274e5c31af7Sopenharmony_ci m_gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_rb); 3275e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferRenderbuffer() call failed."); 3276e5c31af7Sopenharmony_ci 3277e5c31af7Sopenharmony_ci if (m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 3278e5c31af7Sopenharmony_ci { 3279e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Cannot execute the test - driver does not support rendering" 3280e5c31af7Sopenharmony_ci "to a GL_RGBA8 renderbuffer-based color attachment"); 3281e5c31af7Sopenharmony_ci } 3282e5c31af7Sopenharmony_ci 3283e5c31af7Sopenharmony_ci m_gl.viewport(0, /* x */ 3284e5c31af7Sopenharmony_ci 0, /* y */ 3285e5c31af7Sopenharmony_ci m_color_rb_width, m_color_rb_height); 3286e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glViewport() call failed."); 3287e5c31af7Sopenharmony_ci 3288e5c31af7Sopenharmony_ci /* Determine what sparse buffer storage size we are going to need*/ 3289e5c31af7Sopenharmony_ci m_sparse_bo_size = m_ref_data_size; 3290e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 3291e5c31af7Sopenharmony_ci 3292e5c31af7Sopenharmony_ci /* Prepare the texture data */ 3293e5c31af7Sopenharmony_ci unsigned char* ref_data_traveller_ptr = DE_NULL; 3294e5c31af7Sopenharmony_ci 3295e5c31af7Sopenharmony_ci m_ref_data_ptr = new unsigned char[m_ref_data_size]; 3296e5c31af7Sopenharmony_ci ref_data_traveller_ptr = m_ref_data_ptr; 3297e5c31af7Sopenharmony_ci 3298e5c31af7Sopenharmony_ci for (unsigned int y = 0; y < m_color_rb_height; ++y) 3299e5c31af7Sopenharmony_ci { 3300e5c31af7Sopenharmony_ci const unsigned char color = (unsigned char)((1.0f - float(y) / float(m_color_rb_height - 1)) * 255.0f); 3301e5c31af7Sopenharmony_ci 3302e5c31af7Sopenharmony_ci for (unsigned int x = 0; x < m_color_rb_width; ++x) 3303e5c31af7Sopenharmony_ci { 3304e5c31af7Sopenharmony_ci memset(ref_data_traveller_ptr, color, 4); /* rgba */ 3305e5c31af7Sopenharmony_ci 3306e5c31af7Sopenharmony_ci ref_data_traveller_ptr += 4; /* rgba */ 3307e5c31af7Sopenharmony_ci } /* for (all columns) */ 3308e5c31af7Sopenharmony_ci } /* for (all rows) */ 3309e5c31af7Sopenharmony_ci 3310e5c31af7Sopenharmony_ci /* Set up the helper buffer object. */ 3311e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 3312e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 3313e5c31af7Sopenharmony_ci 3314e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 3315e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3316e5c31af7Sopenharmony_ci 3317e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_ref_data_size, m_ref_data_ptr, GL_MAP_READ_BIT); 3318e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 3319e5c31af7Sopenharmony_ci 3320e5c31af7Sopenharmony_ci return true; 3321e5c31af7Sopenharmony_ci} 3322e5c31af7Sopenharmony_ci 3323e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 3324e5c31af7Sopenharmony_ci * 3325e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 3326e5c31af7Sopenharmony_ci * to release these objects. 3327e5c31af7Sopenharmony_ci **/ 3328e5c31af7Sopenharmony_cibool PixelPackBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 3329e5c31af7Sopenharmony_ci{ 3330e5c31af7Sopenharmony_ci bool result = true; 3331e5c31af7Sopenharmony_ci 3332e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 3333e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 3334e5c31af7Sopenharmony_ci 3335e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 3336e5c31af7Sopenharmony_ci 3337e5c31af7Sopenharmony_ci return result; 3338e5c31af7Sopenharmony_ci} 3339e5c31af7Sopenharmony_ci 3340e5c31af7Sopenharmony_ci/** Constructor. 3341e5c31af7Sopenharmony_ci * 3342e5c31af7Sopenharmony_ci * @param gl GL entry-points container 3343e5c31af7Sopenharmony_ci * @param testContext CTS test context 3344e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 3345e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 3346e5c31af7Sopenharmony_ci */ 3347e5c31af7Sopenharmony_ciPixelUnpackBufferStorageTestCase::PixelUnpackBufferStorageTestCase(const glw::Functions& gl, 3348e5c31af7Sopenharmony_ci tcu::TestContext& testContext, glw::GLint page_size) 3349e5c31af7Sopenharmony_ci : m_gl(gl) 3350e5c31af7Sopenharmony_ci , m_helper_bo(0) 3351e5c31af7Sopenharmony_ci , m_page_size(page_size) 3352e5c31af7Sopenharmony_ci , m_read_data_ptr(DE_NULL) 3353e5c31af7Sopenharmony_ci , m_sparse_bo(0) 3354e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 3355e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 3356e5c31af7Sopenharmony_ci , m_testCtx(testContext) 3357e5c31af7Sopenharmony_ci , m_texture_data_ptr(DE_NULL) 3358e5c31af7Sopenharmony_ci , m_texture_data_size(0) 3359e5c31af7Sopenharmony_ci , m_to(0) 3360e5c31af7Sopenharmony_ci , m_to_data_zero(DE_NULL) 3361e5c31af7Sopenharmony_ci , m_to_height(1024) 3362e5c31af7Sopenharmony_ci , m_to_width(1024) 3363e5c31af7Sopenharmony_ci{ 3364e5c31af7Sopenharmony_ci m_texture_data_size = m_to_width * m_to_height * 4; /* rgba */ 3365e5c31af7Sopenharmony_ci} 3366e5c31af7Sopenharmony_ci 3367e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 3368e5c31af7Sopenharmony_ci * 3369e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 3370e5c31af7Sopenharmony_ci */ 3371e5c31af7Sopenharmony_civoid PixelUnpackBufferStorageTestCase::deinitTestCaseGlobal() 3372e5c31af7Sopenharmony_ci{ 3373e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 3374e5c31af7Sopenharmony_ci { 3375e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 3376e5c31af7Sopenharmony_ci 3377e5c31af7Sopenharmony_ci m_helper_bo = 0; 3378e5c31af7Sopenharmony_ci } 3379e5c31af7Sopenharmony_ci 3380e5c31af7Sopenharmony_ci if (m_read_data_ptr != DE_NULL) 3381e5c31af7Sopenharmony_ci { 3382e5c31af7Sopenharmony_ci delete[] m_read_data_ptr; 3383e5c31af7Sopenharmony_ci 3384e5c31af7Sopenharmony_ci m_read_data_ptr = DE_NULL; 3385e5c31af7Sopenharmony_ci } 3386e5c31af7Sopenharmony_ci 3387e5c31af7Sopenharmony_ci if (m_texture_data_ptr != DE_NULL) 3388e5c31af7Sopenharmony_ci { 3389e5c31af7Sopenharmony_ci delete[] m_texture_data_ptr; 3390e5c31af7Sopenharmony_ci 3391e5c31af7Sopenharmony_ci m_texture_data_ptr = DE_NULL; 3392e5c31af7Sopenharmony_ci } 3393e5c31af7Sopenharmony_ci 3394e5c31af7Sopenharmony_ci if (m_to != 0) 3395e5c31af7Sopenharmony_ci { 3396e5c31af7Sopenharmony_ci m_gl.deleteTextures(1, &m_to); 3397e5c31af7Sopenharmony_ci 3398e5c31af7Sopenharmony_ci m_to = 0; 3399e5c31af7Sopenharmony_ci } 3400e5c31af7Sopenharmony_ci 3401e5c31af7Sopenharmony_ci if (m_to_data_zero != DE_NULL) 3402e5c31af7Sopenharmony_ci { 3403e5c31af7Sopenharmony_ci delete[] m_to_data_zero; 3404e5c31af7Sopenharmony_ci 3405e5c31af7Sopenharmony_ci m_to_data_zero = DE_NULL; 3406e5c31af7Sopenharmony_ci } 3407e5c31af7Sopenharmony_ci} 3408e5c31af7Sopenharmony_ci 3409e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 3410e5c31af7Sopenharmony_civoid PixelUnpackBufferStorageTestCase::deinitTestCaseIteration() 3411e5c31af7Sopenharmony_ci{ 3412e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 3413e5c31af7Sopenharmony_ci { 3414e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 3415e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3416e5c31af7Sopenharmony_ci 3417e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 3418e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 3419e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3420e5c31af7Sopenharmony_ci 3421e5c31af7Sopenharmony_ci m_sparse_bo = 0; 3422e5c31af7Sopenharmony_ci } 3423e5c31af7Sopenharmony_ci} 3424e5c31af7Sopenharmony_ci 3425e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 3426e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 3427e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 3428e5c31af7Sopenharmony_ci * 3429e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 3430e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 3431e5c31af7Sopenharmony_ci * 3432e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 3433e5c31af7Sopenharmony_ci */ 3434e5c31af7Sopenharmony_cibool PixelUnpackBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 3435e5c31af7Sopenharmony_ci{ 3436e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 3437e5c31af7Sopenharmony_ci bool result = true; 3438e5c31af7Sopenharmony_ci 3439e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_sparse_bo); 3440e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3441e5c31af7Sopenharmony_ci 3442e5c31af7Sopenharmony_ci m_gl.bindTexture(GL_TEXTURE_2D, m_to); 3443e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture() call failed."); 3444e5c31af7Sopenharmony_ci 3445e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 3446e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture() call failed."); 3447e5c31af7Sopenharmony_ci 3448e5c31af7Sopenharmony_ci /* Run three separate iterations: 3449e5c31af7Sopenharmony_ci * 3450e5c31af7Sopenharmony_ci * a) All pages holding the source texture data are committed. 3451e5c31af7Sopenharmony_ci * b) Use a zig-zag memory page commitment layout patern. 3452e5c31af7Sopenharmony_ci * b) No pages are committed. 3453e5c31af7Sopenharmony_ci */ 3454e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 3; ++n_iteration) 3455e5c31af7Sopenharmony_ci { 3456e5c31af7Sopenharmony_ci bool result_local = true; 3457e5c31af7Sopenharmony_ci 3458e5c31af7Sopenharmony_ci /* Set up the memory page commitment & the storage contents*/ 3459e5c31af7Sopenharmony_ci switch (n_iteration) 3460e5c31af7Sopenharmony_ci { 3461e5c31af7Sopenharmony_ci case 0: 3462e5c31af7Sopenharmony_ci { 3463e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_UNPACK_BUFFER, 0, /* offset */ 3464e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_TRUE); /* commit */ 3465e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3466e5c31af7Sopenharmony_ci 3467e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, /* readOffset */ 3468e5c31af7Sopenharmony_ci 0, /* writeOffset */ 3469e5c31af7Sopenharmony_ci m_texture_data_size); 3470e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 3471e5c31af7Sopenharmony_ci 3472e5c31af7Sopenharmony_ci break; 3473e5c31af7Sopenharmony_ci } 3474e5c31af7Sopenharmony_ci 3475e5c31af7Sopenharmony_ci case 1: 3476e5c31af7Sopenharmony_ci { 3477e5c31af7Sopenharmony_ci const unsigned int n_pages = m_texture_data_size / m_page_size; 3478e5c31af7Sopenharmony_ci 3479e5c31af7Sopenharmony_ci for (unsigned int n_page = 0; n_page < n_pages; ++n_page) 3480e5c31af7Sopenharmony_ci { 3481e5c31af7Sopenharmony_ci const bool should_commit = ((n_page % 2) == 0); 3482e5c31af7Sopenharmony_ci 3483e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_UNPACK_BUFFER, m_page_size * n_page, m_page_size, 3484e5c31af7Sopenharmony_ci should_commit ? GL_TRUE : GL_FALSE); 3485e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3486e5c31af7Sopenharmony_ci 3487e5c31af7Sopenharmony_ci if (should_commit) 3488e5c31af7Sopenharmony_ci { 3489e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_PIXEL_UNPACK_BUFFER, 3490e5c31af7Sopenharmony_ci m_page_size * n_page, /* readOffset */ 3491e5c31af7Sopenharmony_ci m_page_size * n_page, /* writeOffset */ 3492e5c31af7Sopenharmony_ci m_page_size); 3493e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 3494e5c31af7Sopenharmony_ci } 3495e5c31af7Sopenharmony_ci } /* for (all relevant memory pages) */ 3496e5c31af7Sopenharmony_ci 3497e5c31af7Sopenharmony_ci break; 3498e5c31af7Sopenharmony_ci } 3499e5c31af7Sopenharmony_ci 3500e5c31af7Sopenharmony_ci case 2: 3501e5c31af7Sopenharmony_ci { 3502e5c31af7Sopenharmony_ci /* Do nothing */ 3503e5c31af7Sopenharmony_ci break; 3504e5c31af7Sopenharmony_ci } 3505e5c31af7Sopenharmony_ci 3506e5c31af7Sopenharmony_ci default: 3507e5c31af7Sopenharmony_ci { 3508e5c31af7Sopenharmony_ci TCU_FAIL("Invalid iteration index"); 3509e5c31af7Sopenharmony_ci } 3510e5c31af7Sopenharmony_ci } /* switch (n_iteration) */ 3511e5c31af7Sopenharmony_ci 3512e5c31af7Sopenharmony_ci /* Clean up the base mip-map's contents before we proceeding with updating it 3513e5c31af7Sopenharmony_ci * with data downloaded from the BO, in order to avoid situation where silently 3514e5c31af7Sopenharmony_ci * failing glTexSubImage2D() calls slip past unnoticed */ 3515e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 3516e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3517e5c31af7Sopenharmony_ci 3518e5c31af7Sopenharmony_ci m_gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */ 3519e5c31af7Sopenharmony_ci 0, /* xoffset */ 3520e5c31af7Sopenharmony_ci 0, /* yoffset */ 3521e5c31af7Sopenharmony_ci m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data_zero); 3522e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexSubImage2D() call failed."); 3523e5c31af7Sopenharmony_ci 3524e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_sparse_bo); 3525e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3526e5c31af7Sopenharmony_ci 3527e5c31af7Sopenharmony_ci /* Update the base mip-map's contents */ 3528e5c31af7Sopenharmony_ci m_gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */ 3529e5c31af7Sopenharmony_ci 0, /* xoffset */ 3530e5c31af7Sopenharmony_ci 0, /* yoffset */ 3531e5c31af7Sopenharmony_ci m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, (const glw::GLvoid*)0); 3532e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexSubImage2D() call failed."); 3533e5c31af7Sopenharmony_ci 3534e5c31af7Sopenharmony_ci /* Read back the stored mip-map data */ 3535e5c31af7Sopenharmony_ci memset(m_read_data_ptr, 0xFF, m_texture_data_size); 3536e5c31af7Sopenharmony_ci 3537e5c31af7Sopenharmony_ci m_gl.getTexImage(GL_TEXTURE_2D, 0, /* level */ 3538e5c31af7Sopenharmony_ci GL_RGBA, GL_UNSIGNED_BYTE, m_read_data_ptr); 3539e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetTexImage() call failed."); 3540e5c31af7Sopenharmony_ci 3541e5c31af7Sopenharmony_ci /* Verify the data */ 3542e5c31af7Sopenharmony_ci unsigned int n_current_tex_data_byte = 0; 3543e5c31af7Sopenharmony_ci const char* read_data_traveller_ptr = (const char*)m_read_data_ptr; 3544e5c31af7Sopenharmony_ci const char* texture_data_traveller_ptr = (const char*)m_texture_data_ptr; 3545e5c31af7Sopenharmony_ci 3546e5c31af7Sopenharmony_ci for (unsigned int y = 0; y < m_to_height && result_local; ++y) 3547e5c31af7Sopenharmony_ci { 3548e5c31af7Sopenharmony_ci for (unsigned int x = 0; x < m_to_width && result_local; ++x) 3549e5c31af7Sopenharmony_ci { 3550e5c31af7Sopenharmony_ci for (unsigned int n_component = 0; n_component < 4 /* rgba */ && result_local; ++n_component) 3551e5c31af7Sopenharmony_ci { 3552e5c31af7Sopenharmony_ci char expected_value = 0; 3553e5c31af7Sopenharmony_ci bool is_from_committed_page = true; 3554e5c31af7Sopenharmony_ci 3555e5c31af7Sopenharmony_ci if (n_iteration == 1) /* zig-zag */ 3556e5c31af7Sopenharmony_ci { 3557e5c31af7Sopenharmony_ci is_from_committed_page = ((n_current_tex_data_byte / m_page_size) % 2) == 0; 3558e5c31af7Sopenharmony_ci } 3559e5c31af7Sopenharmony_ci else if (n_iteration == 2) /* no pages committed */ 3560e5c31af7Sopenharmony_ci { 3561e5c31af7Sopenharmony_ci is_from_committed_page = false; 3562e5c31af7Sopenharmony_ci } 3563e5c31af7Sopenharmony_ci 3564e5c31af7Sopenharmony_ci if (is_from_committed_page) 3565e5c31af7Sopenharmony_ci { 3566e5c31af7Sopenharmony_ci expected_value = *texture_data_traveller_ptr; 3567e5c31af7Sopenharmony_ci } 3568e5c31af7Sopenharmony_ci 3569e5c31af7Sopenharmony_ci if (is_from_committed_page && de::abs(expected_value - *read_data_traveller_ptr) >= 1) 3570e5c31af7Sopenharmony_ci { 3571e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel data (channel:" << n_component 3572e5c31af7Sopenharmony_ci << ")" 3573e5c31af7Sopenharmony_ci " found at X:" 3574e5c31af7Sopenharmony_ci << x << ", " 3575e5c31af7Sopenharmony_ci "Y:" 3576e5c31af7Sopenharmony_ci << y << ")." 3577e5c31af7Sopenharmony_ci " Expected value:" 3578e5c31af7Sopenharmony_ci << expected_value << "," 3579e5c31af7Sopenharmony_ci " found value:" 3580e5c31af7Sopenharmony_ci << *read_data_traveller_ptr << tcu::TestLog::EndMessage; 3581e5c31af7Sopenharmony_ci 3582e5c31af7Sopenharmony_ci result_local = false; 3583e5c31af7Sopenharmony_ci } 3584e5c31af7Sopenharmony_ci 3585e5c31af7Sopenharmony_ci n_current_tex_data_byte++; 3586e5c31af7Sopenharmony_ci read_data_traveller_ptr++; 3587e5c31af7Sopenharmony_ci texture_data_traveller_ptr++; 3588e5c31af7Sopenharmony_ci } /* for (all components) */ 3589e5c31af7Sopenharmony_ci } /* for (all columns) */ 3590e5c31af7Sopenharmony_ci } /* for (all rows) */ 3591e5c31af7Sopenharmony_ci 3592e5c31af7Sopenharmony_ci result &= result_local; 3593e5c31af7Sopenharmony_ci 3594e5c31af7Sopenharmony_ci /* Clean up */ 3595e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_PIXEL_UNPACK_BUFFER, 0, /* offset */ 3596e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 3597e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3598e5c31af7Sopenharmony_ci } /* for (three iterations) */ 3599e5c31af7Sopenharmony_ci 3600e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 3601e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3602e5c31af7Sopenharmony_ci 3603e5c31af7Sopenharmony_ci return result; 3604e5c31af7Sopenharmony_ci} 3605e5c31af7Sopenharmony_ci 3606e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 3607e5c31af7Sopenharmony_ci * 3608e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 3609e5c31af7Sopenharmony_ci */ 3610e5c31af7Sopenharmony_cibool PixelUnpackBufferStorageTestCase::initTestCaseGlobal() 3611e5c31af7Sopenharmony_ci{ 3612e5c31af7Sopenharmony_ci /* Determine sparse buffer storage size */ 3613e5c31af7Sopenharmony_ci m_sparse_bo_size = m_texture_data_size; 3614e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 3615e5c31af7Sopenharmony_ci 3616e5c31af7Sopenharmony_ci /* Prepare the texture data */ 3617e5c31af7Sopenharmony_ci unsigned char* texture_data_traveller_ptr = DE_NULL; 3618e5c31af7Sopenharmony_ci 3619e5c31af7Sopenharmony_ci m_read_data_ptr = new unsigned char[m_texture_data_size]; 3620e5c31af7Sopenharmony_ci m_texture_data_ptr = new unsigned char[m_texture_data_size]; 3621e5c31af7Sopenharmony_ci texture_data_traveller_ptr = m_texture_data_ptr; 3622e5c31af7Sopenharmony_ci 3623e5c31af7Sopenharmony_ci for (unsigned int y = 0; y < m_to_height; ++y) 3624e5c31af7Sopenharmony_ci { 3625e5c31af7Sopenharmony_ci for (unsigned int x = 0; x < m_to_width; ++x) 3626e5c31af7Sopenharmony_ci { 3627e5c31af7Sopenharmony_ci const unsigned char color = (unsigned char)(float(x) / float(m_to_width - 1) * 255.0f); 3628e5c31af7Sopenharmony_ci 3629e5c31af7Sopenharmony_ci memset(texture_data_traveller_ptr, color, 4); /* rgba */ 3630e5c31af7Sopenharmony_ci 3631e5c31af7Sopenharmony_ci texture_data_traveller_ptr += 4; /* rgba */ 3632e5c31af7Sopenharmony_ci } /* for (all columns) */ 3633e5c31af7Sopenharmony_ci } /* for (all rows) */ 3634e5c31af7Sopenharmony_ci 3635e5c31af7Sopenharmony_ci m_to_data_zero = new unsigned char[m_texture_data_size]; 3636e5c31af7Sopenharmony_ci 3637e5c31af7Sopenharmony_ci memset(m_to_data_zero, 0, m_texture_data_size); 3638e5c31af7Sopenharmony_ci 3639e5c31af7Sopenharmony_ci /* Set up the helper buffer object */ 3640e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 3641e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 3642e5c31af7Sopenharmony_ci 3643e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 3644e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3645e5c31af7Sopenharmony_ci 3646e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_texture_data_size, m_texture_data_ptr, GL_MAP_READ_BIT); 3647e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 3648e5c31af7Sopenharmony_ci 3649e5c31af7Sopenharmony_ci /* Set up texture object storage */ 3650e5c31af7Sopenharmony_ci m_gl.genTextures(1, &m_to); 3651e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures() call failed."); 3652e5c31af7Sopenharmony_ci 3653e5c31af7Sopenharmony_ci m_gl.bindTexture(GL_TEXTURE_2D, m_to); 3654e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture() call failed."); 3655e5c31af7Sopenharmony_ci 3656e5c31af7Sopenharmony_ci m_gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 3657e5c31af7Sopenharmony_ci GL_RGBA8, m_to_width, m_to_height); 3658e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D() call failed."); 3659e5c31af7Sopenharmony_ci 3660e5c31af7Sopenharmony_ci return true; 3661e5c31af7Sopenharmony_ci} 3662e5c31af7Sopenharmony_ci 3663e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 3664e5c31af7Sopenharmony_ci * 3665e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 3666e5c31af7Sopenharmony_ci * to release these objects. 3667e5c31af7Sopenharmony_ci **/ 3668e5c31af7Sopenharmony_cibool PixelUnpackBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 3669e5c31af7Sopenharmony_ci{ 3670e5c31af7Sopenharmony_ci bool result = true; 3671e5c31af7Sopenharmony_ci 3672e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 3673e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 3674e5c31af7Sopenharmony_ci 3675e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 3676e5c31af7Sopenharmony_ci 3677e5c31af7Sopenharmony_ci return result; 3678e5c31af7Sopenharmony_ci} 3679e5c31af7Sopenharmony_ci 3680e5c31af7Sopenharmony_ci/** Constructor. 3681e5c31af7Sopenharmony_ci * 3682e5c31af7Sopenharmony_ci * @param gl GL entry-points container 3683e5c31af7Sopenharmony_ci * @param testContext CTS test context 3684e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 3685e5c31af7Sopenharmony_ci * @param ibo_usage Specifies if an indexed draw call should be used by the test. For more details, 3686e5c31af7Sopenharmony_ci * please see documentation for _ibo_usage. 3687e5c31af7Sopenharmony_ci * @param use_color_data true to use the color data for the tested draw call; 3688e5c31af7Sopenharmony_ci * false to omit usage of attribute data. 3689e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 3690e5c31af7Sopenharmony_ci */ 3691e5c31af7Sopenharmony_ciQuadsBufferStorageTestCase::QuadsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 3692e5c31af7Sopenharmony_ci glw::GLint page_size, _ibo_usage ibo_usage, bool use_color_data) 3693e5c31af7Sopenharmony_ci : m_attribute_color_location(0) /* predefined attribute locations */ 3694e5c31af7Sopenharmony_ci , m_attribute_position_location(1) /* predefined attribute locations */ 3695e5c31af7Sopenharmony_ci , m_color_data_offset(0) 3696e5c31af7Sopenharmony_ci , m_data(DE_NULL) 3697e5c31af7Sopenharmony_ci , m_data_size(0) 3698e5c31af7Sopenharmony_ci , m_data_size_rounded(0) 3699e5c31af7Sopenharmony_ci , m_fbo(0) 3700e5c31af7Sopenharmony_ci , m_gl(gl) 3701e5c31af7Sopenharmony_ci , m_helper_bo(0) 3702e5c31af7Sopenharmony_ci , m_ibo_data_offset(-1) 3703e5c31af7Sopenharmony_ci , m_ibo_usage(ibo_usage) 3704e5c31af7Sopenharmony_ci , m_n_quad_delta_x(5) 3705e5c31af7Sopenharmony_ci , m_n_quad_delta_y(5) 3706e5c31af7Sopenharmony_ci , m_n_quad_height(5) 3707e5c31af7Sopenharmony_ci , m_n_quad_width(5) 3708e5c31af7Sopenharmony_ci , m_n_quads_x(100) /* as per spec */ 3709e5c31af7Sopenharmony_ci , m_n_quads_y(100) /* as per spec */ 3710e5c31af7Sopenharmony_ci , m_n_vertices_to_draw(0) 3711e5c31af7Sopenharmony_ci , m_pages_committed(false) 3712e5c31af7Sopenharmony_ci , m_po(0) 3713e5c31af7Sopenharmony_ci , m_sparse_bo(0) 3714e5c31af7Sopenharmony_ci , m_testCtx(testContext) 3715e5c31af7Sopenharmony_ci , m_to(0) 3716e5c31af7Sopenharmony_ci , m_to_height(1024) /* as per spec */ 3717e5c31af7Sopenharmony_ci , m_to_width(1024) /* as per spec */ 3718e5c31af7Sopenharmony_ci , m_use_color_data(use_color_data) 3719e5c31af7Sopenharmony_ci , m_vao(0) 3720e5c31af7Sopenharmony_ci , m_vbo_data_offset(-1) 3721e5c31af7Sopenharmony_ci{ 3722e5c31af7Sopenharmony_ci /* 3723e5c31af7Sopenharmony_ci * Each quad = 2 triangles, 1 triangle = 3 vertices, 1 vertex = 4 components. 3724e5c31af7Sopenharmony_ci * The inefficient representation has been used on purpose - we want the data to take 3725e5c31af7Sopenharmony_ci * more than 64KB so that it is guaranteed that it will span over more than 1 page. 3726e5c31af7Sopenharmony_ci */ 3727e5c31af7Sopenharmony_ci m_data_size = 0; 3728e5c31af7Sopenharmony_ci 3729e5c31af7Sopenharmony_ci m_n_vertices_to_draw = m_n_quads_x * /* quads in X */ 3730e5c31af7Sopenharmony_ci m_n_quads_y * /* quads in Y */ 3731e5c31af7Sopenharmony_ci 2 * /* triangles */ 3732e5c31af7Sopenharmony_ci 3; /* vertices per triangle */ 3733e5c31af7Sopenharmony_ci 3734e5c31af7Sopenharmony_ci m_data_size = static_cast<glw::GLuint>(m_n_vertices_to_draw * 4 /* components */ * sizeof(float)); 3735e5c31af7Sopenharmony_ci 3736e5c31af7Sopenharmony_ci if (m_ibo_usage != IBO_USAGE_NONE) 3737e5c31af7Sopenharmony_ci { 3738e5c31af7Sopenharmony_ci DE_ASSERT(m_n_vertices_to_draw < 65536); 3739e5c31af7Sopenharmony_ci 3740e5c31af7Sopenharmony_ci m_data_size = static_cast<glw::GLuint>(m_data_size + (m_n_vertices_to_draw * sizeof(unsigned short))); 3741e5c31af7Sopenharmony_ci } 3742e5c31af7Sopenharmony_ci 3743e5c31af7Sopenharmony_ci if (m_use_color_data) 3744e5c31af7Sopenharmony_ci { 3745e5c31af7Sopenharmony_ci m_data_size = static_cast<glw::GLuint>(m_data_size + 3746e5c31af7Sopenharmony_ci (m_n_vertices_to_draw * sizeof(unsigned char) * 4 * /* rgba components */ 3747e5c31af7Sopenharmony_ci 2 * /* triangles */ 3748e5c31af7Sopenharmony_ci 3)); /* vertices per triangle */ 3749e5c31af7Sopenharmony_ci } 3750e5c31af7Sopenharmony_ci 3751e5c31af7Sopenharmony_ci m_data_size_rounded = SparseBufferTestUtilities::alignOffset(m_data_size, page_size); 3752e5c31af7Sopenharmony_ci} 3753e5c31af7Sopenharmony_ci 3754e5c31af7Sopenharmony_ci/** Allocates a data buffer and fills it with vertex/index/color data. Vertex data is always stored, 3755e5c31af7Sopenharmony_ci * index data only if m_ibo_usage is different from IBO_USAGE_NONE. Color data is only saved if 3756e5c31af7Sopenharmony_ci * m_use_color_data is true. 3757e5c31af7Sopenharmony_ci * 3758e5c31af7Sopenharmony_ci * @param out_data Deref will be used to store a pointer to the allocated data buffer. 3759e5c31af7Sopenharmony_ci * Ownership is transferred to the caller. Must not be NULL. 3760e5c31af7Sopenharmony_ci * @param out_vbo_data_offset Deref will be used to store an offset, from which VBO data starts, 3761e5c31af7Sopenharmony_ci * relative to the beginning of *out_data. Must not be NULL. 3762e5c31af7Sopenharmony_ci * @param out_ibo_data_offset Deref will be used to store an offset, from which IBO data starts, 3763e5c31af7Sopenharmony_ci * relative to the beginning of *out_data. May be NULL if m_ibo_usage 3764e5c31af7Sopenharmony_ci * is IBO_USAGE_NONE. 3765e5c31af7Sopenharmony_ci * @param out_color_data_offset Deref will be used to store na offset, from which color data starts, 3766e5c31af7Sopenharmony_ci * relative to the beginning of *out_data. May be NULL if m_use_color_data 3767e5c31af7Sopenharmony_ci * is false. 3768e5c31af7Sopenharmony_ci * 3769e5c31af7Sopenharmony_ci */ 3770e5c31af7Sopenharmony_civoid QuadsBufferStorageTestCase::createTestData(unsigned char** out_data, unsigned int* out_vbo_data_offset, 3771e5c31af7Sopenharmony_ci unsigned int* out_ibo_data_offset, 3772e5c31af7Sopenharmony_ci unsigned int* out_color_data_offset) const 3773e5c31af7Sopenharmony_ci{ 3774e5c31af7Sopenharmony_ci unsigned char* data_traveller_ptr = NULL; 3775e5c31af7Sopenharmony_ci 3776e5c31af7Sopenharmony_ci *out_data = new unsigned char[m_data_size]; 3777e5c31af7Sopenharmony_ci *out_vbo_data_offset = 0; 3778e5c31af7Sopenharmony_ci 3779e5c31af7Sopenharmony_ci data_traveller_ptr = *out_data; 3780e5c31af7Sopenharmony_ci 3781e5c31af7Sopenharmony_ci for (unsigned int n_quad_y = 0; n_quad_y < m_n_quads_y; ++n_quad_y) 3782e5c31af7Sopenharmony_ci { 3783e5c31af7Sopenharmony_ci for (unsigned int n_quad_x = 0; n_quad_x < m_n_quads_x; ++n_quad_x) 3784e5c31af7Sopenharmony_ci { 3785e5c31af7Sopenharmony_ci const unsigned int quad_start_x_px = n_quad_x * (m_n_quad_delta_x + m_n_quad_width); 3786e5c31af7Sopenharmony_ci const unsigned int quad_start_y_px = n_quad_y * (m_n_quad_delta_y + m_n_quad_height); 3787e5c31af7Sopenharmony_ci const unsigned int quad_end_x_px = quad_start_x_px + m_n_quad_width; 3788e5c31af7Sopenharmony_ci const unsigned int quad_end_y_px = quad_start_y_px + m_n_quad_height; 3789e5c31af7Sopenharmony_ci 3790e5c31af7Sopenharmony_ci const float quad_end_x_ss = float(quad_end_x_px) / float(m_to_width) * 2.0f - 1.0f; 3791e5c31af7Sopenharmony_ci const float quad_end_y_ss = float(quad_end_y_px) / float(m_to_height) * 2.0f - 1.0f; 3792e5c31af7Sopenharmony_ci const float quad_start_x_ss = float(quad_start_x_px) / float(m_to_width) * 2.0f - 1.0f; 3793e5c31af7Sopenharmony_ci const float quad_start_y_ss = float(quad_start_y_px) / float(m_to_height) * 2.0f - 1.0f; 3794e5c31af7Sopenharmony_ci 3795e5c31af7Sopenharmony_ci /* 1,4--5 3796e5c31af7Sopenharmony_ci * |\ | 3797e5c31af7Sopenharmony_ci * | \ | 3798e5c31af7Sopenharmony_ci * 2----3,6 3799e5c31af7Sopenharmony_ci */ 3800e5c31af7Sopenharmony_ci const float v1_4[] = { 3801e5c31af7Sopenharmony_ci quad_start_x_ss, quad_start_y_ss, 0.0f, /* z */ 3802e5c31af7Sopenharmony_ci 1.0f, /* w */ 3803e5c31af7Sopenharmony_ci }; 3804e5c31af7Sopenharmony_ci const float v2[] = { 3805e5c31af7Sopenharmony_ci quad_start_x_ss, quad_end_y_ss, 0.0f, /* z */ 3806e5c31af7Sopenharmony_ci 1.0f /* w */ 3807e5c31af7Sopenharmony_ci }; 3808e5c31af7Sopenharmony_ci const float v3_6[] = { 3809e5c31af7Sopenharmony_ci quad_end_x_ss, quad_end_y_ss, 0.0f, /* z */ 3810e5c31af7Sopenharmony_ci 1.0f /* w */ 3811e5c31af7Sopenharmony_ci }; 3812e5c31af7Sopenharmony_ci const float v5[] = { 3813e5c31af7Sopenharmony_ci quad_end_x_ss, quad_start_y_ss, 0.0f, /* z */ 3814e5c31af7Sopenharmony_ci 1.0f /* w */ 3815e5c31af7Sopenharmony_ci }; 3816e5c31af7Sopenharmony_ci 3817e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v1_4, sizeof(v1_4)); 3818e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v1_4); 3819e5c31af7Sopenharmony_ci 3820e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v2, sizeof(v2)); 3821e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v2); 3822e5c31af7Sopenharmony_ci 3823e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v3_6, sizeof(v3_6)); 3824e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v3_6); 3825e5c31af7Sopenharmony_ci 3826e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v1_4, sizeof(v1_4)); 3827e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v1_4); 3828e5c31af7Sopenharmony_ci 3829e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v5, sizeof(v5)); 3830e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v5); 3831e5c31af7Sopenharmony_ci 3832e5c31af7Sopenharmony_ci memcpy(data_traveller_ptr, v3_6, sizeof(v3_6)); 3833e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(v3_6); 3834e5c31af7Sopenharmony_ci } /* for (all quads in X) */ 3835e5c31af7Sopenharmony_ci } /* for (all quads in Y) */ 3836e5c31af7Sopenharmony_ci 3837e5c31af7Sopenharmony_ci /* Set up index data if needed */ 3838e5c31af7Sopenharmony_ci if (m_ibo_usage != IBO_USAGE_NONE) 3839e5c31af7Sopenharmony_ci { 3840e5c31af7Sopenharmony_ci *out_ibo_data_offset = static_cast<unsigned int>(data_traveller_ptr - *out_data); 3841e5c31af7Sopenharmony_ci 3842e5c31af7Sopenharmony_ci for (int index = m_n_vertices_to_draw - 1; index >= 0; --index) 3843e5c31af7Sopenharmony_ci { 3844e5c31af7Sopenharmony_ci *(unsigned short*)data_traveller_ptr = (unsigned short)index; 3845e5c31af7Sopenharmony_ci data_traveller_ptr += sizeof(unsigned short); 3846e5c31af7Sopenharmony_ci } /* for (all index values) */ 3847e5c31af7Sopenharmony_ci } /* if (m_use_ibo) */ 3848e5c31af7Sopenharmony_ci else 3849e5c31af7Sopenharmony_ci { 3850e5c31af7Sopenharmony_ci *out_ibo_data_offset = 0; 3851e5c31af7Sopenharmony_ci } 3852e5c31af7Sopenharmony_ci 3853e5c31af7Sopenharmony_ci /* Set up color data if needed */ 3854e5c31af7Sopenharmony_ci if (m_use_color_data) 3855e5c31af7Sopenharmony_ci { 3856e5c31af7Sopenharmony_ci *out_color_data_offset = static_cast<unsigned int>(data_traveller_ptr - *out_data); 3857e5c31af7Sopenharmony_ci 3858e5c31af7Sopenharmony_ci for (unsigned int n_quad = 0; n_quad < m_n_quads_x * m_n_quads_y; ++n_quad) 3859e5c31af7Sopenharmony_ci { 3860e5c31af7Sopenharmony_ci /* Use magic formulas to generate a color data set for the quads. The data 3861e5c31af7Sopenharmony_ci * needs to be duplicated for 6 vertices forming a single quad. */ 3862e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < 6; ++n_vertex) 3863e5c31af7Sopenharmony_ci { 3864e5c31af7Sopenharmony_ci /* Red */ 3865e5c31af7Sopenharmony_ci *data_traveller_ptr = static_cast<unsigned char>(n_quad % 256); //((n_quad + 15) * 14) % 256; 3866e5c31af7Sopenharmony_ci data_traveller_ptr++; 3867e5c31af7Sopenharmony_ci 3868e5c31af7Sopenharmony_ci /* Green */ 3869e5c31af7Sopenharmony_ci *data_traveller_ptr = static_cast<unsigned char>(((n_quad + 32) * 7) % 255); 3870e5c31af7Sopenharmony_ci data_traveller_ptr++; 3871e5c31af7Sopenharmony_ci 3872e5c31af7Sopenharmony_ci /* Blue */ 3873e5c31af7Sopenharmony_ci *data_traveller_ptr = static_cast<unsigned char>(((n_quad + 7) * 53) % 255); 3874e5c31af7Sopenharmony_ci data_traveller_ptr++; 3875e5c31af7Sopenharmony_ci 3876e5c31af7Sopenharmony_ci /* Alpha */ 3877e5c31af7Sopenharmony_ci *data_traveller_ptr = static_cast<unsigned char>(((n_quad + 13) * 3) % 255); 3878e5c31af7Sopenharmony_ci data_traveller_ptr++; 3879e5c31af7Sopenharmony_ci } 3880e5c31af7Sopenharmony_ci } /* for (all quads) */ 3881e5c31af7Sopenharmony_ci } 3882e5c31af7Sopenharmony_ci else 3883e5c31af7Sopenharmony_ci { 3884e5c31af7Sopenharmony_ci *out_color_data_offset = 0; 3885e5c31af7Sopenharmony_ci } 3886e5c31af7Sopenharmony_ci} 3887e5c31af7Sopenharmony_ci 3888e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 3889e5c31af7Sopenharmony_ci * 3890e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 3891e5c31af7Sopenharmony_ci */ 3892e5c31af7Sopenharmony_civoid QuadsBufferStorageTestCase::deinitTestCaseGlobal() 3893e5c31af7Sopenharmony_ci{ 3894e5c31af7Sopenharmony_ci if (m_data != DE_NULL) 3895e5c31af7Sopenharmony_ci { 3896e5c31af7Sopenharmony_ci delete[] m_data; 3897e5c31af7Sopenharmony_ci 3898e5c31af7Sopenharmony_ci m_data = DE_NULL; 3899e5c31af7Sopenharmony_ci } 3900e5c31af7Sopenharmony_ci 3901e5c31af7Sopenharmony_ci if (m_fbo != 0) 3902e5c31af7Sopenharmony_ci { 3903e5c31af7Sopenharmony_ci m_gl.deleteFramebuffers(1, &m_fbo); 3904e5c31af7Sopenharmony_ci 3905e5c31af7Sopenharmony_ci m_fbo = 0; 3906e5c31af7Sopenharmony_ci } 3907e5c31af7Sopenharmony_ci 3908e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 3909e5c31af7Sopenharmony_ci { 3910e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 3911e5c31af7Sopenharmony_ci 3912e5c31af7Sopenharmony_ci m_helper_bo = 0; 3913e5c31af7Sopenharmony_ci } 3914e5c31af7Sopenharmony_ci 3915e5c31af7Sopenharmony_ci if (m_po != 0) 3916e5c31af7Sopenharmony_ci { 3917e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 3918e5c31af7Sopenharmony_ci 3919e5c31af7Sopenharmony_ci m_po = 0; 3920e5c31af7Sopenharmony_ci } 3921e5c31af7Sopenharmony_ci 3922e5c31af7Sopenharmony_ci if (m_to != 0) 3923e5c31af7Sopenharmony_ci { 3924e5c31af7Sopenharmony_ci m_gl.deleteTextures(1, &m_to); 3925e5c31af7Sopenharmony_ci 3926e5c31af7Sopenharmony_ci m_to = 0; 3927e5c31af7Sopenharmony_ci } 3928e5c31af7Sopenharmony_ci 3929e5c31af7Sopenharmony_ci if (m_vao != 0) 3930e5c31af7Sopenharmony_ci { 3931e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 3932e5c31af7Sopenharmony_ci 3933e5c31af7Sopenharmony_ci m_vao = 0; 3934e5c31af7Sopenharmony_ci } 3935e5c31af7Sopenharmony_ci} 3936e5c31af7Sopenharmony_ci 3937e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 3938e5c31af7Sopenharmony_civoid QuadsBufferStorageTestCase::deinitTestCaseIteration() 3939e5c31af7Sopenharmony_ci{ 3940e5c31af7Sopenharmony_ci /* If the test executed successfully, all pages should've been released by now. 3941e5c31af7Sopenharmony_ci * However, if it failed, it's a good idea to de-commit them at this point. 3942e5c31af7Sopenharmony_ci * Redundant calls are fine spec-wise, too. */ 3943e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 3944e5c31af7Sopenharmony_ci { 3945e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 3946e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 3947e5c31af7Sopenharmony_ci 3948e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 3949e5c31af7Sopenharmony_ci m_data_size_rounded, GL_FALSE); /* commit */ 3950e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 3951e5c31af7Sopenharmony_ci 3952e5c31af7Sopenharmony_ci m_sparse_bo = 0; 3953e5c31af7Sopenharmony_ci } 3954e5c31af7Sopenharmony_ci} 3955e5c31af7Sopenharmony_ci 3956e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 3957e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 3958e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 3959e5c31af7Sopenharmony_ci * 3960e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 3961e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 3962e5c31af7Sopenharmony_ci * 3963e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 3964e5c31af7Sopenharmony_ci */ 3965e5c31af7Sopenharmony_cibool QuadsBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 3966e5c31af7Sopenharmony_ci{ 3967e5c31af7Sopenharmony_ci bool result = true; 3968e5c31af7Sopenharmony_ci 3969e5c31af7Sopenharmony_ci m_gl.viewport(0, /* x */ 3970e5c31af7Sopenharmony_ci 0, /* y */ 3971e5c31af7Sopenharmony_ci m_to_width, m_to_height); 3972e5c31af7Sopenharmony_ci 3973e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 3974e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 3975e5c31af7Sopenharmony_ci 3976e5c31af7Sopenharmony_ci m_gl.clearColor(0.0f, /* red */ 3977e5c31af7Sopenharmony_ci 0.0f, /* green */ 3978e5c31af7Sopenharmony_ci 0.0f, /* blue */ 3979e5c31af7Sopenharmony_ci 0.0f); /* alpha */ 3980e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearColor() call failed."); 3981e5c31af7Sopenharmony_ci 3982e5c31af7Sopenharmony_ci /* Render the quads. 3983e5c31af7Sopenharmony_ci * 3984e5c31af7Sopenharmony_ci * Run in two iterations: 3985e5c31af7Sopenharmony_ci * 3986e5c31af7Sopenharmony_ci * a) Iteration 1 performs the draw call with the VBO & IBO pages committed 3987e5c31af7Sopenharmony_ci * b) Iteration 2 performs the draw call with the VBO & IBO pages without any 3988e5c31af7Sopenharmony_ci * physical backing. 3989e5c31af7Sopenharmony_ci **/ 3990e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2; ++n_iteration) 3991e5c31af7Sopenharmony_ci { 3992e5c31af7Sopenharmony_ci initSparseBO((n_iteration == 0), /* decommit pages after upload */ 3993e5c31af7Sopenharmony_ci (sparse_bo_storage_flags & GL_DYNAMIC_STORAGE_BIT) != 0); 3994e5c31af7Sopenharmony_ci 3995e5c31af7Sopenharmony_ci m_gl.clear(GL_COLOR_BUFFER_BIT); 3996e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClear() call failed."); 3997e5c31af7Sopenharmony_ci 3998e5c31af7Sopenharmony_ci switch (m_ibo_usage) 3999e5c31af7Sopenharmony_ci { 4000e5c31af7Sopenharmony_ci case IBO_USAGE_NONE: 4001e5c31af7Sopenharmony_ci { 4002e5c31af7Sopenharmony_ci m_gl.drawArrays(GL_TRIANGLES, 0, /* first */ 4003e5c31af7Sopenharmony_ci m_n_vertices_to_draw); 4004e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() call failed."); 4005e5c31af7Sopenharmony_ci 4006e5c31af7Sopenharmony_ci break; 4007e5c31af7Sopenharmony_ci } 4008e5c31af7Sopenharmony_ci 4009e5c31af7Sopenharmony_ci case IBO_USAGE_INDEXED_DRAW_CALL: 4010e5c31af7Sopenharmony_ci { 4011e5c31af7Sopenharmony_ci m_gl.drawElements(GL_TRIANGLES, m_n_vertices_to_draw, GL_UNSIGNED_SHORT, 4012e5c31af7Sopenharmony_ci (glw::GLvoid*)(intptr_t)m_ibo_data_offset); 4013e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElements() call failed."); 4014e5c31af7Sopenharmony_ci 4015e5c31af7Sopenharmony_ci break; 4016e5c31af7Sopenharmony_ci } 4017e5c31af7Sopenharmony_ci 4018e5c31af7Sopenharmony_ci case IBO_USAGE_INDEXED_RANGED_DRAW_CALL: 4019e5c31af7Sopenharmony_ci { 4020e5c31af7Sopenharmony_ci m_gl.drawRangeElements(GL_TRIANGLES, 0, /* start */ 4021e5c31af7Sopenharmony_ci m_n_vertices_to_draw, /* end */ 4022e5c31af7Sopenharmony_ci m_n_vertices_to_draw, /* count */ 4023e5c31af7Sopenharmony_ci GL_UNSIGNED_SHORT, (glw::GLvoid*)(intptr_t)m_ibo_data_offset); 4024e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawRangeElements() call failed."); 4025e5c31af7Sopenharmony_ci 4026e5c31af7Sopenharmony_ci break; 4027e5c31af7Sopenharmony_ci } 4028e5c31af7Sopenharmony_ci 4029e5c31af7Sopenharmony_ci default: 4030e5c31af7Sopenharmony_ci { 4031e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized IBO usage value"); 4032e5c31af7Sopenharmony_ci } 4033e5c31af7Sopenharmony_ci } /* switch (m_ibo_usage) */ 4034e5c31af7Sopenharmony_ci 4035e5c31af7Sopenharmony_ci /* Retrieve the rendered output */ 4036e5c31af7Sopenharmony_ci unsigned char* read_data = new unsigned char[m_to_width * m_to_height * sizeof(char) * 4 /* rgba */]; 4037e5c31af7Sopenharmony_ci 4038e5c31af7Sopenharmony_ci m_gl.readPixels(0, /* x */ 4039e5c31af7Sopenharmony_ci 0, /* y */ 4040e5c31af7Sopenharmony_ci m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, read_data); 4041e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glReadPixels() call failed."); 4042e5c31af7Sopenharmony_ci 4043e5c31af7Sopenharmony_ci /* IF the data pages have been committed by the time the draw call was made, validate the data. 4044e5c31af7Sopenharmony_ci * 4045e5c31af7Sopenharmony_ci * For each quad region (be it filled or not), check the center and make sure the retrieved 4046e5c31af7Sopenharmony_ci * color corresponds to the expected value. 4047e5c31af7Sopenharmony_ci */ 4048e5c31af7Sopenharmony_ci if (m_pages_committed) 4049e5c31af7Sopenharmony_ci { 4050e5c31af7Sopenharmony_ci for (unsigned int n_quad_region_y = 0; n_quad_region_y < m_n_quads_y * 2; /* quad + empty "delta" region */ 4051e5c31af7Sopenharmony_ci ++n_quad_region_y) 4052e5c31af7Sopenharmony_ci { 4053e5c31af7Sopenharmony_ci for (unsigned int n_quad_region_x = 0; n_quad_region_x < m_n_quads_x * 2; ++n_quad_region_x) 4054e5c31af7Sopenharmony_ci { 4055e5c31af7Sopenharmony_ci /* Determine the expected texel color */ 4056e5c31af7Sopenharmony_ci unsigned char expected_color[4]; 4057e5c31af7Sopenharmony_ci unsigned char found_color[4]; 4058e5c31af7Sopenharmony_ci bool is_delta_region = (n_quad_region_x % 2) != 0 || (n_quad_region_y % 2) != 0; 4059e5c31af7Sopenharmony_ci 4060e5c31af7Sopenharmony_ci if (is_delta_region) 4061e5c31af7Sopenharmony_ci { 4062e5c31af7Sopenharmony_ci memset(expected_color, 0, sizeof(expected_color)); 4063e5c31af7Sopenharmony_ci } /* if (is_delta_region) */ 4064e5c31af7Sopenharmony_ci else 4065e5c31af7Sopenharmony_ci { 4066e5c31af7Sopenharmony_ci if (m_use_color_data) 4067e5c31af7Sopenharmony_ci { 4068e5c31af7Sopenharmony_ci const unsigned int n_quad_x = n_quad_region_x / 2; 4069e5c31af7Sopenharmony_ci const unsigned int n_quad_y = n_quad_region_y / 2; 4070e5c31af7Sopenharmony_ci const unsigned char* data_ptr = 4071e5c31af7Sopenharmony_ci m_data + m_color_data_offset + 4072e5c31af7Sopenharmony_ci (n_quad_y * m_n_quads_x + n_quad_x) * 4 /* rgba */ * 6; /* vertices */ 4073e5c31af7Sopenharmony_ci 4074e5c31af7Sopenharmony_ci memcpy(expected_color, data_ptr, sizeof(expected_color)); 4075e5c31af7Sopenharmony_ci } /* if (m_use_color_data) */ 4076e5c31af7Sopenharmony_ci else 4077e5c31af7Sopenharmony_ci { 4078e5c31af7Sopenharmony_ci memset(expected_color, 255, sizeof(expected_color)); 4079e5c31af7Sopenharmony_ci } 4080e5c31af7Sopenharmony_ci } 4081e5c31af7Sopenharmony_ci 4082e5c31af7Sopenharmony_ci /* Do we have a match? */ 4083e5c31af7Sopenharmony_ci DE_ASSERT(m_n_quad_height == m_n_quad_delta_y); 4084e5c31af7Sopenharmony_ci DE_ASSERT(m_n_quad_width == m_n_quad_delta_x); 4085e5c31af7Sopenharmony_ci 4086e5c31af7Sopenharmony_ci const unsigned int sample_texel_x = m_n_quad_delta_x * n_quad_region_x; 4087e5c31af7Sopenharmony_ci const unsigned int sample_texel_y = m_n_quad_delta_y * n_quad_region_y; 4088e5c31af7Sopenharmony_ci 4089e5c31af7Sopenharmony_ci memcpy(found_color, read_data + (sample_texel_y * m_to_width + sample_texel_x) * 4, /* rgba */ 4090e5c31af7Sopenharmony_ci sizeof(found_color)); 4091e5c31af7Sopenharmony_ci 4092e5c31af7Sopenharmony_ci if (memcmp(expected_color, found_color, sizeof(expected_color)) != 0) 4093e5c31af7Sopenharmony_ci { 4094e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid color found at " 4095e5c31af7Sopenharmony_ci "(" 4096e5c31af7Sopenharmony_ci << sample_texel_x << ", " << sample_texel_y << "): " 4097e5c31af7Sopenharmony_ci "Expected color:" 4098e5c31af7Sopenharmony_ci "(" 4099e5c31af7Sopenharmony_ci << (int)expected_color[0] << ", " << (int)expected_color[1] << ", " 4100e5c31af7Sopenharmony_ci << (int)expected_color[2] << ", " << (int)expected_color[3] << "), " 4101e5c31af7Sopenharmony_ci "Found:" 4102e5c31af7Sopenharmony_ci "(" 4103e5c31af7Sopenharmony_ci << (int)found_color[0] << ", " << (int)found_color[1] << ", " 4104e5c31af7Sopenharmony_ci << (int)found_color[2] << ", " << (int)found_color[3] << "), " 4105e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 4106e5c31af7Sopenharmony_ci 4107e5c31af7Sopenharmony_ci result = false; 4108e5c31af7Sopenharmony_ci goto end; 4109e5c31af7Sopenharmony_ci } 4110e5c31af7Sopenharmony_ci } /* for (all quads in X) */ 4111e5c31af7Sopenharmony_ci } /* for (all quads in Y) */ 4112e5c31af7Sopenharmony_ci } /* if (m_pages_committed) */ 4113e5c31af7Sopenharmony_ci 4114e5c31af7Sopenharmony_ci delete[] read_data; 4115e5c31af7Sopenharmony_ci read_data = DE_NULL; 4116e5c31af7Sopenharmony_ci } /* for (both iterations) */ 4117e5c31af7Sopenharmony_ci 4118e5c31af7Sopenharmony_ciend: 4119e5c31af7Sopenharmony_ci return result; 4120e5c31af7Sopenharmony_ci} 4121e5c31af7Sopenharmony_ci 4122e5c31af7Sopenharmony_ci/** Creates test data and fills the result buffer object (whose ID is stored under m_helper_bo) 4123e5c31af7Sopenharmony_ci * with the data. 4124e5c31af7Sopenharmony_ci */ 4125e5c31af7Sopenharmony_civoid QuadsBufferStorageTestCase::initHelperBO() 4126e5c31af7Sopenharmony_ci{ 4127e5c31af7Sopenharmony_ci DE_ASSERT(m_data == DE_NULL); 4128e5c31af7Sopenharmony_ci DE_ASSERT(m_helper_bo == 0); 4129e5c31af7Sopenharmony_ci 4130e5c31af7Sopenharmony_ci createTestData(&m_data, &m_vbo_data_offset, &m_ibo_data_offset, &m_color_data_offset); 4131e5c31af7Sopenharmony_ci 4132e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 4133e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 4134e5c31af7Sopenharmony_ci 4135e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 4136e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4137e5c31af7Sopenharmony_ci 4138e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_data_size, m_data, 0); /* flags */ 4139e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 4140e5c31af7Sopenharmony_ci} 4141e5c31af7Sopenharmony_ci 4142e5c31af7Sopenharmony_ci/** Creates test data (if necessary), configures sparse buffer's memory page commitment 4143e5c31af7Sopenharmony_ci * and uploads the test data to the buffer object. Finally, the method configures the 4144e5c31af7Sopenharmony_ci * vertex array object, used by ::execute() at the draw call time. 4145e5c31af7Sopenharmony_ci * 4146e5c31af7Sopenharmony_ci * @param decommit_data_pages_after_upload true to de-commit memory pages requested before 4147e5c31af7Sopenharmony_ci * uploading the vertex/index/color data. 4148e5c31af7Sopenharmony_ci * @param is_dynamic_storage true to upload the data via glBufferSubData() call. 4149e5c31af7Sopenharmony_ci * false to use a copy op for the operation. 4150e5c31af7Sopenharmony_ci **/ 4151e5c31af7Sopenharmony_civoid QuadsBufferStorageTestCase::initSparseBO(bool decommit_data_pages_after_upload, bool is_dynamic_storage) 4152e5c31af7Sopenharmony_ci{ 4153e5c31af7Sopenharmony_ci /* Set up the vertex buffer object. */ 4154e5c31af7Sopenharmony_ci if (m_data == DE_NULL) 4155e5c31af7Sopenharmony_ci { 4156e5c31af7Sopenharmony_ci createTestData(&m_data, &m_vbo_data_offset, &m_ibo_data_offset, &m_color_data_offset); 4157e5c31af7Sopenharmony_ci } 4158e5c31af7Sopenharmony_ci else 4159e5c31af7Sopenharmony_ci { 4160e5c31af7Sopenharmony_ci /* Quick checks */ 4161e5c31af7Sopenharmony_ci if (m_ibo_usage != IBO_USAGE_NONE) 4162e5c31af7Sopenharmony_ci { 4163e5c31af7Sopenharmony_ci DE_ASSERT(m_vbo_data_offset != m_ibo_data_offset); 4164e5c31af7Sopenharmony_ci } 4165e5c31af7Sopenharmony_ci 4166e5c31af7Sopenharmony_ci if (m_use_color_data) 4167e5c31af7Sopenharmony_ci { 4168e5c31af7Sopenharmony_ci DE_ASSERT(m_vbo_data_offset != m_ibo_data_offset); 4169e5c31af7Sopenharmony_ci DE_ASSERT(m_ibo_data_offset != m_color_data_offset); 4170e5c31af7Sopenharmony_ci } 4171e5c31af7Sopenharmony_ci } 4172e5c31af7Sopenharmony_ci 4173e5c31af7Sopenharmony_ci /* Commit as many pages as we need to upload the data */ 4174e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 4175e5c31af7Sopenharmony_ci m_data_size_rounded, GL_TRUE); /* commit */ 4176e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4177e5c31af7Sopenharmony_ci 4178e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 4179e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4180e5c31af7Sopenharmony_ci 4181e5c31af7Sopenharmony_ci m_pages_committed = true; 4182e5c31af7Sopenharmony_ci 4183e5c31af7Sopenharmony_ci /* Upload the data */ 4184e5c31af7Sopenharmony_ci if (is_dynamic_storage) 4185e5c31af7Sopenharmony_ci { 4186e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */ 4187e5c31af7Sopenharmony_ci m_data_size, m_data); 4188e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call failed."); 4189e5c31af7Sopenharmony_ci } 4190e5c31af7Sopenharmony_ci else 4191e5c31af7Sopenharmony_ci { 4192e5c31af7Sopenharmony_ci /* Sparse BO cannot be directly uploaded data to. Copy the data from a helper BO */ 4193e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_ARRAY_BUFFER, 0, /* readOffset */ 4194e5c31af7Sopenharmony_ci 0, /* writeOffset */ 4195e5c31af7Sopenharmony_ci m_data_size); 4196e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 4197e5c31af7Sopenharmony_ci } 4198e5c31af7Sopenharmony_ci 4199e5c31af7Sopenharmony_ci /* Set the VAO up */ 4200e5c31af7Sopenharmony_ci m_gl.vertexAttribPointer(m_attribute_position_location, 4, /* size */ 4201e5c31af7Sopenharmony_ci GL_FLOAT, GL_FALSE, /* normalized */ 4202e5c31af7Sopenharmony_ci 0, /* stride */ 4203e5c31af7Sopenharmony_ci (glw::GLvoid*)(intptr_t)m_vbo_data_offset); 4204e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribPointer() call failed."); 4205e5c31af7Sopenharmony_ci 4206e5c31af7Sopenharmony_ci m_gl.enableVertexAttribArray(m_attribute_position_location); /* index */ 4207e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEnableVertexAttribPointer() call failed."); 4208e5c31af7Sopenharmony_ci 4209e5c31af7Sopenharmony_ci if (m_use_color_data) 4210e5c31af7Sopenharmony_ci { 4211e5c31af7Sopenharmony_ci m_gl.vertexAttribPointer(m_attribute_color_location, 4, /* size */ 4212e5c31af7Sopenharmony_ci GL_UNSIGNED_BYTE, GL_TRUE, /* normalized */ 4213e5c31af7Sopenharmony_ci 0, /* stride */ 4214e5c31af7Sopenharmony_ci (glw::GLvoid*)(intptr_t)m_color_data_offset); 4215e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribPointer() call failed."); 4216e5c31af7Sopenharmony_ci 4217e5c31af7Sopenharmony_ci m_gl.enableVertexAttribArray(m_attribute_color_location); /* index */ 4218e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEnableVertexAttribPointer() call failed."); 4219e5c31af7Sopenharmony_ci } 4220e5c31af7Sopenharmony_ci else 4221e5c31af7Sopenharmony_ci { 4222e5c31af7Sopenharmony_ci m_gl.vertexAttrib4f(m_attribute_color_location, 1.0f, 1.0f, 1.0f, 1.0f); 4223e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttrib4f() call failed."); 4224e5c31af7Sopenharmony_ci 4225e5c31af7Sopenharmony_ci m_gl.disableVertexAttribArray(m_attribute_color_location); 4226e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDisableVertexAttribArray() call failed."); 4227e5c31af7Sopenharmony_ci } 4228e5c31af7Sopenharmony_ci 4229e5c31af7Sopenharmony_ci if (m_ibo_usage != IBO_USAGE_NONE) 4230e5c31af7Sopenharmony_ci { 4231e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sparse_bo); 4232e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4233e5c31af7Sopenharmony_ci } /* if (m_use_ibo) */ 4234e5c31af7Sopenharmony_ci 4235e5c31af7Sopenharmony_ci /* If we were requested to do so, decommit the pages we have just uploaded 4236e5c31af7Sopenharmony_ci * the data to. 4237e5c31af7Sopenharmony_ci */ 4238e5c31af7Sopenharmony_ci if (decommit_data_pages_after_upload) 4239e5c31af7Sopenharmony_ci { 4240e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 4241e5c31af7Sopenharmony_ci m_data_size_rounded, GL_FALSE); /* commit */ 4242e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4243e5c31af7Sopenharmony_ci 4244e5c31af7Sopenharmony_ci m_pages_committed = false; 4245e5c31af7Sopenharmony_ci } /* if (decommit_data_pages_after_upload) */ 4246e5c31af7Sopenharmony_ci} 4247e5c31af7Sopenharmony_ci 4248e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 4249e5c31af7Sopenharmony_ci * 4250e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 4251e5c31af7Sopenharmony_ci */ 4252e5c31af7Sopenharmony_cibool QuadsBufferStorageTestCase::initTestCaseGlobal() 4253e5c31af7Sopenharmony_ci{ 4254e5c31af7Sopenharmony_ci bool result = true; 4255e5c31af7Sopenharmony_ci 4256e5c31af7Sopenharmony_ci /* Set up the texture object */ 4257e5c31af7Sopenharmony_ci DE_ASSERT(m_to == 0); 4258e5c31af7Sopenharmony_ci 4259e5c31af7Sopenharmony_ci m_gl.genTextures(1, &m_to); 4260e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures() call failed."); 4261e5c31af7Sopenharmony_ci 4262e5c31af7Sopenharmony_ci m_gl.bindTexture(GL_TEXTURE_2D, m_to); 4263e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture() call failed."); 4264e5c31af7Sopenharmony_ci 4265e5c31af7Sopenharmony_ci m_gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 4266e5c31af7Sopenharmony_ci GL_RGBA8, m_to_width, m_to_height); 4267e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D() call failed."); 4268e5c31af7Sopenharmony_ci 4269e5c31af7Sopenharmony_ci /* Set up the framebuffer object */ 4270e5c31af7Sopenharmony_ci DE_ASSERT(m_fbo == 0); 4271e5c31af7Sopenharmony_ci 4272e5c31af7Sopenharmony_ci m_gl.genFramebuffers(1, &m_fbo); 4273e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers() call failed."); 4274e5c31af7Sopenharmony_ci 4275e5c31af7Sopenharmony_ci m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 4276e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer() call failed."); 4277e5c31af7Sopenharmony_ci 4278e5c31af7Sopenharmony_ci m_gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to, 0); /* level */ 4279e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferTexture2D() call failed."); 4280e5c31af7Sopenharmony_ci 4281e5c31af7Sopenharmony_ci /* Set up the vertex array object */ 4282e5c31af7Sopenharmony_ci DE_ASSERT(m_vao == 0); 4283e5c31af7Sopenharmony_ci 4284e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 4285e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 4286e5c31af7Sopenharmony_ci 4287e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 4288e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 4289e5c31af7Sopenharmony_ci 4290e5c31af7Sopenharmony_ci /* Init a helper BO */ 4291e5c31af7Sopenharmony_ci initHelperBO(); 4292e5c31af7Sopenharmony_ci 4293e5c31af7Sopenharmony_ci /* Set up the program object */ 4294e5c31af7Sopenharmony_ci const char* fs_body = "#version 430 core\n" 4295e5c31af7Sopenharmony_ci "\n" 4296e5c31af7Sopenharmony_ci "flat in vec4 fs_color;\n" 4297e5c31af7Sopenharmony_ci " out vec4 color;\n" 4298e5c31af7Sopenharmony_ci "\n" 4299e5c31af7Sopenharmony_ci "void main()\n" 4300e5c31af7Sopenharmony_ci "{\n" 4301e5c31af7Sopenharmony_ci " color = fs_color;\n" 4302e5c31af7Sopenharmony_ci "}\n"; 4303e5c31af7Sopenharmony_ci 4304e5c31af7Sopenharmony_ci const char* vs_body = "#version 430 core\n" 4305e5c31af7Sopenharmony_ci "\n" 4306e5c31af7Sopenharmony_ci "in vec4 color;\n" 4307e5c31af7Sopenharmony_ci "in vec4 position;\n" 4308e5c31af7Sopenharmony_ci "\n" 4309e5c31af7Sopenharmony_ci "flat out vec4 fs_color;\n" 4310e5c31af7Sopenharmony_ci "\n" 4311e5c31af7Sopenharmony_ci "void main()\n" 4312e5c31af7Sopenharmony_ci "{\n" 4313e5c31af7Sopenharmony_ci " fs_color = color;\n" 4314e5c31af7Sopenharmony_ci " gl_Position = position;\n" 4315e5c31af7Sopenharmony_ci "}\n"; 4316e5c31af7Sopenharmony_ci 4317e5c31af7Sopenharmony_ci const unsigned int attribute_locations[] = { m_attribute_color_location, m_attribute_position_location }; 4318e5c31af7Sopenharmony_ci const char* attribute_names[] = { "color", "position" }; 4319e5c31af7Sopenharmony_ci const unsigned int n_attributes = sizeof(attribute_locations) / sizeof(attribute_locations[0]); 4320e5c31af7Sopenharmony_ci 4321e5c31af7Sopenharmony_ci DE_ASSERT(m_po == 0); 4322e5c31af7Sopenharmony_ci 4323e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createProgram(m_gl, &fs_body, 1, /* n_fs_body_parts */ 4324e5c31af7Sopenharmony_ci &vs_body, 1, attribute_names, attribute_locations, 4325e5c31af7Sopenharmony_ci n_attributes); /* n_vs_body_parts */ 4326e5c31af7Sopenharmony_ci 4327e5c31af7Sopenharmony_ci if (m_po == 0) 4328e5c31af7Sopenharmony_ci { 4329e5c31af7Sopenharmony_ci result = false; 4330e5c31af7Sopenharmony_ci 4331e5c31af7Sopenharmony_ci goto end; 4332e5c31af7Sopenharmony_ci } 4333e5c31af7Sopenharmony_ci 4334e5c31af7Sopenharmony_ciend: 4335e5c31af7Sopenharmony_ci return result; 4336e5c31af7Sopenharmony_ci} 4337e5c31af7Sopenharmony_ci 4338e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 4339e5c31af7Sopenharmony_ci * 4340e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 4341e5c31af7Sopenharmony_ci * to release these objects. 4342e5c31af7Sopenharmony_ci **/ 4343e5c31af7Sopenharmony_cibool QuadsBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 4344e5c31af7Sopenharmony_ci{ 4345e5c31af7Sopenharmony_ci bool result = true; 4346e5c31af7Sopenharmony_ci 4347e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 4348e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 4349e5c31af7Sopenharmony_ci 4350e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 4351e5c31af7Sopenharmony_ci 4352e5c31af7Sopenharmony_ci return result; 4353e5c31af7Sopenharmony_ci} 4354e5c31af7Sopenharmony_ci 4355e5c31af7Sopenharmony_ci/** Constructor. 4356e5c31af7Sopenharmony_ci * 4357e5c31af7Sopenharmony_ci * @param gl GL entry-points container 4358e5c31af7Sopenharmony_ci * @param testContext CTS test context 4359e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 4360e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 4361e5c31af7Sopenharmony_ci */ 4362e5c31af7Sopenharmony_ciQueryBufferStorageTestCase::QueryBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 4363e5c31af7Sopenharmony_ci glw::GLint page_size) 4364e5c31af7Sopenharmony_ci : m_gl(gl) 4365e5c31af7Sopenharmony_ci , m_helper_bo(0) 4366e5c31af7Sopenharmony_ci , m_n_triangles(15) 4367e5c31af7Sopenharmony_ci , m_page_size(page_size) 4368e5c31af7Sopenharmony_ci , m_po(0) 4369e5c31af7Sopenharmony_ci , m_qo(0) 4370e5c31af7Sopenharmony_ci , m_sparse_bo(0) 4371e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 4372e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 4373e5c31af7Sopenharmony_ci , m_testCtx(testContext) 4374e5c31af7Sopenharmony_ci , m_vao(0) 4375e5c31af7Sopenharmony_ci{ 4376e5c31af7Sopenharmony_ci /* Left blank on purpose */ 4377e5c31af7Sopenharmony_ci} 4378e5c31af7Sopenharmony_ci 4379e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 4380e5c31af7Sopenharmony_ci * 4381e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 4382e5c31af7Sopenharmony_ci */ 4383e5c31af7Sopenharmony_civoid QueryBufferStorageTestCase::deinitTestCaseGlobal() 4384e5c31af7Sopenharmony_ci{ 4385e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 4386e5c31af7Sopenharmony_ci { 4387e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 4388e5c31af7Sopenharmony_ci 4389e5c31af7Sopenharmony_ci m_helper_bo = 0; 4390e5c31af7Sopenharmony_ci } 4391e5c31af7Sopenharmony_ci 4392e5c31af7Sopenharmony_ci if (m_po != 0) 4393e5c31af7Sopenharmony_ci { 4394e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 4395e5c31af7Sopenharmony_ci 4396e5c31af7Sopenharmony_ci m_po = 0; 4397e5c31af7Sopenharmony_ci } 4398e5c31af7Sopenharmony_ci 4399e5c31af7Sopenharmony_ci if (m_qo != 0) 4400e5c31af7Sopenharmony_ci { 4401e5c31af7Sopenharmony_ci m_gl.deleteQueries(1, &m_qo); 4402e5c31af7Sopenharmony_ci 4403e5c31af7Sopenharmony_ci m_qo = 0; 4404e5c31af7Sopenharmony_ci } 4405e5c31af7Sopenharmony_ci 4406e5c31af7Sopenharmony_ci if (m_vao != 0) 4407e5c31af7Sopenharmony_ci { 4408e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 4409e5c31af7Sopenharmony_ci 4410e5c31af7Sopenharmony_ci m_vao = 0; 4411e5c31af7Sopenharmony_ci } 4412e5c31af7Sopenharmony_ci} 4413e5c31af7Sopenharmony_ci 4414e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 4415e5c31af7Sopenharmony_civoid QueryBufferStorageTestCase::deinitTestCaseIteration() 4416e5c31af7Sopenharmony_ci{ 4417e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 4418e5c31af7Sopenharmony_ci { 4419e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 4420e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4421e5c31af7Sopenharmony_ci 4422e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 4423e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 4424e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4425e5c31af7Sopenharmony_ci 4426e5c31af7Sopenharmony_ci m_sparse_bo = 0; 4427e5c31af7Sopenharmony_ci } 4428e5c31af7Sopenharmony_ci} 4429e5c31af7Sopenharmony_ci 4430e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 4431e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 4432e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 4433e5c31af7Sopenharmony_ci * 4434e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 4435e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 4436e5c31af7Sopenharmony_ci * 4437e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 4438e5c31af7Sopenharmony_ci */ 4439e5c31af7Sopenharmony_cibool QueryBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 4440e5c31af7Sopenharmony_ci{ 4441e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 4442e5c31af7Sopenharmony_ci static const unsigned char data_r8_zero = 0; 4443e5c31af7Sopenharmony_ci bool result = true; 4444e5c31af7Sopenharmony_ci 4445e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_sparse_bo); 4446e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4447e5c31af7Sopenharmony_ci 4448e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 4449e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 4450e5c31af7Sopenharmony_ci 4451e5c31af7Sopenharmony_ci /* Run two separate iterations: 4452e5c31af7Sopenharmony_ci * 4453e5c31af7Sopenharmony_ci * a) The page holding the query result value is committed. 4454e5c31af7Sopenharmony_ci * b) The page is not committed. 4455e5c31af7Sopenharmony_ci */ 4456e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2; ++n_iteration) 4457e5c31af7Sopenharmony_ci { 4458e5c31af7Sopenharmony_ci const bool should_commit_page = (n_iteration == 0); 4459e5c31af7Sopenharmony_ci 4460e5c31af7Sopenharmony_ci /* Set up the memory page commitment */ 4461e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_QUERY_BUFFER, 0, /* offset */ 4462e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, should_commit_page ? GL_TRUE : GL_FALSE); 4463e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4464e5c31af7Sopenharmony_ci 4465e5c31af7Sopenharmony_ci /* Run the draw call */ 4466e5c31af7Sopenharmony_ci m_gl.beginQuery(GL_PRIMITIVES_GENERATED, m_qo); 4467e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBeginQuery() call failed."); 4468e5c31af7Sopenharmony_ci 4469e5c31af7Sopenharmony_ci m_gl.drawArrays(GL_TRIANGLES, 0, /* first */ 4470e5c31af7Sopenharmony_ci m_n_triangles * 3); 4471e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() call failed."); 4472e5c31af7Sopenharmony_ci 4473e5c31af7Sopenharmony_ci m_gl.endQuery(GL_PRIMITIVES_GENERATED); 4474e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEndQuery() call failed."); 4475e5c31af7Sopenharmony_ci 4476e5c31af7Sopenharmony_ci /* Copy the query result to the sparse buffer */ 4477e5c31af7Sopenharmony_ci for (unsigned int n_getter_call = 0; n_getter_call < 4; ++n_getter_call) 4478e5c31af7Sopenharmony_ci { 4479e5c31af7Sopenharmony_ci glw::GLsizei result_n_bytes; 4480e5c31af7Sopenharmony_ci 4481e5c31af7Sopenharmony_ci switch (n_getter_call) 4482e5c31af7Sopenharmony_ci { 4483e5c31af7Sopenharmony_ci case 0: 4484e5c31af7Sopenharmony_ci { 4485e5c31af7Sopenharmony_ci result_n_bytes = sizeof(glw::GLint); 4486e5c31af7Sopenharmony_ci m_gl.getQueryObjectiv(m_qo, GL_QUERY_RESULT, (glw::GLint*)0); /* params */ 4487e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetQueryObjectiv() call failed."); 4488e5c31af7Sopenharmony_ci 4489e5c31af7Sopenharmony_ci break; 4490e5c31af7Sopenharmony_ci } 4491e5c31af7Sopenharmony_ci 4492e5c31af7Sopenharmony_ci case 1: 4493e5c31af7Sopenharmony_ci { 4494e5c31af7Sopenharmony_ci result_n_bytes = sizeof(glw::GLint); 4495e5c31af7Sopenharmony_ci m_gl.getQueryObjectuiv(m_qo, GL_QUERY_RESULT, (glw::GLuint*)0); /* params */ 4496e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetQueryObjectuiv() call failed."); 4497e5c31af7Sopenharmony_ci 4498e5c31af7Sopenharmony_ci break; 4499e5c31af7Sopenharmony_ci } 4500e5c31af7Sopenharmony_ci 4501e5c31af7Sopenharmony_ci case 2: 4502e5c31af7Sopenharmony_ci { 4503e5c31af7Sopenharmony_ci result_n_bytes = sizeof(glw::GLint64); 4504e5c31af7Sopenharmony_ci m_gl.getQueryObjecti64v(m_qo, GL_QUERY_RESULT, (glw::GLint64*)0); 4505e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetQueryObjecti64v() call failed."); 4506e5c31af7Sopenharmony_ci 4507e5c31af7Sopenharmony_ci break; 4508e5c31af7Sopenharmony_ci } 4509e5c31af7Sopenharmony_ci 4510e5c31af7Sopenharmony_ci case 3: 4511e5c31af7Sopenharmony_ci { 4512e5c31af7Sopenharmony_ci result_n_bytes = sizeof(glw::GLint64); 4513e5c31af7Sopenharmony_ci m_gl.getQueryObjectui64v(m_qo, GL_QUERY_RESULT, (glw::GLuint64*)0); 4514e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetQueryObjectui64v() call failed."); 4515e5c31af7Sopenharmony_ci 4516e5c31af7Sopenharmony_ci break; 4517e5c31af7Sopenharmony_ci } 4518e5c31af7Sopenharmony_ci 4519e5c31af7Sopenharmony_ci default: 4520e5c31af7Sopenharmony_ci { 4521e5c31af7Sopenharmony_ci TCU_FAIL("Invalid getter call type"); 4522e5c31af7Sopenharmony_ci } 4523e5c31af7Sopenharmony_ci } /* switch (n_getter_call) */ 4524e5c31af7Sopenharmony_ci 4525e5c31af7Sopenharmony_ci /* Verify the query result */ 4526e5c31af7Sopenharmony_ci if (should_commit_page) 4527e5c31af7Sopenharmony_ci { 4528e5c31af7Sopenharmony_ci const glw::GLint64* result_ptr = NULL; 4529e5c31af7Sopenharmony_ci 4530e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_helper_bo); 4531e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4532e5c31af7Sopenharmony_ci 4533e5c31af7Sopenharmony_ci m_gl.clearBufferData(GL_COPY_WRITE_BUFFER, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &data_r8_zero); 4534e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferData() call failed."); 4535e5c31af7Sopenharmony_ci 4536e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 4537e5c31af7Sopenharmony_ci 0, /* writeOffset */ 4538e5c31af7Sopenharmony_ci result_n_bytes); 4539e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 4540e5c31af7Sopenharmony_ci 4541e5c31af7Sopenharmony_ci result_ptr = (const glw::GLint64*)m_gl.mapBuffer(GL_COPY_WRITE_BUFFER, GL_READ_ONLY); 4542e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer() call failed."); 4543e5c31af7Sopenharmony_ci 4544e5c31af7Sopenharmony_ci if (*result_ptr != m_n_triangles) 4545e5c31af7Sopenharmony_ci { 4546e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 4547e5c31af7Sopenharmony_ci << "Invalid query result stored in a sparse buffer. Found: " 4548e5c31af7Sopenharmony_ci "[" 4549e5c31af7Sopenharmony_ci << *result_ptr << "]" 4550e5c31af7Sopenharmony_ci ", expected: " 4551e5c31af7Sopenharmony_ci "[" 4552e5c31af7Sopenharmony_ci << m_n_triangles << "]" << tcu::TestLog::EndMessage; 4553e5c31af7Sopenharmony_ci 4554e5c31af7Sopenharmony_ci result = false; 4555e5c31af7Sopenharmony_ci } 4556e5c31af7Sopenharmony_ci 4557e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_WRITE_BUFFER); 4558e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 4559e5c31af7Sopenharmony_ci } /* for (all query getter call types) */ 4560e5c31af7Sopenharmony_ci } /* if (should_commit_page) */ 4561e5c31af7Sopenharmony_ci } /* for (both iterations) */ 4562e5c31af7Sopenharmony_ci 4563e5c31af7Sopenharmony_ci return result; 4564e5c31af7Sopenharmony_ci} 4565e5c31af7Sopenharmony_ci 4566e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 4567e5c31af7Sopenharmony_ci * 4568e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 4569e5c31af7Sopenharmony_ci */ 4570e5c31af7Sopenharmony_cibool QueryBufferStorageTestCase::initTestCaseGlobal() 4571e5c31af7Sopenharmony_ci{ 4572e5c31af7Sopenharmony_ci /* Determine sparse buffer storage size */ 4573e5c31af7Sopenharmony_ci m_sparse_bo_size = sizeof(glw::GLuint64); 4574e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 4575e5c31af7Sopenharmony_ci 4576e5c31af7Sopenharmony_ci /* Set up the test program object */ 4577e5c31af7Sopenharmony_ci static const char* vs_body = "#version 140\n" 4578e5c31af7Sopenharmony_ci "\n" 4579e5c31af7Sopenharmony_ci "void main()\n" 4580e5c31af7Sopenharmony_ci "{\n" 4581e5c31af7Sopenharmony_ci " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 4582e5c31af7Sopenharmony_ci "}\n"; 4583e5c31af7Sopenharmony_ci 4584e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createProgram(m_gl, DE_NULL, /* fs_body_parts */ 4585e5c31af7Sopenharmony_ci 0, /* n_fs_body_parts */ 4586e5c31af7Sopenharmony_ci &vs_body, 1, /* n_vs_body_parts */ 4587e5c31af7Sopenharmony_ci DE_NULL, /* attribute_names */ 4588e5c31af7Sopenharmony_ci DE_NULL, /* attribute_locations */ 4589e5c31af7Sopenharmony_ci 0); /* n_attribute_locations */ 4590e5c31af7Sopenharmony_ci 4591e5c31af7Sopenharmony_ci if (m_po == 0) 4592e5c31af7Sopenharmony_ci { 4593e5c31af7Sopenharmony_ci TCU_FAIL("Test program linking failure"); 4594e5c31af7Sopenharmony_ci } 4595e5c31af7Sopenharmony_ci 4596e5c31af7Sopenharmony_ci /* Set up the helper buffer object */ 4597e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 4598e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 4599e5c31af7Sopenharmony_ci 4600e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_helper_bo); 4601e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4602e5c31af7Sopenharmony_ci 4603e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_WRITE_BUFFER, sizeof(glw::GLint64), DE_NULL, /* data */ 4604e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 4605e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 4606e5c31af7Sopenharmony_ci 4607e5c31af7Sopenharmony_ci /* Set up the test query object */ 4608e5c31af7Sopenharmony_ci m_gl.genQueries(1, &m_qo); 4609e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenQueries() call failed."); 4610e5c31af7Sopenharmony_ci 4611e5c31af7Sopenharmony_ci /* Set up the VAO */ 4612e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 4613e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 4614e5c31af7Sopenharmony_ci 4615e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 4616e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 4617e5c31af7Sopenharmony_ci 4618e5c31af7Sopenharmony_ci return true; 4619e5c31af7Sopenharmony_ci} 4620e5c31af7Sopenharmony_ci 4621e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 4622e5c31af7Sopenharmony_ci * 4623e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 4624e5c31af7Sopenharmony_ci * to release these objects. 4625e5c31af7Sopenharmony_ci **/ 4626e5c31af7Sopenharmony_cibool QueryBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 4627e5c31af7Sopenharmony_ci{ 4628e5c31af7Sopenharmony_ci bool result = true; 4629e5c31af7Sopenharmony_ci 4630e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 4631e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 4632e5c31af7Sopenharmony_ci 4633e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 4634e5c31af7Sopenharmony_ci 4635e5c31af7Sopenharmony_ci /* Set up the sparse buffer. */ 4636e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_QUERY_BUFFER, m_sparse_bo); 4637e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4638e5c31af7Sopenharmony_ci 4639e5c31af7Sopenharmony_ci return result; 4640e5c31af7Sopenharmony_ci} 4641e5c31af7Sopenharmony_ci 4642e5c31af7Sopenharmony_ci/** Constructor. 4643e5c31af7Sopenharmony_ci * 4644e5c31af7Sopenharmony_ci * @param gl GL entry-points container 4645e5c31af7Sopenharmony_ci * @param testContext CTS test context 4646e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 4647e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 4648e5c31af7Sopenharmony_ci */ 4649e5c31af7Sopenharmony_ciSSBOStorageTestCase::SSBOStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size) 4650e5c31af7Sopenharmony_ci : m_gl(gl) 4651e5c31af7Sopenharmony_ci , m_helper_bo(0) 4652e5c31af7Sopenharmony_ci , m_page_size(page_size) 4653e5c31af7Sopenharmony_ci , m_po(0) 4654e5c31af7Sopenharmony_ci , m_po_local_wg_size(1024) 4655e5c31af7Sopenharmony_ci , m_result_bo(0) 4656e5c31af7Sopenharmony_ci , m_sparse_bo(0) 4657e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 4658e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 4659e5c31af7Sopenharmony_ci , m_ssbo_data(DE_NULL) 4660e5c31af7Sopenharmony_ci , m_testCtx(testContext) 4661e5c31af7Sopenharmony_ci{ 4662e5c31af7Sopenharmony_ci /* min max for SSBO size from GL_ARB_shader_storage_buffer_object is 16mb; 4663e5c31af7Sopenharmony_ci * 4664e5c31af7Sopenharmony_ci * The specified amount of space lets the test write as many 4665e5c31af7Sopenharmony_ci * ints as it's possible, with an assertion that our CS 4666e5c31af7Sopenharmony_ci * uses a std140 layout and the SSBO only contains an unsized array. 4667e5c31af7Sopenharmony_ci * 4668e5c31af7Sopenharmony_ci * NOTE: 16777216 % 1024 = 0, which is awesome because we can hardcode the 4669e5c31af7Sopenharmony_ci * local workgroup size directly in the CS. 4670e5c31af7Sopenharmony_ci */ 4671e5c31af7Sopenharmony_ci m_sparse_bo_size = (16777216 / (sizeof(int) * 4) /* std140 */) * (sizeof(int) * 4); 4672e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_sparse_bo_size, m_page_size); 4673e5c31af7Sopenharmony_ci} 4674e5c31af7Sopenharmony_ci 4675e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 4676e5c31af7Sopenharmony_ci * 4677e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 4678e5c31af7Sopenharmony_ci */ 4679e5c31af7Sopenharmony_civoid SSBOStorageTestCase::deinitTestCaseGlobal() 4680e5c31af7Sopenharmony_ci{ 4681e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 4682e5c31af7Sopenharmony_ci { 4683e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 4684e5c31af7Sopenharmony_ci 4685e5c31af7Sopenharmony_ci m_helper_bo = 0; 4686e5c31af7Sopenharmony_ci } 4687e5c31af7Sopenharmony_ci 4688e5c31af7Sopenharmony_ci if (m_po != 0) 4689e5c31af7Sopenharmony_ci { 4690e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 4691e5c31af7Sopenharmony_ci 4692e5c31af7Sopenharmony_ci m_po = 0; 4693e5c31af7Sopenharmony_ci } 4694e5c31af7Sopenharmony_ci 4695e5c31af7Sopenharmony_ci if (m_result_bo != 0) 4696e5c31af7Sopenharmony_ci { 4697e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_result_bo); 4698e5c31af7Sopenharmony_ci 4699e5c31af7Sopenharmony_ci m_result_bo = 0; 4700e5c31af7Sopenharmony_ci } 4701e5c31af7Sopenharmony_ci 4702e5c31af7Sopenharmony_ci if (m_ssbo_data != DE_NULL) 4703e5c31af7Sopenharmony_ci { 4704e5c31af7Sopenharmony_ci delete[] m_ssbo_data; 4705e5c31af7Sopenharmony_ci 4706e5c31af7Sopenharmony_ci m_ssbo_data = DE_NULL; 4707e5c31af7Sopenharmony_ci } 4708e5c31af7Sopenharmony_ci} 4709e5c31af7Sopenharmony_ci 4710e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 4711e5c31af7Sopenharmony_civoid SSBOStorageTestCase::deinitTestCaseIteration() 4712e5c31af7Sopenharmony_ci{ 4713e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 4714e5c31af7Sopenharmony_ci { 4715e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 4716e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4717e5c31af7Sopenharmony_ci 4718e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 4719e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 4720e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4721e5c31af7Sopenharmony_ci 4722e5c31af7Sopenharmony_ci m_sparse_bo = 0; 4723e5c31af7Sopenharmony_ci } 4724e5c31af7Sopenharmony_ci} 4725e5c31af7Sopenharmony_ci 4726e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 4727e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 4728e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 4729e5c31af7Sopenharmony_ci * 4730e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 4731e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 4732e5c31af7Sopenharmony_ci * 4733e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 4734e5c31af7Sopenharmony_ci */ 4735e5c31af7Sopenharmony_cibool SSBOStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 4736e5c31af7Sopenharmony_ci{ 4737e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 4738e5c31af7Sopenharmony_ci bool result = true; 4739e5c31af7Sopenharmony_ci 4740e5c31af7Sopenharmony_ci /* Bind the program object */ 4741e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 4742e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 4743e5c31af7Sopenharmony_ci 4744e5c31af7Sopenharmony_ci /* Set up shader storage buffer bindings */ 4745e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_sparse_bo); 4746e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4747e5c31af7Sopenharmony_ci 4748e5c31af7Sopenharmony_ci m_gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, /* index */ 4749e5c31af7Sopenharmony_ci m_sparse_bo); 4750e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase() call failed."); 4751e5c31af7Sopenharmony_ci 4752e5c31af7Sopenharmony_ci /* Run the test in three iterations: 4753e5c31af7Sopenharmony_ci * 4754e5c31af7Sopenharmony_ci * a) All required pages are committed. 4755e5c31af7Sopenharmony_ci * b) Only half of the pages are committed (in a zig-zag layout) 4756e5c31af7Sopenharmony_ci * c) None of the pages are committed. 4757e5c31af7Sopenharmony_ci */ 4758e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 3; ++n_iteration) 4759e5c31af7Sopenharmony_ci { 4760e5c31af7Sopenharmony_ci bool result_local = true; 4761e5c31af7Sopenharmony_ci 4762e5c31af7Sopenharmony_ci /* Set up the shader storage buffer object's memory backing */ 4763e5c31af7Sopenharmony_ci const bool is_zigzag_ssbo = (n_iteration == 1); 4764e5c31af7Sopenharmony_ci unsigned int ssbo_commit_size = 0; 4765e5c31af7Sopenharmony_ci unsigned int ssbo_commit_start_offset = 0; 4766e5c31af7Sopenharmony_ci 4767e5c31af7Sopenharmony_ci switch (n_iteration) 4768e5c31af7Sopenharmony_ci { 4769e5c31af7Sopenharmony_ci case 0: 4770e5c31af7Sopenharmony_ci case 1: 4771e5c31af7Sopenharmony_ci { 4772e5c31af7Sopenharmony_ci ssbo_commit_size = m_sparse_bo_size_rounded; 4773e5c31af7Sopenharmony_ci ssbo_commit_start_offset = 0; 4774e5c31af7Sopenharmony_ci 4775e5c31af7Sopenharmony_ci if (is_zigzag_ssbo) 4776e5c31af7Sopenharmony_ci { 4777e5c31af7Sopenharmony_ci const unsigned int n_pages = ssbo_commit_size / m_page_size; 4778e5c31af7Sopenharmony_ci 4779e5c31af7Sopenharmony_ci for (unsigned int n_page = 0; n_page < n_pages; n_page += 2) 4780e5c31af7Sopenharmony_ci { 4781e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_SHADER_STORAGE_BUFFER, m_page_size * n_page, /* offset */ 4782e5c31af7Sopenharmony_ci m_page_size, /* size */ 4783e5c31af7Sopenharmony_ci GL_TRUE); /* commit */ 4784e5c31af7Sopenharmony_ci } /* for (all memory pages) */ 4785e5c31af7Sopenharmony_ci } 4786e5c31af7Sopenharmony_ci else 4787e5c31af7Sopenharmony_ci { 4788e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_SHADER_STORAGE_BUFFER, 0, /* offset */ 4789e5c31af7Sopenharmony_ci ssbo_commit_size, GL_TRUE); /* commit */ 4790e5c31af7Sopenharmony_ci } 4791e5c31af7Sopenharmony_ci 4792e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call(s) failed."); 4793e5c31af7Sopenharmony_ci 4794e5c31af7Sopenharmony_ci break; 4795e5c31af7Sopenharmony_ci } 4796e5c31af7Sopenharmony_ci 4797e5c31af7Sopenharmony_ci case 2: 4798e5c31af7Sopenharmony_ci { 4799e5c31af7Sopenharmony_ci /* Use no physical memory backing */ 4800e5c31af7Sopenharmony_ci break; 4801e5c31af7Sopenharmony_ci } 4802e5c31af7Sopenharmony_ci 4803e5c31af7Sopenharmony_ci default: 4804e5c31af7Sopenharmony_ci { 4805e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized iteration index"); 4806e5c31af7Sopenharmony_ci } 4807e5c31af7Sopenharmony_ci } /* switch (n_iteration) */ 4808e5c31af7Sopenharmony_ci 4809e5c31af7Sopenharmony_ci /* Set up bindings for the copy op */ 4810e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 4811e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bo); 4812e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 4813e5c31af7Sopenharmony_ci 4814e5c31af7Sopenharmony_ci /* Set up the sparse buffer's data storage */ 4815e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 4816e5c31af7Sopenharmony_ci 0, /* writeOffset */ 4817e5c31af7Sopenharmony_ci m_sparse_bo_size); 4818e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 4819e5c31af7Sopenharmony_ci 4820e5c31af7Sopenharmony_ci /* Run the compute program */ 4821e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size % m_po_local_wg_size) == 0); 4822e5c31af7Sopenharmony_ci 4823e5c31af7Sopenharmony_ci m_gl.dispatchCompute(m_sparse_bo_size / m_po_local_wg_size, 1, /* num_groups_y */ 4824e5c31af7Sopenharmony_ci 1); /* num_groups_z */ 4825e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDispatchCompute() call failed."); 4826e5c31af7Sopenharmony_ci 4827e5c31af7Sopenharmony_ci /* Flush the caches */ 4828e5c31af7Sopenharmony_ci m_gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4829e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMemoryBarrier() call failed."); 4830e5c31af7Sopenharmony_ci 4831e5c31af7Sopenharmony_ci /* Copy SSBO's storage to a mappable result BO */ 4832e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_sparse_bo); 4833e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_result_bo); 4834e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 4835e5c31af7Sopenharmony_ci 4836e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 4837e5c31af7Sopenharmony_ci 0, /* writeOffset */ 4838e5c31af7Sopenharmony_ci m_sparse_bo_size); 4839e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 4840e5c31af7Sopenharmony_ci 4841e5c31af7Sopenharmony_ci /* Map the result BO to the process space */ 4842e5c31af7Sopenharmony_ci unsigned int current_ssbo_offset = 0; 4843e5c31af7Sopenharmony_ci const unsigned int* ssbo_data_ptr = (const unsigned int*)m_gl.mapBuffer(GL_COPY_WRITE_BUFFER, GL_READ_ONLY); 4844e5c31af7Sopenharmony_ci 4845e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer() call failed."); 4846e5c31af7Sopenharmony_ci 4847e5c31af7Sopenharmony_ci for (unsigned int n_invocation = 0; current_ssbo_offset < m_sparse_bo_size && result_local; ++n_invocation, 4848e5c31af7Sopenharmony_ci current_ssbo_offset = static_cast<unsigned int>(current_ssbo_offset + 4849e5c31af7Sopenharmony_ci (sizeof(int) * 4 /* std140 */))) 4850e5c31af7Sopenharmony_ci { 4851e5c31af7Sopenharmony_ci const unsigned int n_page = current_ssbo_offset / m_page_size; 4852e5c31af7Sopenharmony_ci 4853e5c31af7Sopenharmony_ci if ((is_zigzag_ssbo && (n_page % 2) == 0) || 4854e5c31af7Sopenharmony_ci (!is_zigzag_ssbo && (current_ssbo_offset >= ssbo_commit_start_offset && 4855e5c31af7Sopenharmony_ci current_ssbo_offset < (ssbo_commit_start_offset + ssbo_commit_size)))) 4856e5c31af7Sopenharmony_ci { 4857e5c31af7Sopenharmony_ci if (ssbo_data_ptr[n_invocation * 4] != (n_invocation + 1)) 4858e5c31af7Sopenharmony_ci { 4859e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Value written to the SSBO at byte " 4860e5c31af7Sopenharmony_ci "[" 4861e5c31af7Sopenharmony_ci << (sizeof(int) * n_invocation) << "]" 4862e5c31af7Sopenharmony_ci " is invalid. Found:" 4863e5c31af7Sopenharmony_ci << "[" << ssbo_data_ptr[n_invocation * 4] << "]" 4864e5c31af7Sopenharmony_ci ", expected:" 4865e5c31af7Sopenharmony_ci << "[" << (n_invocation + 1) << "]" << tcu::TestLog::EndMessage; 4866e5c31af7Sopenharmony_ci 4867e5c31af7Sopenharmony_ci result_local = false; 4868e5c31af7Sopenharmony_ci } 4869e5c31af7Sopenharmony_ci } /* if (ssbo_data_ptr[n_texel] != 1) */ 4870e5c31af7Sopenharmony_ci } /* for (all result values) */ 4871e5c31af7Sopenharmony_ci 4872e5c31af7Sopenharmony_ci result &= result_local; 4873e5c31af7Sopenharmony_ci 4874e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_COPY_WRITE_BUFFER); 4875e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 4876e5c31af7Sopenharmony_ci 4877e5c31af7Sopenharmony_ci /* Remove the physical backing from the sparse buffer */ 4878e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_SHADER_STORAGE_BUFFER, 0, /* offset */ 4879e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 4880e5c31af7Sopenharmony_ci 4881e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 4882e5c31af7Sopenharmony_ci } /* for (three iterations) */ 4883e5c31af7Sopenharmony_ci 4884e5c31af7Sopenharmony_ci return result; 4885e5c31af7Sopenharmony_ci} 4886e5c31af7Sopenharmony_ci 4887e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 4888e5c31af7Sopenharmony_ci * 4889e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 4890e5c31af7Sopenharmony_ci */ 4891e5c31af7Sopenharmony_cibool SSBOStorageTestCase::initTestCaseGlobal() 4892e5c31af7Sopenharmony_ci{ 4893e5c31af7Sopenharmony_ci /* Set up the test program */ 4894e5c31af7Sopenharmony_ci static const char* cs_body = 4895e5c31af7Sopenharmony_ci "#version 430 core\n" 4896e5c31af7Sopenharmony_ci "\n" 4897e5c31af7Sopenharmony_ci "layout(local_size_x = 1024) in;\n" 4898e5c31af7Sopenharmony_ci "\n" 4899e5c31af7Sopenharmony_ci "layout(std140, binding = 0) buffer data\n" 4900e5c31af7Sopenharmony_ci "{\n" 4901e5c31af7Sopenharmony_ci " restrict uint io_values[];\n" 4902e5c31af7Sopenharmony_ci "};\n" 4903e5c31af7Sopenharmony_ci "\n" 4904e5c31af7Sopenharmony_ci "void main()\n" 4905e5c31af7Sopenharmony_ci "{\n" 4906e5c31af7Sopenharmony_ci " uint value_index = gl_GlobalInvocationID.x;\n" 4907e5c31af7Sopenharmony_ci " uint new_value = (io_values[value_index] == value_index) ? (value_index + 1u) : value_index;\n" 4908e5c31af7Sopenharmony_ci "\n" 4909e5c31af7Sopenharmony_ci " io_values[value_index] = new_value;\n" 4910e5c31af7Sopenharmony_ci "}\n"; 4911e5c31af7Sopenharmony_ci 4912e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createComputeProgram(m_gl, &cs_body, 1); /* n_cs_body_parts */ 4913e5c31af7Sopenharmony_ci 4914e5c31af7Sopenharmony_ci /* Set up a data buffer we will use to initialize the SSBO with default data. 4915e5c31af7Sopenharmony_ci * 4916e5c31af7Sopenharmony_ci * CS uses a std140 layout for the SSBO, so we need to add the additional padding. 4917e5c31af7Sopenharmony_ci */ 4918e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size) != 0); 4919e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size % (sizeof(int) * 4)) == 0); 4920e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_size % 1024) == 0); 4921e5c31af7Sopenharmony_ci 4922e5c31af7Sopenharmony_ci m_ssbo_data = new unsigned int[m_sparse_bo_size / sizeof(int)]; 4923e5c31af7Sopenharmony_ci 4924e5c31af7Sopenharmony_ci memset(m_ssbo_data, 0, m_sparse_bo_size); 4925e5c31af7Sopenharmony_ci 4926e5c31af7Sopenharmony_ci for (unsigned int index = 0; index < m_sparse_bo_size / sizeof(int) / 4; ++index) 4927e5c31af7Sopenharmony_ci { 4928e5c31af7Sopenharmony_ci /* Mind the std140 rules for arrays of ints */ 4929e5c31af7Sopenharmony_ci m_ssbo_data[4 * index] = index; 4930e5c31af7Sopenharmony_ci } 4931e5c31af7Sopenharmony_ci 4932e5c31af7Sopenharmony_ci /* During execution, we will need to use a helper buffer object. The BO will hold 4933e5c31af7Sopenharmony_ci * data we will be copying into the sparse buffer object for each iteration. 4934e5c31af7Sopenharmony_ci */ 4935e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 4936e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 4937e5c31af7Sopenharmony_ci 4938e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 4939e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4940e5c31af7Sopenharmony_ci 4941e5c31af7Sopenharmony_ci m_gl.bufferData(GL_COPY_READ_BUFFER, m_sparse_bo_size, m_ssbo_data, GL_STATIC_DRAW); 4942e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData() call failed."); 4943e5c31af7Sopenharmony_ci 4944e5c31af7Sopenharmony_ci /* To retrieve the data written to a sparse SSBO, we need to use another 4945e5c31af7Sopenharmony_ci * non-sparse helper BO. 4946e5c31af7Sopenharmony_ci */ 4947e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_result_bo); 4948e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 4949e5c31af7Sopenharmony_ci 4950e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_result_bo); 4951e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 4952e5c31af7Sopenharmony_ci 4953e5c31af7Sopenharmony_ci m_gl.bufferData(GL_ARRAY_BUFFER, m_sparse_bo_size, DE_NULL, /* data */ 4954e5c31af7Sopenharmony_ci GL_STATIC_DRAW); 4955e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData() call failed."); 4956e5c31af7Sopenharmony_ci 4957e5c31af7Sopenharmony_ci return true; 4958e5c31af7Sopenharmony_ci} 4959e5c31af7Sopenharmony_ci 4960e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 4961e5c31af7Sopenharmony_ci * 4962e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 4963e5c31af7Sopenharmony_ci * to release these objects. 4964e5c31af7Sopenharmony_ci **/ 4965e5c31af7Sopenharmony_cibool SSBOStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 4966e5c31af7Sopenharmony_ci{ 4967e5c31af7Sopenharmony_ci bool result = true; 4968e5c31af7Sopenharmony_ci 4969e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 4970e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 4971e5c31af7Sopenharmony_ci 4972e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 4973e5c31af7Sopenharmony_ci 4974e5c31af7Sopenharmony_ci return result; 4975e5c31af7Sopenharmony_ci} 4976e5c31af7Sopenharmony_ci 4977e5c31af7Sopenharmony_ci/** Constructor. 4978e5c31af7Sopenharmony_ci * 4979e5c31af7Sopenharmony_ci * @param gl GL entry-points container 4980e5c31af7Sopenharmony_ci * @param testContext CTS test context 4981e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 4982e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 4983e5c31af7Sopenharmony_ci * @param all_pages_committed true to provide memory backing for all memory pages holding data used by the test. 4984e5c31af7Sopenharmony_ci * false to leave some of them uncommitted. 4985e5c31af7Sopenharmony_ci */ 4986e5c31af7Sopenharmony_ciTransformFeedbackBufferStorageTestCase::TransformFeedbackBufferStorageTestCase(const glw::Functions& gl, 4987e5c31af7Sopenharmony_ci tcu::TestContext& testContext, 4988e5c31af7Sopenharmony_ci glw::GLint page_size, 4989e5c31af7Sopenharmony_ci bool all_pages_committed) 4990e5c31af7Sopenharmony_ci : m_all_pages_committed(all_pages_committed) 4991e5c31af7Sopenharmony_ci , m_data_bo(0) 4992e5c31af7Sopenharmony_ci , m_data_bo_index_data_offset(0) 4993e5c31af7Sopenharmony_ci , m_data_bo_indexed_indirect_arg_offset(0) 4994e5c31af7Sopenharmony_ci , m_data_bo_indexed_mdi_arg_offset(0) 4995e5c31af7Sopenharmony_ci , m_data_bo_regular_indirect_arg_offset(0) 4996e5c31af7Sopenharmony_ci , m_data_bo_regular_mdi_arg_offset(0) 4997e5c31af7Sopenharmony_ci , m_data_bo_size(0) 4998e5c31af7Sopenharmony_ci , m_draw_call_baseInstance(1231) 4999e5c31af7Sopenharmony_ci , m_draw_call_baseVertex(65537) 5000e5c31af7Sopenharmony_ci , m_draw_call_first(913) 5001e5c31af7Sopenharmony_ci , m_draw_call_firstIndex(4) 5002e5c31af7Sopenharmony_ci , m_gl(gl) 5003e5c31af7Sopenharmony_ci , m_helper_bo(0) 5004e5c31af7Sopenharmony_ci , m_index_data(DE_NULL) 5005e5c31af7Sopenharmony_ci , m_index_data_size(0) 5006e5c31af7Sopenharmony_ci , m_indirect_arg_data(DE_NULL) 5007e5c31af7Sopenharmony_ci , m_indirect_arg_data_size(0) 5008e5c31af7Sopenharmony_ci , m_min_memory_page_span(4) /* as per test spec */ 5009e5c31af7Sopenharmony_ci , m_multidrawcall_drawcount(-1) 5010e5c31af7Sopenharmony_ci , m_multidrawcall_primcount(-1) 5011e5c31af7Sopenharmony_ci , m_n_instances_to_test(4) 5012e5c31af7Sopenharmony_ci , m_n_vertices_per_instance(0) 5013e5c31af7Sopenharmony_ci , m_page_size(page_size) 5014e5c31af7Sopenharmony_ci , m_po_ia(0) 5015e5c31af7Sopenharmony_ci , m_po_sa(0) 5016e5c31af7Sopenharmony_ci , m_result_bo(0) 5017e5c31af7Sopenharmony_ci , m_result_bo_size(0) 5018e5c31af7Sopenharmony_ci , m_result_bo_size_rounded(0) 5019e5c31af7Sopenharmony_ci , m_testCtx(testContext) 5020e5c31af7Sopenharmony_ci , m_vao(0) 5021e5c31af7Sopenharmony_ci{ 5022e5c31af7Sopenharmony_ci /* Left blank on purpose */ 5023e5c31af7Sopenharmony_ci} 5024e5c31af7Sopenharmony_ci 5025e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 5026e5c31af7Sopenharmony_ci * 5027e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 5028e5c31af7Sopenharmony_ci */ 5029e5c31af7Sopenharmony_civoid TransformFeedbackBufferStorageTestCase::deinitTestCaseGlobal() 5030e5c31af7Sopenharmony_ci{ 5031e5c31af7Sopenharmony_ci if (m_data_bo != 0) 5032e5c31af7Sopenharmony_ci { 5033e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_data_bo); 5034e5c31af7Sopenharmony_ci 5035e5c31af7Sopenharmony_ci m_data_bo = 0; 5036e5c31af7Sopenharmony_ci } 5037e5c31af7Sopenharmony_ci 5038e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 5039e5c31af7Sopenharmony_ci { 5040e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 5041e5c31af7Sopenharmony_ci 5042e5c31af7Sopenharmony_ci m_helper_bo = 0; 5043e5c31af7Sopenharmony_ci } 5044e5c31af7Sopenharmony_ci 5045e5c31af7Sopenharmony_ci if (m_index_data != DE_NULL) 5046e5c31af7Sopenharmony_ci { 5047e5c31af7Sopenharmony_ci delete[] m_index_data; 5048e5c31af7Sopenharmony_ci 5049e5c31af7Sopenharmony_ci m_index_data = DE_NULL; 5050e5c31af7Sopenharmony_ci } 5051e5c31af7Sopenharmony_ci 5052e5c31af7Sopenharmony_ci if (m_indirect_arg_data != DE_NULL) 5053e5c31af7Sopenharmony_ci { 5054e5c31af7Sopenharmony_ci delete[] m_indirect_arg_data; 5055e5c31af7Sopenharmony_ci 5056e5c31af7Sopenharmony_ci m_indirect_arg_data = DE_NULL; 5057e5c31af7Sopenharmony_ci } 5058e5c31af7Sopenharmony_ci 5059e5c31af7Sopenharmony_ci if (m_po_ia != 0) 5060e5c31af7Sopenharmony_ci { 5061e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po_ia); 5062e5c31af7Sopenharmony_ci 5063e5c31af7Sopenharmony_ci m_po_ia = 0; 5064e5c31af7Sopenharmony_ci } 5065e5c31af7Sopenharmony_ci 5066e5c31af7Sopenharmony_ci if (m_po_sa != 0) 5067e5c31af7Sopenharmony_ci { 5068e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po_sa); 5069e5c31af7Sopenharmony_ci 5070e5c31af7Sopenharmony_ci m_po_sa = 0; 5071e5c31af7Sopenharmony_ci } 5072e5c31af7Sopenharmony_ci 5073e5c31af7Sopenharmony_ci if (m_result_bo != 0) 5074e5c31af7Sopenharmony_ci { 5075e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_result_bo); 5076e5c31af7Sopenharmony_ci 5077e5c31af7Sopenharmony_ci m_result_bo = 0; 5078e5c31af7Sopenharmony_ci } 5079e5c31af7Sopenharmony_ci 5080e5c31af7Sopenharmony_ci if (m_vao != 0) 5081e5c31af7Sopenharmony_ci { 5082e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 5083e5c31af7Sopenharmony_ci 5084e5c31af7Sopenharmony_ci m_vao = 0; 5085e5c31af7Sopenharmony_ci } 5086e5c31af7Sopenharmony_ci} 5087e5c31af7Sopenharmony_ci 5088e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 5089e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 5090e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 5091e5c31af7Sopenharmony_ci * 5092e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 5093e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 5094e5c31af7Sopenharmony_ci * 5095e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 5096e5c31af7Sopenharmony_ci */ 5097e5c31af7Sopenharmony_cibool TransformFeedbackBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 5098e5c31af7Sopenharmony_ci{ 5099e5c31af7Sopenharmony_ci bool result = true; 5100e5c31af7Sopenharmony_ci 5101e5c31af7Sopenharmony_ci /* Iterate through two different transform feedback modes we need to test */ 5102e5c31af7Sopenharmony_ci for (unsigned int n_tf_type = 0; n_tf_type < 2; /* interleaved & separate attribs */ 5103e5c31af7Sopenharmony_ci ++n_tf_type) 5104e5c31af7Sopenharmony_ci { 5105e5c31af7Sopenharmony_ci const bool is_ia_iteration = (n_tf_type == 0); 5106e5c31af7Sopenharmony_ci 5107e5c31af7Sopenharmony_ci /* Bind the test PO to the context */ 5108e5c31af7Sopenharmony_ci m_gl.useProgram(is_ia_iteration ? m_po_ia : m_po_sa); 5109e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 5110e5c31af7Sopenharmony_ci 5111e5c31af7Sopenharmony_ci /* Set up TF general binding, which is needed for a glClearBufferData() call 5112e5c31af7Sopenharmony_ci * we'll be firing shortly. 5113e5c31af7Sopenharmony_ci */ 5114e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, /* needed for the subsequent glClearBufferData() call */ 5115e5c31af7Sopenharmony_ci m_result_bo); 5116e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 5117e5c31af7Sopenharmony_ci 5118e5c31af7Sopenharmony_ci /* Iterate through all draw call types */ 5119e5c31af7Sopenharmony_ci for (unsigned int n_draw_call_type = 0; n_draw_call_type < DRAW_CALL_COUNT; ++n_draw_call_type) 5120e5c31af7Sopenharmony_ci { 5121e5c31af7Sopenharmony_ci int draw_call_count = 0; /* != 1 for multi-draw calls only */ 5122e5c31af7Sopenharmony_ci int draw_call_first_instance_id[2] = { -1 }; 5123e5c31af7Sopenharmony_ci int draw_call_first_vertex_id[2] = { -1 }; 5124e5c31af7Sopenharmony_ci int draw_call_n_instances[2] = { 0 }; 5125e5c31af7Sopenharmony_ci int draw_call_n_vertices[2] = { 0 }; 5126e5c31af7Sopenharmony_ci bool draw_call_is_vertex_id_ascending = false; 5127e5c31af7Sopenharmony_ci const _draw_call draw_call_type = (_draw_call)n_draw_call_type; 5128e5c31af7Sopenharmony_ci unsigned int n_result_bytes_per_instance[2] = { 0 }; 5129e5c31af7Sopenharmony_ci const unsigned int n_result_bytes_per_vertex = sizeof(unsigned int) * 2; 5130e5c31af7Sopenharmony_ci unsigned int n_result_bytes_total = 0; 5131e5c31af7Sopenharmony_ci glw::GLuint* result_ptr = DE_NULL; 5132e5c31af7Sopenharmony_ci 5133e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data_bo); 5134e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_data_bo); 5135e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 5136e5c31af7Sopenharmony_ci 5137e5c31af7Sopenharmony_ci /* Commit pages needed to execute transform feed-back */ 5138e5c31af7Sopenharmony_ci if (m_all_pages_committed) 5139e5c31af7Sopenharmony_ci { 5140e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 5141e5c31af7Sopenharmony_ci m_result_bo_size_rounded, GL_TRUE); /* commit */ 5142e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 5143e5c31af7Sopenharmony_ci } 5144e5c31af7Sopenharmony_ci else 5145e5c31af7Sopenharmony_ci { 5146e5c31af7Sopenharmony_ci for (unsigned int n_page = 0; n_page < m_result_bo_size_rounded / m_page_size; ++n_page) 5147e5c31af7Sopenharmony_ci { 5148e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_TRANSFORM_FEEDBACK_BUFFER, n_page * m_page_size, /* offset */ 5149e5c31af7Sopenharmony_ci m_page_size, /* size */ 5150e5c31af7Sopenharmony_ci (n_page % 2 == 0) ? GL_TRUE : GL_FALSE); /* commit */ 5151e5c31af7Sopenharmony_ci } 5152e5c31af7Sopenharmony_ci 5153e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 5154e5c31af7Sopenharmony_ci } 5155e5c31af7Sopenharmony_ci 5156e5c31af7Sopenharmony_ci /* Zero out the target BO before we begin the TF */ 5157e5c31af7Sopenharmony_ci static const unsigned char data_zero = 0; 5158e5c31af7Sopenharmony_ci 5159e5c31af7Sopenharmony_ci m_gl.clearBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &data_zero); 5160e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferData() call failed."); 5161e5c31af7Sopenharmony_ci 5162e5c31af7Sopenharmony_ci /* Set up transform feed-back buffer bindings */ 5163e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo_size != 0); 5164e5c31af7Sopenharmony_ci 5165e5c31af7Sopenharmony_ci if (is_ia_iteration) 5166e5c31af7Sopenharmony_ci { 5167e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo != 0); 5168e5c31af7Sopenharmony_ci 5169e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 5170e5c31af7Sopenharmony_ci m_result_bo, 0, /* offset */ 5171e5c31af7Sopenharmony_ci m_result_bo_size); 5172e5c31af7Sopenharmony_ci 5173e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferRange() call failed."); 5174e5c31af7Sopenharmony_ci } 5175e5c31af7Sopenharmony_ci else 5176e5c31af7Sopenharmony_ci { 5177e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo_size % 2 == 0); 5178e5c31af7Sopenharmony_ci 5179e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 5180e5c31af7Sopenharmony_ci m_result_bo, 0, /* offset */ 5181e5c31af7Sopenharmony_ci m_result_bo_size / 2); 5182e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, /* index */ 5183e5c31af7Sopenharmony_ci m_result_bo, m_result_bo_size / 2, m_result_bo_size / 2); 5184e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferRange() call(s) failed."); 5185e5c31af7Sopenharmony_ci } 5186e5c31af7Sopenharmony_ci 5187e5c31af7Sopenharmony_ci m_gl.beginTransformFeedback(GL_POINTS); 5188e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBeginTransformFeedback() call failed."); 5189e5c31af7Sopenharmony_ci 5190e5c31af7Sopenharmony_ci /* NOTE: Some discussion about the expected "vertex id" value: 5191e5c31af7Sopenharmony_ci * 5192e5c31af7Sopenharmony_ci * In GL 4.5 core spec (Feb2/2015 version), we have: 5193e5c31af7Sopenharmony_ci * 5194e5c31af7Sopenharmony_ci * >> 5195e5c31af7Sopenharmony_ci * The index of any element transferred to the GL by DrawElementsOneInstance 5196e5c31af7Sopenharmony_ci * is referred to as its vertex ID, and may be read by a vertex shader as 5197e5c31af7Sopenharmony_ci * gl_VertexID. The vertex ID of the ith element transferred is the sum of 5198e5c31af7Sopenharmony_ci * basevertex and the value stored in the currently bound element array buffer at 5199e5c31af7Sopenharmony_ci * offset indices +i. 5200e5c31af7Sopenharmony_ci * << 5201e5c31af7Sopenharmony_ci * 5202e5c31af7Sopenharmony_ci * So for glDrawElements*() derivatives, we will be expecting gl_VertexID to be set to 5203e5c31af7Sopenharmony_ci * (basevertex + index[i] + i) 5204e5c31af7Sopenharmony_ci * 5205e5c31af7Sopenharmony_ci * DrawArrays does not support the "base vertex" concept at all: 5206e5c31af7Sopenharmony_ci * 5207e5c31af7Sopenharmony_ci * >> 5208e5c31af7Sopenharmony_ci * The index of any element transferred to the GL by DrawArraysOneInstance 5209e5c31af7Sopenharmony_ci * is referred to as its vertex ID, and may be read by a vertex shader as gl_VertexID. 5210e5c31af7Sopenharmony_ci * The vertex ID of the ith element transferred is first + i. 5211e5c31af7Sopenharmony_ci * << 5212e5c31af7Sopenharmony_ci * 5213e5c31af7Sopenharmony_ci * For regular draw calls, gl_VertexID should be of form: 5214e5c31af7Sopenharmony_ci * 5215e5c31af7Sopenharmony_ci * (first + i) 5216e5c31af7Sopenharmony_ci * 5217e5c31af7Sopenharmony_ci * In both cases, gl_InstanceID does NOT include the baseinstance value, as per: 5218e5c31af7Sopenharmony_ci * 5219e5c31af7Sopenharmony_ci * >> 5220e5c31af7Sopenharmony_ci * If an enabled vertex attribute array is instanced (it has a non-zero divisor as 5221e5c31af7Sopenharmony_ci * specified by VertexAttribDivisor), the element index that is transferred to the GL, 5222e5c31af7Sopenharmony_ci * for all vertices, is given by 5223e5c31af7Sopenharmony_ci * 5224e5c31af7Sopenharmony_ci * floor(instance / divisor) + baseinstance 5225e5c31af7Sopenharmony_ci * 5226e5c31af7Sopenharmony_ci * The value of instance may be read by a vertex shader as gl_InstanceID, as 5227e5c31af7Sopenharmony_ci * described in section 11.1.3.9 5228e5c31af7Sopenharmony_ci * << 5229e5c31af7Sopenharmony_ci */ 5230e5c31af7Sopenharmony_ci switch (draw_call_type) 5231e5c31af7Sopenharmony_ci { 5232e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED: 5233e5c31af7Sopenharmony_ci { 5234e5c31af7Sopenharmony_ci m_gl.drawElements(GL_POINTS, m_n_vertices_per_instance, GL_UNSIGNED_INT, 5235e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset); 5236e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElements() call failed."); 5237e5c31af7Sopenharmony_ci 5238e5c31af7Sopenharmony_ci draw_call_count = 1; 5239e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5240e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_n_vertices_per_instance; 5241e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5242e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5243e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5244e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5245e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5246e5c31af7Sopenharmony_ci 5247e5c31af7Sopenharmony_ci break; 5248e5c31af7Sopenharmony_ci } 5249e5c31af7Sopenharmony_ci 5250e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_BASE_VERTEX: 5251e5c31af7Sopenharmony_ci { 5252e5c31af7Sopenharmony_ci m_gl.drawElementsBaseVertex(GL_POINTS, m_n_vertices_per_instance, GL_UNSIGNED_INT, 5253e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset, 5254e5c31af7Sopenharmony_ci m_draw_call_baseVertex); 5255e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElementsBaseVertex() call failed."); 5256e5c31af7Sopenharmony_ci 5257e5c31af7Sopenharmony_ci draw_call_count = 1; 5258e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5259e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_baseVertex + m_n_vertices_per_instance; 5260e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5261e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5262e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5263e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5264e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5265e5c31af7Sopenharmony_ci 5266e5c31af7Sopenharmony_ci break; 5267e5c31af7Sopenharmony_ci } 5268e5c31af7Sopenharmony_ci 5269e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_INDIRECT: 5270e5c31af7Sopenharmony_ci { 5271e5c31af7Sopenharmony_ci m_gl.drawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, 5272e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_indexed_indirect_arg_offset); 5273e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElementsIndirect() call failed."); 5274e5c31af7Sopenharmony_ci 5275e5c31af7Sopenharmony_ci draw_call_count = 1; 5276e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5277e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = 5278e5c31af7Sopenharmony_ci m_draw_call_baseVertex + 5279e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[1] - m_data_bo_index_data_offset) / 5280e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5281e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5282e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5283e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[1]; 5284e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5285e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5286e5c31af7Sopenharmony_ci 5287e5c31af7Sopenharmony_ci break; 5288e5c31af7Sopenharmony_ci } 5289e5c31af7Sopenharmony_ci 5290e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_INDIRECT_MULTI: 5291e5c31af7Sopenharmony_ci { 5292e5c31af7Sopenharmony_ci m_gl.multiDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, 5293e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_indexed_mdi_arg_offset, 5294e5c31af7Sopenharmony_ci m_multidrawcall_drawcount, 0); /* stride */ 5295e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMultiDrawElementsIndirect() call failed."); 5296e5c31af7Sopenharmony_ci 5297e5c31af7Sopenharmony_ci draw_call_count = m_multidrawcall_drawcount; 5298e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5299e5c31af7Sopenharmony_ci draw_call_first_instance_id[1] = 0; 5300e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = 5301e5c31af7Sopenharmony_ci m_draw_call_baseVertex + 5302e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[0] - m_data_bo_index_data_offset) / 5303e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5304e5c31af7Sopenharmony_ci draw_call_first_vertex_id[1] = 5305e5c31af7Sopenharmony_ci m_draw_call_baseVertex + 5306e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[1] - m_data_bo_index_data_offset) / 5307e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5308e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5309e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5310e5c31af7Sopenharmony_ci draw_call_n_instances[1] = m_n_instances_to_test; 5311e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[0]; 5312e5c31af7Sopenharmony_ci draw_call_n_vertices[1] = m_multidrawcall_count[1]; 5313e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5314e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] = n_result_bytes_per_vertex * draw_call_n_vertices[1]; 5315e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0] + 5316e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] * draw_call_n_instances[1]; 5317e5c31af7Sopenharmony_ci 5318e5c31af7Sopenharmony_ci break; 5319e5c31af7Sopenharmony_ci } 5320e5c31af7Sopenharmony_ci 5321e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_MULTI: 5322e5c31af7Sopenharmony_ci { 5323e5c31af7Sopenharmony_ci m_gl.multiDrawElements(GL_POINTS, m_multidrawcall_count, GL_UNSIGNED_INT, m_multidrawcall_index, 5324e5c31af7Sopenharmony_ci m_multidrawcall_drawcount); 5325e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMultiDrawElements() call failed"); 5326e5c31af7Sopenharmony_ci 5327e5c31af7Sopenharmony_ci draw_call_count = m_multidrawcall_drawcount; 5328e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5329e5c31af7Sopenharmony_ci draw_call_first_instance_id[1] = 0; 5330e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = 5331e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[0] - m_data_bo_index_data_offset) / 5332e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5333e5c31af7Sopenharmony_ci draw_call_first_vertex_id[1] = 5334e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[1] - m_data_bo_index_data_offset) / 5335e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5336e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5337e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5338e5c31af7Sopenharmony_ci draw_call_n_instances[1] = 1; 5339e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[0]; 5340e5c31af7Sopenharmony_ci draw_call_n_vertices[1] = m_multidrawcall_count[1]; 5341e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_multidrawcall_count[0]; 5342e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] = n_result_bytes_per_vertex * m_multidrawcall_count[1]; 5343e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0] + 5344e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] * draw_call_n_instances[1]; 5345e5c31af7Sopenharmony_ci 5346e5c31af7Sopenharmony_ci break; 5347e5c31af7Sopenharmony_ci } 5348e5c31af7Sopenharmony_ci 5349e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_MULTI_BASE_VERTEX: 5350e5c31af7Sopenharmony_ci { 5351e5c31af7Sopenharmony_ci m_gl.multiDrawElementsBaseVertex(GL_POINTS, m_multidrawcall_count, GL_UNSIGNED_INT, 5352e5c31af7Sopenharmony_ci m_multidrawcall_index, m_multidrawcall_drawcount, 5353e5c31af7Sopenharmony_ci m_multidrawcall_basevertex); 5354e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMultiDrawElementsBaseVertex() call failed."); 5355e5c31af7Sopenharmony_ci 5356e5c31af7Sopenharmony_ci draw_call_count = m_multidrawcall_drawcount; 5357e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5358e5c31af7Sopenharmony_ci draw_call_first_instance_id[1] = 0; 5359e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = 5360e5c31af7Sopenharmony_ci m_multidrawcall_basevertex[0] + 5361e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[0] - m_data_bo_index_data_offset) / 5362e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5363e5c31af7Sopenharmony_ci draw_call_first_vertex_id[1] = 5364e5c31af7Sopenharmony_ci m_multidrawcall_basevertex[1] + 5365e5c31af7Sopenharmony_ci m_index_data[((unsigned int)(intptr_t)m_multidrawcall_index[1] - m_data_bo_index_data_offset) / 5366e5c31af7Sopenharmony_ci sizeof(unsigned int)]; 5367e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5368e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5369e5c31af7Sopenharmony_ci draw_call_n_instances[1] = 1; 5370e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[0]; 5371e5c31af7Sopenharmony_ci draw_call_n_vertices[1] = m_multidrawcall_count[1]; 5372e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_multidrawcall_count[0]; 5373e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] = n_result_bytes_per_vertex * m_multidrawcall_count[1]; 5374e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0] + 5375e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] * draw_call_n_instances[1]; 5376e5c31af7Sopenharmony_ci 5377e5c31af7Sopenharmony_ci break; 5378e5c31af7Sopenharmony_ci } 5379e5c31af7Sopenharmony_ci 5380e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED: 5381e5c31af7Sopenharmony_ci { 5382e5c31af7Sopenharmony_ci m_gl.drawElementsInstanced(GL_POINTS, m_n_vertices_per_instance, GL_UNSIGNED_INT, 5383e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset, 5384e5c31af7Sopenharmony_ci m_n_instances_to_test); 5385e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElementsInstanced() call failed."); 5386e5c31af7Sopenharmony_ci 5387e5c31af7Sopenharmony_ci draw_call_count = 1; 5388e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5389e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_index_data[0]; 5390e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5391e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5392e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5393e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5394e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5395e5c31af7Sopenharmony_ci 5396e5c31af7Sopenharmony_ci break; 5397e5c31af7Sopenharmony_ci } 5398e5c31af7Sopenharmony_ci 5399e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX: 5400e5c31af7Sopenharmony_ci { 5401e5c31af7Sopenharmony_ci m_gl.drawElementsInstancedBaseVertex(GL_POINTS, m_n_vertices_per_instance, GL_UNSIGNED_INT, 5402e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset, 5403e5c31af7Sopenharmony_ci m_n_instances_to_test, m_draw_call_baseVertex); 5404e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElementsInstancedBaseVertex() call failed."); 5405e5c31af7Sopenharmony_ci 5406e5c31af7Sopenharmony_ci draw_call_count = 1; 5407e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5408e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_baseVertex + m_index_data[0]; 5409e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5410e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5411e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5412e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5413e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5414e5c31af7Sopenharmony_ci 5415e5c31af7Sopenharmony_ci break; 5416e5c31af7Sopenharmony_ci } 5417e5c31af7Sopenharmony_ci 5418e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX_BASE_INSTANCE: 5419e5c31af7Sopenharmony_ci { 5420e5c31af7Sopenharmony_ci m_gl.drawElementsInstancedBaseVertexBaseInstance( 5421e5c31af7Sopenharmony_ci GL_POINTS, m_n_vertices_per_instance, GL_UNSIGNED_INT, 5422e5c31af7Sopenharmony_ci (const glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset, m_n_instances_to_test, 5423e5c31af7Sopenharmony_ci m_draw_call_baseVertex, m_draw_call_baseInstance); 5424e5c31af7Sopenharmony_ci 5425e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawElementsInstancedBaseVertexBaseInstance() call failed."); 5426e5c31af7Sopenharmony_ci 5427e5c31af7Sopenharmony_ci draw_call_count = 1; 5428e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5429e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_baseVertex + m_index_data[0]; 5430e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = false; 5431e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5432e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5433e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5434e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5435e5c31af7Sopenharmony_ci 5436e5c31af7Sopenharmony_ci break; 5437e5c31af7Sopenharmony_ci } 5438e5c31af7Sopenharmony_ci 5439e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR: 5440e5c31af7Sopenharmony_ci { 5441e5c31af7Sopenharmony_ci m_gl.drawArrays(GL_POINTS, m_draw_call_first, m_n_vertices_per_instance); 5442e5c31af7Sopenharmony_ci 5443e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() call failed"); 5444e5c31af7Sopenharmony_ci 5445e5c31af7Sopenharmony_ci draw_call_count = 1; 5446e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5447e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_first; 5448e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5449e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5450e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5451e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_n_vertices_per_instance; 5452e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5453e5c31af7Sopenharmony_ci 5454e5c31af7Sopenharmony_ci break; 5455e5c31af7Sopenharmony_ci } 5456e5c31af7Sopenharmony_ci 5457e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INDIRECT: 5458e5c31af7Sopenharmony_ci { 5459e5c31af7Sopenharmony_ci m_gl.drawArraysIndirect(GL_POINTS, (glw::GLvoid*)(intptr_t)m_data_bo_regular_indirect_arg_offset); 5460e5c31af7Sopenharmony_ci 5461e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArraysIndirect() call failed."); 5462e5c31af7Sopenharmony_ci 5463e5c31af7Sopenharmony_ci draw_call_count = 1; 5464e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5465e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_first; 5466e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5467e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5468e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[1]; 5469e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5470e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5471e5c31af7Sopenharmony_ci 5472e5c31af7Sopenharmony_ci break; 5473e5c31af7Sopenharmony_ci } 5474e5c31af7Sopenharmony_ci 5475e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INDIRECT_MULTI: 5476e5c31af7Sopenharmony_ci { 5477e5c31af7Sopenharmony_ci m_gl.multiDrawArraysIndirect(GL_POINTS, (glw::GLvoid*)(intptr_t)m_data_bo_regular_mdi_arg_offset, 5478e5c31af7Sopenharmony_ci m_multidrawcall_drawcount, 0); /* stride */ 5479e5c31af7Sopenharmony_ci 5480e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMultiDrawArraysIndirect() call failed."); 5481e5c31af7Sopenharmony_ci 5482e5c31af7Sopenharmony_ci draw_call_count = 2; 5483e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5484e5c31af7Sopenharmony_ci draw_call_first_instance_id[1] = 0; 5485e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_first; 5486e5c31af7Sopenharmony_ci draw_call_first_vertex_id[1] = m_draw_call_first; 5487e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5488e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5489e5c31af7Sopenharmony_ci draw_call_n_instances[1] = m_n_instances_to_test; 5490e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[0]; 5491e5c31af7Sopenharmony_ci draw_call_n_vertices[1] = m_multidrawcall_count[1]; 5492e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5493e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] = n_result_bytes_per_vertex * draw_call_n_vertices[1]; 5494e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0] + 5495e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] * draw_call_n_instances[1]; 5496e5c31af7Sopenharmony_ci 5497e5c31af7Sopenharmony_ci break; 5498e5c31af7Sopenharmony_ci } 5499e5c31af7Sopenharmony_ci 5500e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INSTANCED: 5501e5c31af7Sopenharmony_ci { 5502e5c31af7Sopenharmony_ci m_gl.drawArraysInstanced(GL_POINTS, m_draw_call_first, m_n_vertices_per_instance, 5503e5c31af7Sopenharmony_ci m_n_instances_to_test); 5504e5c31af7Sopenharmony_ci 5505e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArraysInstanced() call failed."); 5506e5c31af7Sopenharmony_ci 5507e5c31af7Sopenharmony_ci draw_call_count = 1; 5508e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5509e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_first; 5510e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5511e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5512e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5513e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5514e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5515e5c31af7Sopenharmony_ci 5516e5c31af7Sopenharmony_ci break; 5517e5c31af7Sopenharmony_ci } 5518e5c31af7Sopenharmony_ci 5519e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INSTANCED_BASE_INSTANCE: 5520e5c31af7Sopenharmony_ci { 5521e5c31af7Sopenharmony_ci m_gl.drawArraysInstancedBaseInstance(GL_POINTS, m_draw_call_first, m_n_vertices_per_instance, 5522e5c31af7Sopenharmony_ci m_n_instances_to_test, m_draw_call_baseInstance); 5523e5c31af7Sopenharmony_ci 5524e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArraysInstancedBaseInstance() call failed."); 5525e5c31af7Sopenharmony_ci 5526e5c31af7Sopenharmony_ci draw_call_count = 1; 5527e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5528e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_draw_call_first; 5529e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5530e5c31af7Sopenharmony_ci draw_call_n_instances[0] = m_n_instances_to_test; 5531e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_n_vertices_per_instance; 5532e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * draw_call_n_vertices[0]; 5533e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] * draw_call_n_instances[0]; 5534e5c31af7Sopenharmony_ci 5535e5c31af7Sopenharmony_ci break; 5536e5c31af7Sopenharmony_ci } 5537e5c31af7Sopenharmony_ci 5538e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_MULTI: 5539e5c31af7Sopenharmony_ci { 5540e5c31af7Sopenharmony_ci m_gl.multiDrawArrays(GL_POINTS, m_multidrawcall_first, m_multidrawcall_count, 5541e5c31af7Sopenharmony_ci m_multidrawcall_drawcount); 5542e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMultiDrawArrays() call failed."); 5543e5c31af7Sopenharmony_ci 5544e5c31af7Sopenharmony_ci draw_call_count = m_multidrawcall_drawcount; 5545e5c31af7Sopenharmony_ci draw_call_first_instance_id[0] = 0; 5546e5c31af7Sopenharmony_ci draw_call_first_instance_id[1] = 0; 5547e5c31af7Sopenharmony_ci draw_call_first_vertex_id[0] = m_multidrawcall_first[0]; 5548e5c31af7Sopenharmony_ci draw_call_first_vertex_id[1] = m_multidrawcall_first[1]; 5549e5c31af7Sopenharmony_ci draw_call_is_vertex_id_ascending = true; 5550e5c31af7Sopenharmony_ci draw_call_n_instances[0] = 1; 5551e5c31af7Sopenharmony_ci draw_call_n_instances[1] = 1; 5552e5c31af7Sopenharmony_ci draw_call_n_vertices[0] = m_multidrawcall_count[0]; 5553e5c31af7Sopenharmony_ci draw_call_n_vertices[1] = m_multidrawcall_count[1]; 5554e5c31af7Sopenharmony_ci n_result_bytes_per_instance[0] = n_result_bytes_per_vertex * m_multidrawcall_count[0]; 5555e5c31af7Sopenharmony_ci n_result_bytes_per_instance[1] = n_result_bytes_per_vertex * m_multidrawcall_count[1]; 5556e5c31af7Sopenharmony_ci n_result_bytes_total = n_result_bytes_per_instance[0] + n_result_bytes_per_instance[1]; 5557e5c31af7Sopenharmony_ci 5558e5c31af7Sopenharmony_ci break; 5559e5c31af7Sopenharmony_ci } 5560e5c31af7Sopenharmony_ci 5561e5c31af7Sopenharmony_ci default: 5562e5c31af7Sopenharmony_ci { 5563e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized draw call type"); 5564e5c31af7Sopenharmony_ci } 5565e5c31af7Sopenharmony_ci } /* switch (draw_call_type) */ 5566e5c31af7Sopenharmony_ci 5567e5c31af7Sopenharmony_ci DE_ASSERT(n_result_bytes_total <= m_result_bo_size); 5568e5c31af7Sopenharmony_ci 5569e5c31af7Sopenharmony_ci m_gl.endTransformFeedback(); 5570e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEndTransformFeedback() call failed."); 5571e5c31af7Sopenharmony_ci 5572e5c31af7Sopenharmony_ci /* Retrieve the captured data */ 5573e5c31af7Sopenharmony_ci glw::GLuint mappable_bo_id = m_helper_bo; 5574e5c31af7Sopenharmony_ci unsigned int mappable_bo_start_offset = 0; 5575e5c31af7Sopenharmony_ci 5576e5c31af7Sopenharmony_ci /* We cannot map the result BO storage directly into process space, since 5577e5c31af7Sopenharmony_ci * it's a sparse buffer. Copy the generated data to a helper BO and map 5578e5c31af7Sopenharmony_ci * that BO instead. */ 5579e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_result_bo); 5580e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_helper_bo); 5581e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 5582e5c31af7Sopenharmony_ci 5583e5c31af7Sopenharmony_ci if (is_ia_iteration) 5584e5c31af7Sopenharmony_ci { 5585e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 5586e5c31af7Sopenharmony_ci 0, /* writeOffset */ 5587e5c31af7Sopenharmony_ci n_result_bytes_total); 5588e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 5589e5c31af7Sopenharmony_ci } 5590e5c31af7Sopenharmony_ci else 5591e5c31af7Sopenharmony_ci { 5592e5c31af7Sopenharmony_ci DE_ASSERT((n_result_bytes_total % 2) == 0); 5593e5c31af7Sopenharmony_ci 5594e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 5595e5c31af7Sopenharmony_ci 0, /* writeOffset */ 5596e5c31af7Sopenharmony_ci n_result_bytes_total / 2); 5597e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 5598e5c31af7Sopenharmony_ci m_result_bo_size / 2, /* readOffset */ 5599e5c31af7Sopenharmony_ci m_result_bo_size / 2, /* writeOffset */ 5600e5c31af7Sopenharmony_ci n_result_bytes_total / 2); /* size */ 5601e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 5602e5c31af7Sopenharmony_ci } 5603e5c31af7Sopenharmony_ci 5604e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, mappable_bo_id); 5605e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 5606e5c31af7Sopenharmony_ci 5607e5c31af7Sopenharmony_ci result_ptr = (unsigned int*)m_gl.mapBufferRange(GL_ARRAY_BUFFER, mappable_bo_start_offset, m_result_bo_size, 5608e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 5609e5c31af7Sopenharmony_ci 5610e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBufferRange() call failed."); 5611e5c31af7Sopenharmony_ci 5612e5c31af7Sopenharmony_ci /* Verify the generated output */ 5613e5c31af7Sopenharmony_ci bool continue_checking = true; 5614e5c31af7Sopenharmony_ci glw::GLuint result_instance_id_stride = 0; 5615e5c31af7Sopenharmony_ci glw::GLuint result_vertex_id_stride = 0; 5616e5c31af7Sopenharmony_ci 5617e5c31af7Sopenharmony_ci if (is_ia_iteration) 5618e5c31af7Sopenharmony_ci { 5619e5c31af7Sopenharmony_ci result_instance_id_stride = 2; 5620e5c31af7Sopenharmony_ci result_vertex_id_stride = 2; 5621e5c31af7Sopenharmony_ci } 5622e5c31af7Sopenharmony_ci else 5623e5c31af7Sopenharmony_ci { 5624e5c31af7Sopenharmony_ci result_instance_id_stride = 1; 5625e5c31af7Sopenharmony_ci result_vertex_id_stride = 1; 5626e5c31af7Sopenharmony_ci } 5627e5c31af7Sopenharmony_ci 5628e5c31af7Sopenharmony_ci /* For all draw calls.. */ 5629e5c31af7Sopenharmony_ci for (int n_draw_call = 0; n_draw_call < draw_call_count && continue_checking; ++n_draw_call) 5630e5c31af7Sopenharmony_ci { 5631e5c31af7Sopenharmony_ci /* ..and resulting draw call instances.. */ 5632e5c31af7Sopenharmony_ci for (int n_instance = 0; n_instance < draw_call_n_instances[n_draw_call] && continue_checking; 5633e5c31af7Sopenharmony_ci ++n_instance) 5634e5c31af7Sopenharmony_ci { 5635e5c31af7Sopenharmony_ci DE_ASSERT((n_result_bytes_per_instance[n_draw_call] % sizeof(unsigned int)) == 0); 5636e5c31af7Sopenharmony_ci 5637e5c31af7Sopenharmony_ci /* Determine where the result TF data start from */ 5638e5c31af7Sopenharmony_ci const glw::GLuint expected_instance_id = draw_call_first_instance_id[n_draw_call] + n_instance; 5639e5c31af7Sopenharmony_ci glw::GLuint* result_instance_id_traveller_ptr = DE_NULL; 5640e5c31af7Sopenharmony_ci glw::GLuint* result_vertex_id_traveller_ptr = DE_NULL; 5641e5c31af7Sopenharmony_ci 5642e5c31af7Sopenharmony_ci if (is_ia_iteration) 5643e5c31af7Sopenharmony_ci { 5644e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr = result_ptr; 5645e5c31af7Sopenharmony_ci 5646e5c31af7Sopenharmony_ci for (int n_prev_draw_call = 0; n_prev_draw_call < n_draw_call; ++n_prev_draw_call) 5647e5c31af7Sopenharmony_ci { 5648e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr += draw_call_n_instances[n_prev_draw_call] * 5649e5c31af7Sopenharmony_ci n_result_bytes_per_instance[n_prev_draw_call] / 5650e5c31af7Sopenharmony_ci sizeof(unsigned int); 5651e5c31af7Sopenharmony_ci } 5652e5c31af7Sopenharmony_ci 5653e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr += 5654e5c31af7Sopenharmony_ci n_instance * n_result_bytes_per_instance[n_draw_call] / sizeof(unsigned int); 5655e5c31af7Sopenharmony_ci result_vertex_id_traveller_ptr = result_instance_id_traveller_ptr + 1; 5656e5c31af7Sopenharmony_ci } /* if (is_ia_iteration) */ 5657e5c31af7Sopenharmony_ci else 5658e5c31af7Sopenharmony_ci { 5659e5c31af7Sopenharmony_ci DE_ASSERT((m_result_bo_size % 2) == 0); 5660e5c31af7Sopenharmony_ci 5661e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr = result_ptr; 5662e5c31af7Sopenharmony_ci 5663e5c31af7Sopenharmony_ci for (int n_prev_draw_call = 0; n_prev_draw_call < n_draw_call; ++n_prev_draw_call) 5664e5c31af7Sopenharmony_ci { 5665e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr += 5666e5c31af7Sopenharmony_ci draw_call_n_instances[n_prev_draw_call] * 5667e5c31af7Sopenharmony_ci n_result_bytes_per_instance[n_prev_draw_call] / 5668e5c31af7Sopenharmony_ci 2 / /* instance id..instance id data | vertex id..vertex id data */ 5669e5c31af7Sopenharmony_ci sizeof(unsigned int); 5670e5c31af7Sopenharmony_ci } 5671e5c31af7Sopenharmony_ci 5672e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr += 5673e5c31af7Sopenharmony_ci n_instance * n_result_bytes_per_instance[n_draw_call] / 2 / sizeof(unsigned int); 5674e5c31af7Sopenharmony_ci result_vertex_id_traveller_ptr = 5675e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr + (m_result_bo_size / 2) / sizeof(unsigned int); 5676e5c31af7Sopenharmony_ci } 5677e5c31af7Sopenharmony_ci 5678e5c31af7Sopenharmony_ci /* Start checking the generated output */ 5679e5c31af7Sopenharmony_ci for (int n_point = 0; n_point < draw_call_n_vertices[n_draw_call] && continue_checking; ++n_point) 5680e5c31af7Sopenharmony_ci { 5681e5c31af7Sopenharmony_ci glw::GLuint expected_vertex_id = 1; 5682e5c31af7Sopenharmony_ci glw::GLuint retrieved_instance_id = 2; 5683e5c31af7Sopenharmony_ci glw::GLuint retrieved_vertex_id = 3; 5684e5c31af7Sopenharmony_ci 5685e5c31af7Sopenharmony_ci if (draw_call_is_vertex_id_ascending) 5686e5c31af7Sopenharmony_ci { 5687e5c31af7Sopenharmony_ci expected_vertex_id = draw_call_first_vertex_id[n_draw_call] + n_point; 5688e5c31af7Sopenharmony_ci } /* if (draw_call_is_vertex_id_ascending) */ 5689e5c31af7Sopenharmony_ci else 5690e5c31af7Sopenharmony_ci { 5691e5c31af7Sopenharmony_ci if (draw_call_first_vertex_id[n_draw_call] >= n_point) 5692e5c31af7Sopenharmony_ci { 5693e5c31af7Sopenharmony_ci expected_vertex_id = draw_call_first_vertex_id[n_draw_call] - n_point; 5694e5c31af7Sopenharmony_ci } 5695e5c31af7Sopenharmony_ci else 5696e5c31af7Sopenharmony_ci { 5697e5c31af7Sopenharmony_ci expected_vertex_id = 0; 5698e5c31af7Sopenharmony_ci } 5699e5c31af7Sopenharmony_ci } 5700e5c31af7Sopenharmony_ci 5701e5c31af7Sopenharmony_ci /* Only perform the check if the offsets refer to pages with physical backing. 5702e5c31af7Sopenharmony_ci * 5703e5c31af7Sopenharmony_ci * Note that, on platforms, whose page size % 4 != 0, the values can land partially out of bounds, 5704e5c31af7Sopenharmony_ci * and partially in the safe zone. In such cases, skip the verification. */ 5705e5c31af7Sopenharmony_ci const bool result_instance_id_page_has_physical_backing = 5706e5c31af7Sopenharmony_ci (((((char*)result_instance_id_traveller_ptr - (char*)result_ptr) / m_page_size) % 2) == 5707e5c31af7Sopenharmony_ci 0) && 5708e5c31af7Sopenharmony_ci ((((((char*)result_instance_id_traveller_ptr - (char*)result_ptr) + sizeof(unsigned int) - 5709e5c31af7Sopenharmony_ci 1) / 5710e5c31af7Sopenharmony_ci m_page_size) % 5711e5c31af7Sopenharmony_ci 2) == 0); 5712e5c31af7Sopenharmony_ci const bool result_vertex_id_page_has_physical_backing = 5713e5c31af7Sopenharmony_ci (((((char*)result_vertex_id_traveller_ptr - (char*)result_ptr) / m_page_size) % 2) == 0) && 5714e5c31af7Sopenharmony_ci ((((((char*)result_vertex_id_traveller_ptr - (char*)result_ptr) + sizeof(unsigned int) - 5715e5c31af7Sopenharmony_ci 1) / 5716e5c31af7Sopenharmony_ci m_page_size) % 5717e5c31af7Sopenharmony_ci 2) == 0); 5718e5c31af7Sopenharmony_ci 5719e5c31af7Sopenharmony_ci retrieved_instance_id = *result_instance_id_traveller_ptr; 5720e5c31af7Sopenharmony_ci result_instance_id_traveller_ptr += result_instance_id_stride; 5721e5c31af7Sopenharmony_ci 5722e5c31af7Sopenharmony_ci retrieved_vertex_id = *result_vertex_id_traveller_ptr; 5723e5c31af7Sopenharmony_ci result_vertex_id_traveller_ptr += result_vertex_id_stride; 5724e5c31af7Sopenharmony_ci 5725e5c31af7Sopenharmony_ci if ((result_instance_id_page_has_physical_backing && 5726e5c31af7Sopenharmony_ci retrieved_instance_id != expected_instance_id) || 5727e5c31af7Sopenharmony_ci (result_vertex_id_page_has_physical_backing && retrieved_vertex_id != expected_vertex_id)) 5728e5c31af7Sopenharmony_ci { 5729e5c31af7Sopenharmony_ci m_testCtx.getLog() 5730e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "For " 5731e5c31af7Sopenharmony_ci "[" 5732e5c31af7Sopenharmony_ci << getName() << "]" 5733e5c31af7Sopenharmony_ci ", sparse BO flags " 5734e5c31af7Sopenharmony_ci "[" 5735e5c31af7Sopenharmony_ci << SparseBufferTestUtilities::getSparseBOFlagsString(sparse_bo_storage_flags) 5736e5c31af7Sopenharmony_ci << "]" 5737e5c31af7Sopenharmony_ci ", draw call type " 5738e5c31af7Sopenharmony_ci << getDrawCallTypeString(draw_call_type) << " at index " 5739e5c31af7Sopenharmony_ci "[" 5740e5c31af7Sopenharmony_ci << n_draw_call << " / " << (draw_call_count - 1) << "]" 5741e5c31af7Sopenharmony_ci ", TF mode " 5742e5c31af7Sopenharmony_ci "[" 5743e5c31af7Sopenharmony_ci << ((is_ia_iteration) ? "interleaved attribs" : "separate attribs") << "]" 5744e5c31af7Sopenharmony_ci << ", instance " 5745e5c31af7Sopenharmony_ci "[" 5746e5c31af7Sopenharmony_ci << n_instance << " / " << (draw_call_n_instances[n_draw_call] - 1) << "]" 5747e5c31af7Sopenharmony_ci << ", point at index " 5748e5c31af7Sopenharmony_ci "[" 5749e5c31af7Sopenharmony_ci << n_point << " / " << (draw_call_n_vertices[n_draw_call] - 1) << "]" 5750e5c31af7Sopenharmony_ci << ", VS-level gl_VertexID was equal to " 5751e5c31af7Sopenharmony_ci "[" 5752e5c31af7Sopenharmony_ci << retrieved_vertex_id << "]" 5753e5c31af7Sopenharmony_ci " and gl_InstanceID was set to " 5754e5c31af7Sopenharmony_ci "[" 5755e5c31af7Sopenharmony_ci << retrieved_instance_id << "]" 5756e5c31af7Sopenharmony_ci ", whereas gl_VertexID of value " 5757e5c31af7Sopenharmony_ci "[" 5758e5c31af7Sopenharmony_ci << expected_vertex_id << "]" 5759e5c31af7Sopenharmony_ci " and gl_InstanceID of value " 5760e5c31af7Sopenharmony_ci "[" 5761e5c31af7Sopenharmony_ci << expected_instance_id << "]" 5762e5c31af7Sopenharmony_ci " were anticipated." 5763e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 5764e5c31af7Sopenharmony_ci 5765e5c31af7Sopenharmony_ci continue_checking = false; 5766e5c31af7Sopenharmony_ci result = false; 5767e5c31af7Sopenharmony_ci 5768e5c31af7Sopenharmony_ci break; 5769e5c31af7Sopenharmony_ci } /* if (reported gl_InstanceID / gl_VertexID values are wrong) */ 5770e5c31af7Sopenharmony_ci } /* for (all drawn points) */ 5771e5c31af7Sopenharmony_ci } /* for (all instances) */ 5772e5c31af7Sopenharmony_ci 5773e5c31af7Sopenharmony_ci /* Release memory pages we have allocated for the transform feed-back. 5774e5c31af7Sopenharmony_ci * 5775e5c31af7Sopenharmony_ci * NOTE: For some iterations, this call will attempt to de-commit pages which 5776e5c31af7Sopenharmony_ci * have not been assigned physical backing. This is a valid behavior, 5777e5c31af7Sopenharmony_ci * as per spec. 5778e5c31af7Sopenharmony_ci */ 5779e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 5780e5c31af7Sopenharmony_ci m_result_bo_size_rounded, GL_FALSE); /* commit */ 5781e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 5782e5c31af7Sopenharmony_ci } /* for (all draw call) */ 5783e5c31af7Sopenharmony_ci 5784e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_ARRAY_BUFFER); 5785e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 5786e5c31af7Sopenharmony_ci } /* for (all draw call types) */ 5787e5c31af7Sopenharmony_ci } /* for (both TF modes) */ 5788e5c31af7Sopenharmony_ci 5789e5c31af7Sopenharmony_ci return result; 5790e5c31af7Sopenharmony_ci} 5791e5c31af7Sopenharmony_ci 5792e5c31af7Sopenharmony_ci/** Converts the internal enum to a null-terminated text string. 5793e5c31af7Sopenharmony_ci * 5794e5c31af7Sopenharmony_ci * @param draw_call Draw call type to return a string for. 5795e5c31af7Sopenharmony_ci * 5796e5c31af7Sopenharmony_ci * @return The requested string or "[?!]", if the enum was not recognized. 5797e5c31af7Sopenharmony_ci **/ 5798e5c31af7Sopenharmony_ciconst char* TransformFeedbackBufferStorageTestCase::getDrawCallTypeString(_draw_call draw_call) 5799e5c31af7Sopenharmony_ci{ 5800e5c31af7Sopenharmony_ci const char* result = "[?!]"; 5801e5c31af7Sopenharmony_ci 5802e5c31af7Sopenharmony_ci switch (draw_call) 5803e5c31af7Sopenharmony_ci { 5804e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED: 5805e5c31af7Sopenharmony_ci result = "glDrawElements()"; 5806e5c31af7Sopenharmony_ci break; 5807e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_BASE_VERTEX: 5808e5c31af7Sopenharmony_ci result = "glDrawElementsBaseVertex()"; 5809e5c31af7Sopenharmony_ci break; 5810e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_INDIRECT: 5811e5c31af7Sopenharmony_ci result = "glDrawElementsIndirect()"; 5812e5c31af7Sopenharmony_ci break; 5813e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_INDIRECT_MULTI: 5814e5c31af7Sopenharmony_ci result = "glMultiDrawElementIndirect()"; 5815e5c31af7Sopenharmony_ci break; 5816e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_MULTI: 5817e5c31af7Sopenharmony_ci result = "glMultiDrawElements()"; 5818e5c31af7Sopenharmony_ci break; 5819e5c31af7Sopenharmony_ci case DRAW_CALL_INDEXED_MULTI_BASE_VERTEX: 5820e5c31af7Sopenharmony_ci result = "glMultiDrawElementsBaseVertex()"; 5821e5c31af7Sopenharmony_ci break; 5822e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED: 5823e5c31af7Sopenharmony_ci result = "glDrawElementsInstanced()"; 5824e5c31af7Sopenharmony_ci break; 5825e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX: 5826e5c31af7Sopenharmony_ci result = "glDrawElementsInstancedBaseVertex()"; 5827e5c31af7Sopenharmony_ci break; 5828e5c31af7Sopenharmony_ci case DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX_BASE_INSTANCE: 5829e5c31af7Sopenharmony_ci result = "glDrawElementsInstancedBaseVertexBaseInstance()"; 5830e5c31af7Sopenharmony_ci break; 5831e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR: 5832e5c31af7Sopenharmony_ci result = "glDrawArrays()"; 5833e5c31af7Sopenharmony_ci break; 5834e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INDIRECT: 5835e5c31af7Sopenharmony_ci result = "glDrawArraysIndirect()"; 5836e5c31af7Sopenharmony_ci break; 5837e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INDIRECT_MULTI: 5838e5c31af7Sopenharmony_ci result = "glMultiDrawArraysIndirect()"; 5839e5c31af7Sopenharmony_ci break; 5840e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INSTANCED: 5841e5c31af7Sopenharmony_ci result = "glDrawArraysInstanced()"; 5842e5c31af7Sopenharmony_ci break; 5843e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_INSTANCED_BASE_INSTANCE: 5844e5c31af7Sopenharmony_ci result = "glDrawArraysInstancedBaseInstance()"; 5845e5c31af7Sopenharmony_ci break; 5846e5c31af7Sopenharmony_ci case DRAW_CALL_REGULAR_MULTI: 5847e5c31af7Sopenharmony_ci result = "glMultiDrawArrays()"; 5848e5c31af7Sopenharmony_ci break; 5849e5c31af7Sopenharmony_ci 5850e5c31af7Sopenharmony_ci default: 5851e5c31af7Sopenharmony_ci break; 5852e5c31af7Sopenharmony_ci } /* switch (draw_call) */ 5853e5c31af7Sopenharmony_ci 5854e5c31af7Sopenharmony_ci return result; 5855e5c31af7Sopenharmony_ci} 5856e5c31af7Sopenharmony_ci 5857e5c31af7Sopenharmony_ci/** Initializes test data buffer, and then sets up: 5858e5c31af7Sopenharmony_ci * 5859e5c31af7Sopenharmony_ci * - an immutable buffer object (id stored in m_data_bo), to which the test data 5860e5c31af7Sopenharmony_ci * is copied. 5861e5c31af7Sopenharmony_ci * - a mappable immutable buffer object (id stored in m_helper_bo) 5862e5c31af7Sopenharmony_ci **/ 5863e5c31af7Sopenharmony_civoid TransformFeedbackBufferStorageTestCase::initDataBO() 5864e5c31af7Sopenharmony_ci{ 5865e5c31af7Sopenharmony_ci initTestData(); 5866e5c31af7Sopenharmony_ci 5867e5c31af7Sopenharmony_ci /* Initialize data BO (the BO which holds index + indirect draw call args */ 5868e5c31af7Sopenharmony_ci DE_ASSERT(m_data_bo == 0); 5869e5c31af7Sopenharmony_ci 5870e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_data_bo); 5871e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 5872e5c31af7Sopenharmony_ci 5873e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_data_bo); 5874e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 5875e5c31af7Sopenharmony_ci 5876e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_ARRAY_BUFFER, m_data_bo_size, DE_NULL, GL_DYNAMIC_STORAGE_BIT); 5877e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 5878e5c31af7Sopenharmony_ci 5879e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ARRAY_BUFFER, m_data_bo_indexed_indirect_arg_offset, m_indirect_arg_data_size, 5880e5c31af7Sopenharmony_ci m_indirect_arg_data); 5881e5c31af7Sopenharmony_ci m_gl.bufferSubData(GL_ARRAY_BUFFER, m_data_bo_index_data_offset, m_index_data_size, m_index_data); 5882e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferSubData() call(s) failed."); 5883e5c31af7Sopenharmony_ci 5884e5c31af7Sopenharmony_ci /* Generate & bind a helper BO we need to copy the data to from the sparse BO 5885e5c31af7Sopenharmony_ci * if direct mapping is not possible. 5886e5c31af7Sopenharmony_ci */ 5887e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo_size != 0); 5888e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo == 0); 5889e5c31af7Sopenharmony_ci DE_ASSERT(m_helper_bo == 0); 5890e5c31af7Sopenharmony_ci 5891e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 5892e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 5893e5c31af7Sopenharmony_ci 5894e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_helper_bo); 5895e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 5896e5c31af7Sopenharmony_ci 5897e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_ARRAY_BUFFER, m_result_bo_size, DE_NULL, /* data */ 5898e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 5899e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 5900e5c31af7Sopenharmony_ci} 5901e5c31af7Sopenharmony_ci 5902e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 5903e5c31af7Sopenharmony_ci * 5904e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 5905e5c31af7Sopenharmony_ci */ 5906e5c31af7Sopenharmony_cibool TransformFeedbackBufferStorageTestCase::initTestCaseGlobal() 5907e5c31af7Sopenharmony_ci{ 5908e5c31af7Sopenharmony_ci bool result = true; 5909e5c31af7Sopenharmony_ci 5910e5c31af7Sopenharmony_ci /* Initialize test program object */ 5911e5c31af7Sopenharmony_ci static const char* tf_varyings[] = { "instance_id", "vertex_id" }; 5912e5c31af7Sopenharmony_ci static const unsigned int n_tf_varyings = sizeof(tf_varyings) / sizeof(tf_varyings[0]); 5913e5c31af7Sopenharmony_ci static const char* vs_body = "#version 420 core\n" 5914e5c31af7Sopenharmony_ci "\n" 5915e5c31af7Sopenharmony_ci "out uint instance_id;\n" 5916e5c31af7Sopenharmony_ci "out uint vertex_id;\n" 5917e5c31af7Sopenharmony_ci "\n" 5918e5c31af7Sopenharmony_ci "void main()\n" 5919e5c31af7Sopenharmony_ci "{\n" 5920e5c31af7Sopenharmony_ci " instance_id = gl_InstanceID;\n" 5921e5c31af7Sopenharmony_ci " vertex_id = gl_VertexID;\n" 5922e5c31af7Sopenharmony_ci "}\n"; 5923e5c31af7Sopenharmony_ci 5924e5c31af7Sopenharmony_ci m_po_ia = SparseBufferTestUtilities::createProgram(m_gl, DE_NULL, /* fs_body_parts */ 5925e5c31af7Sopenharmony_ci 0, /* n_fs_body_parts */ 5926e5c31af7Sopenharmony_ci &vs_body, 1, /* n_vs_body_parts */ 5927e5c31af7Sopenharmony_ci DE_NULL, /* attribute_names */ 5928e5c31af7Sopenharmony_ci DE_NULL, /* attribute_locations */ 5929e5c31af7Sopenharmony_ci 0, /* n_attribute_properties */ 5930e5c31af7Sopenharmony_ci tf_varyings, n_tf_varyings, GL_INTERLEAVED_ATTRIBS); 5931e5c31af7Sopenharmony_ci 5932e5c31af7Sopenharmony_ci m_po_sa = SparseBufferTestUtilities::createProgram(m_gl, DE_NULL, /* fs_body_parts */ 5933e5c31af7Sopenharmony_ci 0, /* n_fs_body_parts */ 5934e5c31af7Sopenharmony_ci &vs_body, 1, /* n_vs_body_parts */ 5935e5c31af7Sopenharmony_ci DE_NULL, /* attribute_names */ 5936e5c31af7Sopenharmony_ci DE_NULL, /* attribute_locations */ 5937e5c31af7Sopenharmony_ci 0, /* n_attribute_properties */ 5938e5c31af7Sopenharmony_ci tf_varyings, n_tf_varyings, GL_SEPARATE_ATTRIBS); 5939e5c31af7Sopenharmony_ci 5940e5c31af7Sopenharmony_ci if (m_po_ia == 0 || m_po_sa == 0) 5941e5c31af7Sopenharmony_ci { 5942e5c31af7Sopenharmony_ci result = false; 5943e5c31af7Sopenharmony_ci 5944e5c31af7Sopenharmony_ci goto end; 5945e5c31af7Sopenharmony_ci } 5946e5c31af7Sopenharmony_ci 5947e5c31af7Sopenharmony_ci /* Generate & bind a VAO */ 5948e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 5949e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 5950e5c31af7Sopenharmony_ci 5951e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 5952e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 5953e5c31af7Sopenharmony_ci 5954e5c31af7Sopenharmony_ci initDataBO(); 5955e5c31af7Sopenharmony_ci 5956e5c31af7Sopenharmony_ciend: 5957e5c31af7Sopenharmony_ci return result; 5958e5c31af7Sopenharmony_ci} 5959e5c31af7Sopenharmony_ci 5960e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 5961e5c31af7Sopenharmony_ci * 5962e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 5963e5c31af7Sopenharmony_ci * to release these objects. 5964e5c31af7Sopenharmony_ci **/ 5965e5c31af7Sopenharmony_cibool TransformFeedbackBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 5966e5c31af7Sopenharmony_ci{ 5967e5c31af7Sopenharmony_ci bool result = true; 5968e5c31af7Sopenharmony_ci 5969e5c31af7Sopenharmony_ci /* Initialize buffer objects used by the test case */ 5970e5c31af7Sopenharmony_ci m_result_bo = sparse_bo; 5971e5c31af7Sopenharmony_ci 5972e5c31af7Sopenharmony_ci /* Quick check */ 5973e5c31af7Sopenharmony_ci DE_ASSERT(m_data_bo != 0); 5974e5c31af7Sopenharmony_ci 5975e5c31af7Sopenharmony_ci return result; 5976e5c31af7Sopenharmony_ci} 5977e5c31af7Sopenharmony_ci 5978e5c31af7Sopenharmony_ci/** Sets up client-side data arrays, later uploaded to the test buffer object, used as a source for: 5979e5c31af7Sopenharmony_ci * 5980e5c31af7Sopenharmony_ci * - index data 5981e5c31af7Sopenharmony_ci * - indirect draw call arguments 5982e5c31af7Sopenharmony_ci * - multi draw call arguments 5983e5c31af7Sopenharmony_ci **/ 5984e5c31af7Sopenharmony_civoid TransformFeedbackBufferStorageTestCase::initTestData() 5985e5c31af7Sopenharmony_ci{ 5986e5c31af7Sopenharmony_ci /* We need the result data to span across at least m_min_memory_page_span memory pages. 5987e5c31af7Sopenharmony_ci * Each vertex outputs 2 * sizeof(int) = 8 bytes of data. 5988e5c31af7Sopenharmony_ci * 5989e5c31af7Sopenharmony_ci * For simplicity, we assume the number of bytes we calculate here is per instance. */ 5990e5c31af7Sopenharmony_ci m_n_vertices_per_instance = static_cast<unsigned int>((m_page_size * m_min_memory_page_span / (sizeof(int) * 2))); 5991e5c31af7Sopenharmony_ci 5992e5c31af7Sopenharmony_ci /* Let: 5993e5c31af7Sopenharmony_ci * 5994e5c31af7Sopenharmony_ci * index_data_size = (n of vertices per a single instance) * sizeof(unsigned int) 5995e5c31af7Sopenharmony_ci * indexed_indirect_size = sizeof(glDrawElementsIndirect() indirect arguments) 5996e5c31af7Sopenharmony_ci * indexed_mdi_size = sizeof(glMultiDrawElementsIndirect() indirect arguments) * 2 (single instance & multiple instances case) 5997e5c31af7Sopenharmony_ci * regular_indirect_size = sizeof(glDrawArraysIndirect() indirect arguments) 5998e5c31af7Sopenharmony_ci * regular_mdi_size = sizeof(glMultiDrawArraysIndirect() indirect arguments) * 2 (single instance & multiple instances case) 5999e5c31af7Sopenharmony_ci * 6000e5c31af7Sopenharmony_ci * 6001e5c31af7Sopenharmony_ci * The layout we will use for the data buffer is: 6002e5c31af7Sopenharmony_ci * 6003e5c31af7Sopenharmony_ci * [indexed indirect arg data // Size: indexed_indirect_size bytes] 6004e5c31af7Sopenharmony_ci * [indexed MDI arg data // Size: indexed_mdi_size bytes] 6005e5c31af7Sopenharmony_ci * [regular indirect arg data // Size: regular_indirect_size bytes] 6006e5c31af7Sopenharmony_ci * [regular MDI arg data // Size: regular_mdi_size bytes] 6007e5c31af7Sopenharmony_ci * [index data // Size: index_data_size bytes] 6008e5c31af7Sopenharmony_ci */ 6009e5c31af7Sopenharmony_ci const unsigned int indexed_indirect_size = sizeof(unsigned int) * 5 /* as per GL spec */; 6010e5c31af7Sopenharmony_ci const unsigned int indexed_mdi_size = sizeof(unsigned int) * 5 /* as per GL spec */ * 2; /* draw calls */ 6011e5c31af7Sopenharmony_ci const unsigned int regular_indirect_size = sizeof(unsigned int) * 4; /* as per GL spec */ 6012e5c31af7Sopenharmony_ci const unsigned int regular_mdi_size = sizeof(unsigned int) * 4 /* as per GL spec */ * 2; /* draw calls */ 6013e5c31af7Sopenharmony_ci 6014e5c31af7Sopenharmony_ci m_data_bo_indexed_indirect_arg_offset = 0; 6015e5c31af7Sopenharmony_ci m_data_bo_indexed_mdi_arg_offset = m_data_bo_indexed_indirect_arg_offset + indexed_indirect_size; 6016e5c31af7Sopenharmony_ci m_data_bo_regular_indirect_arg_offset = m_data_bo_indexed_mdi_arg_offset + indexed_mdi_size; 6017e5c31af7Sopenharmony_ci m_data_bo_regular_mdi_arg_offset = m_data_bo_regular_indirect_arg_offset + regular_indirect_size; 6018e5c31af7Sopenharmony_ci m_data_bo_index_data_offset = m_data_bo_regular_mdi_arg_offset + regular_mdi_size; 6019e5c31af7Sopenharmony_ci 6020e5c31af7Sopenharmony_ci /* Form the index data */ 6021e5c31af7Sopenharmony_ci DE_ASSERT(m_index_data == DE_NULL); 6022e5c31af7Sopenharmony_ci DE_ASSERT(m_draw_call_firstIndex == sizeof(unsigned int)); 6023e5c31af7Sopenharmony_ci 6024e5c31af7Sopenharmony_ci m_index_data_size = static_cast<glw::GLuint>( 6025e5c31af7Sopenharmony_ci (1 /* extra index, as per m_draw_call_firstIndex */ + m_n_vertices_per_instance) * sizeof(unsigned int)); 6026e5c31af7Sopenharmony_ci m_index_data = (unsigned int*)new unsigned char[m_index_data_size]; 6027e5c31af7Sopenharmony_ci 6028e5c31af7Sopenharmony_ci for (unsigned int n_index = 0; n_index < m_n_vertices_per_instance + 1; ++n_index) 6029e5c31af7Sopenharmony_ci { 6030e5c31af7Sopenharmony_ci m_index_data[n_index] = m_n_vertices_per_instance - n_index; 6031e5c31af7Sopenharmony_ci } /* for (all available indices) */ 6032e5c31af7Sopenharmony_ci 6033e5c31af7Sopenharmony_ci /* Set multi draw-call arguments */ 6034e5c31af7Sopenharmony_ci m_multidrawcall_basevertex[0] = m_draw_call_baseVertex; 6035e5c31af7Sopenharmony_ci m_multidrawcall_basevertex[1] = 257; 6036e5c31af7Sopenharmony_ci m_multidrawcall_count[0] = m_n_vertices_per_instance; 6037e5c31af7Sopenharmony_ci m_multidrawcall_count[1] = m_n_vertices_per_instance - 16; 6038e5c31af7Sopenharmony_ci m_multidrawcall_drawcount = 2; 6039e5c31af7Sopenharmony_ci m_multidrawcall_first[0] = 0; 6040e5c31af7Sopenharmony_ci m_multidrawcall_first[1] = m_draw_call_first; 6041e5c31af7Sopenharmony_ci m_multidrawcall_index[0] = (glw::GLvoid*)(intptr_t)m_data_bo_index_data_offset; 6042e5c31af7Sopenharmony_ci m_multidrawcall_index[1] = (glw::GLvoid*)(intptr_t)(m_data_bo_index_data_offset + m_draw_call_firstIndex); 6043e5c31af7Sopenharmony_ci m_multidrawcall_primcount = m_n_instances_to_test; 6044e5c31af7Sopenharmony_ci 6045e5c31af7Sopenharmony_ci /* Form the indirect data */ 6046e5c31af7Sopenharmony_ci DE_ASSERT(m_indirect_arg_data == DE_NULL); 6047e5c31af7Sopenharmony_ci 6048e5c31af7Sopenharmony_ci m_indirect_arg_data_size = m_data_bo_index_data_offset - m_data_bo_indexed_indirect_arg_offset; 6049e5c31af7Sopenharmony_ci m_indirect_arg_data = (unsigned int*)new unsigned char[m_indirect_arg_data_size]; 6050e5c31af7Sopenharmony_ci 6051e5c31af7Sopenharmony_ci unsigned int* indirect_arg_data_traveller_ptr = m_indirect_arg_data; 6052e5c31af7Sopenharmony_ci 6053e5c31af7Sopenharmony_ci /* 1. Indexed indirect arg data */ 6054e5c31af7Sopenharmony_ci DE_ASSERT(((unsigned int)(intptr_t)(m_multidrawcall_index[1]) % sizeof(unsigned int)) == 0); 6055e5c31af7Sopenharmony_ci 6056e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_multidrawcall_count[1]; /* count */ 6057e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6058e5c31af7Sopenharmony_ci 6059e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_n_instances_to_test; /* primCount */ 6060e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6061e5c31af7Sopenharmony_ci 6062e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = static_cast<unsigned int>((unsigned int)(intptr_t)(m_multidrawcall_index[1]) / 6063e5c31af7Sopenharmony_ci sizeof(unsigned int)); /* firstIndex */ 6064e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6065e5c31af7Sopenharmony_ci 6066e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseVertex; /* baseVertex */ 6067e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6068e5c31af7Sopenharmony_ci 6069e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseInstance; /* baseInstance */ 6070e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6071e5c31af7Sopenharmony_ci 6072e5c31af7Sopenharmony_ci /* 2. Indexed MDI arg data */ 6073e5c31af7Sopenharmony_ci for (unsigned int n_draw_call = 0; n_draw_call < 2; ++n_draw_call) 6074e5c31af7Sopenharmony_ci { 6075e5c31af7Sopenharmony_ci DE_ASSERT(((unsigned int)(intptr_t)(m_multidrawcall_index[n_draw_call]) % sizeof(unsigned int)) == 0); 6076e5c31af7Sopenharmony_ci 6077e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_multidrawcall_count[n_draw_call]; /* count */ 6078e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6079e5c31af7Sopenharmony_ci 6080e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = (n_draw_call == 0) ? 1 : m_n_instances_to_test; /* primCount */ 6081e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6082e5c31af7Sopenharmony_ci 6083e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = static_cast<unsigned int>( 6084e5c31af7Sopenharmony_ci (unsigned int)(intptr_t)(m_multidrawcall_index[n_draw_call]) / sizeof(unsigned int)); /* firstIndex */ 6085e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6086e5c31af7Sopenharmony_ci 6087e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseVertex; 6088e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6089e5c31af7Sopenharmony_ci 6090e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseInstance; 6091e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6092e5c31af7Sopenharmony_ci } /* for (both single-instanced and multi-instanced cases) */ 6093e5c31af7Sopenharmony_ci 6094e5c31af7Sopenharmony_ci /* 3. Regular indirect arg data */ 6095e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_multidrawcall_count[1]; /* count */ 6096e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6097e5c31af7Sopenharmony_ci 6098e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_n_instances_to_test; /* primCount */ 6099e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6100e5c31af7Sopenharmony_ci 6101e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_first; /* first */ 6102e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6103e5c31af7Sopenharmony_ci 6104e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseInstance; /* baseInstance */ 6105e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6106e5c31af7Sopenharmony_ci 6107e5c31af7Sopenharmony_ci /* 4. Regular MDI arg data */ 6108e5c31af7Sopenharmony_ci for (unsigned int n_draw_call = 0; n_draw_call < 2; ++n_draw_call) 6109e5c31af7Sopenharmony_ci { 6110e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_multidrawcall_count[n_draw_call]; /* count */ 6111e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6112e5c31af7Sopenharmony_ci 6113e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = (n_draw_call == 0) ? 1 : m_n_instances_to_test; /* instanceCount */ 6114e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6115e5c31af7Sopenharmony_ci 6116e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_first; /* first */ 6117e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6118e5c31af7Sopenharmony_ci 6119e5c31af7Sopenharmony_ci *indirect_arg_data_traveller_ptr = m_draw_call_baseInstance; /* baseInstance */ 6120e5c31af7Sopenharmony_ci indirect_arg_data_traveller_ptr++; 6121e5c31af7Sopenharmony_ci } /* for (both single-instanced and multi-instanced cases) */ 6122e5c31af7Sopenharmony_ci 6123e5c31af7Sopenharmony_ci /* Store the number of bytes we will need to allocate for the data BO */ 6124e5c31af7Sopenharmony_ci m_data_bo_size = m_index_data_size + m_indirect_arg_data_size; 6125e5c31af7Sopenharmony_ci 6126e5c31af7Sopenharmony_ci /* Determine the number of bytes we will need to have at hand to hold all the captured TF varyings. 6127e5c31af7Sopenharmony_ci * The equation below takes into account the heaviest draw call the test will ever issue. 6128e5c31af7Sopenharmony_ci */ 6129e5c31af7Sopenharmony_ci m_result_bo_size = 6130e5c31af7Sopenharmony_ci static_cast<glw::GLuint>(sizeof(unsigned int) * 2 /* TF varyings per vertex */ * 6131e5c31af7Sopenharmony_ci (m_multidrawcall_count[0] + m_multidrawcall_count[1]) * m_multidrawcall_primcount); 6132e5c31af7Sopenharmony_ci m_result_bo_size_rounded = SparseBufferTestUtilities::alignOffset(m_result_bo_size, m_page_size); 6133e5c31af7Sopenharmony_ci 6134e5c31af7Sopenharmony_ci /* Quick checks */ 6135e5c31af7Sopenharmony_ci DE_ASSERT(m_min_memory_page_span > 0); 6136e5c31af7Sopenharmony_ci DE_ASSERT(m_page_size > 0); 6137e5c31af7Sopenharmony_ci DE_ASSERT(m_result_bo_size >= (m_min_memory_page_span * m_page_size)); 6138e5c31af7Sopenharmony_ci} 6139e5c31af7Sopenharmony_ci 6140e5c31af7Sopenharmony_ci/** Constructor. 6141e5c31af7Sopenharmony_ci * 6142e5c31af7Sopenharmony_ci * @param gl GL entry-points container 6143e5c31af7Sopenharmony_ci * @param testContext CTS test context 6144e5c31af7Sopenharmony_ci * @param page_size Page size, as reported by implementation for the GL_SPARSE_BUFFER_PAGE_SIZE_ARB query. 6145e5c31af7Sopenharmony_ci * @param pGLBufferPageCommitmentARB Func ptr to glBufferPageCommitmentARB() entry-point. 6146e5c31af7Sopenharmony_ci */ 6147e5c31af7Sopenharmony_ciUniformBufferStorageTestCase::UniformBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, 6148e5c31af7Sopenharmony_ci glw::GLint page_size) 6149e5c31af7Sopenharmony_ci : m_gl(gl) 6150e5c31af7Sopenharmony_ci , m_gl_uniform_buffer_offset_alignment_value(0) 6151e5c31af7Sopenharmony_ci , m_helper_bo(0) 6152e5c31af7Sopenharmony_ci , m_n_pages_to_use(4) 6153e5c31af7Sopenharmony_ci , m_n_ubo_uints(0) 6154e5c31af7Sopenharmony_ci , m_page_size(page_size) 6155e5c31af7Sopenharmony_ci , m_po(0) 6156e5c31af7Sopenharmony_ci , m_sparse_bo(0) 6157e5c31af7Sopenharmony_ci , m_sparse_bo_data_size(0) 6158e5c31af7Sopenharmony_ci , m_sparse_bo_data_start_offset(0) 6159e5c31af7Sopenharmony_ci , m_sparse_bo_size(0) 6160e5c31af7Sopenharmony_ci , m_sparse_bo_size_rounded(0) 6161e5c31af7Sopenharmony_ci , m_testCtx(testContext) 6162e5c31af7Sopenharmony_ci , m_tf_bo(0) 6163e5c31af7Sopenharmony_ci , m_ubo_data(DE_NULL) 6164e5c31af7Sopenharmony_ci , m_vao(0) 6165e5c31af7Sopenharmony_ci{ 6166e5c31af7Sopenharmony_ci if ((m_n_pages_to_use % 2) != 0) 6167e5c31af7Sopenharmony_ci { 6168e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 6169e5c31af7Sopenharmony_ci } 6170e5c31af7Sopenharmony_ci} 6171e5c31af7Sopenharmony_ci 6172e5c31af7Sopenharmony_ci/** Releases all GL objects used across all test case iterations. 6173e5c31af7Sopenharmony_ci * 6174e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 6175e5c31af7Sopenharmony_ci */ 6176e5c31af7Sopenharmony_civoid UniformBufferStorageTestCase::deinitTestCaseGlobal() 6177e5c31af7Sopenharmony_ci{ 6178e5c31af7Sopenharmony_ci if (m_helper_bo != 0) 6179e5c31af7Sopenharmony_ci { 6180e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_helper_bo); 6181e5c31af7Sopenharmony_ci 6182e5c31af7Sopenharmony_ci m_helper_bo = 0; 6183e5c31af7Sopenharmony_ci } 6184e5c31af7Sopenharmony_ci 6185e5c31af7Sopenharmony_ci if (m_po != 0) 6186e5c31af7Sopenharmony_ci { 6187e5c31af7Sopenharmony_ci m_gl.deleteProgram(m_po); 6188e5c31af7Sopenharmony_ci 6189e5c31af7Sopenharmony_ci m_po = 0; 6190e5c31af7Sopenharmony_ci } 6191e5c31af7Sopenharmony_ci 6192e5c31af7Sopenharmony_ci if (m_tf_bo != 0) 6193e5c31af7Sopenharmony_ci { 6194e5c31af7Sopenharmony_ci m_gl.deleteBuffers(1, &m_tf_bo); 6195e5c31af7Sopenharmony_ci 6196e5c31af7Sopenharmony_ci m_tf_bo = 0; 6197e5c31af7Sopenharmony_ci } 6198e5c31af7Sopenharmony_ci 6199e5c31af7Sopenharmony_ci if (m_ubo_data != DE_NULL) 6200e5c31af7Sopenharmony_ci { 6201e5c31af7Sopenharmony_ci delete[] m_ubo_data; 6202e5c31af7Sopenharmony_ci 6203e5c31af7Sopenharmony_ci m_ubo_data = DE_NULL; 6204e5c31af7Sopenharmony_ci } 6205e5c31af7Sopenharmony_ci 6206e5c31af7Sopenharmony_ci if (m_vao != 0) 6207e5c31af7Sopenharmony_ci { 6208e5c31af7Sopenharmony_ci m_gl.deleteVertexArrays(1, &m_vao); 6209e5c31af7Sopenharmony_ci 6210e5c31af7Sopenharmony_ci m_vao = 0; 6211e5c31af7Sopenharmony_ci } 6212e5c31af7Sopenharmony_ci} 6213e5c31af7Sopenharmony_ci 6214e5c31af7Sopenharmony_ci/** Releases temporary GL objects, created specifically for one test case iteration. */ 6215e5c31af7Sopenharmony_civoid UniformBufferStorageTestCase::deinitTestCaseIteration() 6216e5c31af7Sopenharmony_ci{ 6217e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 6218e5c31af7Sopenharmony_ci { 6219e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 6220e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6221e5c31af7Sopenharmony_ci 6222e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ 6223e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 6224e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 6225e5c31af7Sopenharmony_ci 6226e5c31af7Sopenharmony_ci m_sparse_bo = 0; 6227e5c31af7Sopenharmony_ci } 6228e5c31af7Sopenharmony_ci} 6229e5c31af7Sopenharmony_ci 6230e5c31af7Sopenharmony_ci/** Executes a single test iteration. The BufferStorage test will call this method 6231e5c31af7Sopenharmony_ci * numerously during its life-time, testing various valid flag combinations applied 6232e5c31af7Sopenharmony_ci * to the tested sparse buffer object at glBufferStorage() call time. 6233e5c31af7Sopenharmony_ci * 6234e5c31af7Sopenharmony_ci * @param sparse_bo_storage_flags <flags> argument, used by the test in the glBufferStorage() 6235e5c31af7Sopenharmony_ci * call to set up the sparse buffer's storage. 6236e5c31af7Sopenharmony_ci * 6237e5c31af7Sopenharmony_ci * @return true if the test case executed correctly, false otherwise. 6238e5c31af7Sopenharmony_ci */ 6239e5c31af7Sopenharmony_cibool UniformBufferStorageTestCase::execute(glw::GLuint sparse_bo_storage_flags) 6240e5c31af7Sopenharmony_ci{ 6241e5c31af7Sopenharmony_ci (void)sparse_bo_storage_flags; 6242e5c31af7Sopenharmony_ci bool result = true; 6243e5c31af7Sopenharmony_ci 6244e5c31af7Sopenharmony_ci m_gl.bindBufferRange(GL_UNIFORM_BUFFER, 0, /* index */ 6245e5c31af7Sopenharmony_ci m_sparse_bo, m_sparse_bo_data_start_offset, m_n_ubo_uints * 4 * sizeof(unsigned int)); 6246e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase() call failed."); 6247e5c31af7Sopenharmony_ci 6248e5c31af7Sopenharmony_ci /* Run the test in three iterations: 6249e5c31af7Sopenharmony_ci * 6250e5c31af7Sopenharmony_ci * 1) Whole UBO storage is backed by physical backing. 6251e5c31af7Sopenharmony_ci * 2) Half the UBO storage is backed by physical backing. 6252e5c31af7Sopenharmony_ci * 3) None of the UBO storage is backed by physical backing. 6253e5c31af7Sopenharmony_ci */ 6254e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 3; ++n_iteration) 6255e5c31af7Sopenharmony_ci { 6256e5c31af7Sopenharmony_ci bool result_local = true; 6257e5c31af7Sopenharmony_ci unsigned int ubo_commit_size = 0; 6258e5c31af7Sopenharmony_ci unsigned int ubo_commit_start_offset = 0; 6259e5c31af7Sopenharmony_ci 6260e5c31af7Sopenharmony_ci switch (n_iteration) 6261e5c31af7Sopenharmony_ci { 6262e5c31af7Sopenharmony_ci case 0: 6263e5c31af7Sopenharmony_ci { 6264e5c31af7Sopenharmony_ci ubo_commit_size = m_sparse_bo_data_size; 6265e5c31af7Sopenharmony_ci ubo_commit_start_offset = m_sparse_bo_data_start_offset; 6266e5c31af7Sopenharmony_ci 6267e5c31af7Sopenharmony_ci break; 6268e5c31af7Sopenharmony_ci } 6269e5c31af7Sopenharmony_ci 6270e5c31af7Sopenharmony_ci case 1: 6271e5c31af7Sopenharmony_ci { 6272e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_data_size % 2) == 0); 6273e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_data_size % m_page_size) == 0); 6274e5c31af7Sopenharmony_ci 6275e5c31af7Sopenharmony_ci ubo_commit_size = m_sparse_bo_data_size / 2; 6276e5c31af7Sopenharmony_ci ubo_commit_start_offset = m_sparse_bo_data_start_offset; 6277e5c31af7Sopenharmony_ci 6278e5c31af7Sopenharmony_ci break; 6279e5c31af7Sopenharmony_ci } 6280e5c31af7Sopenharmony_ci 6281e5c31af7Sopenharmony_ci case 2: 6282e5c31af7Sopenharmony_ci { 6283e5c31af7Sopenharmony_ci /* The default values do just fine */ 6284e5c31af7Sopenharmony_ci 6285e5c31af7Sopenharmony_ci break; 6286e5c31af7Sopenharmony_ci } 6287e5c31af7Sopenharmony_ci 6288e5c31af7Sopenharmony_ci default: 6289e5c31af7Sopenharmony_ci { 6290e5c31af7Sopenharmony_ci TCU_FAIL("Invalid iteration index"); 6291e5c31af7Sopenharmony_ci } 6292e5c31af7Sopenharmony_ci } /* switch (n_iteration) */ 6293e5c31af7Sopenharmony_ci 6294e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_UNIFORM_BUFFER, ubo_commit_start_offset, ubo_commit_size, GL_TRUE); /* commit */ 6295e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 6296e5c31af7Sopenharmony_ci 6297e5c31af7Sopenharmony_ci /* Copy the UBO data */ 6298e5c31af7Sopenharmony_ci m_gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, /* readOffset */ 6299e5c31af7Sopenharmony_ci ubo_commit_start_offset, ubo_commit_size); 6300e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCopyBufferSubData() call failed."); 6301e5c31af7Sopenharmony_ci 6302e5c31af7Sopenharmony_ci /* Issue the draw call to execute the test */ 6303e5c31af7Sopenharmony_ci m_gl.useProgram(m_po); 6304e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() call failed."); 6305e5c31af7Sopenharmony_ci 6306e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo); 6307e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6308e5c31af7Sopenharmony_ci 6309e5c31af7Sopenharmony_ci m_gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 6310e5c31af7Sopenharmony_ci m_tf_bo); 6311e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase() call failed."); 6312e5c31af7Sopenharmony_ci 6313e5c31af7Sopenharmony_ci m_gl.beginTransformFeedback(GL_POINTS); 6314e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBeginTransformFeedback() call failed."); 6315e5c31af7Sopenharmony_ci 6316e5c31af7Sopenharmony_ci m_gl.drawArrays(GL_POINTS, 0, /* first */ 6317e5c31af7Sopenharmony_ci m_n_ubo_uints); 6318e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() call failed."); 6319e5c31af7Sopenharmony_ci 6320e5c31af7Sopenharmony_ci m_gl.endTransformFeedback(); 6321e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEndTransformFeedback() call failed."); 6322e5c31af7Sopenharmony_ci 6323e5c31af7Sopenharmony_ci /* Retrieve the data, verify the output */ 6324e5c31af7Sopenharmony_ci const unsigned int* result_data_ptr = 6325e5c31af7Sopenharmony_ci (const unsigned int*)m_gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 6326e5c31af7Sopenharmony_ci unsigned int ubo_data_offset = m_sparse_bo_data_start_offset; 6327e5c31af7Sopenharmony_ci 6328e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer() call failed."); 6329e5c31af7Sopenharmony_ci 6330e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < m_n_ubo_uints && result_local; 6331e5c31af7Sopenharmony_ci ++n_vertex, ubo_data_offset = static_cast<unsigned int>(ubo_data_offset + 4 * sizeof(unsigned int))) 6332e5c31af7Sopenharmony_ci { 6333e5c31af7Sopenharmony_ci const bool is_ub_data_physically_backed = (ubo_data_offset >= ubo_commit_start_offset && 6334e5c31af7Sopenharmony_ci ubo_data_offset < (ubo_commit_start_offset + ubo_commit_size)) ? 6335e5c31af7Sopenharmony_ci 1 : 6336e5c31af7Sopenharmony_ci 0; 6337e5c31af7Sopenharmony_ci unsigned int expected_value = -1; 6338e5c31af7Sopenharmony_ci const unsigned int retrieved_value = result_data_ptr[n_vertex]; 6339e5c31af7Sopenharmony_ci 6340e5c31af7Sopenharmony_ci if (is_ub_data_physically_backed) 6341e5c31af7Sopenharmony_ci { 6342e5c31af7Sopenharmony_ci expected_value = 1; 6343e5c31af7Sopenharmony_ci } 6344e5c31af7Sopenharmony_ci else 6345e5c31af7Sopenharmony_ci { 6346e5c31af7Sopenharmony_ci /* Read ops applied against non-committed sparse buffers return an undefined value. 6347e5c31af7Sopenharmony_ci */ 6348e5c31af7Sopenharmony_ci continue; 6349e5c31af7Sopenharmony_ci } 6350e5c31af7Sopenharmony_ci 6351e5c31af7Sopenharmony_ci if (expected_value != retrieved_value) 6352e5c31af7Sopenharmony_ci { 6353e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value " 6354e5c31af7Sopenharmony_ci "(" 6355e5c31af7Sopenharmony_ci << retrieved_value << ") " 6356e5c31af7Sopenharmony_ci "found at index " 6357e5c31af7Sopenharmony_ci "(" 6358e5c31af7Sopenharmony_ci << n_vertex << ")" 6359e5c31af7Sopenharmony_ci ", instead of the expected value " 6360e5c31af7Sopenharmony_ci "(" 6361e5c31af7Sopenharmony_ci << expected_value << ")" 6362e5c31af7Sopenharmony_ci ". Iteration index:" 6363e5c31af7Sopenharmony_ci "(" 6364e5c31af7Sopenharmony_ci << n_iteration << ")" << tcu::TestLog::EndMessage; 6365e5c31af7Sopenharmony_ci 6366e5c31af7Sopenharmony_ci result_local = false; 6367e5c31af7Sopenharmony_ci } 6368e5c31af7Sopenharmony_ci } 6369e5c31af7Sopenharmony_ci 6370e5c31af7Sopenharmony_ci result &= result_local; 6371e5c31af7Sopenharmony_ci 6372e5c31af7Sopenharmony_ci /* Clean up in anticipation for the next iteration */ 6373e5c31af7Sopenharmony_ci static const unsigned char data_zero_r8 = 0; 6374e5c31af7Sopenharmony_ci 6375e5c31af7Sopenharmony_ci m_gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 6376e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer() call failed."); 6377e5c31af7Sopenharmony_ci 6378e5c31af7Sopenharmony_ci m_gl.clearBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &data_zero_r8); 6379e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glClearBufferData() call failed."); 6380e5c31af7Sopenharmony_ci 6381e5c31af7Sopenharmony_ci m_gl.bufferPageCommitmentARB(GL_UNIFORM_BUFFER, 0, m_sparse_bo_size_rounded, GL_FALSE); /* commit */ 6382e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferPageCommitmentARB() call failed."); 6383e5c31af7Sopenharmony_ci } /* for (all three iterations) */ 6384e5c31af7Sopenharmony_ci 6385e5c31af7Sopenharmony_ci return result; 6386e5c31af7Sopenharmony_ci} 6387e5c31af7Sopenharmony_ci 6388e5c31af7Sopenharmony_ci/** Initializes GL objects used across all test case iterations. 6389e5c31af7Sopenharmony_ci * 6390e5c31af7Sopenharmony_ci * Called once during BufferStorage test run-time. 6391e5c31af7Sopenharmony_ci */ 6392e5c31af7Sopenharmony_cibool UniformBufferStorageTestCase::initTestCaseGlobal() 6393e5c31af7Sopenharmony_ci{ 6394e5c31af7Sopenharmony_ci /* Cache GL constant values */ 6395e5c31af7Sopenharmony_ci glw::GLint gl_max_uniform_block_size_value = 0; 6396e5c31af7Sopenharmony_ci 6397e5c31af7Sopenharmony_ci m_gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &gl_max_uniform_block_size_value); 6398e5c31af7Sopenharmony_ci m_gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_gl_uniform_buffer_offset_alignment_value); 6399e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetIntegerv() call(s) failed."); 6400e5c31af7Sopenharmony_ci 6401e5c31af7Sopenharmony_ci /* Determine the number of uints we can access at once from a single VS invocation */ 6402e5c31af7Sopenharmony_ci DE_ASSERT(gl_max_uniform_block_size_value >= 1); 6403e5c31af7Sopenharmony_ci 6404e5c31af7Sopenharmony_ci /* Account for the fact that in std140 layout, array elements will be rounded up 6405e5c31af7Sopenharmony_ci * to the size of a vec4, i.e. 16 bytes. */ 6406e5c31af7Sopenharmony_ci m_n_ubo_uints = static_cast<unsigned int>(gl_max_uniform_block_size_value / (4 * sizeof(unsigned int))); 6407e5c31af7Sopenharmony_ci 6408e5c31af7Sopenharmony_ci /* Prepare the test program */ 6409e5c31af7Sopenharmony_ci std::stringstream vs_body_define_sstream; 6410e5c31af7Sopenharmony_ci std::string vs_body_define_string; 6411e5c31af7Sopenharmony_ci 6412e5c31af7Sopenharmony_ci const char* tf_varying = "result"; 6413e5c31af7Sopenharmony_ci const char* vs_body_preamble = "#version 140\n" 6414e5c31af7Sopenharmony_ci "\n"; 6415e5c31af7Sopenharmony_ci 6416e5c31af7Sopenharmony_ci const char* vs_body_main = "\n" 6417e5c31af7Sopenharmony_ci "layout(std140) uniform data\n" 6418e5c31af7Sopenharmony_ci "{\n" 6419e5c31af7Sopenharmony_ci " uint data_input[N_UBO_UINTS];" 6420e5c31af7Sopenharmony_ci "};\n" 6421e5c31af7Sopenharmony_ci "\n" 6422e5c31af7Sopenharmony_ci "out uint result;\n" 6423e5c31af7Sopenharmony_ci "\n" 6424e5c31af7Sopenharmony_ci "void main()\n" 6425e5c31af7Sopenharmony_ci "{\n" 6426e5c31af7Sopenharmony_ci " result = (data_input[gl_VertexID] == uint(gl_VertexID) ) ? 1u : 0u;\n" 6427e5c31af7Sopenharmony_ci "}"; 6428e5c31af7Sopenharmony_ci 6429e5c31af7Sopenharmony_ci vs_body_define_sstream << "#define N_UBO_UINTS (" << m_n_ubo_uints << ")\n"; 6430e5c31af7Sopenharmony_ci vs_body_define_string = vs_body_define_sstream.str(); 6431e5c31af7Sopenharmony_ci 6432e5c31af7Sopenharmony_ci const char* vs_body_parts[] = { vs_body_preamble, vs_body_define_string.c_str(), vs_body_main }; 6433e5c31af7Sopenharmony_ci const unsigned int n_vs_body_parts = sizeof(vs_body_parts) / sizeof(vs_body_parts[0]); 6434e5c31af7Sopenharmony_ci 6435e5c31af7Sopenharmony_ci m_po = SparseBufferTestUtilities::createProgram(m_gl, DE_NULL, /* fs_body_parts */ 6436e5c31af7Sopenharmony_ci 0, /* n_fs_body_parts */ 6437e5c31af7Sopenharmony_ci vs_body_parts, n_vs_body_parts, DE_NULL, /* attribute_names */ 6438e5c31af7Sopenharmony_ci DE_NULL, /* attribute_locations */ 6439e5c31af7Sopenharmony_ci 0, /* n_attribute_properties */ 6440e5c31af7Sopenharmony_ci &tf_varying, 1, /* n_tf_varyings */ 6441e5c31af7Sopenharmony_ci GL_INTERLEAVED_ATTRIBS); 6442e5c31af7Sopenharmony_ci 6443e5c31af7Sopenharmony_ci if (m_po == 0) 6444e5c31af7Sopenharmony_ci { 6445e5c31af7Sopenharmony_ci TCU_FAIL("The test program failed to link"); 6446e5c31af7Sopenharmony_ci } 6447e5c31af7Sopenharmony_ci 6448e5c31af7Sopenharmony_ci /* Determine the number of bytes the sparse buffer needs to be able to have 6449e5c31af7Sopenharmony_ci * a physical backing or. 6450e5c31af7Sopenharmony_ci * 6451e5c31af7Sopenharmony_ci * We will provide physical backing for twice the required size and then use 6452e5c31af7Sopenharmony_ci * a region in the centered of the allocated memory block. 6453e5c31af7Sopenharmony_ci * 6454e5c31af7Sopenharmony_ci * NOTE: We need to be able to use an offset which is aligned to both the page size, 6455e5c31af7Sopenharmony_ci * and the UB offset alignment. 6456e5c31af7Sopenharmony_ci * */ 6457e5c31af7Sopenharmony_ci m_sparse_bo_data_size = static_cast<unsigned int>(sizeof(unsigned int) * m_page_size); 6458e5c31af7Sopenharmony_ci m_sparse_bo_size = (m_page_size * m_gl_uniform_buffer_offset_alignment_value) * 2; 6459e5c31af7Sopenharmony_ci 6460e5c31af7Sopenharmony_ci if (m_sparse_bo_size < m_sparse_bo_data_size * 2) 6461e5c31af7Sopenharmony_ci { 6462e5c31af7Sopenharmony_ci m_sparse_bo_size = m_sparse_bo_data_size * 2; 6463e5c31af7Sopenharmony_ci } 6464e5c31af7Sopenharmony_ci 6465e5c31af7Sopenharmony_ci m_sparse_bo_size_rounded = m_sparse_bo_size; /* rounded to the page size by default */ 6466e5c31af7Sopenharmony_ci m_sparse_bo_data_start_offset = (m_sparse_bo_size - m_sparse_bo_data_size) / 2; 6467e5c31af7Sopenharmony_ci 6468e5c31af7Sopenharmony_ci /* Set up the TFBO storage */ 6469e5c31af7Sopenharmony_ci const unsigned tfbo_size = static_cast<unsigned int>(sizeof(unsigned int) * m_n_ubo_uints); 6470e5c31af7Sopenharmony_ci 6471e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_tf_bo); 6472e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 6473e5c31af7Sopenharmony_ci 6474e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo); 6475e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6476e5c31af7Sopenharmony_ci 6477e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, tfbo_size, DE_NULL, /* data */ 6478e5c31af7Sopenharmony_ci GL_MAP_READ_BIT); 6479e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 6480e5c31af7Sopenharmony_ci 6481e5c31af7Sopenharmony_ci /* Set up the UBO contents. We're actually setting up an immutable BO here, 6482e5c31af7Sopenharmony_ci * but we'll use its contents for a copy op, executed at the beginning of 6483e5c31af7Sopenharmony_ci * each iteration. 6484e5c31af7Sopenharmony_ci */ 6485e5c31af7Sopenharmony_ci unsigned int* ubo_data_traveller_ptr = DE_NULL; 6486e5c31af7Sopenharmony_ci 6487e5c31af7Sopenharmony_ci DE_ASSERT((m_sparse_bo_data_size % sizeof(unsigned int)) == 0); 6488e5c31af7Sopenharmony_ci 6489e5c31af7Sopenharmony_ci m_ubo_data = new (std::nothrow) unsigned char[m_sparse_bo_data_size]; 6490e5c31af7Sopenharmony_ci ubo_data_traveller_ptr = (unsigned int*)m_ubo_data; 6491e5c31af7Sopenharmony_ci 6492e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < m_sparse_bo_data_size / (4 * sizeof(unsigned int)); ++n_vertex) 6493e5c31af7Sopenharmony_ci { 6494e5c31af7Sopenharmony_ci *ubo_data_traveller_ptr = n_vertex; 6495e5c31af7Sopenharmony_ci ubo_data_traveller_ptr += 4; 6496e5c31af7Sopenharmony_ci } 6497e5c31af7Sopenharmony_ci 6498e5c31af7Sopenharmony_ci m_gl.genBuffers(1, &m_helper_bo); 6499e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers() call failed."); 6500e5c31af7Sopenharmony_ci 6501e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 6502e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6503e5c31af7Sopenharmony_ci 6504e5c31af7Sopenharmony_ci /* Set up helper BO storage */ 6505e5c31af7Sopenharmony_ci m_gl.bufferStorage(GL_COPY_READ_BUFFER, m_sparse_bo_data_size, m_ubo_data, 0); /* flags */ 6506e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferStorage() call failed."); 6507e5c31af7Sopenharmony_ci 6508e5c31af7Sopenharmony_ci /* Set up the VAO */ 6509e5c31af7Sopenharmony_ci m_gl.genVertexArrays(1, &m_vao); 6510e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays() call failed."); 6511e5c31af7Sopenharmony_ci 6512e5c31af7Sopenharmony_ci m_gl.bindVertexArray(m_vao); 6513e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray() call failed."); 6514e5c31af7Sopenharmony_ci 6515e5c31af7Sopenharmony_ci return true; 6516e5c31af7Sopenharmony_ci} 6517e5c31af7Sopenharmony_ci 6518e5c31af7Sopenharmony_ci/** Initializes GL objects which are needed for a single test case iteration. 6519e5c31af7Sopenharmony_ci * 6520e5c31af7Sopenharmony_ci * deinitTestCaseIteration() will be called after the test case is executed in ::execute() 6521e5c31af7Sopenharmony_ci * to release these objects. 6522e5c31af7Sopenharmony_ci **/ 6523e5c31af7Sopenharmony_cibool UniformBufferStorageTestCase::initTestCaseIteration(glw::GLuint sparse_bo) 6524e5c31af7Sopenharmony_ci{ 6525e5c31af7Sopenharmony_ci bool result = true; 6526e5c31af7Sopenharmony_ci 6527e5c31af7Sopenharmony_ci /* Cache the BO id, if not cached already */ 6528e5c31af7Sopenharmony_ci DE_ASSERT(m_sparse_bo == 0 || m_sparse_bo == sparse_bo); 6529e5c31af7Sopenharmony_ci 6530e5c31af7Sopenharmony_ci m_sparse_bo = sparse_bo; 6531e5c31af7Sopenharmony_ci 6532e5c31af7Sopenharmony_ci /* Set up the sparse buffer bindings. */ 6533e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_WRITE_BUFFER, m_sparse_bo); 6534e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call(s) failed."); 6535e5c31af7Sopenharmony_ci 6536e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_COPY_READ_BUFFER, m_helper_bo); 6537e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6538e5c31af7Sopenharmony_ci 6539e5c31af7Sopenharmony_ci m_gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo); 6540e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer() call failed."); 6541e5c31af7Sopenharmony_ci 6542e5c31af7Sopenharmony_ci return result; 6543e5c31af7Sopenharmony_ci} 6544e5c31af7Sopenharmony_ci 6545e5c31af7Sopenharmony_ci/** Constructor. 6546e5c31af7Sopenharmony_ci * 6547e5c31af7Sopenharmony_ci * @param context Rendering context 6548e5c31af7Sopenharmony_ci * @param name Test name 6549e5c31af7Sopenharmony_ci * @param description Test description 6550e5c31af7Sopenharmony_ci */ 6551e5c31af7Sopenharmony_ciBufferStorageTest::BufferStorageTest(deqp::Context& context) 6552e5c31af7Sopenharmony_ci : TestCase(context, "BufferStorageTest", "Tests various interactions between sparse buffers and other API areas") 6553e5c31af7Sopenharmony_ci , m_sparse_bo(0) 6554e5c31af7Sopenharmony_ci{ 6555e5c31af7Sopenharmony_ci /* Left blank intentionally */ 6556e5c31af7Sopenharmony_ci} 6557e5c31af7Sopenharmony_ci 6558e5c31af7Sopenharmony_ci/** Tears down any GL objects set up to run the test. */ 6559e5c31af7Sopenharmony_civoid BufferStorageTest::deinit() 6560e5c31af7Sopenharmony_ci{ 6561e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6562e5c31af7Sopenharmony_ci 6563e5c31af7Sopenharmony_ci /* De-initialize all test the test cases */ 6564e5c31af7Sopenharmony_ci for (TestCasesVectorIterator itTestCase = m_testCases.begin(); itTestCase != m_testCases.end(); ++itTestCase) 6565e5c31af7Sopenharmony_ci { 6566e5c31af7Sopenharmony_ci (*itTestCase)->deinitTestCaseGlobal(); 6567e5c31af7Sopenharmony_ci 6568e5c31af7Sopenharmony_ci delete (*itTestCase); 6569e5c31af7Sopenharmony_ci } /* for (all registered test case objects) */ 6570e5c31af7Sopenharmony_ci 6571e5c31af7Sopenharmony_ci m_testCases.clear(); 6572e5c31af7Sopenharmony_ci 6573e5c31af7Sopenharmony_ci if (m_sparse_bo != 0) 6574e5c31af7Sopenharmony_ci { 6575e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_sparse_bo); 6576e5c31af7Sopenharmony_ci 6577e5c31af7Sopenharmony_ci m_sparse_bo = 0; 6578e5c31af7Sopenharmony_ci } 6579e5c31af7Sopenharmony_ci} 6580e5c31af7Sopenharmony_ci 6581e5c31af7Sopenharmony_ci/** Stub init method */ 6582e5c31af7Sopenharmony_civoid BufferStorageTest::init() 6583e5c31af7Sopenharmony_ci{ 6584e5c31af7Sopenharmony_ci /* We cannot initialize the test case objects here as there are cases where there 6585e5c31af7Sopenharmony_ci * is no rendering context bound to the thread, when this method is called. */ 6586e5c31af7Sopenharmony_ci} 6587e5c31af7Sopenharmony_ci 6588e5c31af7Sopenharmony_ci/** Fills m_testCases with BufferStorageTestCase instances which implement the sub-cases 6589e5c31af7Sopenharmony_ci * for the second test described in the CTS_ARB_sparse_buffer test specification 6590e5c31af7Sopenharmony_ci **/ 6591e5c31af7Sopenharmony_civoid BufferStorageTest::initTestCases() 6592e5c31af7Sopenharmony_ci{ 6593e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6594e5c31af7Sopenharmony_ci glw::GLint page_size = 0; 6595e5c31af7Sopenharmony_ci 6596e5c31af7Sopenharmony_ci /* Retrieve "sparse buffer" GL constant values and entry-point func ptrs */ 6597e5c31af7Sopenharmony_ci gl.getIntegerv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &page_size); 6598e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_SPARSE_BUFFER_PAGE_SIZE_ARB pname"); 6599e5c31af7Sopenharmony_ci 6600e5c31af7Sopenharmony_ci /* Initialize all test case objects: 6601e5c31af7Sopenharmony_ci * 6602e5c31af7Sopenharmony_ci * Test cases a1-a6 */ 6603e5c31af7Sopenharmony_ci m_testCases.push_back(new QuadsBufferStorageTestCase( 6604e5c31af7Sopenharmony_ci gl, m_testCtx, page_size, QuadsBufferStorageTestCase::IBO_USAGE_NONE, false)); /* use_color_data */ 6605e5c31af7Sopenharmony_ci m_testCases.push_back(new QuadsBufferStorageTestCase( 6606e5c31af7Sopenharmony_ci gl, m_testCtx, page_size, QuadsBufferStorageTestCase::IBO_USAGE_INDEXED_DRAW_CALL, false)); /* use_color_data */ 6607e5c31af7Sopenharmony_ci m_testCases.push_back(new QuadsBufferStorageTestCase(gl, m_testCtx, page_size, 6608e5c31af7Sopenharmony_ci QuadsBufferStorageTestCase::IBO_USAGE_INDEXED_RANGED_DRAW_CALL, 6609e5c31af7Sopenharmony_ci false)); /* use_color_data */ 6610e5c31af7Sopenharmony_ci m_testCases.push_back(new QuadsBufferStorageTestCase( 6611e5c31af7Sopenharmony_ci gl, m_testCtx, page_size, QuadsBufferStorageTestCase::IBO_USAGE_INDEXED_DRAW_CALL, true)); /* use_color_data */ 6612e5c31af7Sopenharmony_ci m_testCases.push_back(new QuadsBufferStorageTestCase(gl, m_testCtx, page_size, 6613e5c31af7Sopenharmony_ci QuadsBufferStorageTestCase::IBO_USAGE_INDEXED_RANGED_DRAW_CALL, 6614e5c31af7Sopenharmony_ci true)); /* use_color_data */ 6615e5c31af7Sopenharmony_ci 6616e5c31af7Sopenharmony_ci /* Test case b1 */ 6617e5c31af7Sopenharmony_ci m_testCases.push_back( 6618e5c31af7Sopenharmony_ci new TransformFeedbackBufferStorageTestCase(gl, m_testCtx, page_size, true)); /* all_tf_pages_committed */ 6619e5c31af7Sopenharmony_ci 6620e5c31af7Sopenharmony_ci /* Test case b2 */ 6621e5c31af7Sopenharmony_ci m_testCases.push_back( 6622e5c31af7Sopenharmony_ci new TransformFeedbackBufferStorageTestCase(gl, m_testCtx, page_size, false)); /* all_tf_pages_committed */ 6623e5c31af7Sopenharmony_ci 6624e5c31af7Sopenharmony_ci /* Test case c */ 6625e5c31af7Sopenharmony_ci m_testCases.push_back(new ClearOpsBufferStorageTestCase(gl, m_testCtx, page_size)); 6626e5c31af7Sopenharmony_ci 6627e5c31af7Sopenharmony_ci /* Test case d */ 6628e5c31af7Sopenharmony_ci m_testCases.push_back(new InvalidateBufferStorageTestCase(gl, m_testCtx, page_size)); 6629e5c31af7Sopenharmony_ci 6630e5c31af7Sopenharmony_ci /* Test case e */ 6631e5c31af7Sopenharmony_ci m_testCases.push_back( 6632e5c31af7Sopenharmony_ci new AtomicCounterBufferStorageTestCase(gl, m_testCtx, page_size, false)); /* all_pages_committed */ 6633e5c31af7Sopenharmony_ci m_testCases.push_back( 6634e5c31af7Sopenharmony_ci new AtomicCounterBufferStorageTestCase(gl, m_testCtx, page_size, true)); /* all_pages_committed */ 6635e5c31af7Sopenharmony_ci 6636e5c31af7Sopenharmony_ci /* Test case f */ 6637e5c31af7Sopenharmony_ci m_testCases.push_back(new BufferTextureStorageTestCase(gl, m_context, m_testCtx, page_size)); 6638e5c31af7Sopenharmony_ci 6639e5c31af7Sopenharmony_ci /* Test case g */ 6640e5c31af7Sopenharmony_ci m_testCases.push_back(new CopyOpsBufferStorageTestCase(gl, m_testCtx, page_size)); 6641e5c31af7Sopenharmony_ci 6642e5c31af7Sopenharmony_ci /* Test case h */ 6643e5c31af7Sopenharmony_ci m_testCases.push_back(new IndirectDispatchBufferStorageTestCase(gl, m_testCtx, page_size)); 6644e5c31af7Sopenharmony_ci 6645e5c31af7Sopenharmony_ci /* Test case i */ 6646e5c31af7Sopenharmony_ci m_testCases.push_back(new SSBOStorageTestCase(gl, m_testCtx, page_size)); 6647e5c31af7Sopenharmony_ci 6648e5c31af7Sopenharmony_ci /* Test case j */ 6649e5c31af7Sopenharmony_ci m_testCases.push_back(new UniformBufferStorageTestCase(gl, m_testCtx, page_size)); 6650e5c31af7Sopenharmony_ci 6651e5c31af7Sopenharmony_ci /* Test case k */ 6652e5c31af7Sopenharmony_ci m_testCases.push_back(new PixelPackBufferStorageTestCase(gl, m_testCtx, page_size)); 6653e5c31af7Sopenharmony_ci 6654e5c31af7Sopenharmony_ci /* Test case l */ 6655e5c31af7Sopenharmony_ci m_testCases.push_back(new PixelUnpackBufferStorageTestCase(gl, m_testCtx, page_size)); 6656e5c31af7Sopenharmony_ci 6657e5c31af7Sopenharmony_ci /* Test case m */ 6658e5c31af7Sopenharmony_ci m_testCases.push_back(new QueryBufferStorageTestCase(gl, m_testCtx, page_size)); 6659e5c31af7Sopenharmony_ci 6660e5c31af7Sopenharmony_ci /* Initialize all test cases */ 6661e5c31af7Sopenharmony_ci for (TestCasesVectorIterator itTestCase = m_testCases.begin(); itTestCase != m_testCases.end(); ++itTestCase) 6662e5c31af7Sopenharmony_ci { 6663e5c31af7Sopenharmony_ci (*itTestCase)->initTestCaseGlobal(); 6664e5c31af7Sopenharmony_ci } 6665e5c31af7Sopenharmony_ci} 6666e5c31af7Sopenharmony_ci 6667e5c31af7Sopenharmony_ci/** Executes test iteration. 6668e5c31af7Sopenharmony_ci * 6669e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 6670e5c31af7Sopenharmony_ci */ 6671e5c31af7Sopenharmony_citcu::TestNode::IterateResult BufferStorageTest::iterate() 6672e5c31af7Sopenharmony_ci{ 6673e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6674e5c31af7Sopenharmony_ci bool result = true; 6675e5c31af7Sopenharmony_ci 6676e5c31af7Sopenharmony_ci /* Only execute if the implementation supports the GL_ARB_sparse_buffer extension */ 6677e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_buffer")) 6678e5c31af7Sopenharmony_ci { 6679e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_sparse_buffer is not supported"); 6680e5c31af7Sopenharmony_ci } 6681e5c31af7Sopenharmony_ci 6682e5c31af7Sopenharmony_ci /* The buffer storage test cases require OpenGL 4.3 feature-set. */ 6683e5c31af7Sopenharmony_ci if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 3))) 6684e5c31af7Sopenharmony_ci { 6685e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_sparse_buffer conformance tests require OpenGL 4.3 core feature-set"); 6686e5c31af7Sopenharmony_ci } 6687e5c31af7Sopenharmony_ci 6688e5c31af7Sopenharmony_ci /* Register & initialize the test case objects */ 6689e5c31af7Sopenharmony_ci initTestCases(); 6690e5c31af7Sopenharmony_ci 6691e5c31af7Sopenharmony_ci /* Iterate over all sparse BO flag combinations. We need to consider a total of 4 flags: 6692e5c31af7Sopenharmony_ci * 6693e5c31af7Sopenharmony_ci * - GL_CLIENT_STORAGE_BIT (bit 0) 6694e5c31af7Sopenharmony_ci * - GL_DYNAMIC_STORAGE_BIT (bit 1) 6695e5c31af7Sopenharmony_ci * - GL_MAP_COHERENT_BIT (bit 2) 6696e5c31af7Sopenharmony_ci * - GL_MAP_PERSISTENT_BIT (bit 3) 6697e5c31af7Sopenharmony_ci * 6698e5c31af7Sopenharmony_ci * GL_MAP_READ_BIT and GL_MAP_WRITE_BIT are excluded, since they are incompatible 6699e5c31af7Sopenharmony_ci * with sparse buffers by definition. 6700e5c31af7Sopenharmony_ci * 6701e5c31af7Sopenharmony_ci * GL_SPARSE_STORAGE_BIT_ARB is assumed to be always defined. Some of the combinations are invalid. 6702e5c31af7Sopenharmony_ci * Such loop iterations will be skipped. 6703e5c31af7Sopenharmony_ci * */ 6704e5c31af7Sopenharmony_ci 6705e5c31af7Sopenharmony_ci for (unsigned int n_flag_combination = 0; n_flag_combination < (1 << 4); ++n_flag_combination) 6706e5c31af7Sopenharmony_ci { 6707e5c31af7Sopenharmony_ci const glw::GLint flags = ((n_flag_combination & (1 << 0)) ? GL_CLIENT_STORAGE_BIT : 0) | 6708e5c31af7Sopenharmony_ci ((n_flag_combination & (1 << 1)) ? GL_DYNAMIC_STORAGE_BIT : 0) | 6709e5c31af7Sopenharmony_ci ((n_flag_combination & (1 << 2)) ? GL_MAP_COHERENT_BIT : 0) | 6710e5c31af7Sopenharmony_ci ((n_flag_combination & (1 << 3)) ? GL_MAP_PERSISTENT_BIT : 0) | 6711e5c31af7Sopenharmony_ci GL_SPARSE_STORAGE_BIT_ARB; 6712e5c31af7Sopenharmony_ci 6713e5c31af7Sopenharmony_ci if ((flags & GL_MAP_PERSISTENT_BIT) != 0) 6714e5c31af7Sopenharmony_ci { 6715e5c31af7Sopenharmony_ci if ((flags & GL_MAP_READ_BIT) == 0 && (flags & GL_MAP_WRITE_BIT) == 0) 6716e5c31af7Sopenharmony_ci { 6717e5c31af7Sopenharmony_ci continue; 6718e5c31af7Sopenharmony_ci } 6719e5c31af7Sopenharmony_ci } 6720e5c31af7Sopenharmony_ci 6721e5c31af7Sopenharmony_ci if (((flags & GL_MAP_COHERENT_BIT) != 0) && ((flags & GL_MAP_PERSISTENT_BIT) == 0)) 6722e5c31af7Sopenharmony_ci { 6723e5c31af7Sopenharmony_ci continue; 6724e5c31af7Sopenharmony_ci } 6725e5c31af7Sopenharmony_ci 6726e5c31af7Sopenharmony_ci /* Set up the sparse BO */ 6727e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_sparse_bo); 6728e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 6729e5c31af7Sopenharmony_ci 6730e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 6731e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 6732e5c31af7Sopenharmony_ci 6733e5c31af7Sopenharmony_ci gl.bufferStorage(GL_ARRAY_BUFFER, 1024768 * 1024, /* as per test spec */ 6734e5c31af7Sopenharmony_ci DE_NULL, /* data */ 6735e5c31af7Sopenharmony_ci flags); 6736e5c31af7Sopenharmony_ci 6737e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage() call failed."); 6738e5c31af7Sopenharmony_ci 6739e5c31af7Sopenharmony_ci for (TestCasesVectorIterator itTestCase = m_testCases.begin(); itTestCase != m_testCases.end(); ++itTestCase) 6740e5c31af7Sopenharmony_ci { 6741e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_sparse_bo); 6742e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 6743e5c31af7Sopenharmony_ci 6744e5c31af7Sopenharmony_ci if (!(*itTestCase)->initTestCaseIteration(m_sparse_bo)) 6745e5c31af7Sopenharmony_ci { 6746e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Test case [" << (*itTestCase)->getName() 6747e5c31af7Sopenharmony_ci << "] " 6748e5c31af7Sopenharmony_ci "has failed to initialize." 6749e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 6750e5c31af7Sopenharmony_ci 6751e5c31af7Sopenharmony_ci result = false; 6752e5c31af7Sopenharmony_ci goto end; 6753e5c31af7Sopenharmony_ci } 6754e5c31af7Sopenharmony_ci 6755e5c31af7Sopenharmony_ci if (!(*itTestCase)->execute(flags)) 6756e5c31af7Sopenharmony_ci { 6757e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Test case [" << (*itTestCase)->getName() 6758e5c31af7Sopenharmony_ci << "] " 6759e5c31af7Sopenharmony_ci "has failed to execute correctly." 6760e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 6761e5c31af7Sopenharmony_ci 6762e5c31af7Sopenharmony_ci result = false; 6763e5c31af7Sopenharmony_ci } /* if (!testCaseResult) */ 6764e5c31af7Sopenharmony_ci 6765e5c31af7Sopenharmony_ci (*itTestCase)->deinitTestCaseIteration(); 6766e5c31af7Sopenharmony_ci } /* for (all added test cases) */ 6767e5c31af7Sopenharmony_ci 6768e5c31af7Sopenharmony_ci /* Release the sparse BO */ 6769e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_sparse_bo); 6770e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() call failed."); 6771e5c31af7Sopenharmony_ci 6772e5c31af7Sopenharmony_ci m_sparse_bo = 0; 6773e5c31af7Sopenharmony_ci } 6774e5c31af7Sopenharmony_ci 6775e5c31af7Sopenharmony_ciend: 6776e5c31af7Sopenharmony_ci m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); 6777e5c31af7Sopenharmony_ci 6778e5c31af7Sopenharmony_ci return STOP; 6779e5c31af7Sopenharmony_ci} 6780e5c31af7Sopenharmony_ci 6781e5c31af7Sopenharmony_ci/** Constructor. 6782e5c31af7Sopenharmony_ci * 6783e5c31af7Sopenharmony_ci * @param context Rendering context. 6784e5c31af7Sopenharmony_ci */ 6785e5c31af7Sopenharmony_ciSparseBufferTests::SparseBufferTests(deqp::Context& context) 6786e5c31af7Sopenharmony_ci : TestCaseGroup(context, "sparse_buffer_tests", "Verify conformance of CTS_ARB_sparse_buffer implementation") 6787e5c31af7Sopenharmony_ci{ 6788e5c31af7Sopenharmony_ci} 6789e5c31af7Sopenharmony_ci 6790e5c31af7Sopenharmony_ci/** Initializes the test group contents. */ 6791e5c31af7Sopenharmony_civoid SparseBufferTests::init() 6792e5c31af7Sopenharmony_ci{ 6793e5c31af7Sopenharmony_ci addChild(new BufferStorageTest(m_context)); 6794e5c31af7Sopenharmony_ci addChild(new NegativeTests(m_context)); 6795e5c31af7Sopenharmony_ci addChild(new PageSizeGetterTest(m_context)); 6796e5c31af7Sopenharmony_ci} 6797e5c31af7Sopenharmony_ci 6798e5c31af7Sopenharmony_ci} /* gl4cts namespace */ 6799