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