1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module 3e5c31af7Sopenharmony_ci * ------------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Special float stress tests. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es3sSpecialFloatTests.hpp" 25e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp" 26e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 27e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 28e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 29e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 30e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 31e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 32e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 33e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 34e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 35e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 36e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 37e5c31af7Sopenharmony_ci#include "deMath.h" 38e5c31af7Sopenharmony_ci#include "deRandom.hpp" 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_ci#include <limits> 41e5c31af7Sopenharmony_ci#include <sstream> 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_ciusing namespace glw; 44e5c31af7Sopenharmony_ci 45e5c31af7Sopenharmony_cinamespace deqp 46e5c31af7Sopenharmony_ci{ 47e5c31af7Sopenharmony_cinamespace gles3 48e5c31af7Sopenharmony_ci{ 49e5c31af7Sopenharmony_cinamespace Stress 50e5c31af7Sopenharmony_ci{ 51e5c31af7Sopenharmony_cinamespace 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_cistatic const int TEST_CANVAS_SIZE = 256; 55e5c31af7Sopenharmony_cistatic const int TEST_TEXTURE_SIZE = 128; 56e5c31af7Sopenharmony_cistatic const int TEST_TEXTURE_CUBE_SIZE = 32; 57e5c31af7Sopenharmony_cistatic const deUint32 s_specialFloats[] = 58e5c31af7Sopenharmony_ci{ 59e5c31af7Sopenharmony_ci 0x00000000, // zero 60e5c31af7Sopenharmony_ci 0x80000000, // negative zero 61e5c31af7Sopenharmony_ci 0x3F800000, // one 62e5c31af7Sopenharmony_ci 0xBF800000, // negative one 63e5c31af7Sopenharmony_ci 0x00800000, // minimum positive normalized value 64e5c31af7Sopenharmony_ci 0x80800000, // maximum negative normalized value 65e5c31af7Sopenharmony_ci 0x00000001, // minimum positive denorm value 66e5c31af7Sopenharmony_ci 0x80000001, // maximum negative denorm value 67e5c31af7Sopenharmony_ci 0x7F7FFFFF, // maximum finite value. 68e5c31af7Sopenharmony_ci 0xFF7FFFFF, // minimum finite value. 69e5c31af7Sopenharmony_ci 0x7F800000, // inf 70e5c31af7Sopenharmony_ci 0xFF800000, // -inf 71e5c31af7Sopenharmony_ci 0x34000000, // epsilon 72e5c31af7Sopenharmony_ci 0xB4000000, // negative epsilon 73e5c31af7Sopenharmony_ci 0x7FC00000, // quiet_NaN 74e5c31af7Sopenharmony_ci 0xFFC00000, // negative quiet_NaN 75e5c31af7Sopenharmony_ci 0x7FC00001, // signaling_NaN 76e5c31af7Sopenharmony_ci 0xFFC00001, // negative signaling_NaN 77e5c31af7Sopenharmony_ci 0x7FEAAAAA, // quiet payloaded NaN (payload of repeated pattern of 101010...) 78e5c31af7Sopenharmony_ci 0xFFEAAAAA, // negative quiet payloaded NaN ( .. ) 79e5c31af7Sopenharmony_ci 0x7FAAAAAA, // signaling payloaded NaN ( .. ) 80e5c31af7Sopenharmony_ci 0xFFAAAAAA, // negative signaling payloaded NaN ( .. ) 81e5c31af7Sopenharmony_ci}; 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_cistatic const char* const s_colorPassthroughFragmentShaderSource = "#version 300 es\n" 84e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n" 85e5c31af7Sopenharmony_ci "in mediump vec4 v_out;\n" 86e5c31af7Sopenharmony_ci "void main ()\n" 87e5c31af7Sopenharmony_ci "{\n" 88e5c31af7Sopenharmony_ci " fragColor = v_out;\n" 89e5c31af7Sopenharmony_ci "}\n"; 90e5c31af7Sopenharmony_cistatic const char* const s_attrPassthroughVertexShaderSource = "#version 300 es\n" 91e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 92e5c31af7Sopenharmony_ci "in highp vec4 a_attr;\n" 93e5c31af7Sopenharmony_ci "out highp vec4 v_attr;\n" 94e5c31af7Sopenharmony_ci "void main ()\n" 95e5c31af7Sopenharmony_ci "{\n" 96e5c31af7Sopenharmony_ci " v_attr = a_attr;\n" 97e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 98e5c31af7Sopenharmony_ci "}\n"; 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ciclass RenderCase : public TestCase 101e5c31af7Sopenharmony_ci{ 102e5c31af7Sopenharmony_cipublic: 103e5c31af7Sopenharmony_ci enum RenderTargetType 104e5c31af7Sopenharmony_ci { 105e5c31af7Sopenharmony_ci RENDERTARGETTYPE_SCREEN, 106e5c31af7Sopenharmony_ci RENDERTARGETTYPE_FBO 107e5c31af7Sopenharmony_ci }; 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_ci RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType = RENDERTARGETTYPE_SCREEN); 110e5c31af7Sopenharmony_ci virtual ~RenderCase (void); 111e5c31af7Sopenharmony_ci 112e5c31af7Sopenharmony_ci virtual void init (void); 113e5c31af7Sopenharmony_ci virtual void deinit (void); 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ciprotected: 116e5c31af7Sopenharmony_ci bool checkResultImage (const tcu::Surface& result); 117e5c31af7Sopenharmony_ci bool drawTestPattern (bool useTexture); 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci virtual std::string genVertexSource (void) const = 0; 120e5c31af7Sopenharmony_ci virtual std::string genFragmentSource (void) const = 0; 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci const glu::ShaderProgram* m_program; 123e5c31af7Sopenharmony_ci const RenderTargetType m_renderTargetType; 124e5c31af7Sopenharmony_ci}; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ciRenderCase::RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType) 127e5c31af7Sopenharmony_ci : TestCase (context, name, desc) 128e5c31af7Sopenharmony_ci , m_program (DE_NULL) 129e5c31af7Sopenharmony_ci , m_renderTargetType (renderTargetType) 130e5c31af7Sopenharmony_ci{ 131e5c31af7Sopenharmony_ci} 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ciRenderCase::~RenderCase (void) 134e5c31af7Sopenharmony_ci{ 135e5c31af7Sopenharmony_ci deinit(); 136e5c31af7Sopenharmony_ci} 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_civoid RenderCase::init (void) 139e5c31af7Sopenharmony_ci{ 140e5c31af7Sopenharmony_ci const int width = m_context.getRenderTarget().getWidth(); 141e5c31af7Sopenharmony_ci const int height = m_context.getRenderTarget().getHeight(); 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci // check target size 144e5c31af7Sopenharmony_ci if (m_renderTargetType == RENDERTARGETTYPE_SCREEN) 145e5c31af7Sopenharmony_ci { 146e5c31af7Sopenharmony_ci if (width < TEST_CANVAS_SIZE || height < TEST_CANVAS_SIZE) 147e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(TEST_CANVAS_SIZE) + "x" + de::toString(TEST_CANVAS_SIZE)); 148e5c31af7Sopenharmony_ci } 149e5c31af7Sopenharmony_ci else if (m_renderTargetType == RENDERTARGETTYPE_FBO) 150e5c31af7Sopenharmony_ci { 151e5c31af7Sopenharmony_ci GLint maxTexSize = 0; 152e5c31af7Sopenharmony_ci m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci if (maxTexSize < TEST_CANVAS_SIZE) 155e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_CANVAS_SIZE)); 156e5c31af7Sopenharmony_ci } 157e5c31af7Sopenharmony_ci else 158e5c31af7Sopenharmony_ci DE_ASSERT(false); 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci // gen shader 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shader." << tcu::TestLog::EndMessage; 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(genFragmentSource())); 165e5c31af7Sopenharmony_ci m_testCtx.getLog() << *m_program; 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci if (!m_program->isOk()) 168e5c31af7Sopenharmony_ci throw tcu::TestError("shader compile failed"); 169e5c31af7Sopenharmony_ci} 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_civoid RenderCase::deinit (void) 172e5c31af7Sopenharmony_ci{ 173e5c31af7Sopenharmony_ci if (m_program) 174e5c31af7Sopenharmony_ci { 175e5c31af7Sopenharmony_ci delete m_program; 176e5c31af7Sopenharmony_ci m_program = DE_NULL; 177e5c31af7Sopenharmony_ci } 178e5c31af7Sopenharmony_ci} 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_cibool RenderCase::checkResultImage (const tcu::Surface& result) 181e5c31af7Sopenharmony_ci{ 182e5c31af7Sopenharmony_ci tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 183e5c31af7Sopenharmony_ci bool error = false; 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image." << tcu::TestLog::EndMessage; 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci for (int y = 0; y < TEST_CANVAS_SIZE; ++y) 188e5c31af7Sopenharmony_ci for (int x = 0; x < TEST_CANVAS_SIZE; ++x) 189e5c31af7Sopenharmony_ci { 190e5c31af7Sopenharmony_ci const tcu::RGBA col = result.getPixel(x, y); 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci if (col.getGreen() == 255) 193e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, tcu::RGBA::green()); 194e5c31af7Sopenharmony_ci else 195e5c31af7Sopenharmony_ci { 196e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, tcu::RGBA::red()); 197e5c31af7Sopenharmony_ci error = true; 198e5c31af7Sopenharmony_ci } 199e5c31af7Sopenharmony_ci } 200e5c31af7Sopenharmony_ci 201e5c31af7Sopenharmony_ci if (error) 202e5c31af7Sopenharmony_ci { 203e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Result image has missing or invalid pixels" << tcu::TestLog::EndMessage; 204e5c31af7Sopenharmony_ci m_testCtx.getLog() 205e5c31af7Sopenharmony_ci << tcu::TestLog::ImageSet("Results", "Result verification") 206e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Result", "Result", result) 207e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Error mask", "Error mask", errorMask) 208e5c31af7Sopenharmony_ci << tcu::TestLog::EndImageSet; 209e5c31af7Sopenharmony_ci } 210e5c31af7Sopenharmony_ci else 211e5c31af7Sopenharmony_ci { 212e5c31af7Sopenharmony_ci m_testCtx.getLog() 213e5c31af7Sopenharmony_ci << tcu::TestLog::ImageSet("Results", "Result verification") 214e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Result", "Result", result) 215e5c31af7Sopenharmony_ci << tcu::TestLog::EndImageSet; 216e5c31af7Sopenharmony_ci } 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci return !error; 219e5c31af7Sopenharmony_ci} 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_cibool RenderCase::drawTestPattern (bool useTexture) 222e5c31af7Sopenharmony_ci{ 223e5c31af7Sopenharmony_ci static const tcu::Vec4 fullscreenQuad[4] = 224e5c31af7Sopenharmony_ci { 225e5c31af7Sopenharmony_ci tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 226e5c31af7Sopenharmony_ci tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 227e5c31af7Sopenharmony_ci tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 228e5c31af7Sopenharmony_ci tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), 229e5c31af7Sopenharmony_ci }; 230e5c31af7Sopenharmony_ci const char* const vertexSource = "#version 300 es\n" 231e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 232e5c31af7Sopenharmony_ci "out mediump vec4 v_position;\n" 233e5c31af7Sopenharmony_ci "void main ()\n" 234e5c31af7Sopenharmony_ci "{\n" 235e5c31af7Sopenharmony_ci " v_position = a_pos;\n" 236e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 237e5c31af7Sopenharmony_ci "}\n"; 238e5c31af7Sopenharmony_ci const char* const fragmentSourceNoTex = "#version 300 es\n" 239e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n" 240e5c31af7Sopenharmony_ci "in mediump vec4 v_position;\n" 241e5c31af7Sopenharmony_ci "void main ()\n" 242e5c31af7Sopenharmony_ci "{\n" 243e5c31af7Sopenharmony_ci " fragColor = vec4((v_position.x + 1.0) * 0.5, 1.0, 1.0, 1.0);\n" 244e5c31af7Sopenharmony_ci "}\n"; 245e5c31af7Sopenharmony_ci const char* const fragmentSourceTex = "#version 300 es\n" 246e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n" 247e5c31af7Sopenharmony_ci "uniform mediump sampler2D u_sampler;\n" 248e5c31af7Sopenharmony_ci "in mediump vec4 v_position;\n" 249e5c31af7Sopenharmony_ci "void main ()\n" 250e5c31af7Sopenharmony_ci "{\n" 251e5c31af7Sopenharmony_ci " fragColor = texture(u_sampler, v_position.xy);\n" 252e5c31af7Sopenharmony_ci "}\n"; 253e5c31af7Sopenharmony_ci const char* const fragmentSource = (useTexture) ? (fragmentSourceTex) : (fragmentSourceNoTex); 254e5c31af7Sopenharmony_ci const tcu::RGBA formatThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold(); 255e5c31af7Sopenharmony_ci 256e5c31af7Sopenharmony_ci tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 257e5c31af7Sopenharmony_ci tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 258e5c31af7Sopenharmony_ci bool error = false; 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a test pattern to detect " << ((useTexture) ? ("texture sampling") : ("")) << " side-effects." << tcu::TestLog::EndMessage; 261e5c31af7Sopenharmony_ci 262e5c31af7Sopenharmony_ci // draw pattern 263e5c31af7Sopenharmony_ci { 264e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 265e5c31af7Sopenharmony_ci const glu::ShaderProgram patternProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource)); 266e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(patternProgram.getProgram(), "a_pos"); 267e5c31af7Sopenharmony_ci GLuint textureID = 0; 268e5c31af7Sopenharmony_ci 269e5c31af7Sopenharmony_ci if (useTexture) 270e5c31af7Sopenharmony_ci { 271e5c31af7Sopenharmony_ci const int textureSize = 32; 272e5c31af7Sopenharmony_ci std::vector<tcu::Vector<deUint8, 4> > buffer(textureSize*textureSize); 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci for (int x = 0; x < textureSize; ++x) 275e5c31af7Sopenharmony_ci for (int y = 0; y < textureSize; ++y) 276e5c31af7Sopenharmony_ci { 277e5c31af7Sopenharmony_ci // sum of two axis aligned gradients. Each gradient is 127 at the edges and 0 at the center. 278e5c31af7Sopenharmony_ci // pattern is symmetric (x and y) => no discontinuity near boundary => no need to worry of results with LINEAR filtering near boundaries 279e5c31af7Sopenharmony_ci const deUint8 redComponent = (deUint8)de::clamp(de::abs((float)x / (float)textureSize - 0.5f) * 255.0f + de::abs((float)y / (float)textureSize - 0.5f) * 255.0f, 0.0f, 255.0f); 280e5c31af7Sopenharmony_ci 281e5c31af7Sopenharmony_ci buffer[x * textureSize + y] = tcu::Vector<deUint8, 4>(redComponent, 255, 255, 255); 282e5c31af7Sopenharmony_ci } 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ci gl.genTextures(1, &textureID); 285e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, textureID); 286e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer[0].getPtr()); 287e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 288e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 289e5c31af7Sopenharmony_ci } 290e5c31af7Sopenharmony_ci 291e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 292e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 293e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 294e5c31af7Sopenharmony_ci gl.useProgram(patternProgram.getProgram()); 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci if (useTexture) 297e5c31af7Sopenharmony_ci gl.uniform1i(gl.getUniformLocation(patternProgram.getProgram(), "u_sampler"), 0); 298e5c31af7Sopenharmony_ci 299e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &fullscreenQuad[0]); 300e5c31af7Sopenharmony_ci 301e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 302e5c31af7Sopenharmony_ci gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 303e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 304e5c31af7Sopenharmony_ci 305e5c31af7Sopenharmony_ci gl.useProgram(0); 306e5c31af7Sopenharmony_ci gl.finish(); 307e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "RenderCase::drawTestPattern"); 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci if (textureID) 310e5c31af7Sopenharmony_ci gl.deleteTextures(1, &textureID); 311e5c31af7Sopenharmony_ci 312e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 313e5c31af7Sopenharmony_ci } 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci // verify pattern 316e5c31af7Sopenharmony_ci for (int y = 0; y < TEST_CANVAS_SIZE; ++y) 317e5c31af7Sopenharmony_ci for (int x = 0; x < TEST_CANVAS_SIZE; ++x) 318e5c31af7Sopenharmony_ci { 319e5c31af7Sopenharmony_ci const float texGradientPosX = deFloatFrac((float)x * 2.0f / (float)TEST_CANVAS_SIZE); 320e5c31af7Sopenharmony_ci const float texGradientPosY = deFloatFrac((float)y * 2.0f / (float)TEST_CANVAS_SIZE); 321e5c31af7Sopenharmony_ci const deUint8 texRedComponent = (deUint8)de::clamp(de::abs(texGradientPosX - 0.5f) * 255.0f + de::abs(texGradientPosY - 0.5f) * 255.0f, 0.0f, 255.0f); 322e5c31af7Sopenharmony_ci 323e5c31af7Sopenharmony_ci const tcu::RGBA refColTexture = tcu::RGBA(texRedComponent, 255, 255, 255); 324e5c31af7Sopenharmony_ci const tcu::RGBA refColGradient = tcu::RGBA((int)((float)x / (float)TEST_CANVAS_SIZE * 255.0f), 255, 255, 255); 325e5c31af7Sopenharmony_ci const tcu::RGBA& refCol = (useTexture) ? (refColTexture) : (refColGradient); 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci const int colorThreshold = 10; 328e5c31af7Sopenharmony_ci const tcu::RGBA col = resultImage.getPixel(x, y); 329e5c31af7Sopenharmony_ci const tcu::IVec4 colorDiff = tcu::abs(col.toIVec() - refCol.toIVec()); 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci if (colorDiff.x() > formatThreshold.getRed() + colorThreshold || 332e5c31af7Sopenharmony_ci colorDiff.y() > formatThreshold.getGreen() + colorThreshold || 333e5c31af7Sopenharmony_ci colorDiff.z() > formatThreshold.getBlue() + colorThreshold) 334e5c31af7Sopenharmony_ci { 335e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, tcu::RGBA::red()); 336e5c31af7Sopenharmony_ci error = true; 337e5c31af7Sopenharmony_ci } 338e5c31af7Sopenharmony_ci else 339e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, tcu::RGBA::green()); 340e5c31af7Sopenharmony_ci } 341e5c31af7Sopenharmony_ci 342e5c31af7Sopenharmony_ci // report error 343e5c31af7Sopenharmony_ci if (error) 344e5c31af7Sopenharmony_ci { 345e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Test pattern has missing/invalid pixels" << tcu::TestLog::EndMessage; 346e5c31af7Sopenharmony_ci m_testCtx.getLog() 347e5c31af7Sopenharmony_ci << tcu::TestLog::ImageSet("Results", "Result verification") 348e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Result", "Result", resultImage) 349e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Error mask", "Error mask", errorMask) 350e5c31af7Sopenharmony_ci << tcu::TestLog::EndImageSet; 351e5c31af7Sopenharmony_ci } 352e5c31af7Sopenharmony_ci else 353e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "No side-effects found." << tcu::TestLog::EndMessage; 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci return !error; 356e5c31af7Sopenharmony_ci} 357e5c31af7Sopenharmony_ci 358e5c31af7Sopenharmony_ciclass FramebufferRenderCase : public RenderCase 359e5c31af7Sopenharmony_ci{ 360e5c31af7Sopenharmony_cipublic: 361e5c31af7Sopenharmony_ci enum FrameBufferType 362e5c31af7Sopenharmony_ci { 363e5c31af7Sopenharmony_ci FBO_DEFAULT = 0, 364e5c31af7Sopenharmony_ci FBO_RGBA4, 365e5c31af7Sopenharmony_ci FBO_RGB5_A1, 366e5c31af7Sopenharmony_ci FBO_RGB565, 367e5c31af7Sopenharmony_ci FBO_RGBA8, 368e5c31af7Sopenharmony_ci FBO_RGB10_A2, 369e5c31af7Sopenharmony_ci FBO_RGBA_FLOAT16, 370e5c31af7Sopenharmony_ci FBO_RGBA_FLOAT32, 371e5c31af7Sopenharmony_ci 372e5c31af7Sopenharmony_ci FBO_LAST 373e5c31af7Sopenharmony_ci }; 374e5c31af7Sopenharmony_ci 375e5c31af7Sopenharmony_ci FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType); 376e5c31af7Sopenharmony_ci virtual ~FramebufferRenderCase (void); 377e5c31af7Sopenharmony_ci 378e5c31af7Sopenharmony_ci virtual void init (void); 379e5c31af7Sopenharmony_ci virtual void deinit (void); 380e5c31af7Sopenharmony_ci IterateResult iterate (void); 381e5c31af7Sopenharmony_ci 382e5c31af7Sopenharmony_ci virtual void testFBO (void) = DE_NULL; 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ciprotected: 385e5c31af7Sopenharmony_ci const FrameBufferType m_fboType; 386e5c31af7Sopenharmony_ci 387e5c31af7Sopenharmony_ciprivate: 388e5c31af7Sopenharmony_ci GLuint m_texID; 389e5c31af7Sopenharmony_ci GLuint m_fboID; 390e5c31af7Sopenharmony_ci}; 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ciFramebufferRenderCase::FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType) 393e5c31af7Sopenharmony_ci : RenderCase (context, name, desc, (fboType == FBO_DEFAULT) ? (RENDERTARGETTYPE_SCREEN) : (RENDERTARGETTYPE_FBO)) 394e5c31af7Sopenharmony_ci , m_fboType (fboType) 395e5c31af7Sopenharmony_ci , m_texID (0) 396e5c31af7Sopenharmony_ci , m_fboID (0) 397e5c31af7Sopenharmony_ci{ 398e5c31af7Sopenharmony_ci DE_ASSERT(m_fboType < FBO_LAST); 399e5c31af7Sopenharmony_ci} 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_ciFramebufferRenderCase::~FramebufferRenderCase (void) 402e5c31af7Sopenharmony_ci{ 403e5c31af7Sopenharmony_ci deinit(); 404e5c31af7Sopenharmony_ci} 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_civoid FramebufferRenderCase::init (void) 407e5c31af7Sopenharmony_ci{ 408e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 409e5c31af7Sopenharmony_ci 410e5c31af7Sopenharmony_ci // check requirements 411e5c31af7Sopenharmony_ci if (m_fboType == FBO_RGBA_FLOAT16) 412e5c31af7Sopenharmony_ci { 413e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_half_float") && 414e5c31af7Sopenharmony_ci !m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float")) 415e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Color renderable half float texture required."); 416e5c31af7Sopenharmony_ci } 417e5c31af7Sopenharmony_ci else if (m_fboType == FBO_RGBA_FLOAT32) 418e5c31af7Sopenharmony_ci { 419e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float")) 420e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Color renderable float texture required."); 421e5c31af7Sopenharmony_ci } 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci // gen shader 424e5c31af7Sopenharmony_ci RenderCase::init(); 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci // create render target 427e5c31af7Sopenharmony_ci if (m_fboType == FBO_DEFAULT) 428e5c31af7Sopenharmony_ci { 429e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Using default framebuffer." << tcu::TestLog::EndMessage; 430e5c31af7Sopenharmony_ci } 431e5c31af7Sopenharmony_ci else 432e5c31af7Sopenharmony_ci { 433e5c31af7Sopenharmony_ci GLuint internalFormat = 0; 434e5c31af7Sopenharmony_ci GLuint format = 0; 435e5c31af7Sopenharmony_ci GLuint type = 0; 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_ci switch (m_fboType) 438e5c31af7Sopenharmony_ci { 439e5c31af7Sopenharmony_ci case FBO_RGBA4: internalFormat = GL_RGBA4; format = GL_RGBA; type = GL_UNSIGNED_SHORT_4_4_4_4; break; 440e5c31af7Sopenharmony_ci case FBO_RGB5_A1: internalFormat = GL_RGB5_A1; format = GL_RGBA; type = GL_UNSIGNED_SHORT_5_5_5_1; break; 441e5c31af7Sopenharmony_ci case FBO_RGB565: internalFormat = GL_RGB565; format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break; 442e5c31af7Sopenharmony_ci case FBO_RGBA8: internalFormat = GL_RGBA8; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; 443e5c31af7Sopenharmony_ci case FBO_RGB10_A2: internalFormat = GL_RGB10_A2; format = GL_RGBA; type = GL_UNSIGNED_INT_2_10_10_10_REV; break; 444e5c31af7Sopenharmony_ci case FBO_RGBA_FLOAT16: internalFormat = GL_RGBA16F; format = GL_RGBA; type = GL_HALF_FLOAT; break; 445e5c31af7Sopenharmony_ci case FBO_RGBA_FLOAT32: internalFormat = GL_RGBA32F; format = GL_RGBA; type = GL_FLOAT; break; 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci default: 448e5c31af7Sopenharmony_ci DE_ASSERT(false); 449e5c31af7Sopenharmony_ci break; 450e5c31af7Sopenharmony_ci } 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 453e5c31af7Sopenharmony_ci << "Creating fbo. Texture internalFormat = " << glu::getTextureFormatStr(internalFormat) 454e5c31af7Sopenharmony_ci << ", format = " << glu::getTextureFormatStr(format) 455e5c31af7Sopenharmony_ci << ", type = " << glu::getTypeStr(type) 456e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 457e5c31af7Sopenharmony_ci 458e5c31af7Sopenharmony_ci // gen texture 459e5c31af7Sopenharmony_ci gl.genTextures(1, &m_texID); 460e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_texID); 461e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, 0, internalFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, 0, format, type, DE_NULL); 462e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "texture init"); 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_ci // gen fbo 465e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_fboID); 466e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID); 467e5c31af7Sopenharmony_ci gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texID, 0); 468e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "fbo init"); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 471e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("could not create fbo for testing."); 472e5c31af7Sopenharmony_ci } 473e5c31af7Sopenharmony_ci} 474e5c31af7Sopenharmony_ci 475e5c31af7Sopenharmony_civoid FramebufferRenderCase::deinit (void) 476e5c31af7Sopenharmony_ci{ 477e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_ci if (m_texID) 480e5c31af7Sopenharmony_ci { 481e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_texID); 482e5c31af7Sopenharmony_ci m_texID = 0; 483e5c31af7Sopenharmony_ci } 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_ci if (m_fboID) 486e5c31af7Sopenharmony_ci { 487e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_fboID); 488e5c31af7Sopenharmony_ci m_fboID = 0; 489e5c31af7Sopenharmony_ci } 490e5c31af7Sopenharmony_ci} 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ciFramebufferRenderCase::IterateResult FramebufferRenderCase::iterate (void) 493e5c31af7Sopenharmony_ci{ 494e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 495e5c31af7Sopenharmony_ci 496e5c31af7Sopenharmony_ci // bind fbo (or don't if we are using default) 497e5c31af7Sopenharmony_ci if (m_fboID) 498e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID); 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci // do something with special floats 501e5c31af7Sopenharmony_ci testFBO(); 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci return STOP; 504e5c31af7Sopenharmony_ci} 505e5c31af7Sopenharmony_ci 506e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 507e5c31af7Sopenharmony_ci * \brief Tests special floats as vertex attributes 508e5c31af7Sopenharmony_ci * 509e5c31af7Sopenharmony_ci * Tests that special floats transferred to the shader using vertex 510e5c31af7Sopenharmony_ci * attributes do not change the results of normal floating point 511e5c31af7Sopenharmony_ci * calculations. Special floats are put to 4-vector's x and y components and 512e5c31af7Sopenharmony_ci * value 1.0 is put to z and w. The resulting fragment's green channel 513e5c31af7Sopenharmony_ci * should be 1.0 everywhere. 514e5c31af7Sopenharmony_ci * 515e5c31af7Sopenharmony_ci * After the calculation test a test pattern is drawn to detect possible 516e5c31af7Sopenharmony_ci * floating point operation anomalies. 517e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 518e5c31af7Sopenharmony_ciclass VertexAttributeCase : public RenderCase 519e5c31af7Sopenharmony_ci{ 520e5c31af7Sopenharmony_cipublic: 521e5c31af7Sopenharmony_ci enum Storage 522e5c31af7Sopenharmony_ci { 523e5c31af7Sopenharmony_ci STORAGE_BUFFER = 0, 524e5c31af7Sopenharmony_ci STORAGE_CLIENT, 525e5c31af7Sopenharmony_ci 526e5c31af7Sopenharmony_ci STORAGE_LAST 527e5c31af7Sopenharmony_ci }; 528e5c31af7Sopenharmony_ci enum ShaderType 529e5c31af7Sopenharmony_ci { 530e5c31af7Sopenharmony_ci TYPE_VERTEX = 0, 531e5c31af7Sopenharmony_ci TYPE_FRAGMENT, 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci TYPE_LAST 534e5c31af7Sopenharmony_ci }; 535e5c31af7Sopenharmony_ci 536e5c31af7Sopenharmony_ci VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type); 537e5c31af7Sopenharmony_ci ~VertexAttributeCase (void); 538e5c31af7Sopenharmony_ci 539e5c31af7Sopenharmony_ci void init (void); 540e5c31af7Sopenharmony_ci void deinit (void); 541e5c31af7Sopenharmony_ci IterateResult iterate (void); 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ciprivate: 544e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 545e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 546e5c31af7Sopenharmony_ci 547e5c31af7Sopenharmony_ci const Storage m_storage; 548e5c31af7Sopenharmony_ci const ShaderType m_type; 549e5c31af7Sopenharmony_ci GLuint m_positionVboID; 550e5c31af7Sopenharmony_ci GLuint m_attribVboID; 551e5c31af7Sopenharmony_ci GLuint m_elementVboID; 552e5c31af7Sopenharmony_ci}; 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ciVertexAttributeCase::VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type) 555e5c31af7Sopenharmony_ci : RenderCase (context, name, desc) 556e5c31af7Sopenharmony_ci , m_storage (storage) 557e5c31af7Sopenharmony_ci , m_type (type) 558e5c31af7Sopenharmony_ci , m_positionVboID (0) 559e5c31af7Sopenharmony_ci , m_attribVboID (0) 560e5c31af7Sopenharmony_ci , m_elementVboID (0) 561e5c31af7Sopenharmony_ci{ 562e5c31af7Sopenharmony_ci DE_ASSERT(storage < STORAGE_LAST); 563e5c31af7Sopenharmony_ci DE_ASSERT(type < TYPE_LAST); 564e5c31af7Sopenharmony_ci} 565e5c31af7Sopenharmony_ci 566e5c31af7Sopenharmony_ciVertexAttributeCase::~VertexAttributeCase (void) 567e5c31af7Sopenharmony_ci{ 568e5c31af7Sopenharmony_ci deinit(); 569e5c31af7Sopenharmony_ci} 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_civoid VertexAttributeCase::init (void) 572e5c31af7Sopenharmony_ci{ 573e5c31af7Sopenharmony_ci RenderCase::init(); 574e5c31af7Sopenharmony_ci 575e5c31af7Sopenharmony_ci // init gl resources 576e5c31af7Sopenharmony_ci if (m_storage == STORAGE_BUFFER) 577e5c31af7Sopenharmony_ci { 578e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_positionVboID); 581e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_attribVboID); 582e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_elementVboID); 583e5c31af7Sopenharmony_ci } 584e5c31af7Sopenharmony_ci} 585e5c31af7Sopenharmony_ci 586e5c31af7Sopenharmony_civoid VertexAttributeCase::deinit (void) 587e5c31af7Sopenharmony_ci{ 588e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 589e5c31af7Sopenharmony_ci 590e5c31af7Sopenharmony_ci RenderCase::deinit(); 591e5c31af7Sopenharmony_ci 592e5c31af7Sopenharmony_ci if (m_attribVboID) 593e5c31af7Sopenharmony_ci { 594e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_attribVboID); 595e5c31af7Sopenharmony_ci m_attribVboID = 0; 596e5c31af7Sopenharmony_ci } 597e5c31af7Sopenharmony_ci 598e5c31af7Sopenharmony_ci if (m_positionVboID) 599e5c31af7Sopenharmony_ci { 600e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_positionVboID); 601e5c31af7Sopenharmony_ci m_positionVboID = 0; 602e5c31af7Sopenharmony_ci } 603e5c31af7Sopenharmony_ci 604e5c31af7Sopenharmony_ci if (m_elementVboID) 605e5c31af7Sopenharmony_ci { 606e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_elementVboID); 607e5c31af7Sopenharmony_ci m_elementVboID = 0; 608e5c31af7Sopenharmony_ci } 609e5c31af7Sopenharmony_ci} 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ciVertexAttributeCase::IterateResult VertexAttributeCase::iterate (void) 612e5c31af7Sopenharmony_ci{ 613e5c31af7Sopenharmony_ci // Create a [s_specialFloats] X [s_specialFloats] grid of vertices with each vertex having 2 [s_specialFloats] values 614e5c31af7Sopenharmony_ci // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 617e5c31af7Sopenharmony_ci std::vector<tcu::UVec4> gridAttributes (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 618e5c31af7Sopenharmony_ci std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6); 619e5c31af7Sopenharmony_ci tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci // vertices 622e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 623e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 624e5c31af7Sopenharmony_ci { 625e5c31af7Sopenharmony_ci const deUint32 one = 0x3F800000; 626e5c31af7Sopenharmony_ci const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1] 627e5c31af7Sopenharmony_ci const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; 628e5c31af7Sopenharmony_ci 629e5c31af7Sopenharmony_ci gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 630e5c31af7Sopenharmony_ci gridAttributes[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one); 631e5c31af7Sopenharmony_ci } 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci // tiles 634e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x) 635e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y) 636e5c31af7Sopenharmony_ci { 637e5c31af7Sopenharmony_ci const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6; 638e5c31af7Sopenharmony_ci 639e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 640e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 641e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 642e5c31af7Sopenharmony_ci 643e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 644e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 645e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 646e5c31af7Sopenharmony_ci } 647e5c31af7Sopenharmony_ci 648e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting a_attr for each vertex to (special, special, 1, 1)." << tcu::TestLog::EndMessage; 649e5c31af7Sopenharmony_ci 650e5c31af7Sopenharmony_ci // Draw grid 651e5c31af7Sopenharmony_ci { 652e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 653e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 654e5c31af7Sopenharmony_ci const GLint attribLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 655e5c31af7Sopenharmony_ci 656e5c31af7Sopenharmony_ci if (m_storage == STORAGE_BUFFER) 657e5c31af7Sopenharmony_ci { 658e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID); 659e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridVertices.size() * sizeof(tcu::Vec4)), &gridVertices[0], GL_STATIC_DRAW); 660e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 661e5c31af7Sopenharmony_ci 662e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID); 663e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridAttributes.size() * sizeof(tcu::UVec4)), &gridAttributes[0], GL_STATIC_DRAW); 664e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 665e5c31af7Sopenharmony_ci 666e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementVboID); 667e5c31af7Sopenharmony_ci gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size() * sizeof(deUint16)), &indices[0], GL_STATIC_DRAW); 668e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 669e5c31af7Sopenharmony_ci } 670e5c31af7Sopenharmony_ci 671e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 672e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 673e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 674e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 675e5c31af7Sopenharmony_ci 676e5c31af7Sopenharmony_ci if (m_storage == STORAGE_BUFFER) 677e5c31af7Sopenharmony_ci { 678e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID); 679e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 680e5c31af7Sopenharmony_ci 681e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID); 682e5c31af7Sopenharmony_ci gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 683e5c31af7Sopenharmony_ci 684e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 685e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(attribLoc); 686e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, DE_NULL); 687e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 688e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(attribLoc); 689e5c31af7Sopenharmony_ci 690e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, 0); 691e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 692e5c31af7Sopenharmony_ci } 693e5c31af7Sopenharmony_ci else if (m_storage == STORAGE_CLIENT) 694e5c31af7Sopenharmony_ci { 695e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 696e5c31af7Sopenharmony_ci gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridAttributes[0]); 697e5c31af7Sopenharmony_ci 698e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 699e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(attribLoc); 700e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 701e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 702e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(attribLoc); 703e5c31af7Sopenharmony_ci } 704e5c31af7Sopenharmony_ci else 705e5c31af7Sopenharmony_ci DE_ASSERT(false); 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ci gl.useProgram(0); 708e5c31af7Sopenharmony_ci gl.finish(); 709e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 712e5c31af7Sopenharmony_ci } 713e5c31af7Sopenharmony_ci 714e5c31af7Sopenharmony_ci // verify everywhere was drawn (all pixels have Green = 255) 715e5c31af7Sopenharmony_ci if (!checkResultImage(resultImage)) 716e5c31af7Sopenharmony_ci { 717e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 718e5c31af7Sopenharmony_ci return STOP; 719e5c31af7Sopenharmony_ci } 720e5c31af7Sopenharmony_ci 721e5c31af7Sopenharmony_ci // test drawing still works 722e5c31af7Sopenharmony_ci if (!drawTestPattern(false)) 723e5c31af7Sopenharmony_ci { 724e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 725e5c31af7Sopenharmony_ci return STOP; 726e5c31af7Sopenharmony_ci } 727e5c31af7Sopenharmony_ci 728e5c31af7Sopenharmony_ci // all ok 729e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 730e5c31af7Sopenharmony_ci return STOP; 731e5c31af7Sopenharmony_ci} 732e5c31af7Sopenharmony_ci 733e5c31af7Sopenharmony_cistd::string VertexAttributeCase::genVertexSource (void) const 734e5c31af7Sopenharmony_ci{ 735e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 736e5c31af7Sopenharmony_ci return 737e5c31af7Sopenharmony_ci "#version 300 es\n" 738e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 739e5c31af7Sopenharmony_ci "in highp vec4 a_attr;\n" 740e5c31af7Sopenharmony_ci "out mediump vec4 v_out;\n" 741e5c31af7Sopenharmony_ci "void main ()\n" 742e5c31af7Sopenharmony_ci "{\n" 743e5c31af7Sopenharmony_ci " highp vec2 a1 = a_attr.xz + a_attr.yw; // add\n" 744e5c31af7Sopenharmony_ci " highp vec2 a2 = a_attr.xz - a_attr.yw; // sub\n" 745e5c31af7Sopenharmony_ci " highp vec2 a3 = a_attr.xz * a_attr.yw; // mul\n" 746e5c31af7Sopenharmony_ci " highp vec2 a4 = a_attr.xz / a_attr.yw; // div\n" 747e5c31af7Sopenharmony_ci " highp vec2 a5 = a_attr.xz + a_attr.yw * a_attr.xz; // fma\n" 748e5c31af7Sopenharmony_ci "\n" 749e5c31af7Sopenharmony_ci " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n" 750e5c31af7Sopenharmony_ci " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n" 751e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 752e5c31af7Sopenharmony_ci "}\n"; 753e5c31af7Sopenharmony_ci else 754e5c31af7Sopenharmony_ci return s_attrPassthroughVertexShaderSource; 755e5c31af7Sopenharmony_ci} 756e5c31af7Sopenharmony_ci 757e5c31af7Sopenharmony_cistd::string VertexAttributeCase::genFragmentSource (void) const 758e5c31af7Sopenharmony_ci{ 759e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 760e5c31af7Sopenharmony_ci return s_colorPassthroughFragmentShaderSource; 761e5c31af7Sopenharmony_ci else 762e5c31af7Sopenharmony_ci return 763e5c31af7Sopenharmony_ci "#version 300 es\n" 764e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n" 765e5c31af7Sopenharmony_ci "in highp vec4 v_attr;\n" 766e5c31af7Sopenharmony_ci "void main ()\n" 767e5c31af7Sopenharmony_ci "{\n" 768e5c31af7Sopenharmony_ci " highp vec2 a1 = v_attr.xz + v_attr.yw; // add\n" 769e5c31af7Sopenharmony_ci " highp vec2 a2 = v_attr.xz - v_attr.yw; // sub\n" 770e5c31af7Sopenharmony_ci " highp vec2 a3 = v_attr.xz * v_attr.yw; // mul\n" 771e5c31af7Sopenharmony_ci " highp vec2 a4 = v_attr.xz / v_attr.yw; // div\n" 772e5c31af7Sopenharmony_ci " highp vec2 a5 = v_attr.xz + v_attr.yw * v_attr.xz; // fma\n" 773e5c31af7Sopenharmony_ci " highp vec2 a6 = dFdx(v_attr.xz);\n" 774e5c31af7Sopenharmony_ci "\n" 775e5c31af7Sopenharmony_ci " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y) - 6.0);\n" 776e5c31af7Sopenharmony_ci " fragColor = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x+a6.x, 1.0);\n" 777e5c31af7Sopenharmony_ci "}\n"; 778e5c31af7Sopenharmony_ci} 779e5c31af7Sopenharmony_ci 780e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 781e5c31af7Sopenharmony_ci * \brief Tests special floats as uniforms 782e5c31af7Sopenharmony_ci * 783e5c31af7Sopenharmony_ci * Tests that special floats transferred to the shader as uniforms do 784e5c31af7Sopenharmony_ci * not change the results of normal floating point calculations. Special 785e5c31af7Sopenharmony_ci * floats are put to 4-vector's x and y components and value 1.0 is put to 786e5c31af7Sopenharmony_ci * z and w. The resulting fragment's green channel should be 1.0 787e5c31af7Sopenharmony_ci * everywhere. 788e5c31af7Sopenharmony_ci * 789e5c31af7Sopenharmony_ci * After the calculation test a test pattern is drawn to detect possible 790e5c31af7Sopenharmony_ci * floating point operation anomalies. 791e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 792e5c31af7Sopenharmony_ciclass UniformCase : public RenderCase 793e5c31af7Sopenharmony_ci{ 794e5c31af7Sopenharmony_cipublic: 795e5c31af7Sopenharmony_ci enum ShaderType 796e5c31af7Sopenharmony_ci { 797e5c31af7Sopenharmony_ci TYPE_VERTEX = 0, 798e5c31af7Sopenharmony_ci TYPE_FRAGMENT, 799e5c31af7Sopenharmony_ci }; 800e5c31af7Sopenharmony_ci 801e5c31af7Sopenharmony_ci UniformCase (Context& context, const char* name, const char* desc, ShaderType type); 802e5c31af7Sopenharmony_ci ~UniformCase (void); 803e5c31af7Sopenharmony_ci 804e5c31af7Sopenharmony_ci void init (void); 805e5c31af7Sopenharmony_ci void deinit (void); 806e5c31af7Sopenharmony_ci IterateResult iterate (void); 807e5c31af7Sopenharmony_ci 808e5c31af7Sopenharmony_ciprivate: 809e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 810e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 811e5c31af7Sopenharmony_ci 812e5c31af7Sopenharmony_ci const ShaderType m_type; 813e5c31af7Sopenharmony_ci}; 814e5c31af7Sopenharmony_ci 815e5c31af7Sopenharmony_ciUniformCase::UniformCase (Context& context, const char* name, const char* desc, ShaderType type) 816e5c31af7Sopenharmony_ci : RenderCase (context, name, desc) 817e5c31af7Sopenharmony_ci , m_type (type) 818e5c31af7Sopenharmony_ci{ 819e5c31af7Sopenharmony_ci} 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_ciUniformCase::~UniformCase (void) 822e5c31af7Sopenharmony_ci{ 823e5c31af7Sopenharmony_ci deinit(); 824e5c31af7Sopenharmony_ci} 825e5c31af7Sopenharmony_ci 826e5c31af7Sopenharmony_civoid UniformCase::init (void) 827e5c31af7Sopenharmony_ci{ 828e5c31af7Sopenharmony_ci RenderCase::init(); 829e5c31af7Sopenharmony_ci} 830e5c31af7Sopenharmony_ci 831e5c31af7Sopenharmony_civoid UniformCase::deinit (void) 832e5c31af7Sopenharmony_ci{ 833e5c31af7Sopenharmony_ci RenderCase::deinit(); 834e5c31af7Sopenharmony_ci} 835e5c31af7Sopenharmony_ci 836e5c31af7Sopenharmony_ciUniformCase::IterateResult UniformCase::iterate (void) 837e5c31af7Sopenharmony_ci{ 838e5c31af7Sopenharmony_ci // Create a [s_specialFloats] X [s_specialFloats] grid of tile with each tile having 2 [s_specialFloats] values 839e5c31af7Sopenharmony_ci // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen 840e5c31af7Sopenharmony_ci 841e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1)); 842e5c31af7Sopenharmony_ci std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 843e5c31af7Sopenharmony_ci tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 844e5c31af7Sopenharmony_ci 845e5c31af7Sopenharmony_ci // vertices 846e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x) 847e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y) 848e5c31af7Sopenharmony_ci { 849e5c31af7Sopenharmony_ci const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1] 850e5c31af7Sopenharmony_ci const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_ci gridVertices[x * (DE_LENGTH_OF_ARRAY(s_specialFloats)+1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 853e5c31af7Sopenharmony_ci } 854e5c31af7Sopenharmony_ci 855e5c31af7Sopenharmony_ci // tiles 856e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 857e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 858e5c31af7Sopenharmony_ci { 859e5c31af7Sopenharmony_ci const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats)) + y) * 6; 860e5c31af7Sopenharmony_ci 861e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 862e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 863e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 864e5c31af7Sopenharmony_ci 865e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 866e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 867e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 868e5c31af7Sopenharmony_ci } 869e5c31af7Sopenharmony_ci 870e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting u_special for vertex each tile to (special, special, 1, 1)." << tcu::TestLog::EndMessage; 871e5c31af7Sopenharmony_ci 872e5c31af7Sopenharmony_ci // Draw grid 873e5c31af7Sopenharmony_ci { 874e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 875e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 876e5c31af7Sopenharmony_ci const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 877e5c31af7Sopenharmony_ci 878e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 879e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 880e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 881e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 882e5c31af7Sopenharmony_ci 883e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 884e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 885e5c31af7Sopenharmony_ci 886e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 887e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 888e5c31af7Sopenharmony_ci { 889e5c31af7Sopenharmony_ci const deUint32 one = 0x3F800000; 890e5c31af7Sopenharmony_ci const tcu::UVec4 uniformValue = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one); 891e5c31af7Sopenharmony_ci const int indexIndex = (x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y) * 6; 892e5c31af7Sopenharmony_ci 893e5c31af7Sopenharmony_ci gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr()); 894e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 895e5c31af7Sopenharmony_ci } 896e5c31af7Sopenharmony_ci 897e5c31af7Sopenharmony_ci 898e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 899e5c31af7Sopenharmony_ci 900e5c31af7Sopenharmony_ci gl.useProgram(0); 901e5c31af7Sopenharmony_ci gl.finish(); 902e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "UniformCase::iterate"); 903e5c31af7Sopenharmony_ci 904e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 905e5c31af7Sopenharmony_ci } 906e5c31af7Sopenharmony_ci 907e5c31af7Sopenharmony_ci // verify everywhere was drawn (all pixels have Green = 255) 908e5c31af7Sopenharmony_ci if (!checkResultImage(resultImage)) 909e5c31af7Sopenharmony_ci { 910e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 911e5c31af7Sopenharmony_ci return STOP; 912e5c31af7Sopenharmony_ci } 913e5c31af7Sopenharmony_ci 914e5c31af7Sopenharmony_ci // test drawing still works 915e5c31af7Sopenharmony_ci if (!drawTestPattern(false)) 916e5c31af7Sopenharmony_ci { 917e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 918e5c31af7Sopenharmony_ci return STOP; 919e5c31af7Sopenharmony_ci } 920e5c31af7Sopenharmony_ci 921e5c31af7Sopenharmony_ci // all ok 922e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 923e5c31af7Sopenharmony_ci return STOP; 924e5c31af7Sopenharmony_ci} 925e5c31af7Sopenharmony_ci 926e5c31af7Sopenharmony_cistd::string UniformCase::genVertexSource (void) const 927e5c31af7Sopenharmony_ci{ 928e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 929e5c31af7Sopenharmony_ci return 930e5c31af7Sopenharmony_ci "#version 300 es\n" 931e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 932e5c31af7Sopenharmony_ci "uniform highp vec4 u_special;\n" 933e5c31af7Sopenharmony_ci "out mediump vec4 v_out;\n" 934e5c31af7Sopenharmony_ci "void main ()\n" 935e5c31af7Sopenharmony_ci "{\n" 936e5c31af7Sopenharmony_ci " highp vec2 a1 = u_special.xz + u_special.yw; // add\n" 937e5c31af7Sopenharmony_ci " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n" 938e5c31af7Sopenharmony_ci " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n" 939e5c31af7Sopenharmony_ci " highp vec2 a4 = u_special.xz / u_special.yw; // div\n" 940e5c31af7Sopenharmony_ci " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n" 941e5c31af7Sopenharmony_ci "\n" 942e5c31af7Sopenharmony_ci " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n" 943e5c31af7Sopenharmony_ci " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n" 944e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 945e5c31af7Sopenharmony_ci "}\n"; 946e5c31af7Sopenharmony_ci else 947e5c31af7Sopenharmony_ci return 948e5c31af7Sopenharmony_ci "#version 300 es\n" 949e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 950e5c31af7Sopenharmony_ci "void main ()\n" 951e5c31af7Sopenharmony_ci "{\n" 952e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 953e5c31af7Sopenharmony_ci "}\n"; 954e5c31af7Sopenharmony_ci} 955e5c31af7Sopenharmony_ci 956e5c31af7Sopenharmony_cistd::string UniformCase::genFragmentSource (void) const 957e5c31af7Sopenharmony_ci{ 958e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 959e5c31af7Sopenharmony_ci return s_colorPassthroughFragmentShaderSource; 960e5c31af7Sopenharmony_ci else 961e5c31af7Sopenharmony_ci return 962e5c31af7Sopenharmony_ci "#version 300 es\n" 963e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n" 964e5c31af7Sopenharmony_ci "uniform highp vec4 u_special;\n" 965e5c31af7Sopenharmony_ci "void main ()\n" 966e5c31af7Sopenharmony_ci "{\n" 967e5c31af7Sopenharmony_ci " highp vec2 a1 = u_special.xz + u_special.yw; // add\n" 968e5c31af7Sopenharmony_ci " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n" 969e5c31af7Sopenharmony_ci " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n" 970e5c31af7Sopenharmony_ci " highp vec2 a4 = u_special.xz / u_special.yw; // div\n" 971e5c31af7Sopenharmony_ci " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n" 972e5c31af7Sopenharmony_ci " highp vec2 a6 = mod(u_special.xz, u_special.yw);\n" 973e5c31af7Sopenharmony_ci " highp vec2 a7 = mix(u_special.xz, u_special.yw, a6);\n" 974e5c31af7Sopenharmony_ci "\n" 975e5c31af7Sopenharmony_ci " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y + a7.y) - 7.0);\n" 976e5c31af7Sopenharmony_ci " fragColor = vec4(a1.x*a3.x, green, a5.x*a4.x + a2.x*a7.x, 1.0);\n" 977e5c31af7Sopenharmony_ci "}\n"; 978e5c31af7Sopenharmony_ci} 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 981e5c31af7Sopenharmony_ci * \brief Tests special floats in floating point textures 982e5c31af7Sopenharmony_ci * 983e5c31af7Sopenharmony_ci * Tests that sampling special floats from a floating point texture 984e5c31af7Sopenharmony_ci * does not affect the values of other color components of the sample. Test 985e5c31af7Sopenharmony_ci * samples a RG texture with R channel filled with special floats and G 986e5c31af7Sopenharmony_ci * channel filled with test values. 987e5c31af7Sopenharmony_ci * 988e5c31af7Sopenharmony_ci * Tests that linear sampling using compare mode = COMPARE_REF_TO_TEXTURE 989e5c31af7Sopenharmony_ci * of a floating point depth texture containing special floating point 990e5c31af7Sopenharmony_ci * values does not produce values outside the [0, 1] range. 991e5c31af7Sopenharmony_ci * 992e5c31af7Sopenharmony_ci * After the calculation test a test pattern is drawn to detect possible 993e5c31af7Sopenharmony_ci * texture sampling anomalies. 994e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 995e5c31af7Sopenharmony_ciclass TextureCase : public RenderCase 996e5c31af7Sopenharmony_ci{ 997e5c31af7Sopenharmony_cipublic: 998e5c31af7Sopenharmony_ci enum ShaderType 999e5c31af7Sopenharmony_ci { 1000e5c31af7Sopenharmony_ci TYPE_VERTEX = 0, 1001e5c31af7Sopenharmony_ci TYPE_FRAGMENT, 1002e5c31af7Sopenharmony_ci 1003e5c31af7Sopenharmony_ci TYPE_LAST 1004e5c31af7Sopenharmony_ci }; 1005e5c31af7Sopenharmony_ci enum TextureType 1006e5c31af7Sopenharmony_ci { 1007e5c31af7Sopenharmony_ci TEXTURE_FLOAT = 0, 1008e5c31af7Sopenharmony_ci TEXTURE_DEPTH, 1009e5c31af7Sopenharmony_ci 1010e5c31af7Sopenharmony_ci TEXTURE_LAST 1011e5c31af7Sopenharmony_ci }; 1012e5c31af7Sopenharmony_ci enum UploadType 1013e5c31af7Sopenharmony_ci { 1014e5c31af7Sopenharmony_ci UPLOAD_CLIENT = 0, 1015e5c31af7Sopenharmony_ci UPLOAD_PBO, 1016e5c31af7Sopenharmony_ci 1017e5c31af7Sopenharmony_ci UPLOAD_LAST 1018e5c31af7Sopenharmony_ci }; 1019e5c31af7Sopenharmony_ci 1020e5c31af7Sopenharmony_ci TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType); 1021e5c31af7Sopenharmony_ci ~TextureCase (void); 1022e5c31af7Sopenharmony_ci 1023e5c31af7Sopenharmony_ci void init (void); 1024e5c31af7Sopenharmony_ci void deinit (void); 1025e5c31af7Sopenharmony_ci IterateResult iterate (void); 1026e5c31af7Sopenharmony_ci 1027e5c31af7Sopenharmony_ciprivate: 1028e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 1029e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 1030e5c31af7Sopenharmony_ci 1031e5c31af7Sopenharmony_ci const ShaderType m_type; 1032e5c31af7Sopenharmony_ci const TextureType m_textureType; 1033e5c31af7Sopenharmony_ci const UploadType m_uploadType; 1034e5c31af7Sopenharmony_ci GLuint m_textureID; 1035e5c31af7Sopenharmony_ci GLuint m_pboID; 1036e5c31af7Sopenharmony_ci}; 1037e5c31af7Sopenharmony_ci 1038e5c31af7Sopenharmony_ciTextureCase::TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType) 1039e5c31af7Sopenharmony_ci : RenderCase (context, name, desc) 1040e5c31af7Sopenharmony_ci , m_type (type) 1041e5c31af7Sopenharmony_ci , m_textureType (texType) 1042e5c31af7Sopenharmony_ci , m_uploadType (uploadType) 1043e5c31af7Sopenharmony_ci , m_textureID (0) 1044e5c31af7Sopenharmony_ci , m_pboID (0) 1045e5c31af7Sopenharmony_ci{ 1046e5c31af7Sopenharmony_ci DE_ASSERT(type < TYPE_LAST); 1047e5c31af7Sopenharmony_ci DE_ASSERT(texType < TEXTURE_LAST); 1048e5c31af7Sopenharmony_ci DE_ASSERT(uploadType < UPLOAD_LAST); 1049e5c31af7Sopenharmony_ci} 1050e5c31af7Sopenharmony_ci 1051e5c31af7Sopenharmony_ciTextureCase::~TextureCase (void) 1052e5c31af7Sopenharmony_ci{ 1053e5c31af7Sopenharmony_ci deinit(); 1054e5c31af7Sopenharmony_ci} 1055e5c31af7Sopenharmony_ci 1056e5c31af7Sopenharmony_civoid TextureCase::init (void) 1057e5c31af7Sopenharmony_ci{ 1058e5c31af7Sopenharmony_ci // requirements 1059e5c31af7Sopenharmony_ci { 1060e5c31af7Sopenharmony_ci GLint maxTextureSize = 0; 1061e5c31af7Sopenharmony_ci m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 1062e5c31af7Sopenharmony_ci if (maxTextureSize < TEST_TEXTURE_SIZE) 1063e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE)); 1064e5c31af7Sopenharmony_ci } 1065e5c31af7Sopenharmony_ci 1066e5c31af7Sopenharmony_ci RenderCase::init(); 1067e5c31af7Sopenharmony_ci 1068e5c31af7Sopenharmony_ci // gen texture 1069e5c31af7Sopenharmony_ci { 1070e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1071e5c31af7Sopenharmony_ci de::Random rnd (12345); 1072e5c31af7Sopenharmony_ci 1073e5c31af7Sopenharmony_ci gl.genTextures(1, &m_textureID); 1074e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1075e5c31af7Sopenharmony_ci 1076e5c31af7Sopenharmony_ci if (m_uploadType == UPLOAD_PBO) 1077e5c31af7Sopenharmony_ci { 1078e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_pboID); 1079e5c31af7Sopenharmony_ci gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pboID); 1080e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1081e5c31af7Sopenharmony_ci } 1082e5c31af7Sopenharmony_ci 1083e5c31af7Sopenharmony_ci if (m_textureType == TEXTURE_FLOAT) 1084e5c31af7Sopenharmony_ci { 1085e5c31af7Sopenharmony_ci std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*2); 1086e5c31af7Sopenharmony_ci const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL); 1087e5c31af7Sopenharmony_ci 1088e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D 2-component float texture. Pixel contents are of form (special, 1)." << tcu::TestLog::EndMessage; 1089e5c31af7Sopenharmony_ci 1090e5c31af7Sopenharmony_ci // set green channel to 1.0 1091e5c31af7Sopenharmony_ci for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1092e5c31af7Sopenharmony_ci for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1093e5c31af7Sopenharmony_ci { 1094e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 0] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1095e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 1] = 0x3F800000; // one 1096e5c31af7Sopenharmony_ci } 1097e5c31af7Sopenharmony_ci 1098e5c31af7Sopenharmony_ci if (m_uploadType == UPLOAD_PBO) 1099e5c31af7Sopenharmony_ci gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW); 1100e5c31af7Sopenharmony_ci 1101e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, 0, GL_RG32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RG, GL_FLOAT, dataPtr); 1102e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1103e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1104e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1105e5c31af7Sopenharmony_ci } 1106e5c31af7Sopenharmony_ci else if (m_textureType == TEXTURE_DEPTH) 1107e5c31af7Sopenharmony_ci { 1108e5c31af7Sopenharmony_ci std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE); 1109e5c31af7Sopenharmony_ci const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL); 1110e5c31af7Sopenharmony_ci 1111e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 1112e5c31af7Sopenharmony_ci << "Creating a 2D depth texture and filling it with special floating point values.\n" 1113e5c31af7Sopenharmony_ci << " TEXTURE_COMPARE_MODE = COMPARE_REF_TO_TEXTURE" 1114e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1115e5c31af7Sopenharmony_ci 1116e5c31af7Sopenharmony_ci for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1117e5c31af7Sopenharmony_ci for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1118e5c31af7Sopenharmony_ci texData[x * TEST_TEXTURE_SIZE + y] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1119e5c31af7Sopenharmony_ci 1120e5c31af7Sopenharmony_ci if (m_uploadType == UPLOAD_PBO) 1121e5c31af7Sopenharmony_ci gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW); 1122e5c31af7Sopenharmony_ci 1123e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, dataPtr); 1124e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 1125e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); 1126e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1127e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1128e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1129e5c31af7Sopenharmony_ci } 1130e5c31af7Sopenharmony_ci else 1131e5c31af7Sopenharmony_ci DE_ASSERT(false); 1132e5c31af7Sopenharmony_ci 1133e5c31af7Sopenharmony_ci if (m_uploadType == UPLOAD_PBO) 1134e5c31af7Sopenharmony_ci { 1135e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "PBO used for image upload." << tcu::TestLog::EndMessage; 1136e5c31af7Sopenharmony_ci 1137e5c31af7Sopenharmony_ci gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 1138e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_pboID); 1139e5c31af7Sopenharmony_ci m_pboID = 0; 1140e5c31af7Sopenharmony_ci } 1141e5c31af7Sopenharmony_ci } 1142e5c31af7Sopenharmony_ci} 1143e5c31af7Sopenharmony_ci 1144e5c31af7Sopenharmony_civoid TextureCase::deinit (void) 1145e5c31af7Sopenharmony_ci{ 1146e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1147e5c31af7Sopenharmony_ci 1148e5c31af7Sopenharmony_ci RenderCase::deinit(); 1149e5c31af7Sopenharmony_ci 1150e5c31af7Sopenharmony_ci if (m_textureID) 1151e5c31af7Sopenharmony_ci { 1152e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_textureID); 1153e5c31af7Sopenharmony_ci m_textureID = 0; 1154e5c31af7Sopenharmony_ci } 1155e5c31af7Sopenharmony_ci if (m_pboID) 1156e5c31af7Sopenharmony_ci { 1157e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_pboID); 1158e5c31af7Sopenharmony_ci m_pboID = 0; 1159e5c31af7Sopenharmony_ci } 1160e5c31af7Sopenharmony_ci} 1161e5c31af7Sopenharmony_ci 1162e5c31af7Sopenharmony_ciTextureCase::IterateResult TextureCase::iterate (void) 1163e5c31af7Sopenharmony_ci{ 1164e5c31af7Sopenharmony_ci // Draw a grid and texture it with a floating point texture containing special values. If all goes well, nothing special should happen 1165e5c31af7Sopenharmony_ci 1166e5c31af7Sopenharmony_ci const int gridSize = 16; 1167e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices (gridSize * gridSize); 1168e5c31af7Sopenharmony_ci std::vector<tcu::Vec2> gridTexCoords (gridSize * gridSize); 1169e5c31af7Sopenharmony_ci std::vector<deUint16> indices ((gridSize - 1) * (gridSize - 1) * 6); 1170e5c31af7Sopenharmony_ci tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1171e5c31af7Sopenharmony_ci 1172e5c31af7Sopenharmony_ci // vertices 1173e5c31af7Sopenharmony_ci for (int x = 0; x < gridSize; ++x) 1174e5c31af7Sopenharmony_ci for (int y = 0; y < gridSize; ++y) 1175e5c31af7Sopenharmony_ci { 1176e5c31af7Sopenharmony_ci const float posX = (float)x / ((float)gridSize - 1.0f) * 2.0f - 1.0f; // map from [0, gridSize - 1] to [-1, 1] 1177e5c31af7Sopenharmony_ci const float posY = (float)y / ((float)gridSize - 1.0f) * 2.0f - 1.0f; 1178e5c31af7Sopenharmony_ci const float texCoordX = deFloatPow(2.0f, (float)x - (float)gridSize / 2.0f); 1179e5c31af7Sopenharmony_ci const float texCoordY = deFloatPow(2.0f, (float)y - (float)gridSize / 2.0f); 1180e5c31af7Sopenharmony_ci 1181e5c31af7Sopenharmony_ci gridVertices[x * gridSize + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1182e5c31af7Sopenharmony_ci gridTexCoords[x * gridSize + y] = tcu::Vec2(texCoordX, texCoordY); 1183e5c31af7Sopenharmony_ci } 1184e5c31af7Sopenharmony_ci 1185e5c31af7Sopenharmony_ci // tiles 1186e5c31af7Sopenharmony_ci for (int x = 0; x < gridSize - 1; ++x) 1187e5c31af7Sopenharmony_ci for (int y = 0; y < gridSize - 1; ++y) 1188e5c31af7Sopenharmony_ci { 1189e5c31af7Sopenharmony_ci const int baseNdx = (x * (gridSize - 1) + y) * 6; 1190e5c31af7Sopenharmony_ci 1191e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((x+0) * gridSize + (y+0)); 1192e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((x+1) * gridSize + (y+1)); 1193e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((x+1) * gridSize + (y+0)); 1194e5c31af7Sopenharmony_ci 1195e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((x+0) * gridSize + (y+0)); 1196e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((x+1) * gridSize + (y+1)); 1197e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((x+0) * gridSize + (y+1)); 1198e5c31af7Sopenharmony_ci } 1199e5c31af7Sopenharmony_ci 1200e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader." << tcu::TestLog::EndMessage; 1201e5c31af7Sopenharmony_ci 1202e5c31af7Sopenharmony_ci // Draw grid 1203e5c31af7Sopenharmony_ci { 1204e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1205e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1206e5c31af7Sopenharmony_ci const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 1207e5c31af7Sopenharmony_ci const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler"); 1208e5c31af7Sopenharmony_ci 1209e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1210e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1211e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1212e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 1213e5c31af7Sopenharmony_ci 1214e5c31af7Sopenharmony_ci gl.uniform1i(samplerLoc, 0); 1215e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1216e5c31af7Sopenharmony_ci 1217e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1218e5c31af7Sopenharmony_ci gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]); 1219e5c31af7Sopenharmony_ci 1220e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 1221e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(texCoordLoc); 1222e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 1223e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 1224e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(texCoordLoc); 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci gl.useProgram(0); 1227e5c31af7Sopenharmony_ci gl.finish(); 1228e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::iterate"); 1229e5c31af7Sopenharmony_ci 1230e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 1231e5c31af7Sopenharmony_ci } 1232e5c31af7Sopenharmony_ci 1233e5c31af7Sopenharmony_ci // verify everywhere was drawn (all pixels have Green = 255) 1234e5c31af7Sopenharmony_ci if (!checkResultImage(resultImage)) 1235e5c31af7Sopenharmony_ci { 1236e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 1237e5c31af7Sopenharmony_ci return STOP; 1238e5c31af7Sopenharmony_ci } 1239e5c31af7Sopenharmony_ci 1240e5c31af7Sopenharmony_ci // test drawing and textures still works 1241e5c31af7Sopenharmony_ci if (!drawTestPattern(true)) 1242e5c31af7Sopenharmony_ci { 1243e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 1244e5c31af7Sopenharmony_ci return STOP; 1245e5c31af7Sopenharmony_ci } 1246e5c31af7Sopenharmony_ci 1247e5c31af7Sopenharmony_ci // all ok 1248e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1249e5c31af7Sopenharmony_ci return STOP; 1250e5c31af7Sopenharmony_ci} 1251e5c31af7Sopenharmony_ci 1252e5c31af7Sopenharmony_cistd::string TextureCase::genVertexSource (void) const 1253e5c31af7Sopenharmony_ci{ 1254e5c31af7Sopenharmony_ci // vertex shader is passthrough, fragment does the calculations 1255e5c31af7Sopenharmony_ci if (m_type == TYPE_FRAGMENT) 1256e5c31af7Sopenharmony_ci return s_attrPassthroughVertexShaderSource; 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_ci // vertex shader does the calculations 1259e5c31af7Sopenharmony_ci std::ostringstream buf; 1260e5c31af7Sopenharmony_ci buf << "#version 300 es\n" 1261e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 1262e5c31af7Sopenharmony_ci "in highp vec2 a_attr;\n" 1263e5c31af7Sopenharmony_ci "out mediump vec4 v_out;\n"; 1264e5c31af7Sopenharmony_ci 1265e5c31af7Sopenharmony_ci if (m_textureType == TEXTURE_FLOAT) 1266e5c31af7Sopenharmony_ci buf << "uniform highp sampler2D u_sampler;\n"; 1267e5c31af7Sopenharmony_ci else if (m_textureType == TEXTURE_DEPTH) 1268e5c31af7Sopenharmony_ci buf << "uniform highp sampler2DShadow u_sampler;\n"; 1269e5c31af7Sopenharmony_ci else 1270e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1271e5c31af7Sopenharmony_ci 1272e5c31af7Sopenharmony_ci buf << "void main ()\n" 1273e5c31af7Sopenharmony_ci "{\n"; 1274e5c31af7Sopenharmony_ci 1275e5c31af7Sopenharmony_ci if (m_textureType == TEXTURE_FLOAT) 1276e5c31af7Sopenharmony_ci buf << " v_out = vec4(textureLod(u_sampler, a_attr, 0.0).rg, 1.0, 1.0);\n"; 1277e5c31af7Sopenharmony_ci else if (m_textureType == TEXTURE_DEPTH) 1278e5c31af7Sopenharmony_ci buf << " highp float a1 = textureLod(u_sampler, vec3(a_attr, 0.0), 0.0);\n" 1279e5c31af7Sopenharmony_ci " v_out = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n"; 1280e5c31af7Sopenharmony_ci else 1281e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1282e5c31af7Sopenharmony_ci 1283e5c31af7Sopenharmony_ci buf << " gl_Position = a_pos;\n" 1284e5c31af7Sopenharmony_ci "}\n"; 1285e5c31af7Sopenharmony_ci return buf.str(); 1286e5c31af7Sopenharmony_ci} 1287e5c31af7Sopenharmony_ci 1288e5c31af7Sopenharmony_cistd::string TextureCase::genFragmentSource (void) const 1289e5c31af7Sopenharmony_ci{ 1290e5c31af7Sopenharmony_ci // fragment shader is passthrough 1291e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 1292e5c31af7Sopenharmony_ci return s_colorPassthroughFragmentShaderSource; 1293e5c31af7Sopenharmony_ci 1294e5c31af7Sopenharmony_ci // fragment shader does the calculations 1295e5c31af7Sopenharmony_ci std::ostringstream buf; 1296e5c31af7Sopenharmony_ci buf << "#version 300 es\n" 1297e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n"; 1298e5c31af7Sopenharmony_ci 1299e5c31af7Sopenharmony_ci if (m_textureType == TEXTURE_FLOAT) 1300e5c31af7Sopenharmony_ci buf << "uniform highp sampler2D u_sampler;\n"; 1301e5c31af7Sopenharmony_ci else if (m_textureType == TEXTURE_DEPTH) 1302e5c31af7Sopenharmony_ci buf << "uniform highp sampler2DShadow u_sampler;\n"; 1303e5c31af7Sopenharmony_ci else 1304e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1305e5c31af7Sopenharmony_ci 1306e5c31af7Sopenharmony_ci buf << "in highp vec4 v_attr;\n" 1307e5c31af7Sopenharmony_ci "void main ()\n" 1308e5c31af7Sopenharmony_ci "{\n"; 1309e5c31af7Sopenharmony_ci 1310e5c31af7Sopenharmony_ci if (m_textureType == TEXTURE_FLOAT) 1311e5c31af7Sopenharmony_ci buf << " highp vec2 a1 = texture(u_sampler, v_attr.xy).rg;\n" 1312e5c31af7Sopenharmony_ci " fragColor = vec4(a1.x, a1.y, 1.0, 1.0);\n"; 1313e5c31af7Sopenharmony_ci else if (m_textureType == TEXTURE_DEPTH) 1314e5c31af7Sopenharmony_ci buf << " highp float a1 = texture(u_sampler, vec3(v_attr.xy, 0.0));\n" 1315e5c31af7Sopenharmony_ci " fragColor = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n"; 1316e5c31af7Sopenharmony_ci else 1317e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ci buf << "}\n"; 1320e5c31af7Sopenharmony_ci return buf.str(); 1321e5c31af7Sopenharmony_ci} 1322e5c31af7Sopenharmony_ci 1323e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1324e5c31af7Sopenharmony_ci * \brief Tests special floats as texture samping arguments 1325e5c31af7Sopenharmony_ci * 1326e5c31af7Sopenharmony_ci * Tests that special floats given as texture coordinates or LOD levels 1327e5c31af7Sopenharmony_ci * to sampling functions do not return invalid values (values not in the 1328e5c31af7Sopenharmony_ci * texture). Every texel's green component is 1.0. 1329e5c31af7Sopenharmony_ci * 1330e5c31af7Sopenharmony_ci * After the calculation test a test pattern is drawn to detect possible 1331e5c31af7Sopenharmony_ci * texture sampling anomalies. 1332e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1333e5c31af7Sopenharmony_ciclass TextureSamplerCase : public RenderCase 1334e5c31af7Sopenharmony_ci{ 1335e5c31af7Sopenharmony_cipublic: 1336e5c31af7Sopenharmony_ci enum ShaderType 1337e5c31af7Sopenharmony_ci { 1338e5c31af7Sopenharmony_ci TYPE_VERTEX = 0, 1339e5c31af7Sopenharmony_ci TYPE_FRAGMENT, 1340e5c31af7Sopenharmony_ci 1341e5c31af7Sopenharmony_ci TYPE_LAST 1342e5c31af7Sopenharmony_ci }; 1343e5c31af7Sopenharmony_ci enum TestType 1344e5c31af7Sopenharmony_ci { 1345e5c31af7Sopenharmony_ci TEST_TEX_COORD = 0, 1346e5c31af7Sopenharmony_ci TEST_LOD, 1347e5c31af7Sopenharmony_ci TEST_GRAD, 1348e5c31af7Sopenharmony_ci TEST_TEX_COORD_CUBE, 1349e5c31af7Sopenharmony_ci 1350e5c31af7Sopenharmony_ci TEST_LAST 1351e5c31af7Sopenharmony_ci }; 1352e5c31af7Sopenharmony_ci 1353e5c31af7Sopenharmony_ci TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType); 1354e5c31af7Sopenharmony_ci ~TextureSamplerCase (void); 1355e5c31af7Sopenharmony_ci 1356e5c31af7Sopenharmony_ci void init (void); 1357e5c31af7Sopenharmony_ci void deinit (void); 1358e5c31af7Sopenharmony_ci IterateResult iterate (void); 1359e5c31af7Sopenharmony_ci 1360e5c31af7Sopenharmony_ciprivate: 1361e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 1362e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 1363e5c31af7Sopenharmony_ci 1364e5c31af7Sopenharmony_ci const ShaderType m_type; 1365e5c31af7Sopenharmony_ci const TestType m_testType; 1366e5c31af7Sopenharmony_ci GLuint m_textureID; 1367e5c31af7Sopenharmony_ci}; 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ciTextureSamplerCase::TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType) 1370e5c31af7Sopenharmony_ci : RenderCase (context, name, desc) 1371e5c31af7Sopenharmony_ci , m_type (type) 1372e5c31af7Sopenharmony_ci , m_testType (testType) 1373e5c31af7Sopenharmony_ci , m_textureID (0) 1374e5c31af7Sopenharmony_ci{ 1375e5c31af7Sopenharmony_ci DE_ASSERT(type < TYPE_LAST); 1376e5c31af7Sopenharmony_ci DE_ASSERT(testType < TEST_LAST); 1377e5c31af7Sopenharmony_ci} 1378e5c31af7Sopenharmony_ci 1379e5c31af7Sopenharmony_ciTextureSamplerCase::~TextureSamplerCase (void) 1380e5c31af7Sopenharmony_ci{ 1381e5c31af7Sopenharmony_ci deinit(); 1382e5c31af7Sopenharmony_ci} 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_civoid TextureSamplerCase::init (void) 1385e5c31af7Sopenharmony_ci{ 1386e5c31af7Sopenharmony_ci // requirements 1387e5c31af7Sopenharmony_ci { 1388e5c31af7Sopenharmony_ci GLint maxTextureSize = 0; 1389e5c31af7Sopenharmony_ci m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 1390e5c31af7Sopenharmony_ci if (maxTextureSize < TEST_TEXTURE_SIZE) 1391e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE)); 1392e5c31af7Sopenharmony_ci } 1393e5c31af7Sopenharmony_ci 1394e5c31af7Sopenharmony_ci RenderCase::init(); 1395e5c31af7Sopenharmony_ci 1396e5c31af7Sopenharmony_ci // gen texture 1397e5c31af7Sopenharmony_ci { 1398e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1399e5c31af7Sopenharmony_ci std::vector<deUint8> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*4); 1400e5c31af7Sopenharmony_ci de::Random rnd (12345); 1401e5c31af7Sopenharmony_ci 1402e5c31af7Sopenharmony_ci gl.genTextures(1, &m_textureID); 1403e5c31af7Sopenharmony_ci 1404e5c31af7Sopenharmony_ci for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1405e5c31af7Sopenharmony_ci for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1406e5c31af7Sopenharmony_ci { 1407e5c31af7Sopenharmony_ci // RGBA8, green and alpha channel are always 255 for verification 1408e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 0] = rnd.getUint32() & 0xFF; 1409e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 1] = 0xFF; 1410e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 2] = rnd.getUint32() & 0xFF; 1411e5c31af7Sopenharmony_ci texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 3] = 0xFF; 1412e5c31af7Sopenharmony_ci } 1413e5c31af7Sopenharmony_ci 1414e5c31af7Sopenharmony_ci if (m_testType == TEST_TEX_COORD) 1415e5c31af7Sopenharmony_ci { 1416e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D texture with a test pattern." << tcu::TestLog::EndMessage; 1417e5c31af7Sopenharmony_ci 1418e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1419e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1420e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1421e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1422e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1423e5c31af7Sopenharmony_ci } 1424e5c31af7Sopenharmony_ci else if (m_testType == TEST_LOD || m_testType == TEST_GRAD) 1425e5c31af7Sopenharmony_ci { 1426e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Creating a mipmapped 2D texture with a test pattern." << tcu::TestLog::EndMessage; 1427e5c31af7Sopenharmony_ci 1428e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1429e5c31af7Sopenharmony_ci 1430e5c31af7Sopenharmony_ci for (int level = 0; (TEST_TEXTURE_SIZE >> level); ++level) 1431e5c31af7Sopenharmony_ci gl.texImage2D(GL_TEXTURE_2D, level, GL_RGBA8, TEST_TEXTURE_SIZE >> level, TEST_TEXTURE_SIZE >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1432e5c31af7Sopenharmony_ci 1433e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1434e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1435e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1436e5c31af7Sopenharmony_ci } 1437e5c31af7Sopenharmony_ci else if (m_testType == TEST_TEX_COORD_CUBE) 1438e5c31af7Sopenharmony_ci { 1439e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(TEST_TEXTURE_CUBE_SIZE <= TEST_TEXTURE_SIZE); 1440e5c31af7Sopenharmony_ci 1441e5c31af7Sopenharmony_ci static const GLenum faces[] = 1442e5c31af7Sopenharmony_ci { 1443e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1444e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1445e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1446e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1447e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1448e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1449e5c31af7Sopenharmony_ci }; 1450e5c31af7Sopenharmony_ci 1451e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Creating a cube map with a test pattern." << tcu::TestLog::EndMessage; 1452e5c31af7Sopenharmony_ci 1453e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID); 1454e5c31af7Sopenharmony_ci 1455e5c31af7Sopenharmony_ci for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); ++faceNdx) 1456e5c31af7Sopenharmony_ci gl.texImage2D(faces[faceNdx], 0, GL_RGBA8, TEST_TEXTURE_CUBE_SIZE, TEST_TEXTURE_CUBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1457e5c31af7Sopenharmony_ci 1458e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1459e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1460e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1461e5c31af7Sopenharmony_ci } 1462e5c31af7Sopenharmony_ci else 1463e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1464e5c31af7Sopenharmony_ci } 1465e5c31af7Sopenharmony_ci} 1466e5c31af7Sopenharmony_ci 1467e5c31af7Sopenharmony_civoid TextureSamplerCase::deinit (void) 1468e5c31af7Sopenharmony_ci{ 1469e5c31af7Sopenharmony_ci RenderCase::deinit(); 1470e5c31af7Sopenharmony_ci 1471e5c31af7Sopenharmony_ci if (m_textureID) 1472e5c31af7Sopenharmony_ci { 1473e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1474e5c31af7Sopenharmony_ci 1475e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_textureID); 1476e5c31af7Sopenharmony_ci m_textureID = 0; 1477e5c31af7Sopenharmony_ci } 1478e5c31af7Sopenharmony_ci} 1479e5c31af7Sopenharmony_ci 1480e5c31af7Sopenharmony_ciTextureSamplerCase::IterateResult TextureSamplerCase::iterate (void) 1481e5c31af7Sopenharmony_ci{ 1482e5c31af7Sopenharmony_ci // Draw a grid and texture it with a texture and sample it using special special values. The result samples should all have the green channel at 255 as per the test image. 1483e5c31af7Sopenharmony_ci 1484e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 1485e5c31af7Sopenharmony_ci std::vector<tcu::UVec2> gridTexCoords (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 1486e5c31af7Sopenharmony_ci std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6); 1487e5c31af7Sopenharmony_ci tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1488e5c31af7Sopenharmony_ci 1489e5c31af7Sopenharmony_ci // vertices 1490e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1491e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1492e5c31af7Sopenharmony_ci { 1493e5c31af7Sopenharmony_ci const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1] 1494e5c31af7Sopenharmony_ci const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; 1495e5c31af7Sopenharmony_ci 1496e5c31af7Sopenharmony_ci gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1497e5c31af7Sopenharmony_ci gridTexCoords[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec2(s_specialFloats[x], s_specialFloats[y]); 1498e5c31af7Sopenharmony_ci } 1499e5c31af7Sopenharmony_ci 1500e5c31af7Sopenharmony_ci // tiles 1501e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x) 1502e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y) 1503e5c31af7Sopenharmony_ci { 1504e5c31af7Sopenharmony_ci const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6; 1505e5c31af7Sopenharmony_ci 1506e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1507e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1508e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1509e5c31af7Sopenharmony_ci 1510e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1511e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1512e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1513e5c31af7Sopenharmony_ci } 1514e5c31af7Sopenharmony_ci 1515e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader. Sampling from the texture using special floating point values." << tcu::TestLog::EndMessage; 1516e5c31af7Sopenharmony_ci 1517e5c31af7Sopenharmony_ci // Draw grid 1518e5c31af7Sopenharmony_ci { 1519e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1520e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1521e5c31af7Sopenharmony_ci const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 1522e5c31af7Sopenharmony_ci const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler"); 1523e5c31af7Sopenharmony_ci 1524e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1525e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1526e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1527e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 1528e5c31af7Sopenharmony_ci 1529e5c31af7Sopenharmony_ci gl.uniform1i(samplerLoc, 0); 1530e5c31af7Sopenharmony_ci if (m_testType != TEST_TEX_COORD_CUBE) 1531e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1532e5c31af7Sopenharmony_ci else 1533e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID); 1534e5c31af7Sopenharmony_ci 1535e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1536e5c31af7Sopenharmony_ci gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]); 1537e5c31af7Sopenharmony_ci 1538e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 1539e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(texCoordLoc); 1540e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 1541e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 1542e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(texCoordLoc); 1543e5c31af7Sopenharmony_ci 1544e5c31af7Sopenharmony_ci gl.useProgram(0); 1545e5c31af7Sopenharmony_ci gl.finish(); 1546e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::iterate"); 1547e5c31af7Sopenharmony_ci 1548e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 1549e5c31af7Sopenharmony_ci } 1550e5c31af7Sopenharmony_ci 1551e5c31af7Sopenharmony_ci // verify everywhere was drawn and samples were from the texture (all pixels have Green = 255) 1552e5c31af7Sopenharmony_ci if (!checkResultImage(resultImage)) 1553e5c31af7Sopenharmony_ci { 1554e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 1555e5c31af7Sopenharmony_ci return STOP; 1556e5c31af7Sopenharmony_ci } 1557e5c31af7Sopenharmony_ci 1558e5c31af7Sopenharmony_ci // test drawing and textures still works 1559e5c31af7Sopenharmony_ci if (!drawTestPattern(true)) 1560e5c31af7Sopenharmony_ci { 1561e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 1562e5c31af7Sopenharmony_ci return STOP; 1563e5c31af7Sopenharmony_ci } 1564e5c31af7Sopenharmony_ci 1565e5c31af7Sopenharmony_ci // all ok 1566e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1567e5c31af7Sopenharmony_ci return STOP; 1568e5c31af7Sopenharmony_ci} 1569e5c31af7Sopenharmony_ci 1570e5c31af7Sopenharmony_cistd::string TextureSamplerCase::genVertexSource (void) const 1571e5c31af7Sopenharmony_ci{ 1572e5c31af7Sopenharmony_ci // vertex shader is passthrough, fragment does the calculations 1573e5c31af7Sopenharmony_ci if (m_type == TYPE_FRAGMENT) 1574e5c31af7Sopenharmony_ci return s_attrPassthroughVertexShaderSource; 1575e5c31af7Sopenharmony_ci 1576e5c31af7Sopenharmony_ci // vertex shader does the calculations 1577e5c31af7Sopenharmony_ci std::ostringstream buf; 1578e5c31af7Sopenharmony_ci buf << "#version 300 es\n" 1579e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 1580e5c31af7Sopenharmony_ci "in highp vec2 a_attr;\n"; 1581e5c31af7Sopenharmony_ci 1582e5c31af7Sopenharmony_ci if (m_testType != TEST_TEX_COORD_CUBE) 1583e5c31af7Sopenharmony_ci buf << "uniform highp sampler2D u_sampler;\n"; 1584e5c31af7Sopenharmony_ci else 1585e5c31af7Sopenharmony_ci buf << "uniform highp samplerCube u_sampler;\n"; 1586e5c31af7Sopenharmony_ci 1587e5c31af7Sopenharmony_ci buf << "out mediump vec4 v_out;\n" 1588e5c31af7Sopenharmony_ci "void main ()\n" 1589e5c31af7Sopenharmony_ci "{\n"; 1590e5c31af7Sopenharmony_ci 1591e5c31af7Sopenharmony_ci if (m_testType == TEST_TEX_COORD) 1592e5c31af7Sopenharmony_ci buf << " v_out = textureLod(u_sampler, a_attr, 0.0);\n"; 1593e5c31af7Sopenharmony_ci else if (m_testType == TEST_LOD) 1594e5c31af7Sopenharmony_ci buf << " v_out = textureLod(u_sampler, a_attr, a_attr.x);\n"; 1595e5c31af7Sopenharmony_ci else if (m_testType == TEST_GRAD) 1596e5c31af7Sopenharmony_ci buf << " v_out = textureGrad(u_sampler, a_attr, a_attr, a_attr.yx);\n"; 1597e5c31af7Sopenharmony_ci else if (m_testType == TEST_TEX_COORD_CUBE) 1598e5c31af7Sopenharmony_ci buf << " v_out = textureLod(u_sampler, vec3(a_attr, a_attr.x + a_attr.y), 0.0);\n"; 1599e5c31af7Sopenharmony_ci else 1600e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1601e5c31af7Sopenharmony_ci 1602e5c31af7Sopenharmony_ci buf << "\n" 1603e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 1604e5c31af7Sopenharmony_ci "}\n"; 1605e5c31af7Sopenharmony_ci 1606e5c31af7Sopenharmony_ci return buf.str(); 1607e5c31af7Sopenharmony_ci} 1608e5c31af7Sopenharmony_ci 1609e5c31af7Sopenharmony_cistd::string TextureSamplerCase::genFragmentSource (void) const 1610e5c31af7Sopenharmony_ci{ 1611e5c31af7Sopenharmony_ci // fragment shader is passthrough 1612e5c31af7Sopenharmony_ci if (m_type == TYPE_VERTEX) 1613e5c31af7Sopenharmony_ci return s_colorPassthroughFragmentShaderSource; 1614e5c31af7Sopenharmony_ci 1615e5c31af7Sopenharmony_ci // fragment shader does the calculations 1616e5c31af7Sopenharmony_ci std::ostringstream buf; 1617e5c31af7Sopenharmony_ci buf << "#version 300 es\n" 1618e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 fragColor;\n"; 1619e5c31af7Sopenharmony_ci 1620e5c31af7Sopenharmony_ci if (m_testType != TEST_TEX_COORD_CUBE) 1621e5c31af7Sopenharmony_ci buf << "uniform highp sampler2D u_sampler;\n"; 1622e5c31af7Sopenharmony_ci else 1623e5c31af7Sopenharmony_ci buf << "uniform highp samplerCube u_sampler;\n"; 1624e5c31af7Sopenharmony_ci 1625e5c31af7Sopenharmony_ci buf << "in highp vec4 v_attr;\n" 1626e5c31af7Sopenharmony_ci "void main ()\n" 1627e5c31af7Sopenharmony_ci "{\n"; 1628e5c31af7Sopenharmony_ci 1629e5c31af7Sopenharmony_ci if (m_testType == TEST_TEX_COORD) 1630e5c31af7Sopenharmony_ci buf << " fragColor = texture(u_sampler, v_attr.xy);\n"; 1631e5c31af7Sopenharmony_ci else if (m_testType == TEST_LOD) 1632e5c31af7Sopenharmony_ci buf << " fragColor = texture(u_sampler, v_attr.xy, v_attr.x);\n"; 1633e5c31af7Sopenharmony_ci else if (m_testType == TEST_GRAD) 1634e5c31af7Sopenharmony_ci buf << " fragColor = textureGrad(u_sampler, v_attr.xy, v_attr.xy, v_attr.yx);\n"; 1635e5c31af7Sopenharmony_ci else if (m_testType == TEST_TEX_COORD_CUBE) 1636e5c31af7Sopenharmony_ci buf << " fragColor = texture(u_sampler, vec3(v_attr.xy,v_attr.x + v_attr.y));\n"; 1637e5c31af7Sopenharmony_ci else 1638e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1639e5c31af7Sopenharmony_ci 1640e5c31af7Sopenharmony_ci buf << "}\n"; 1641e5c31af7Sopenharmony_ci 1642e5c31af7Sopenharmony_ci return buf.str(); 1643e5c31af7Sopenharmony_ci} 1644e5c31af7Sopenharmony_ci 1645e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1646e5c31af7Sopenharmony_ci * \brief Tests special floats as fragment shader outputs 1647e5c31af7Sopenharmony_ci * 1648e5c31af7Sopenharmony_ci * Tests that outputting special floats from a fragment shader does not change 1649e5c31af7Sopenharmony_ci * the normal floating point values of outputted from a fragment shader. Special 1650e5c31af7Sopenharmony_ci * floats are outputted in the green component, normal floating point values 1651e5c31af7Sopenharmony_ci * in the red and blue component. Potential changes are tested by rendering 1652e5c31af7Sopenharmony_ci * test pattern two times with different floating point values. The resulting 1653e5c31af7Sopenharmony_ci * images' red and blue channels should be equal. 1654e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1655e5c31af7Sopenharmony_ciclass OutputCase : public FramebufferRenderCase 1656e5c31af7Sopenharmony_ci{ 1657e5c31af7Sopenharmony_cipublic: 1658e5c31af7Sopenharmony_ci OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type); 1659e5c31af7Sopenharmony_ci ~OutputCase (void); 1660e5c31af7Sopenharmony_ci 1661e5c31af7Sopenharmony_ci void testFBO (void); 1662e5c31af7Sopenharmony_ci 1663e5c31af7Sopenharmony_ciprivate: 1664e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 1665e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 1666e5c31af7Sopenharmony_ci}; 1667e5c31af7Sopenharmony_ci 1668e5c31af7Sopenharmony_ciOutputCase::OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type) 1669e5c31af7Sopenharmony_ci : FramebufferRenderCase (context, name, desc, type) 1670e5c31af7Sopenharmony_ci{ 1671e5c31af7Sopenharmony_ci} 1672e5c31af7Sopenharmony_ci 1673e5c31af7Sopenharmony_ciOutputCase::~OutputCase (void) 1674e5c31af7Sopenharmony_ci{ 1675e5c31af7Sopenharmony_ci deinit(); 1676e5c31af7Sopenharmony_ci} 1677e5c31af7Sopenharmony_ci 1678e5c31af7Sopenharmony_civoid OutputCase::testFBO (void) 1679e5c31af7Sopenharmony_ci{ 1680e5c31af7Sopenharmony_ci // Create a 1 X [s_specialFloats] grid of tiles (stripes). 1681e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * 2); 1682e5c31af7Sopenharmony_ci std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 1683e5c31af7Sopenharmony_ci tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8)); 1684e5c31af7Sopenharmony_ci tcu::TextureLevel specialImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1685e5c31af7Sopenharmony_ci tcu::TextureLevel normalImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1686e5c31af7Sopenharmony_ci 1687e5c31af7Sopenharmony_ci // vertices 1688e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y) 1689e5c31af7Sopenharmony_ci { 1690e5c31af7Sopenharmony_ci const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1] 1691e5c31af7Sopenharmony_ci 1692e5c31af7Sopenharmony_ci gridVertices[y * 2 + 0] = tcu::Vec4(-1.0, posY, 0.0f, 1.0f); 1693e5c31af7Sopenharmony_ci gridVertices[y * 2 + 1] = tcu::Vec4( 1.0, posY, 0.0f, 1.0f); 1694e5c31af7Sopenharmony_ci } 1695e5c31af7Sopenharmony_ci 1696e5c31af7Sopenharmony_ci // tiles 1697e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1698e5c31af7Sopenharmony_ci { 1699e5c31af7Sopenharmony_ci const int baseNdx = y * 6; 1700e5c31af7Sopenharmony_ci 1701e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((y + 0) * 2); 1702e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((y + 1) * 2); 1703e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((y + 1) * 2 + 1); 1704e5c31af7Sopenharmony_ci 1705e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((y + 0) * 2); 1706e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((y + 1) * 2 + 1); 1707e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((y + 0) * 2 + 1); 1708e5c31af7Sopenharmony_ci } 1709e5c31af7Sopenharmony_ci 1710e5c31af7Sopenharmony_ci // Draw grids 1711e5c31af7Sopenharmony_ci { 1712e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1713e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1714e5c31af7Sopenharmony_ci const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 1715e5c31af7Sopenharmony_ci 1716e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1717e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1718e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 1719e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw"); 1720e5c31af7Sopenharmony_ci 1721e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1722e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 1723e5c31af7Sopenharmony_ci 1724e5c31af7Sopenharmony_ci // draw 2 passes. Special and normal. 1725e5c31af7Sopenharmony_ci for (int passNdx = 0; passNdx < 2; ++passNdx) 1726e5c31af7Sopenharmony_ci { 1727e5c31af7Sopenharmony_ci const bool specialPass = (passNdx == 0); 1728e5c31af7Sopenharmony_ci 1729e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Pass " << passNdx << ": Drawing stripes with the shader. Setting u_special for each stripe to (" << ((specialPass) ? ("special") : ("1.0")) << ")." << tcu::TestLog::EndMessage; 1730e5c31af7Sopenharmony_ci 1731e5c31af7Sopenharmony_ci // draw stripes 1732e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1733e5c31af7Sopenharmony_ci for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1734e5c31af7Sopenharmony_ci { 1735e5c31af7Sopenharmony_ci const deUint32 one = 0x3F800000; 1736e5c31af7Sopenharmony_ci const deUint32 special = s_specialFloats[y]; 1737e5c31af7Sopenharmony_ci const deUint32 uniformValue = (specialPass) ? (special) : (one); 1738e5c31af7Sopenharmony_ci const int indexIndex = y * 6; 1739e5c31af7Sopenharmony_ci 1740e5c31af7Sopenharmony_ci gl.uniform1fv(specialLoc, 1, (const float*)&uniformValue); 1741e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 1742e5c31af7Sopenharmony_ci } 1743e5c31af7Sopenharmony_ci 1744e5c31af7Sopenharmony_ci gl.finish(); 1745e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, ((specialPass) ? (specialImage) : (normalImage)).getAccess()); 1746e5c31af7Sopenharmony_ci } 1747e5c31af7Sopenharmony_ci 1748e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 1749e5c31af7Sopenharmony_ci gl.useProgram(0); 1750e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate"); 1751e5c31af7Sopenharmony_ci } 1752e5c31af7Sopenharmony_ci 1753e5c31af7Sopenharmony_ci // Check results 1754e5c31af7Sopenharmony_ci { 1755e5c31af7Sopenharmony_ci tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1756e5c31af7Sopenharmony_ci const tcu::RGBA badPixelColor = tcu::RGBA::red(); 1757e5c31af7Sopenharmony_ci const tcu::RGBA okPixelColor = tcu::RGBA::green(); 1758e5c31af7Sopenharmony_ci int badPixels = 0; 1759e5c31af7Sopenharmony_ci 1760e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Checking passes have identical red and blue channels and the green channel is correct in the constant pass." << tcu::TestLog::EndMessage; 1761e5c31af7Sopenharmony_ci 1762e5c31af7Sopenharmony_ci for (int y = 0; y < specialImage.getHeight(); ++y) 1763e5c31af7Sopenharmony_ci for (int x = 0; x < specialImage.getWidth(); ++x) 1764e5c31af7Sopenharmony_ci { 1765e5c31af7Sopenharmony_ci const float greenThreshold = 0.1f; 1766e5c31af7Sopenharmony_ci const tcu::Vec4 cNormal = normalImage.getAccess().getPixel(x, y); 1767e5c31af7Sopenharmony_ci const tcu::Vec4 cSpecial = specialImage.getAccess().getPixel(x, y); 1768e5c31af7Sopenharmony_ci 1769e5c31af7Sopenharmony_ci if (cNormal.x() != cSpecial.x() || cNormal.z() != cSpecial.z() || cNormal.y() < 1.0f - greenThreshold) 1770e5c31af7Sopenharmony_ci { 1771e5c31af7Sopenharmony_ci ++badPixels; 1772e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, badPixelColor); 1773e5c31af7Sopenharmony_ci } 1774e5c31af7Sopenharmony_ci else 1775e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, okPixelColor); 1776e5c31af7Sopenharmony_ci } 1777e5c31af7Sopenharmony_ci 1778e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage; 1779e5c31af7Sopenharmony_ci 1780e5c31af7Sopenharmony_ci if (badPixels) 1781e5c31af7Sopenharmony_ci { 1782e5c31af7Sopenharmony_ci m_testCtx.getLog() 1783e5c31af7Sopenharmony_ci << tcu::TestLog::ImageSet("Results", "Result verification") 1784e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Image with special green channel", "Image with special green channel", specialImage) 1785e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Image with constant green channel", "Image with constant green channel", normalImage) 1786e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Error Mask", "Error Mask", errorMask) 1787e5c31af7Sopenharmony_ci << tcu::TestLog::EndImageSet; 1788e5c31af7Sopenharmony_ci 1789e5c31af7Sopenharmony_ci // all ok? 1790e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 1791e5c31af7Sopenharmony_ci } 1792e5c31af7Sopenharmony_ci else 1793e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1794e5c31af7Sopenharmony_ci } 1795e5c31af7Sopenharmony_ci} 1796e5c31af7Sopenharmony_ci 1797e5c31af7Sopenharmony_cistd::string OutputCase::genVertexSource (void) const 1798e5c31af7Sopenharmony_ci{ 1799e5c31af7Sopenharmony_ci return 1800e5c31af7Sopenharmony_ci "#version 300 es\n" 1801e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 1802e5c31af7Sopenharmony_ci "out highp vec2 v_pos;\n" 1803e5c31af7Sopenharmony_ci "void main ()\n" 1804e5c31af7Sopenharmony_ci "{\n" 1805e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 1806e5c31af7Sopenharmony_ci " v_pos = a_pos.xy;\n" 1807e5c31af7Sopenharmony_ci "}\n"; 1808e5c31af7Sopenharmony_ci} 1809e5c31af7Sopenharmony_ci 1810e5c31af7Sopenharmony_cistd::string OutputCase::genFragmentSource (void) const 1811e5c31af7Sopenharmony_ci{ 1812e5c31af7Sopenharmony_ci return 1813e5c31af7Sopenharmony_ci "#version 300 es\n" 1814e5c31af7Sopenharmony_ci "layout(location = 0) out highp vec4 fragColor;\n" 1815e5c31af7Sopenharmony_ci "uniform highp float u_special;\n" 1816e5c31af7Sopenharmony_ci "in highp vec2 v_pos;\n" 1817e5c31af7Sopenharmony_ci "void main ()\n" 1818e5c31af7Sopenharmony_ci "{\n" 1819e5c31af7Sopenharmony_ci " fragColor = vec4((v_pos.x + 1.0) * 0.5, u_special, (v_pos.y + 1.0) * 0.5, 1.0);\n" 1820e5c31af7Sopenharmony_ci "}\n"; 1821e5c31af7Sopenharmony_ci} 1822e5c31af7Sopenharmony_ci 1823e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1824e5c31af7Sopenharmony_ci * \brief Tests special floats in blending 1825e5c31af7Sopenharmony_ci * 1826e5c31af7Sopenharmony_ci * Tests special floats as alpha and color components with various blending 1827e5c31af7Sopenharmony_ci * modes. Test draws a test pattern and then does various blend operations 1828e5c31af7Sopenharmony_ci * with special float values. After the blending test another test pattern 1829e5c31af7Sopenharmony_ci * is drawn to detect possible blending anomalies. Test patterns should be 1830e5c31af7Sopenharmony_ci * identical. 1831e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1832e5c31af7Sopenharmony_ciclass BlendingCase : public FramebufferRenderCase 1833e5c31af7Sopenharmony_ci{ 1834e5c31af7Sopenharmony_cipublic: 1835e5c31af7Sopenharmony_ci BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type); 1836e5c31af7Sopenharmony_ci ~BlendingCase (void); 1837e5c31af7Sopenharmony_ci 1838e5c31af7Sopenharmony_ci void testFBO (void); 1839e5c31af7Sopenharmony_ci 1840e5c31af7Sopenharmony_ciprivate: 1841e5c31af7Sopenharmony_ci void drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex); 1842e5c31af7Sopenharmony_ci 1843e5c31af7Sopenharmony_ci std::string genVertexSource (void) const; 1844e5c31af7Sopenharmony_ci std::string genFragmentSource (void) const; 1845e5c31af7Sopenharmony_ci}; 1846e5c31af7Sopenharmony_ci 1847e5c31af7Sopenharmony_ciBlendingCase::BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type) 1848e5c31af7Sopenharmony_ci : FramebufferRenderCase (context, name, desc, type) 1849e5c31af7Sopenharmony_ci{ 1850e5c31af7Sopenharmony_ci} 1851e5c31af7Sopenharmony_ci 1852e5c31af7Sopenharmony_ciBlendingCase::~BlendingCase (void) 1853e5c31af7Sopenharmony_ci{ 1854e5c31af7Sopenharmony_ci deinit(); 1855e5c31af7Sopenharmony_ci} 1856e5c31af7Sopenharmony_ci 1857e5c31af7Sopenharmony_civoid BlendingCase::testFBO (void) 1858e5c31af7Sopenharmony_ci{ 1859e5c31af7Sopenharmony_ci static const GLenum equations[] = 1860e5c31af7Sopenharmony_ci { 1861e5c31af7Sopenharmony_ci GL_FUNC_ADD, 1862e5c31af7Sopenharmony_ci GL_FUNC_SUBTRACT, 1863e5c31af7Sopenharmony_ci GL_FUNC_REVERSE_SUBTRACT, 1864e5c31af7Sopenharmony_ci GL_MIN, 1865e5c31af7Sopenharmony_ci GL_MAX 1866e5c31af7Sopenharmony_ci }; 1867e5c31af7Sopenharmony_ci static const GLenum functions[] = 1868e5c31af7Sopenharmony_ci { 1869e5c31af7Sopenharmony_ci GL_ZERO, 1870e5c31af7Sopenharmony_ci GL_ONE, 1871e5c31af7Sopenharmony_ci GL_SRC_COLOR, 1872e5c31af7Sopenharmony_ci GL_ONE_MINUS_SRC_COLOR, 1873e5c31af7Sopenharmony_ci GL_SRC_ALPHA, 1874e5c31af7Sopenharmony_ci GL_ONE_MINUS_SRC_ALPHA, 1875e5c31af7Sopenharmony_ci }; 1876e5c31af7Sopenharmony_ci 1877e5c31af7Sopenharmony_ci // Create a [BlendFuncs] X [s_specialFloats] grid of tiles. ( BlendFuncs = equations x functions ) 1878e5c31af7Sopenharmony_ci 1879e5c31af7Sopenharmony_ci const int numBlendFuncs = DE_LENGTH_OF_ARRAY(equations) * DE_LENGTH_OF_ARRAY(functions); 1880e5c31af7Sopenharmony_ci std::vector<tcu::Vec4> gridVertices ((numBlendFuncs + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1)); 1881e5c31af7Sopenharmony_ci std::vector<deUint16> indices (numBlendFuncs * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 1882e5c31af7Sopenharmony_ci tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8)); 1883e5c31af7Sopenharmony_ci tcu::TextureLevel beforeImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1884e5c31af7Sopenharmony_ci tcu::TextureLevel afterImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1885e5c31af7Sopenharmony_ci 1886e5c31af7Sopenharmony_ci // vertices 1887e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x) 1888e5c31af7Sopenharmony_ci for (int y = 0; y < numBlendFuncs + 1; ++y) 1889e5c31af7Sopenharmony_ci { 1890e5c31af7Sopenharmony_ci const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats)] to [-1, 1] 1891e5c31af7Sopenharmony_ci const float posY = (float)y / (float)numBlendFuncs * 2.0f - 1.0f; 1892e5c31af7Sopenharmony_ci 1893e5c31af7Sopenharmony_ci gridVertices[x * (numBlendFuncs + 1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1894e5c31af7Sopenharmony_ci } 1895e5c31af7Sopenharmony_ci 1896e5c31af7Sopenharmony_ci // tiles 1897e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1898e5c31af7Sopenharmony_ci for (int y = 0; y < numBlendFuncs; ++y) 1899e5c31af7Sopenharmony_ci { 1900e5c31af7Sopenharmony_ci const int baseNdx = (x * numBlendFuncs + y) * 6; 1901e5c31af7Sopenharmony_ci 1902e5c31af7Sopenharmony_ci indices[baseNdx + 0] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0)); 1903e5c31af7Sopenharmony_ci indices[baseNdx + 1] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1)); 1904e5c31af7Sopenharmony_ci indices[baseNdx + 2] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+0)); 1905e5c31af7Sopenharmony_ci 1906e5c31af7Sopenharmony_ci indices[baseNdx + 3] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0)); 1907e5c31af7Sopenharmony_ci indices[baseNdx + 4] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1)); 1908e5c31af7Sopenharmony_ci indices[baseNdx + 5] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+1)); 1909e5c31af7Sopenharmony_ci } 1910e5c31af7Sopenharmony_ci 1911e5c31af7Sopenharmony_ci // Draw tiles 1912e5c31af7Sopenharmony_ci { 1913e5c31af7Sopenharmony_ci const int numPasses = 5; 1914e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1915e5c31af7Sopenharmony_ci const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1916e5c31af7Sopenharmony_ci const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 1917e5c31af7Sopenharmony_ci 1918e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1919e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1920e5c31af7Sopenharmony_ci gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1921e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 1922e5c31af7Sopenharmony_ci gl.enable(GL_BLEND); 1923e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw"); 1924e5c31af7Sopenharmony_ci 1925e5c31af7Sopenharmony_ci gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1926e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(positionLoc); 1927e5c31af7Sopenharmony_ci 1928e5c31af7Sopenharmony_ci // draw "before" image 1929e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing pre-draw pattern." << tcu::TestLog::EndMessage; 1930e5c31af7Sopenharmony_ci drawTestImage(beforeImage.getAccess(), specialLoc, (int)gridVertices.size() - 1); 1931e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw pattern"); 1932e5c31af7Sopenharmony_ci 1933e5c31af7Sopenharmony_ci // draw multiple passes with special floats 1934e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1935e5c31af7Sopenharmony_ci for (int passNdx = 0; passNdx < numPasses; ++passNdx) 1936e5c31af7Sopenharmony_ci { 1937e5c31af7Sopenharmony_ci de::Random rnd(123 + 567 * passNdx); 1938e5c31af7Sopenharmony_ci 1939e5c31af7Sopenharmony_ci m_testCtx.getLog() 1940e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1941e5c31af7Sopenharmony_ci << "Pass " << passNdx << ": Drawing tiles with the shader.\n" 1942e5c31af7Sopenharmony_ci << "\tVarying u_special for each tile.\n" 1943e5c31af7Sopenharmony_ci << "\tVarying blend function and blend equation for each tile.\n" 1944e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1945e5c31af7Sopenharmony_ci 1946e5c31af7Sopenharmony_ci // draw tiles 1947e5c31af7Sopenharmony_ci for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1948e5c31af7Sopenharmony_ci for (int y = 0; y < numBlendFuncs; ++y) 1949e5c31af7Sopenharmony_ci { 1950e5c31af7Sopenharmony_ci const GLenum blendEquation = equations[y % DE_LENGTH_OF_ARRAY(equations)]; 1951e5c31af7Sopenharmony_ci const GLenum blendFunction = functions[y / DE_LENGTH_OF_ARRAY(equations)]; 1952e5c31af7Sopenharmony_ci const GLenum blendFunctionDst = rnd.choose<GLenum>(DE_ARRAY_BEGIN(functions), DE_ARRAY_END(functions)); 1953e5c31af7Sopenharmony_ci const int indexIndex = (x * numBlendFuncs + y) * 6; 1954e5c31af7Sopenharmony_ci 1955e5c31af7Sopenharmony_ci // "rnd.get"s are run in a deterministic order 1956e5c31af7Sopenharmony_ci const deUint32 componentR = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1957e5c31af7Sopenharmony_ci const deUint32 componentG = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1958e5c31af7Sopenharmony_ci const deUint32 componentB = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1959e5c31af7Sopenharmony_ci const deUint32 componentA = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1960e5c31af7Sopenharmony_ci const tcu::UVec4 uniformValue = tcu::UVec4(componentR, componentG, componentB, componentA); 1961e5c31af7Sopenharmony_ci 1962e5c31af7Sopenharmony_ci gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr()); 1963e5c31af7Sopenharmony_ci gl.blendEquation(blendEquation); 1964e5c31af7Sopenharmony_ci gl.blendFunc(blendFunction, blendFunctionDst); 1965e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 1966e5c31af7Sopenharmony_ci } 1967e5c31af7Sopenharmony_ci } 1968e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "special passes"); 1969e5c31af7Sopenharmony_ci 1970e5c31af7Sopenharmony_ci // draw "after" image 1971e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Drawing post-draw pattern." << tcu::TestLog::EndMessage; 1972e5c31af7Sopenharmony_ci drawTestImage(afterImage.getAccess(), specialLoc, (int)gridVertices.size() - 1); 1973e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "post-draw pattern"); 1974e5c31af7Sopenharmony_ci 1975e5c31af7Sopenharmony_ci gl.disableVertexAttribArray(positionLoc); 1976e5c31af7Sopenharmony_ci gl.useProgram(0); 1977e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate"); 1978e5c31af7Sopenharmony_ci } 1979e5c31af7Sopenharmony_ci 1980e5c31af7Sopenharmony_ci // Check results 1981e5c31af7Sopenharmony_ci { 1982e5c31af7Sopenharmony_ci tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1983e5c31af7Sopenharmony_ci const tcu::RGBA badPixelColor = tcu::RGBA::red(); 1984e5c31af7Sopenharmony_ci const tcu::RGBA okPixelColor = tcu::RGBA::green(); 1985e5c31af7Sopenharmony_ci int badPixels = 0; 1986e5c31af7Sopenharmony_ci 1987e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Checking patterns are identical." << tcu::TestLog::EndMessage; 1988e5c31af7Sopenharmony_ci 1989e5c31af7Sopenharmony_ci for (int y = 0; y < beforeImage.getHeight(); ++y) 1990e5c31af7Sopenharmony_ci for (int x = 0; x < beforeImage.getWidth(); ++x) 1991e5c31af7Sopenharmony_ci { 1992e5c31af7Sopenharmony_ci const tcu::Vec4 cBefore = beforeImage.getAccess().getPixel(x, y); 1993e5c31af7Sopenharmony_ci const tcu::Vec4 cAfter = afterImage.getAccess().getPixel(x, y); 1994e5c31af7Sopenharmony_ci 1995e5c31af7Sopenharmony_ci if (cBefore != cAfter) 1996e5c31af7Sopenharmony_ci { 1997e5c31af7Sopenharmony_ci ++badPixels; 1998e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, badPixelColor); 1999e5c31af7Sopenharmony_ci } 2000e5c31af7Sopenharmony_ci else 2001e5c31af7Sopenharmony_ci errorMask.setPixel(x, y, okPixelColor); 2002e5c31af7Sopenharmony_ci } 2003e5c31af7Sopenharmony_ci 2004e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage; 2005e5c31af7Sopenharmony_ci 2006e5c31af7Sopenharmony_ci if (badPixels) 2007e5c31af7Sopenharmony_ci { 2008e5c31af7Sopenharmony_ci m_testCtx.getLog() 2009e5c31af7Sopenharmony_ci << tcu::TestLog::ImageSet("Results", "Result verification") 2010e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Pattern drawn before special float blending", "Pattern drawn before special float blending", beforeImage) 2011e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Pattern drawn after special float blending", "Pattern drawn after special float blending", afterImage) 2012e5c31af7Sopenharmony_ci << tcu::TestLog::EndImageSet; 2013e5c31af7Sopenharmony_ci 2014e5c31af7Sopenharmony_ci // all ok? 2015e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 2016e5c31af7Sopenharmony_ci } 2017e5c31af7Sopenharmony_ci else 2018e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2019e5c31af7Sopenharmony_ci } 2020e5c31af7Sopenharmony_ci} 2021e5c31af7Sopenharmony_ci 2022e5c31af7Sopenharmony_civoid BlendingCase::drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex) 2023e5c31af7Sopenharmony_ci{ 2024e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2025e5c31af7Sopenharmony_ci de::Random rnd (123); 2026e5c31af7Sopenharmony_ci 2027e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 2028e5c31af7Sopenharmony_ci gl.blendEquation(GL_FUNC_ADD); 2029e5c31af7Sopenharmony_ci gl.blendFunc(GL_ONE, GL_ONE); 2030e5c31af7Sopenharmony_ci 2031e5c31af7Sopenharmony_ci for (int tri = 0; tri < 20; ++tri) 2032e5c31af7Sopenharmony_ci { 2033e5c31af7Sopenharmony_ci tcu::Vec4 color; 2034e5c31af7Sopenharmony_ci color.x() = rnd.getFloat(); 2035e5c31af7Sopenharmony_ci color.y() = rnd.getFloat(); 2036e5c31af7Sopenharmony_ci color.z() = rnd.getFloat(); 2037e5c31af7Sopenharmony_ci color.w() = rnd.getFloat(); 2038e5c31af7Sopenharmony_ci gl.uniform4fv(uColorLoc, 1, color.getPtr()); 2039e5c31af7Sopenharmony_ci 2040e5c31af7Sopenharmony_ci deUint16 indices[3]; 2041e5c31af7Sopenharmony_ci indices[0] = (deUint16)rnd.getInt(0, maxVertexIndex); 2042e5c31af7Sopenharmony_ci indices[1] = (deUint16)rnd.getInt(0, maxVertexIndex); 2043e5c31af7Sopenharmony_ci indices[2] = (deUint16)rnd.getInt(0, maxVertexIndex); 2044e5c31af7Sopenharmony_ci 2045e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices); 2046e5c31af7Sopenharmony_ci } 2047e5c31af7Sopenharmony_ci 2048e5c31af7Sopenharmony_ci gl.finish(); 2049e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), 0, 0, dst); 2050e5c31af7Sopenharmony_ci} 2051e5c31af7Sopenharmony_ci 2052e5c31af7Sopenharmony_cistd::string BlendingCase::genVertexSource (void) const 2053e5c31af7Sopenharmony_ci{ 2054e5c31af7Sopenharmony_ci return 2055e5c31af7Sopenharmony_ci "#version 300 es\n" 2056e5c31af7Sopenharmony_ci "in highp vec4 a_pos;\n" 2057e5c31af7Sopenharmony_ci "void main ()\n" 2058e5c31af7Sopenharmony_ci "{\n" 2059e5c31af7Sopenharmony_ci " gl_Position = a_pos;\n" 2060e5c31af7Sopenharmony_ci "}\n"; 2061e5c31af7Sopenharmony_ci} 2062e5c31af7Sopenharmony_ci 2063e5c31af7Sopenharmony_cistd::string BlendingCase::genFragmentSource (void) const 2064e5c31af7Sopenharmony_ci{ 2065e5c31af7Sopenharmony_ci return 2066e5c31af7Sopenharmony_ci "#version 300 es\n" 2067e5c31af7Sopenharmony_ci "layout(location = 0) out highp vec4 fragColor;\n" 2068e5c31af7Sopenharmony_ci "uniform highp vec4 u_special;\n" 2069e5c31af7Sopenharmony_ci "void main ()\n" 2070e5c31af7Sopenharmony_ci "{\n" 2071e5c31af7Sopenharmony_ci " fragColor = u_special;\n" 2072e5c31af7Sopenharmony_ci "}\n"; 2073e5c31af7Sopenharmony_ci} 2074e5c31af7Sopenharmony_ci 2075e5c31af7Sopenharmony_ci} //anonymous 2076e5c31af7Sopenharmony_ci 2077e5c31af7Sopenharmony_ciSpecialFloatTests::SpecialFloatTests (Context& context) 2078e5c31af7Sopenharmony_ci : TestCaseGroup(context, "special_float", "Special float tests") 2079e5c31af7Sopenharmony_ci{ 2080e5c31af7Sopenharmony_ci} 2081e5c31af7Sopenharmony_ci 2082e5c31af7Sopenharmony_ciSpecialFloatTests::~SpecialFloatTests (void) 2083e5c31af7Sopenharmony_ci{ 2084e5c31af7Sopenharmony_ci} 2085e5c31af7Sopenharmony_ci 2086e5c31af7Sopenharmony_civoid SpecialFloatTests::init (void) 2087e5c31af7Sopenharmony_ci{ 2088e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const vertexGroup = new tcu::TestCaseGroup(m_testCtx, "vertex", "Run vertex shader with special float values"); 2089e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const fragmentGroup = new tcu::TestCaseGroup(m_testCtx, "fragment", "Run fragment shader with special float values"); 2090e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const framebufferGroup = new tcu::TestCaseGroup(m_testCtx, "framebuffer", "Test framebuffers containing special float values"); 2091e5c31af7Sopenharmony_ci 2092e5c31af7Sopenharmony_ci // .vertex 2093e5c31af7Sopenharmony_ci { 2094e5c31af7Sopenharmony_ci vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_VERTEX)); 2095e5c31af7Sopenharmony_ci vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_VERTEX)); 2096e5c31af7Sopenharmony_ci vertexGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_VERTEX)); 2097e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT)); 2098e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO)); 2099e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT)); 2100e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD)); 2101e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD_CUBE)); 2102e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_LOD)); 2103e5c31af7Sopenharmony_ci vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_GRAD)); 2104e5c31af7Sopenharmony_ci 2105e5c31af7Sopenharmony_ci addChild(vertexGroup); 2106e5c31af7Sopenharmony_ci } 2107e5c31af7Sopenharmony_ci 2108e5c31af7Sopenharmony_ci // .fragment 2109e5c31af7Sopenharmony_ci { 2110e5c31af7Sopenharmony_ci fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_FRAGMENT)); 2111e5c31af7Sopenharmony_ci fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_FRAGMENT)); 2112e5c31af7Sopenharmony_ci fragmentGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_FRAGMENT)); 2113e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT)); 2114e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO)); 2115e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT)); 2116e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD)); 2117e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD_CUBE)); 2118e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_LOD)); 2119e5c31af7Sopenharmony_ci fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_GRAD)); 2120e5c31af7Sopenharmony_ci 2121e5c31af7Sopenharmony_ci addChild(fragmentGroup); 2122e5c31af7Sopenharmony_ci } 2123e5c31af7Sopenharmony_ci 2124e5c31af7Sopenharmony_ci // .framebuffer 2125e5c31af7Sopenharmony_ci { 2126e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_default", "write special floating point values to default framebuffer", FramebufferRenderCase::FBO_DEFAULT)); 2127e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_rgba4", "write special floating point values to RGBA4 framebuffer", FramebufferRenderCase::FBO_RGBA4)); 2128e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_rgb5_a1", "write special floating point values to RGB5_A1 framebuffer", FramebufferRenderCase::FBO_RGB5_A1)); 2129e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_rgb565", "write special floating point values to RGB565 framebuffer", FramebufferRenderCase::FBO_RGB565)); 2130e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_rgba8", "write special floating point values to RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8)); 2131e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_rgb10_a2", "write special floating point values to RGB10_A2 framebuffer", FramebufferRenderCase::FBO_RGB10_A2)); 2132e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_float16", "write special floating point values to float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16)); 2133e5c31af7Sopenharmony_ci framebufferGroup->addChild(new OutputCase (m_context, "write_float32", "write special floating point values to float32 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT32)); 2134e5c31af7Sopenharmony_ci 2135e5c31af7Sopenharmony_ci framebufferGroup->addChild(new BlendingCase (m_context, "blend_default", "blend special floating point values in a default framebuffer", FramebufferRenderCase::FBO_DEFAULT)); 2136e5c31af7Sopenharmony_ci framebufferGroup->addChild(new BlendingCase (m_context, "blend_rgba8", "blend special floating point values in a RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8)); 2137e5c31af7Sopenharmony_ci framebufferGroup->addChild(new BlendingCase (m_context, "blend_float16", "blend special floating point values in a float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16)); 2138e5c31af7Sopenharmony_ci 2139e5c31af7Sopenharmony_ci addChild(framebufferGroup); 2140e5c31af7Sopenharmony_ci } 2141e5c31af7Sopenharmony_ci} 2142e5c31af7Sopenharmony_ci 2143e5c31af7Sopenharmony_ci} // Stress 2144e5c31af7Sopenharmony_ci} // gles3 2145e5c31af7Sopenharmony_ci} // deqp 2146