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 Fragment shader output tests. 22e5c31af7Sopenharmony_ci * 23e5c31af7Sopenharmony_ci * \todo [2012-04-10 pyry] Missing: 24e5c31af7Sopenharmony_ci * + non-contiguous attachments in framebuffer 25e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 26e5c31af7Sopenharmony_ci 27e5c31af7Sopenharmony_ci#include "es3fFragmentOutputTests.hpp" 28e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp" 29e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 30e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp" 31e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 32e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 33e5c31af7Sopenharmony_ci#include "tcuTexture.hpp" 34e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 35e5c31af7Sopenharmony_ci#include "tcuVector.hpp" 36e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 37e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp" 38e5c31af7Sopenharmony_ci#include "deRandom.hpp" 39e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 40e5c31af7Sopenharmony_ci#include "deMath.h" 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_ci// For getFormatName() \todo [pyry] Move to glu? 43e5c31af7Sopenharmony_ci#include "es3fFboTestUtil.hpp" 44e5c31af7Sopenharmony_ci 45e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 46e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_cinamespace deqp 49e5c31af7Sopenharmony_ci{ 50e5c31af7Sopenharmony_cinamespace gles3 51e5c31af7Sopenharmony_ci{ 52e5c31af7Sopenharmony_cinamespace Functional 53e5c31af7Sopenharmony_ci{ 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ciusing std::vector; 56e5c31af7Sopenharmony_ciusing std::string; 57e5c31af7Sopenharmony_ciusing tcu::IVec2; 58e5c31af7Sopenharmony_ciusing tcu::IVec4; 59e5c31af7Sopenharmony_ciusing tcu::UVec2; 60e5c31af7Sopenharmony_ciusing tcu::UVec4; 61e5c31af7Sopenharmony_ciusing tcu::Vec2; 62e5c31af7Sopenharmony_ciusing tcu::Vec3; 63e5c31af7Sopenharmony_ciusing tcu::Vec4; 64e5c31af7Sopenharmony_ciusing tcu::BVec4; 65e5c31af7Sopenharmony_ciusing tcu::TestLog; 66e5c31af7Sopenharmony_ciusing FboTestUtil::getFormatName; 67e5c31af7Sopenharmony_ciusing FboTestUtil::getFramebufferReadFormat; 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_cistruct BufferSpec 70e5c31af7Sopenharmony_ci{ 71e5c31af7Sopenharmony_ci BufferSpec (void) 72e5c31af7Sopenharmony_ci : format (GL_NONE) 73e5c31af7Sopenharmony_ci , width (0) 74e5c31af7Sopenharmony_ci , height (0) 75e5c31af7Sopenharmony_ci , samples (0) 76e5c31af7Sopenharmony_ci { 77e5c31af7Sopenharmony_ci } 78e5c31af7Sopenharmony_ci 79e5c31af7Sopenharmony_ci BufferSpec (deUint32 format_, int width_, int height_, int samples_) 80e5c31af7Sopenharmony_ci : format (format_) 81e5c31af7Sopenharmony_ci , width (width_) 82e5c31af7Sopenharmony_ci , height (height_) 83e5c31af7Sopenharmony_ci , samples (samples_) 84e5c31af7Sopenharmony_ci { 85e5c31af7Sopenharmony_ci } 86e5c31af7Sopenharmony_ci 87e5c31af7Sopenharmony_ci deUint32 format; 88e5c31af7Sopenharmony_ci int width; 89e5c31af7Sopenharmony_ci int height; 90e5c31af7Sopenharmony_ci int samples; 91e5c31af7Sopenharmony_ci}; 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_cistruct FragmentOutput 94e5c31af7Sopenharmony_ci{ 95e5c31af7Sopenharmony_ci FragmentOutput (void) 96e5c31af7Sopenharmony_ci : type (glu::TYPE_LAST) 97e5c31af7Sopenharmony_ci , precision (glu::PRECISION_LAST) 98e5c31af7Sopenharmony_ci , location (0) 99e5c31af7Sopenharmony_ci , arrayLength (0) 100e5c31af7Sopenharmony_ci { 101e5c31af7Sopenharmony_ci } 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci FragmentOutput (glu::DataType type_, glu::Precision precision_, int location_, int arrayLength_ = 0) 104e5c31af7Sopenharmony_ci : type (type_) 105e5c31af7Sopenharmony_ci , precision (precision_) 106e5c31af7Sopenharmony_ci , location (location_) 107e5c31af7Sopenharmony_ci , arrayLength (arrayLength_) 108e5c31af7Sopenharmony_ci { 109e5c31af7Sopenharmony_ci } 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci glu::DataType type; 112e5c31af7Sopenharmony_ci glu::Precision precision; 113e5c31af7Sopenharmony_ci int location; 114e5c31af7Sopenharmony_ci int arrayLength; //!< 0 if not an array. 115e5c31af7Sopenharmony_ci}; 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_cistruct OutputVec 118e5c31af7Sopenharmony_ci{ 119e5c31af7Sopenharmony_ci vector<FragmentOutput> outputs; 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci OutputVec& operator<< (const FragmentOutput& output) 122e5c31af7Sopenharmony_ci { 123e5c31af7Sopenharmony_ci outputs.push_back(output); 124e5c31af7Sopenharmony_ci return *this; 125e5c31af7Sopenharmony_ci } 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci vector<FragmentOutput> toVec (void) const 128e5c31af7Sopenharmony_ci { 129e5c31af7Sopenharmony_ci return outputs; 130e5c31af7Sopenharmony_ci } 131e5c31af7Sopenharmony_ci}; 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ciclass FragmentOutputCase : public TestCase 134e5c31af7Sopenharmony_ci{ 135e5c31af7Sopenharmony_cipublic: 136e5c31af7Sopenharmony_ci FragmentOutputCase (Context& context, const char* name, const char* desc, const vector<BufferSpec>& fboSpec, const vector<FragmentOutput>& outputs); 137e5c31af7Sopenharmony_ci ~FragmentOutputCase (void); 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci void init (void); 140e5c31af7Sopenharmony_ci void deinit (void); 141e5c31af7Sopenharmony_ci IterateResult iterate (void); 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ciprivate: 144e5c31af7Sopenharmony_ci FragmentOutputCase (const FragmentOutputCase& other); 145e5c31af7Sopenharmony_ci FragmentOutputCase& operator= (const FragmentOutputCase& other); 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_ci vector<BufferSpec> m_fboSpec; 148e5c31af7Sopenharmony_ci vector<FragmentOutput> m_outputs; 149e5c31af7Sopenharmony_ci 150e5c31af7Sopenharmony_ci glu::ShaderProgram* m_program; 151e5c31af7Sopenharmony_ci deUint32 m_framebuffer; 152e5c31af7Sopenharmony_ci vector<deUint32> m_renderbuffers; 153e5c31af7Sopenharmony_ci}; 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ciFragmentOutputCase::FragmentOutputCase (Context& context, const char* name, const char* desc, const vector<BufferSpec>& fboSpec, const vector<FragmentOutput>& outputs) 156e5c31af7Sopenharmony_ci : TestCase (context, name, desc) 157e5c31af7Sopenharmony_ci , m_fboSpec (fboSpec) 158e5c31af7Sopenharmony_ci , m_outputs (outputs) 159e5c31af7Sopenharmony_ci , m_program (DE_NULL) 160e5c31af7Sopenharmony_ci , m_framebuffer (0) 161e5c31af7Sopenharmony_ci{ 162e5c31af7Sopenharmony_ci} 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ciFragmentOutputCase::~FragmentOutputCase (void) 165e5c31af7Sopenharmony_ci{ 166e5c31af7Sopenharmony_ci deinit(); 167e5c31af7Sopenharmony_ci} 168e5c31af7Sopenharmony_ci 169e5c31af7Sopenharmony_cistatic glu::ShaderProgram* createProgram (const glu::RenderContext& context, const vector<FragmentOutput>& outputs) 170e5c31af7Sopenharmony_ci{ 171e5c31af7Sopenharmony_ci std::ostringstream vtx; 172e5c31af7Sopenharmony_ci std::ostringstream frag; 173e5c31af7Sopenharmony_ci 174e5c31af7Sopenharmony_ci vtx << "#version 300 es\n" 175e5c31af7Sopenharmony_ci << "in highp vec4 a_position;\n"; 176e5c31af7Sopenharmony_ci frag << "#version 300 es\n"; 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_ci // Input-output declarations. 179e5c31af7Sopenharmony_ci for (int outNdx = 0; outNdx < (int)outputs.size(); outNdx++) 180e5c31af7Sopenharmony_ci { 181e5c31af7Sopenharmony_ci const FragmentOutput& output = outputs[outNdx]; 182e5c31af7Sopenharmony_ci bool isArray = output.arrayLength > 0; 183e5c31af7Sopenharmony_ci const char* typeName = glu::getDataTypeName(output.type); 184e5c31af7Sopenharmony_ci const char* outputPrec = glu::getPrecisionName(output.precision); 185e5c31af7Sopenharmony_ci bool isFloat = glu::isDataTypeFloatOrVec(output.type); 186e5c31af7Sopenharmony_ci const char* interp = isFloat ? "smooth" : "flat"; 187e5c31af7Sopenharmony_ci const char* interpPrec = isFloat ? "highp" : outputPrec; 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci if (isArray) 190e5c31af7Sopenharmony_ci { 191e5c31af7Sopenharmony_ci for (int elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) 192e5c31af7Sopenharmony_ci { 193e5c31af7Sopenharmony_ci vtx << "in " << interpPrec << " " << typeName << " in" << outNdx << "_" << elemNdx << ";\n" 194e5c31af7Sopenharmony_ci << interp << " out " << interpPrec << " " << typeName << " var" << outNdx << "_" << elemNdx << ";\n"; 195e5c31af7Sopenharmony_ci frag << interp << " in " << interpPrec << " " << typeName << " var" << outNdx << "_" << elemNdx << ";\n"; 196e5c31af7Sopenharmony_ci } 197e5c31af7Sopenharmony_ci frag << "layout(location = " << output.location << ") out " << outputPrec << " " << typeName << " out" << outNdx << "[" << output.arrayLength << "];\n"; 198e5c31af7Sopenharmony_ci } 199e5c31af7Sopenharmony_ci else 200e5c31af7Sopenharmony_ci { 201e5c31af7Sopenharmony_ci vtx << "in " << interpPrec << " " << typeName << " in" << outNdx << ";\n" 202e5c31af7Sopenharmony_ci << interp << " out " << interpPrec << " " << typeName << " var" << outNdx << ";\n"; 203e5c31af7Sopenharmony_ci frag << interp << " in " << interpPrec << " " << typeName << " var" << outNdx << ";\n" 204e5c31af7Sopenharmony_ci << "layout(location = " << output.location << ") out " << outputPrec << " " << typeName << " out" << outNdx << ";\n"; 205e5c31af7Sopenharmony_ci } 206e5c31af7Sopenharmony_ci } 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_ci vtx << "\nvoid main()\n{\n"; 209e5c31af7Sopenharmony_ci frag << "\nvoid main()\n{\n"; 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ci vtx << " gl_Position = a_position;\n"; 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci // Copy body 214e5c31af7Sopenharmony_ci for (int outNdx = 0; outNdx < (int)outputs.size(); outNdx++) 215e5c31af7Sopenharmony_ci { 216e5c31af7Sopenharmony_ci const FragmentOutput& output = outputs[outNdx]; 217e5c31af7Sopenharmony_ci bool isArray = output.arrayLength > 0; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci if (isArray) 220e5c31af7Sopenharmony_ci { 221e5c31af7Sopenharmony_ci for (int elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) 222e5c31af7Sopenharmony_ci { 223e5c31af7Sopenharmony_ci vtx << "\tvar" << outNdx << "_" << elemNdx << " = in" << outNdx << "_" << elemNdx << ";\n"; 224e5c31af7Sopenharmony_ci frag << "\tout" << outNdx << "[" << elemNdx << "] = var" << outNdx << "_" << elemNdx << ";\n"; 225e5c31af7Sopenharmony_ci } 226e5c31af7Sopenharmony_ci } 227e5c31af7Sopenharmony_ci else 228e5c31af7Sopenharmony_ci { 229e5c31af7Sopenharmony_ci vtx << "\tvar" << outNdx << " = in" << outNdx << ";\n"; 230e5c31af7Sopenharmony_ci frag << "\tout" << outNdx << " = var" << outNdx << ";\n"; 231e5c31af7Sopenharmony_ci } 232e5c31af7Sopenharmony_ci } 233e5c31af7Sopenharmony_ci 234e5c31af7Sopenharmony_ci vtx << "}\n"; 235e5c31af7Sopenharmony_ci frag << "}\n"; 236e5c31af7Sopenharmony_ci 237e5c31af7Sopenharmony_ci return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str())); 238e5c31af7Sopenharmony_ci} 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_civoid FragmentOutputCase::init (void) 241e5c31af7Sopenharmony_ci{ 242e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 243e5c31af7Sopenharmony_ci TestLog& log = m_testCtx.getLog(); 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci // Check that all attachments are supported 246e5c31af7Sopenharmony_ci for (std::vector<BufferSpec>::const_iterator bufIter = m_fboSpec.begin(); bufIter != m_fboSpec.end(); ++bufIter) 247e5c31af7Sopenharmony_ci { 248e5c31af7Sopenharmony_ci if (!glu::isSizedFormatColorRenderable(m_context.getRenderContext(), m_context.getContextInfo(), bufIter->format)) 249e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Unsupported attachment format"); 250e5c31af7Sopenharmony_ci } 251e5c31af7Sopenharmony_ci 252e5c31af7Sopenharmony_ci DE_ASSERT(!m_program); 253e5c31af7Sopenharmony_ci m_program = createProgram(m_context.getRenderContext(), m_outputs); 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ci log << *m_program; 256e5c31af7Sopenharmony_ci if (!m_program->isOk()) 257e5c31af7Sopenharmony_ci TCU_FAIL("Compile failed"); 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci // Print render target info to log. 260e5c31af7Sopenharmony_ci log << TestLog::Section("Framebuffer", "Framebuffer configuration"); 261e5c31af7Sopenharmony_ci 262e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)m_fboSpec.size(); ndx++) 263e5c31af7Sopenharmony_ci log << TestLog::Message << "COLOR_ATTACHMENT" << ndx << ": " 264e5c31af7Sopenharmony_ci << glu::getTextureFormatStr(m_fboSpec[ndx].format) << ", " 265e5c31af7Sopenharmony_ci << m_fboSpec[ndx].width << "x" << m_fboSpec[ndx].height << ", " 266e5c31af7Sopenharmony_ci << m_fboSpec[ndx].samples << " samples" 267e5c31af7Sopenharmony_ci << TestLog::EndMessage; 268e5c31af7Sopenharmony_ci 269e5c31af7Sopenharmony_ci log << TestLog::EndSection; 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci // Create framebuffer. 272e5c31af7Sopenharmony_ci m_renderbuffers.resize(m_fboSpec.size(), 0); 273e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_framebuffer); 274e5c31af7Sopenharmony_ci gl.genRenderbuffers((int)m_renderbuffers.size(), &m_renderbuffers[0]); 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 277e5c31af7Sopenharmony_ci 278e5c31af7Sopenharmony_ci for (int bufNdx = 0; bufNdx < (int)m_renderbuffers.size(); bufNdx++) 279e5c31af7Sopenharmony_ci { 280e5c31af7Sopenharmony_ci deUint32 rbo = m_renderbuffers[bufNdx]; 281e5c31af7Sopenharmony_ci const BufferSpec& bufSpec = m_fboSpec[bufNdx]; 282e5c31af7Sopenharmony_ci deUint32 attachment = GL_COLOR_ATTACHMENT0+bufNdx; 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ci gl.bindRenderbuffer(GL_RENDERBUFFER, rbo); 285e5c31af7Sopenharmony_ci gl.renderbufferStorageMultisample(GL_RENDERBUFFER, bufSpec.samples, bufSpec.format, bufSpec.width, bufSpec.height); 286e5c31af7Sopenharmony_ci gl.framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo); 287e5c31af7Sopenharmony_ci } 288e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "After framebuffer setup"); 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci deUint32 fboStatus = gl.checkFramebufferStatus(GL_FRAMEBUFFER); 291e5c31af7Sopenharmony_ci if (fboStatus == GL_FRAMEBUFFER_UNSUPPORTED) 292e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Framebuffer not supported", "", __FILE__, __LINE__); 293e5c31af7Sopenharmony_ci else if (fboStatus != GL_FRAMEBUFFER_COMPLETE) 294e5c31af7Sopenharmony_ci throw tcu::TestError((string("Incomplete framebuffer: ") + glu::getFramebufferStatusStr(fboStatus).toString()).c_str(), "", __FILE__, __LINE__); 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 297e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "After init"); 298e5c31af7Sopenharmony_ci} 299e5c31af7Sopenharmony_ci 300e5c31af7Sopenharmony_civoid FragmentOutputCase::deinit (void) 301e5c31af7Sopenharmony_ci{ 302e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_ci if (m_framebuffer) 305e5c31af7Sopenharmony_ci { 306e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_framebuffer); 307e5c31af7Sopenharmony_ci m_framebuffer = 0; 308e5c31af7Sopenharmony_ci } 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci if (!m_renderbuffers.empty()) 311e5c31af7Sopenharmony_ci { 312e5c31af7Sopenharmony_ci gl.deleteRenderbuffers((int)m_renderbuffers.size(), &m_renderbuffers[0]); 313e5c31af7Sopenharmony_ci m_renderbuffers.clear(); 314e5c31af7Sopenharmony_ci } 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci delete m_program; 317e5c31af7Sopenharmony_ci m_program = DE_NULL; 318e5c31af7Sopenharmony_ci} 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_cistatic IVec2 getMinSize (const vector<BufferSpec>& fboSpec) 321e5c31af7Sopenharmony_ci{ 322e5c31af7Sopenharmony_ci IVec2 minSize(0x7fffffff, 0x7fffffff); 323e5c31af7Sopenharmony_ci for (vector<BufferSpec>::const_iterator i = fboSpec.begin(); i != fboSpec.end(); i++) 324e5c31af7Sopenharmony_ci { 325e5c31af7Sopenharmony_ci minSize.x() = de::min(minSize.x(), i->width); 326e5c31af7Sopenharmony_ci minSize.y() = de::min(minSize.y(), i->height); 327e5c31af7Sopenharmony_ci } 328e5c31af7Sopenharmony_ci return minSize; 329e5c31af7Sopenharmony_ci} 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_cistatic int getNumInputVectors (const vector<FragmentOutput>& outputs) 332e5c31af7Sopenharmony_ci{ 333e5c31af7Sopenharmony_ci int numVecs = 0; 334e5c31af7Sopenharmony_ci for (vector<FragmentOutput>::const_iterator i = outputs.begin(); i != outputs.end(); i++) 335e5c31af7Sopenharmony_ci numVecs += (i->arrayLength > 0 ? i->arrayLength : 1); 336e5c31af7Sopenharmony_ci return numVecs; 337e5c31af7Sopenharmony_ci} 338e5c31af7Sopenharmony_ci 339e5c31af7Sopenharmony_cistatic Vec2 getFloatRange (glu::Precision precision) 340e5c31af7Sopenharmony_ci{ 341e5c31af7Sopenharmony_ci // \todo [2012-04-09 pyry] Not quite the full ranges. 342e5c31af7Sopenharmony_ci static const Vec2 ranges[] = 343e5c31af7Sopenharmony_ci { 344e5c31af7Sopenharmony_ci Vec2(-2.0f, 2.0f), 345e5c31af7Sopenharmony_ci Vec2(-16000.0f, 16000.0f), 346e5c31af7Sopenharmony_ci Vec2(-1e35f, 1e35f) 347e5c31af7Sopenharmony_ci }; 348e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 349e5c31af7Sopenharmony_ci DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 350e5c31af7Sopenharmony_ci return ranges[precision]; 351e5c31af7Sopenharmony_ci} 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_cistatic IVec2 getIntRange (glu::Precision precision) 354e5c31af7Sopenharmony_ci{ 355e5c31af7Sopenharmony_ci static const IVec2 ranges[] = 356e5c31af7Sopenharmony_ci { 357e5c31af7Sopenharmony_ci IVec2(-(1<< 7), (1<< 7)-1), 358e5c31af7Sopenharmony_ci IVec2(-(1<<15), (1<<15)-1), 359e5c31af7Sopenharmony_ci IVec2(0x80000000, 0x7fffffff) 360e5c31af7Sopenharmony_ci }; 361e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 362e5c31af7Sopenharmony_ci DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 363e5c31af7Sopenharmony_ci return ranges[precision]; 364e5c31af7Sopenharmony_ci} 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_cistatic UVec2 getUintRange (glu::Precision precision) 367e5c31af7Sopenharmony_ci{ 368e5c31af7Sopenharmony_ci static const UVec2 ranges[] = 369e5c31af7Sopenharmony_ci { 370e5c31af7Sopenharmony_ci UVec2(0, (1<< 8)-1), 371e5c31af7Sopenharmony_ci UVec2(0, (1<<16)-1), 372e5c31af7Sopenharmony_ci UVec2(0, 0xffffffffu) 373e5c31af7Sopenharmony_ci }; 374e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 375e5c31af7Sopenharmony_ci DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 376e5c31af7Sopenharmony_ci return ranges[precision]; 377e5c31af7Sopenharmony_ci} 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_cistatic inline Vec4 readVec4 (const float* ptr, int numComponents) 380e5c31af7Sopenharmony_ci{ 381e5c31af7Sopenharmony_ci DE_ASSERT(numComponents >= 1); 382e5c31af7Sopenharmony_ci return Vec4(ptr[0], 383e5c31af7Sopenharmony_ci numComponents >= 2 ? ptr[1] : 0.0f, 384e5c31af7Sopenharmony_ci numComponents >= 3 ? ptr[2] : 0.0f, 385e5c31af7Sopenharmony_ci numComponents >= 4 ? ptr[3] : 0.0f); 386e5c31af7Sopenharmony_ci} 387e5c31af7Sopenharmony_ci 388e5c31af7Sopenharmony_cistatic inline IVec4 readIVec4 (const int* ptr, int numComponents) 389e5c31af7Sopenharmony_ci{ 390e5c31af7Sopenharmony_ci DE_ASSERT(numComponents >= 1); 391e5c31af7Sopenharmony_ci return IVec4(ptr[0], 392e5c31af7Sopenharmony_ci numComponents >= 2 ? ptr[1] : 0, 393e5c31af7Sopenharmony_ci numComponents >= 3 ? ptr[2] : 0, 394e5c31af7Sopenharmony_ci numComponents >= 4 ? ptr[3] : 0); 395e5c31af7Sopenharmony_ci} 396e5c31af7Sopenharmony_ci 397e5c31af7Sopenharmony_cistatic void renderFloatReference (const tcu::PixelBufferAccess& dst, int gridWidth, int gridHeight, int numComponents, const float* vertices) 398e5c31af7Sopenharmony_ci{ 399e5c31af7Sopenharmony_ci const bool isSRGB = tcu::isSRGB(dst.getFormat()); 400e5c31af7Sopenharmony_ci const float cellW = (float)dst.getWidth() / (float)(gridWidth-1); 401e5c31af7Sopenharmony_ci const float cellH = (float)dst.getHeight() / (float)(gridHeight-1); 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 404e5c31af7Sopenharmony_ci { 405e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 406e5c31af7Sopenharmony_ci { 407e5c31af7Sopenharmony_ci const int cellX = de::clamp(deFloorFloatToInt32((float)x / cellW), 0, gridWidth-2); 408e5c31af7Sopenharmony_ci const int cellY = de::clamp(deFloorFloatToInt32((float)y / cellH), 0, gridHeight-2); 409e5c31af7Sopenharmony_ci const float xf = ((float)x - (float)cellX*cellW + 0.5f) / cellW; 410e5c31af7Sopenharmony_ci const float yf = ((float)y - (float)cellY*cellH + 0.5f) / cellH; 411e5c31af7Sopenharmony_ci const Vec4 v00 = readVec4(vertices + ((cellY+0)*gridWidth + cellX+0)*numComponents, numComponents); 412e5c31af7Sopenharmony_ci const Vec4 v01 = readVec4(vertices + ((cellY+1)*gridWidth + cellX+0)*numComponents, numComponents); 413e5c31af7Sopenharmony_ci const Vec4 v10 = readVec4(vertices + ((cellY+0)*gridWidth + cellX+1)*numComponents, numComponents); 414e5c31af7Sopenharmony_ci const Vec4 v11 = readVec4(vertices + ((cellY+1)*gridWidth + cellX+1)*numComponents, numComponents); 415e5c31af7Sopenharmony_ci const bool tri = xf + yf >= 1.0f; 416e5c31af7Sopenharmony_ci const Vec4& v0 = tri ? v11 : v00; 417e5c31af7Sopenharmony_ci const Vec4& v1 = tri ? v01 : v10; 418e5c31af7Sopenharmony_ci const Vec4& v2 = tri ? v10 : v01; 419e5c31af7Sopenharmony_ci const float s = tri ? 1.0f-xf : xf; 420e5c31af7Sopenharmony_ci const float t = tri ? 1.0f-yf : yf; 421e5c31af7Sopenharmony_ci const Vec4 color = v0 + (v1-v0)*s + (v2-v0)*t; 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci dst.setPixel(isSRGB ? tcu::linearToSRGB(color) : color, x, y); 424e5c31af7Sopenharmony_ci } 425e5c31af7Sopenharmony_ci } 426e5c31af7Sopenharmony_ci} 427e5c31af7Sopenharmony_ci 428e5c31af7Sopenharmony_cistatic void renderIntReference (const tcu::PixelBufferAccess& dst, int gridWidth, int gridHeight, int numComponents, const int* vertices) 429e5c31af7Sopenharmony_ci{ 430e5c31af7Sopenharmony_ci float cellW = (float)dst.getWidth() / (float)(gridWidth-1); 431e5c31af7Sopenharmony_ci float cellH = (float)dst.getHeight() / (float)(gridHeight-1); 432e5c31af7Sopenharmony_ci 433e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 434e5c31af7Sopenharmony_ci { 435e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 436e5c31af7Sopenharmony_ci { 437e5c31af7Sopenharmony_ci int cellX = de::clamp(deFloorFloatToInt32((float)x / cellW), 0, gridWidth-2); 438e5c31af7Sopenharmony_ci int cellY = de::clamp(deFloorFloatToInt32((float)y / cellH), 0, gridHeight-2); 439e5c31af7Sopenharmony_ci IVec4 c = readIVec4(vertices + (cellY*gridWidth + cellX+1)*numComponents, numComponents); 440e5c31af7Sopenharmony_ci 441e5c31af7Sopenharmony_ci dst.setPixel(c, x, y); 442e5c31af7Sopenharmony_ci } 443e5c31af7Sopenharmony_ci } 444e5c31af7Sopenharmony_ci} 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_cistatic const IVec4 s_swizzles[] = 447e5c31af7Sopenharmony_ci{ 448e5c31af7Sopenharmony_ci IVec4(0,1,2,3), 449e5c31af7Sopenharmony_ci IVec4(1,2,3,0), 450e5c31af7Sopenharmony_ci IVec4(2,3,0,1), 451e5c31af7Sopenharmony_ci IVec4(3,0,1,2), 452e5c31af7Sopenharmony_ci IVec4(3,2,1,0), 453e5c31af7Sopenharmony_ci IVec4(2,1,0,3), 454e5c31af7Sopenharmony_ci IVec4(1,0,3,2), 455e5c31af7Sopenharmony_ci IVec4(0,3,2,1) 456e5c31af7Sopenharmony_ci}; 457e5c31af7Sopenharmony_ci 458e5c31af7Sopenharmony_citemplate <typename T> 459e5c31af7Sopenharmony_ciinline tcu::Vector<T, 4> swizzleVec (const tcu::Vector<T, 4>& vec, int swzNdx) 460e5c31af7Sopenharmony_ci{ 461e5c31af7Sopenharmony_ci const IVec4& swz = s_swizzles[swzNdx % DE_LENGTH_OF_ARRAY(s_swizzles)]; 462e5c31af7Sopenharmony_ci return vec.swizzle(swz[0], swz[1], swz[2], swz[3]); 463e5c31af7Sopenharmony_ci} 464e5c31af7Sopenharmony_ci 465e5c31af7Sopenharmony_cinamespace 466e5c31af7Sopenharmony_ci{ 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_cistruct AttachmentData 469e5c31af7Sopenharmony_ci{ 470e5c31af7Sopenharmony_ci tcu::TextureFormat format; //!< Actual format of attachment. 471e5c31af7Sopenharmony_ci tcu::TextureFormat referenceFormat; //!< Used for reference rendering. 472e5c31af7Sopenharmony_ci tcu::TextureFormat readFormat; 473e5c31af7Sopenharmony_ci int numWrittenChannels; 474e5c31af7Sopenharmony_ci glu::Precision outPrecision; 475e5c31af7Sopenharmony_ci vector<deUint8> renderedData; 476e5c31af7Sopenharmony_ci vector<deUint8> referenceData; 477e5c31af7Sopenharmony_ci}; 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_citemplate<typename Type> 480e5c31af7Sopenharmony_cistring valueRangeToString (int numValidChannels, const tcu::Vector<Type, 4>& minValue, const tcu::Vector<Type, 4>& maxValue) 481e5c31af7Sopenharmony_ci{ 482e5c31af7Sopenharmony_ci std::ostringstream stream; 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci stream << "("; 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci for (int i = 0; i < 4; i++) 487e5c31af7Sopenharmony_ci { 488e5c31af7Sopenharmony_ci if (i != 0) 489e5c31af7Sopenharmony_ci stream << ", "; 490e5c31af7Sopenharmony_ci 491e5c31af7Sopenharmony_ci if (i < numValidChannels) 492e5c31af7Sopenharmony_ci stream << minValue[i] << " -> " << maxValue[i]; 493e5c31af7Sopenharmony_ci else 494e5c31af7Sopenharmony_ci stream << "Undef"; 495e5c31af7Sopenharmony_ci } 496e5c31af7Sopenharmony_ci 497e5c31af7Sopenharmony_ci stream << ")"; 498e5c31af7Sopenharmony_ci 499e5c31af7Sopenharmony_ci return stream.str(); 500e5c31af7Sopenharmony_ci} 501e5c31af7Sopenharmony_ci 502e5c31af7Sopenharmony_civoid clearUndefined (const tcu::PixelBufferAccess& access, int numValidChannels) 503e5c31af7Sopenharmony_ci{ 504e5c31af7Sopenharmony_ci for (int y = 0; y < access.getHeight(); y++) 505e5c31af7Sopenharmony_ci for (int x = 0; x < access.getWidth(); x++) 506e5c31af7Sopenharmony_ci { 507e5c31af7Sopenharmony_ci switch (tcu::getTextureChannelClass(access.getFormat().type)) 508e5c31af7Sopenharmony_ci { 509e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 510e5c31af7Sopenharmony_ci { 511e5c31af7Sopenharmony_ci const Vec4 srcPixel = access.getPixel(x, y); 512e5c31af7Sopenharmony_ci Vec4 dstPixel (0.0f, 0.0f, 0.0f, 1.0f); 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci for (int channelNdx = 0; channelNdx < numValidChannels; channelNdx++) 515e5c31af7Sopenharmony_ci dstPixel[channelNdx] = srcPixel[channelNdx]; 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci access.setPixel(dstPixel, x, y); 518e5c31af7Sopenharmony_ci break; 519e5c31af7Sopenharmony_ci } 520e5c31af7Sopenharmony_ci 521e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 522e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 523e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 524e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 525e5c31af7Sopenharmony_ci { 526e5c31af7Sopenharmony_ci const IVec4 bitDepth = tcu::getTextureFormatBitDepth(access.getFormat()); 527e5c31af7Sopenharmony_ci const IVec4 srcPixel = access.getPixelInt(x, y); 528e5c31af7Sopenharmony_ci IVec4 dstPixel (0, 0, 0, (int)(((deInt64)0x1u << bitDepth.w()) - 1)); 529e5c31af7Sopenharmony_ci 530e5c31af7Sopenharmony_ci for (int channelNdx = 0; channelNdx < numValidChannels; channelNdx++) 531e5c31af7Sopenharmony_ci dstPixel[channelNdx] = srcPixel[channelNdx]; 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci access.setPixel(dstPixel, x, y); 534e5c31af7Sopenharmony_ci break; 535e5c31af7Sopenharmony_ci } 536e5c31af7Sopenharmony_ci 537e5c31af7Sopenharmony_ci default: 538e5c31af7Sopenharmony_ci DE_ASSERT(false); 539e5c31af7Sopenharmony_ci } 540e5c31af7Sopenharmony_ci } 541e5c31af7Sopenharmony_ci} 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci} // anonymous 544e5c31af7Sopenharmony_ci 545e5c31af7Sopenharmony_ciFragmentOutputCase::IterateResult FragmentOutputCase::iterate (void) 546e5c31af7Sopenharmony_ci{ 547e5c31af7Sopenharmony_ci TestLog& log = m_testCtx.getLog(); 548e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 549e5c31af7Sopenharmony_ci 550e5c31af7Sopenharmony_ci // Compute grid size & index list. 551e5c31af7Sopenharmony_ci const int minCellSize = 8; 552e5c31af7Sopenharmony_ci const IVec2 minBufSize = getMinSize(m_fboSpec); 553e5c31af7Sopenharmony_ci const int gridWidth = de::clamp(minBufSize.x()/minCellSize, 1, 255)+1; 554e5c31af7Sopenharmony_ci const int gridHeight = de::clamp(minBufSize.y()/minCellSize, 1, 255)+1; 555e5c31af7Sopenharmony_ci const int numVertices = gridWidth*gridHeight; 556e5c31af7Sopenharmony_ci const int numQuads = (gridWidth-1)*(gridHeight-1); 557e5c31af7Sopenharmony_ci const int numIndices = numQuads*6; 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_ci const int numInputVecs = getNumInputVectors(m_outputs); 560e5c31af7Sopenharmony_ci vector<vector<deUint32> > inputs (numInputVecs); 561e5c31af7Sopenharmony_ci vector<float> positions (numVertices*4); 562e5c31af7Sopenharmony_ci vector<deUint16> indices (numIndices); 563e5c31af7Sopenharmony_ci 564e5c31af7Sopenharmony_ci const int readAlignment = 4; 565e5c31af7Sopenharmony_ci const int viewportW = minBufSize.x(); 566e5c31af7Sopenharmony_ci const int viewportH = minBufSize.y(); 567e5c31af7Sopenharmony_ci const int numAttachments = (int)m_fboSpec.size(); 568e5c31af7Sopenharmony_ci 569e5c31af7Sopenharmony_ci vector<deUint32> drawBuffers (numAttachments); 570e5c31af7Sopenharmony_ci vector<AttachmentData> attachments (numAttachments); 571e5c31af7Sopenharmony_ci 572e5c31af7Sopenharmony_ci // Initialize attachment data. 573e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numAttachments; ndx++) 574e5c31af7Sopenharmony_ci { 575e5c31af7Sopenharmony_ci const tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_fboSpec[ndx].format); 576e5c31af7Sopenharmony_ci const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(texFmt.type); 577e5c31af7Sopenharmony_ci const bool isFixedPoint = chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || 578e5c31af7Sopenharmony_ci chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_ci // \note Fixed-point formats use float reference to enable more accurate result verification. 581e5c31af7Sopenharmony_ci const tcu::TextureFormat refFmt = isFixedPoint ? tcu::TextureFormat(texFmt.order, tcu::TextureFormat::FLOAT) : texFmt; 582e5c31af7Sopenharmony_ci const tcu::TextureFormat readFmt = getFramebufferReadFormat(texFmt); 583e5c31af7Sopenharmony_ci const int attachmentW = m_fboSpec[ndx].width; 584e5c31af7Sopenharmony_ci const int attachmentH = m_fboSpec[ndx].height; 585e5c31af7Sopenharmony_ci 586e5c31af7Sopenharmony_ci drawBuffers[ndx] = GL_COLOR_ATTACHMENT0+ndx; 587e5c31af7Sopenharmony_ci attachments[ndx].format = texFmt; 588e5c31af7Sopenharmony_ci attachments[ndx].readFormat = readFmt; 589e5c31af7Sopenharmony_ci attachments[ndx].referenceFormat = refFmt; 590e5c31af7Sopenharmony_ci attachments[ndx].renderedData.resize(readFmt.getPixelSize()*attachmentW*attachmentH); 591e5c31af7Sopenharmony_ci attachments[ndx].referenceData.resize(refFmt.getPixelSize()*attachmentW*attachmentH); 592e5c31af7Sopenharmony_ci } 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci // Initialize indices. 595e5c31af7Sopenharmony_ci for (int quadNdx = 0; quadNdx < numQuads; quadNdx++) 596e5c31af7Sopenharmony_ci { 597e5c31af7Sopenharmony_ci int quadY = quadNdx / (gridWidth-1); 598e5c31af7Sopenharmony_ci int quadX = quadNdx - quadY*(gridWidth-1); 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci indices[quadNdx*6+0] = deUint16(quadX + quadY*gridWidth); 601e5c31af7Sopenharmony_ci indices[quadNdx*6+1] = deUint16(quadX + (quadY+1)*gridWidth); 602e5c31af7Sopenharmony_ci indices[quadNdx*6+2] = deUint16(quadX + quadY*gridWidth + 1); 603e5c31af7Sopenharmony_ci indices[quadNdx*6+3] = indices[quadNdx*6+1]; 604e5c31af7Sopenharmony_ci indices[quadNdx*6+4] = deUint16(quadX + (quadY+1)*gridWidth + 1); 605e5c31af7Sopenharmony_ci indices[quadNdx*6+5] = indices[quadNdx*6+2]; 606e5c31af7Sopenharmony_ci } 607e5c31af7Sopenharmony_ci 608e5c31af7Sopenharmony_ci for (int y = 0; y < gridHeight; y++) 609e5c31af7Sopenharmony_ci { 610e5c31af7Sopenharmony_ci for (int x = 0; x < gridWidth; x++) 611e5c31af7Sopenharmony_ci { 612e5c31af7Sopenharmony_ci float xf = (float)x / (float)(gridWidth-1); 613e5c31af7Sopenharmony_ci float yf = (float)y / (float)(gridHeight-1); 614e5c31af7Sopenharmony_ci 615e5c31af7Sopenharmony_ci positions[(y*gridWidth + x)*4 + 0] = 2.0f*xf - 1.0f; 616e5c31af7Sopenharmony_ci positions[(y*gridWidth + x)*4 + 1] = 2.0f*yf - 1.0f; 617e5c31af7Sopenharmony_ci positions[(y*gridWidth + x)*4 + 2] = 0.0f; 618e5c31af7Sopenharmony_ci positions[(y*gridWidth + x)*4 + 3] = 1.0f; 619e5c31af7Sopenharmony_ci } 620e5c31af7Sopenharmony_ci } 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_ci // Initialize input vectors. 623e5c31af7Sopenharmony_ci { 624e5c31af7Sopenharmony_ci int curInVec = 0; 625e5c31af7Sopenharmony_ci for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++) 626e5c31af7Sopenharmony_ci { 627e5c31af7Sopenharmony_ci const FragmentOutput& output = m_outputs[outputNdx]; 628e5c31af7Sopenharmony_ci bool isFloat = glu::isDataTypeFloatOrVec(output.type); 629e5c31af7Sopenharmony_ci bool isInt = glu::isDataTypeIntOrIVec(output.type); 630e5c31af7Sopenharmony_ci bool isUint = glu::isDataTypeUintOrUVec(output.type); 631e5c31af7Sopenharmony_ci int numVecs = output.arrayLength > 0 ? output.arrayLength : 1; 632e5c31af7Sopenharmony_ci int numScalars = glu::getDataTypeScalarSize(output.type); 633e5c31af7Sopenharmony_ci 634e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 635e5c31af7Sopenharmony_ci { 636e5c31af7Sopenharmony_ci inputs[curInVec].resize(numVertices*numScalars); 637e5c31af7Sopenharmony_ci 638e5c31af7Sopenharmony_ci // Record how many outputs are written in attachment. 639e5c31af7Sopenharmony_ci DE_ASSERT(output.location+vecNdx < (int)attachments.size()); 640e5c31af7Sopenharmony_ci attachments[output.location+vecNdx].numWrittenChannels = numScalars; 641e5c31af7Sopenharmony_ci attachments[output.location+vecNdx].outPrecision = output.precision; 642e5c31af7Sopenharmony_ci 643e5c31af7Sopenharmony_ci if (isFloat) 644e5c31af7Sopenharmony_ci { 645e5c31af7Sopenharmony_ci Vec2 range = getFloatRange(output.precision); 646e5c31af7Sopenharmony_ci Vec4 minVal (range.x()); 647e5c31af7Sopenharmony_ci Vec4 maxVal (range.y()); 648e5c31af7Sopenharmony_ci float* dst = (float*)&inputs[curInVec][0]; 649e5c31af7Sopenharmony_ci 650e5c31af7Sopenharmony_ci if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size())) 651e5c31af7Sopenharmony_ci { 652e5c31af7Sopenharmony_ci // \note Floating-point precision conversion is not well-defined. For that reason we must 653e5c31af7Sopenharmony_ci // limit value range to intersection of both data type and render target value ranges. 654e5c31af7Sopenharmony_ci const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(attachments[output.location+vecNdx].format); 655e5c31af7Sopenharmony_ci minVal = tcu::max(minVal, fmtInfo.valueMin); 656e5c31af7Sopenharmony_ci maxVal = tcu::min(maxVal, fmtInfo.valueMax); 657e5c31af7Sopenharmony_ci } 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: " << valueRangeToString(numScalars, minVal, maxVal) << TestLog::EndMessage; 660e5c31af7Sopenharmony_ci 661e5c31af7Sopenharmony_ci for (int y = 0; y < gridHeight; y++) 662e5c31af7Sopenharmony_ci { 663e5c31af7Sopenharmony_ci for (int x = 0; x < gridWidth; x++) 664e5c31af7Sopenharmony_ci { 665e5c31af7Sopenharmony_ci float xf = (float)x / (float)(gridWidth-1); 666e5c31af7Sopenharmony_ci float yf = (float)y / (float)(gridHeight-1); 667e5c31af7Sopenharmony_ci 668e5c31af7Sopenharmony_ci float f0 = (xf + yf) * 0.5f; 669e5c31af7Sopenharmony_ci float f1 = 0.5f + (xf - yf) * 0.5f; 670e5c31af7Sopenharmony_ci Vec4 f = swizzleVec(Vec4(f0, f1, 1.0f-f0, 1.0f-f1), curInVec); 671e5c31af7Sopenharmony_ci Vec4 c = minVal + (maxVal-minVal)*f; 672e5c31af7Sopenharmony_ci float* v = dst + (y*gridWidth + x)*numScalars; 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numScalars; ndx++) 675e5c31af7Sopenharmony_ci v[ndx] = c[ndx]; 676e5c31af7Sopenharmony_ci } 677e5c31af7Sopenharmony_ci } 678e5c31af7Sopenharmony_ci } 679e5c31af7Sopenharmony_ci else if (isInt) 680e5c31af7Sopenharmony_ci { 681e5c31af7Sopenharmony_ci const IVec2 range = getIntRange(output.precision); 682e5c31af7Sopenharmony_ci IVec4 minVal (range.x()); 683e5c31af7Sopenharmony_ci IVec4 maxVal (range.y()); 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size())) 686e5c31af7Sopenharmony_ci { 687e5c31af7Sopenharmony_ci // Limit to range of output format as conversion mode is not specified. 688e5c31af7Sopenharmony_ci const IVec4 fmtBits = tcu::getTextureFormatBitDepth(attachments[output.location+vecNdx].format); 689e5c31af7Sopenharmony_ci const BVec4 isZero = lessThanEqual(fmtBits, IVec4(0)); 690e5c31af7Sopenharmony_ci const IVec4 shift = tcu::clamp(fmtBits-1, tcu::IVec4(0), tcu::IVec4(256)); 691e5c31af7Sopenharmony_ci const IVec4 fmtMinVal = (-(tcu::Vector<deInt64, 4>(1) << shift.cast<deInt64>())).asInt(); 692e5c31af7Sopenharmony_ci const IVec4 fmtMaxVal = ((tcu::Vector<deInt64, 4>(1) << shift.cast<deInt64>())-deInt64(1)).asInt(); 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ci minVal = select(minVal, tcu::max(minVal, fmtMinVal), isZero); 695e5c31af7Sopenharmony_ci maxVal = select(maxVal, tcu::min(maxVal, fmtMaxVal), isZero); 696e5c31af7Sopenharmony_ci } 697e5c31af7Sopenharmony_ci 698e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: " << valueRangeToString(numScalars, minVal, maxVal) << TestLog::EndMessage; 699e5c31af7Sopenharmony_ci 700e5c31af7Sopenharmony_ci const IVec4 rangeDiv = swizzleVec((IVec4(gridWidth, gridHeight, gridWidth, gridHeight)-1), curInVec); 701e5c31af7Sopenharmony_ci const IVec4 step = ((maxVal.cast<deInt64>() - minVal.cast<deInt64>()) / (rangeDiv.cast<deInt64>())).asInt(); 702e5c31af7Sopenharmony_ci deInt32* dst = (deInt32*)&inputs[curInVec][0]; 703e5c31af7Sopenharmony_ci 704e5c31af7Sopenharmony_ci for (int y = 0; y < gridHeight; y++) 705e5c31af7Sopenharmony_ci { 706e5c31af7Sopenharmony_ci for (int x = 0; x < gridWidth; x++) 707e5c31af7Sopenharmony_ci { 708e5c31af7Sopenharmony_ci int ix = gridWidth - x - 1; 709e5c31af7Sopenharmony_ci int iy = gridHeight - y - 1; 710e5c31af7Sopenharmony_ci IVec4 c = minVal + step*swizzleVec(IVec4(x, y, ix, iy), curInVec); 711e5c31af7Sopenharmony_ci deInt32* v = dst + (y*gridWidth + x)*numScalars; 712e5c31af7Sopenharmony_ci 713e5c31af7Sopenharmony_ci DE_ASSERT(boolAll(logicalAnd(greaterThanEqual(c, minVal), lessThanEqual(c, maxVal)))); 714e5c31af7Sopenharmony_ci 715e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numScalars; ndx++) 716e5c31af7Sopenharmony_ci v[ndx] = c[ndx]; 717e5c31af7Sopenharmony_ci } 718e5c31af7Sopenharmony_ci } 719e5c31af7Sopenharmony_ci } 720e5c31af7Sopenharmony_ci else if (isUint) 721e5c31af7Sopenharmony_ci { 722e5c31af7Sopenharmony_ci const UVec2 range = getUintRange(output.precision); 723e5c31af7Sopenharmony_ci UVec4 maxVal (range.y()); 724e5c31af7Sopenharmony_ci 725e5c31af7Sopenharmony_ci if (de::inBounds(output.location+vecNdx, 0, (int)attachments.size())) 726e5c31af7Sopenharmony_ci { 727e5c31af7Sopenharmony_ci // Limit to range of output format as conversion mode is not specified. 728e5c31af7Sopenharmony_ci const IVec4 fmtBits = tcu::getTextureFormatBitDepth(attachments[output.location+vecNdx].format); 729e5c31af7Sopenharmony_ci const UVec4 fmtMaxVal = ((tcu::Vector<deUint64, 4>(1) << fmtBits.cast<deUint64>())-deUint64(1)).asUint(); 730e5c31af7Sopenharmony_ci 731e5c31af7Sopenharmony_ci maxVal = tcu::min(maxVal, fmtMaxVal); 732e5c31af7Sopenharmony_ci } 733e5c31af7Sopenharmony_ci 734e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "out" << curInVec << " value range: " << valueRangeToString(numScalars, UVec4(0), maxVal) << TestLog::EndMessage; 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ci const IVec4 rangeDiv = swizzleVec((IVec4(gridWidth, gridHeight, gridWidth, gridHeight)-1), curInVec); 737e5c31af7Sopenharmony_ci const UVec4 step = maxVal / rangeDiv.asUint(); 738e5c31af7Sopenharmony_ci deUint32* dst = &inputs[curInVec][0]; 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ci DE_ASSERT(range.x() == 0); 741e5c31af7Sopenharmony_ci 742e5c31af7Sopenharmony_ci for (int y = 0; y < gridHeight; y++) 743e5c31af7Sopenharmony_ci { 744e5c31af7Sopenharmony_ci for (int x = 0; x < gridWidth; x++) 745e5c31af7Sopenharmony_ci { 746e5c31af7Sopenharmony_ci int ix = gridWidth - x - 1; 747e5c31af7Sopenharmony_ci int iy = gridHeight - y - 1; 748e5c31af7Sopenharmony_ci UVec4 c = step*swizzleVec(IVec4(x, y, ix, iy).asUint(), curInVec); 749e5c31af7Sopenharmony_ci deUint32* v = dst + (y*gridWidth + x)*numScalars; 750e5c31af7Sopenharmony_ci 751e5c31af7Sopenharmony_ci DE_ASSERT(boolAll(lessThanEqual(c, maxVal))); 752e5c31af7Sopenharmony_ci 753e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numScalars; ndx++) 754e5c31af7Sopenharmony_ci v[ndx] = c[ndx]; 755e5c31af7Sopenharmony_ci } 756e5c31af7Sopenharmony_ci } 757e5c31af7Sopenharmony_ci } 758e5c31af7Sopenharmony_ci else 759e5c31af7Sopenharmony_ci DE_ASSERT(false); 760e5c31af7Sopenharmony_ci 761e5c31af7Sopenharmony_ci curInVec += 1; 762e5c31af7Sopenharmony_ci } 763e5c31af7Sopenharmony_ci } 764e5c31af7Sopenharmony_ci } 765e5c31af7Sopenharmony_ci 766e5c31af7Sopenharmony_ci // Render using gl. 767e5c31af7Sopenharmony_ci gl.useProgram(m_program->getProgram()); 768e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 769e5c31af7Sopenharmony_ci gl.viewport(0, 0, viewportW, viewportH); 770e5c31af7Sopenharmony_ci gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]); 771e5c31af7Sopenharmony_ci gl.disable(GL_DITHER); // Dithering causes issues with unorm formats. Those issues could be worked around in threshold, but it makes validation less accurate. 772e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup"); 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci { 775e5c31af7Sopenharmony_ci int curInVec = 0; 776e5c31af7Sopenharmony_ci for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++) 777e5c31af7Sopenharmony_ci { 778e5c31af7Sopenharmony_ci const FragmentOutput& output = m_outputs[outputNdx]; 779e5c31af7Sopenharmony_ci bool isArray = output.arrayLength > 0; 780e5c31af7Sopenharmony_ci bool isFloat = glu::isDataTypeFloatOrVec(output.type); 781e5c31af7Sopenharmony_ci bool isInt = glu::isDataTypeIntOrIVec(output.type); 782e5c31af7Sopenharmony_ci bool isUint = glu::isDataTypeUintOrUVec(output.type); 783e5c31af7Sopenharmony_ci int scalarSize = glu::getDataTypeScalarSize(output.type); 784e5c31af7Sopenharmony_ci deUint32 glScalarType = isFloat ? GL_FLOAT : 785e5c31af7Sopenharmony_ci isInt ? GL_INT : 786e5c31af7Sopenharmony_ci isUint ? GL_UNSIGNED_INT : GL_NONE; 787e5c31af7Sopenharmony_ci int numVecs = isArray ? output.arrayLength : 1; 788e5c31af7Sopenharmony_ci 789e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 790e5c31af7Sopenharmony_ci { 791e5c31af7Sopenharmony_ci string name = string("in") + de::toString(outputNdx) + (isArray ? string("_") + de::toString(vecNdx) : string()); 792e5c31af7Sopenharmony_ci int loc = gl.getAttribLocation(m_program->getProgram(), name.c_str()); 793e5c31af7Sopenharmony_ci 794e5c31af7Sopenharmony_ci if (loc >= 0) 795e5c31af7Sopenharmony_ci { 796e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(loc); 797e5c31af7Sopenharmony_ci if (isFloat) 798e5c31af7Sopenharmony_ci gl.vertexAttribPointer(loc, scalarSize, glScalarType, GL_FALSE, 0, &inputs[curInVec][0]); 799e5c31af7Sopenharmony_ci else 800e5c31af7Sopenharmony_ci gl.vertexAttribIPointer(loc, scalarSize, glScalarType, 0, &inputs[curInVec][0]); 801e5c31af7Sopenharmony_ci } 802e5c31af7Sopenharmony_ci else 803e5c31af7Sopenharmony_ci log << TestLog::Message << "Warning: No location for attribute '" << name << "' found." << TestLog::EndMessage; 804e5c31af7Sopenharmony_ci 805e5c31af7Sopenharmony_ci curInVec += 1; 806e5c31af7Sopenharmony_ci } 807e5c31af7Sopenharmony_ci } 808e5c31af7Sopenharmony_ci } 809e5c31af7Sopenharmony_ci { 810e5c31af7Sopenharmony_ci int posLoc = gl.getAttribLocation(m_program->getProgram(), "a_position"); 811e5c31af7Sopenharmony_ci TCU_CHECK(posLoc >= 0); 812e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(posLoc); 813e5c31af7Sopenharmony_ci gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &positions[0]); 814e5c31af7Sopenharmony_ci } 815e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "After attribute setup"); 816e5c31af7Sopenharmony_ci 817e5c31af7Sopenharmony_ci gl.drawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, &indices[0]); 818e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements"); 819e5c31af7Sopenharmony_ci 820e5c31af7Sopenharmony_ci // Read all attachment points. 821e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numAttachments; ndx++) 822e5c31af7Sopenharmony_ci { 823e5c31af7Sopenharmony_ci const glu::TransferFormat transferFmt = glu::getTransferFormat(attachments[ndx].readFormat); 824e5c31af7Sopenharmony_ci void* dst = &attachments[ndx].renderedData[0]; 825e5c31af7Sopenharmony_ci const int attachmentW = m_fboSpec[ndx].width; 826e5c31af7Sopenharmony_ci const int attachmentH = m_fboSpec[ndx].height; 827e5c31af7Sopenharmony_ci const int numValidChannels = attachments[ndx].numWrittenChannels; 828e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess rendered (attachments[ndx].readFormat, attachmentW, attachmentH, 1, deAlign32(attachments[ndx].readFormat.getPixelSize()*attachmentW, readAlignment), 0, &attachments[ndx].renderedData[0]); 829e5c31af7Sopenharmony_ci 830e5c31af7Sopenharmony_ci gl.readBuffer(GL_COLOR_ATTACHMENT0+ndx); 831e5c31af7Sopenharmony_ci gl.readPixels(0, 0, minBufSize.x(), minBufSize.y(), transferFmt.format, transferFmt.dataType, dst); 832e5c31af7Sopenharmony_ci 833e5c31af7Sopenharmony_ci clearUndefined(rendered, numValidChannels); 834e5c31af7Sopenharmony_ci } 835e5c31af7Sopenharmony_ci 836e5c31af7Sopenharmony_ci // Render reference images. 837e5c31af7Sopenharmony_ci { 838e5c31af7Sopenharmony_ci int curInNdx = 0; 839e5c31af7Sopenharmony_ci for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++) 840e5c31af7Sopenharmony_ci { 841e5c31af7Sopenharmony_ci const FragmentOutput& output = m_outputs[outputNdx]; 842e5c31af7Sopenharmony_ci const bool isArray = output.arrayLength > 0; 843e5c31af7Sopenharmony_ci const bool isFloat = glu::isDataTypeFloatOrVec(output.type); 844e5c31af7Sopenharmony_ci const bool isInt = glu::isDataTypeIntOrIVec(output.type); 845e5c31af7Sopenharmony_ci const bool isUint = glu::isDataTypeUintOrUVec(output.type); 846e5c31af7Sopenharmony_ci const int scalarSize = glu::getDataTypeScalarSize(output.type); 847e5c31af7Sopenharmony_ci const int numVecs = isArray ? output.arrayLength : 1; 848e5c31af7Sopenharmony_ci 849e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 850e5c31af7Sopenharmony_ci { 851e5c31af7Sopenharmony_ci const int location = output.location+vecNdx; 852e5c31af7Sopenharmony_ci const void* inputData = &inputs[curInNdx][0]; 853e5c31af7Sopenharmony_ci 854e5c31af7Sopenharmony_ci DE_ASSERT(de::inBounds(location, 0, (int)m_fboSpec.size())); 855e5c31af7Sopenharmony_ci 856e5c31af7Sopenharmony_ci const int bufW = m_fboSpec[location].width; 857e5c31af7Sopenharmony_ci const int bufH = m_fboSpec[location].height; 858e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess buf (attachments[location].referenceFormat, bufW, bufH, 1, &attachments[location].referenceData[0]); 859e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess viewportBuf = getSubregion(buf, 0, 0, 0, viewportW, viewportH, 1); 860e5c31af7Sopenharmony_ci 861e5c31af7Sopenharmony_ci if (isInt || isUint) 862e5c31af7Sopenharmony_ci renderIntReference(viewportBuf, gridWidth, gridHeight, scalarSize, (const int*)inputData); 863e5c31af7Sopenharmony_ci else if (isFloat) 864e5c31af7Sopenharmony_ci renderFloatReference(viewportBuf, gridWidth, gridHeight, scalarSize, (const float*)inputData); 865e5c31af7Sopenharmony_ci else 866e5c31af7Sopenharmony_ci DE_ASSERT(false); 867e5c31af7Sopenharmony_ci 868e5c31af7Sopenharmony_ci curInNdx += 1; 869e5c31af7Sopenharmony_ci } 870e5c31af7Sopenharmony_ci } 871e5c31af7Sopenharmony_ci } 872e5c31af7Sopenharmony_ci 873e5c31af7Sopenharmony_ci // Compare all images. 874e5c31af7Sopenharmony_ci bool allLevelsOk = true; 875e5c31af7Sopenharmony_ci for (int attachNdx = 0; attachNdx < numAttachments; attachNdx++) 876e5c31af7Sopenharmony_ci { 877e5c31af7Sopenharmony_ci const int attachmentW = m_fboSpec[attachNdx].width; 878e5c31af7Sopenharmony_ci const int attachmentH = m_fboSpec[attachNdx].height; 879e5c31af7Sopenharmony_ci const int numValidChannels = attachments[attachNdx].numWrittenChannels; 880e5c31af7Sopenharmony_ci const tcu::BVec4 cmpMask (numValidChannels >= 1, numValidChannels >= 2, numValidChannels >= 3, numValidChannels >= 4); 881e5c31af7Sopenharmony_ci const glu::Precision outPrecision = attachments[attachNdx].outPrecision; 882e5c31af7Sopenharmony_ci const tcu::TextureFormat& format = attachments[attachNdx].format; 883e5c31af7Sopenharmony_ci tcu::ConstPixelBufferAccess rendered (attachments[attachNdx].readFormat, attachmentW, attachmentH, 1, deAlign32(attachments[attachNdx].readFormat.getPixelSize()*attachmentW, readAlignment), 0, &attachments[attachNdx].renderedData[0]); 884e5c31af7Sopenharmony_ci tcu::ConstPixelBufferAccess reference (attachments[attachNdx].referenceFormat, attachmentW, attachmentH, 1, &attachments[attachNdx].referenceData[0]); 885e5c31af7Sopenharmony_ci tcu::TextureChannelClass texClass = tcu::getTextureChannelClass(format.type); 886e5c31af7Sopenharmony_ci bool isOk = true; 887e5c31af7Sopenharmony_ci const string name = string("Attachment") + de::toString(attachNdx); 888e5c31af7Sopenharmony_ci const string desc = string("Color attachment ") + de::toString(attachNdx); 889e5c31af7Sopenharmony_ci 890e5c31af7Sopenharmony_ci log << TestLog::Message << "Attachment " << attachNdx << ": " << numValidChannels << " channels have defined values and used for comparison" << TestLog::EndMessage; 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_ci switch (texClass) 893e5c31af7Sopenharmony_ci { 894e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 895e5c31af7Sopenharmony_ci { 896e5c31af7Sopenharmony_ci const deUint32 interpThreshold = 4; //!< 4 ULP interpolation threshold (interpolation always in highp) 897e5c31af7Sopenharmony_ci deUint32 outTypeThreshold = 0; //!< Threshold based on output type 898e5c31af7Sopenharmony_ci UVec4 formatThreshold; //!< Threshold computed based on format. 899e5c31af7Sopenharmony_ci UVec4 finalThreshold; 900e5c31af7Sopenharmony_ci 901e5c31af7Sopenharmony_ci // 1 ULP rounding error is allowed for smaller floating-point formats 902e5c31af7Sopenharmony_ci switch (format.type) 903e5c31af7Sopenharmony_ci { 904e5c31af7Sopenharmony_ci case tcu::TextureFormat::FLOAT: formatThreshold = UVec4(0); break; 905e5c31af7Sopenharmony_ci case tcu::TextureFormat::HALF_FLOAT: formatThreshold = UVec4((1<<(23-10))); break; 906e5c31af7Sopenharmony_ci case tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: formatThreshold = UVec4((1<<(23-6)), (1<<(23-6)), (1<<(23-5)), 0); break; 907e5c31af7Sopenharmony_ci default: 908e5c31af7Sopenharmony_ci DE_ASSERT(false); 909e5c31af7Sopenharmony_ci break; 910e5c31af7Sopenharmony_ci } 911e5c31af7Sopenharmony_ci 912e5c31af7Sopenharmony_ci // 1 ULP rounding error for highp -> output precision cast 913e5c31af7Sopenharmony_ci switch (outPrecision) 914e5c31af7Sopenharmony_ci { 915e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: outTypeThreshold = (1<<(23-8)); break; 916e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: outTypeThreshold = (1<<(23-10)); break; 917e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: outTypeThreshold = 0; break; 918e5c31af7Sopenharmony_ci default: 919e5c31af7Sopenharmony_ci DE_ASSERT(false); 920e5c31af7Sopenharmony_ci } 921e5c31af7Sopenharmony_ci 922e5c31af7Sopenharmony_ci finalThreshold = select(max(formatThreshold, UVec4(deMax32(interpThreshold, outTypeThreshold))), UVec4(~0u), cmpMask); 923e5c31af7Sopenharmony_ci 924e5c31af7Sopenharmony_ci isOk = tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, finalThreshold, tcu::COMPARE_LOG_RESULT); 925e5c31af7Sopenharmony_ci break; 926e5c31af7Sopenharmony_ci } 927e5c31af7Sopenharmony_ci 928e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 929e5c31af7Sopenharmony_ci { 930e5c31af7Sopenharmony_ci // \note glReadPixels() allows only 8 bits to be read. This means that RGB10_A2 will loose some 931e5c31af7Sopenharmony_ci // bits in the process and it must be taken into account when computing threshold. 932e5c31af7Sopenharmony_ci const IVec4 bits = min(IVec4(8), tcu::getTextureFormatBitDepth(format)); 933e5c31af7Sopenharmony_ci const Vec4 baseThreshold = 1.0f / ((IVec4(1) << bits)-1).asFloat(); 934e5c31af7Sopenharmony_ci const Vec4 threshold = select(baseThreshold, Vec4(2.0f), cmpMask); 935e5c31af7Sopenharmony_ci 936e5c31af7Sopenharmony_ci isOk = tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT); 937e5c31af7Sopenharmony_ci break; 938e5c31af7Sopenharmony_ci } 939e5c31af7Sopenharmony_ci 940e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 941e5c31af7Sopenharmony_ci case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 942e5c31af7Sopenharmony_ci { 943e5c31af7Sopenharmony_ci const tcu::UVec4 threshold = select(UVec4(0u), UVec4(~0u), cmpMask); 944e5c31af7Sopenharmony_ci isOk = tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT); 945e5c31af7Sopenharmony_ci break; 946e5c31af7Sopenharmony_ci } 947e5c31af7Sopenharmony_ci 948e5c31af7Sopenharmony_ci default: 949e5c31af7Sopenharmony_ci TCU_FAIL("Unsupported comparison"); 950e5c31af7Sopenharmony_ci } 951e5c31af7Sopenharmony_ci 952e5c31af7Sopenharmony_ci if (!isOk) 953e5c31af7Sopenharmony_ci allLevelsOk = false; 954e5c31af7Sopenharmony_ci } 955e5c31af7Sopenharmony_ci 956e5c31af7Sopenharmony_ci m_testCtx.setTestResult(allLevelsOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 957e5c31af7Sopenharmony_ci allLevelsOk ? "Pass" : "Image comparison failed"); 958e5c31af7Sopenharmony_ci return STOP; 959e5c31af7Sopenharmony_ci} 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ciFragmentOutputTests::FragmentOutputTests (Context& context) 962e5c31af7Sopenharmony_ci : TestCaseGroup(context, "fragment_out", "Fragment output tests") 963e5c31af7Sopenharmony_ci{ 964e5c31af7Sopenharmony_ci} 965e5c31af7Sopenharmony_ci 966e5c31af7Sopenharmony_ciFragmentOutputTests::~FragmentOutputTests (void) 967e5c31af7Sopenharmony_ci{ 968e5c31af7Sopenharmony_ci} 969e5c31af7Sopenharmony_ci 970e5c31af7Sopenharmony_cistatic FragmentOutputCase* createRandomCase (Context& context, int minRenderTargets, int maxRenderTargets, deUint32 seed) 971e5c31af7Sopenharmony_ci{ 972e5c31af7Sopenharmony_ci static const glu::DataType outputTypes[] = 973e5c31af7Sopenharmony_ci { 974e5c31af7Sopenharmony_ci glu::TYPE_FLOAT, 975e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC2, 976e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC3, 977e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC4, 978e5c31af7Sopenharmony_ci glu::TYPE_INT, 979e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC2, 980e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC3, 981e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC4, 982e5c31af7Sopenharmony_ci glu::TYPE_UINT, 983e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC2, 984e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC3, 985e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC4 986e5c31af7Sopenharmony_ci }; 987e5c31af7Sopenharmony_ci static const glu::Precision precisions[] = 988e5c31af7Sopenharmony_ci { 989e5c31af7Sopenharmony_ci glu::PRECISION_LOWP, 990e5c31af7Sopenharmony_ci glu::PRECISION_MEDIUMP, 991e5c31af7Sopenharmony_ci glu::PRECISION_HIGHP 992e5c31af7Sopenharmony_ci }; 993e5c31af7Sopenharmony_ci static const deUint32 floatFormats[] = 994e5c31af7Sopenharmony_ci { 995e5c31af7Sopenharmony_ci GL_RGBA32F, 996e5c31af7Sopenharmony_ci GL_RGBA16F, 997e5c31af7Sopenharmony_ci GL_R11F_G11F_B10F, 998e5c31af7Sopenharmony_ci GL_RG32F, 999e5c31af7Sopenharmony_ci GL_RG16F, 1000e5c31af7Sopenharmony_ci GL_R32F, 1001e5c31af7Sopenharmony_ci GL_R16F, 1002e5c31af7Sopenharmony_ci GL_RGBA8, 1003e5c31af7Sopenharmony_ci GL_SRGB8_ALPHA8, 1004e5c31af7Sopenharmony_ci GL_RGB10_A2, 1005e5c31af7Sopenharmony_ci GL_RGBA4, 1006e5c31af7Sopenharmony_ci GL_RGB5_A1, 1007e5c31af7Sopenharmony_ci GL_RGB8, 1008e5c31af7Sopenharmony_ci GL_RGB565, 1009e5c31af7Sopenharmony_ci GL_RG8, 1010e5c31af7Sopenharmony_ci GL_R8 1011e5c31af7Sopenharmony_ci }; 1012e5c31af7Sopenharmony_ci static const deUint32 intFormats[] = 1013e5c31af7Sopenharmony_ci { 1014e5c31af7Sopenharmony_ci GL_RGBA32I, 1015e5c31af7Sopenharmony_ci GL_RGBA16I, 1016e5c31af7Sopenharmony_ci GL_RGBA8I, 1017e5c31af7Sopenharmony_ci GL_RG32I, 1018e5c31af7Sopenharmony_ci GL_RG16I, 1019e5c31af7Sopenharmony_ci GL_RG8I, 1020e5c31af7Sopenharmony_ci GL_R32I, 1021e5c31af7Sopenharmony_ci GL_R16I, 1022e5c31af7Sopenharmony_ci GL_R8I 1023e5c31af7Sopenharmony_ci }; 1024e5c31af7Sopenharmony_ci static const deUint32 uintFormats[] = 1025e5c31af7Sopenharmony_ci { 1026e5c31af7Sopenharmony_ci GL_RGBA32UI, 1027e5c31af7Sopenharmony_ci GL_RGBA16UI, 1028e5c31af7Sopenharmony_ci GL_RGBA8UI, 1029e5c31af7Sopenharmony_ci GL_RGB10_A2UI, 1030e5c31af7Sopenharmony_ci GL_RG32UI, 1031e5c31af7Sopenharmony_ci GL_RG16UI, 1032e5c31af7Sopenharmony_ci GL_RG8UI, 1033e5c31af7Sopenharmony_ci GL_R32UI, 1034e5c31af7Sopenharmony_ci GL_R16UI, 1035e5c31af7Sopenharmony_ci GL_R8UI 1036e5c31af7Sopenharmony_ci }; 1037e5c31af7Sopenharmony_ci 1038e5c31af7Sopenharmony_ci de::Random rnd (seed); 1039e5c31af7Sopenharmony_ci vector<FragmentOutput> outputs; 1040e5c31af7Sopenharmony_ci vector<BufferSpec> targets; 1041e5c31af7Sopenharmony_ci vector<glu::DataType> outTypes; 1042e5c31af7Sopenharmony_ci 1043e5c31af7Sopenharmony_ci int numTargets = rnd.getInt(minRenderTargets, maxRenderTargets); 1044e5c31af7Sopenharmony_ci const int width = 128; // \todo [2012-04-10 pyry] Separate randomized sizes per target? 1045e5c31af7Sopenharmony_ci const int height = 64; 1046e5c31af7Sopenharmony_ci const int samples = 0; 1047e5c31af7Sopenharmony_ci 1048e5c31af7Sopenharmony_ci // Compute outputs. 1049e5c31af7Sopenharmony_ci int curLoc = 0; 1050e5c31af7Sopenharmony_ci while (curLoc < numTargets) 1051e5c31af7Sopenharmony_ci { 1052e5c31af7Sopenharmony_ci bool useArray = rnd.getFloat() < 0.3f; 1053e5c31af7Sopenharmony_ci int maxArrayLen = numTargets-curLoc; 1054e5c31af7Sopenharmony_ci int arrayLen = useArray ? rnd.getInt(1, maxArrayLen) : 0; 1055e5c31af7Sopenharmony_ci glu::DataType basicType = rnd.choose<glu::DataType>(&outputTypes[0], &outputTypes[0] + DE_LENGTH_OF_ARRAY(outputTypes)); 1056e5c31af7Sopenharmony_ci glu::Precision precision = rnd.choose<glu::Precision>(&precisions[0], &precisions[0] + DE_LENGTH_OF_ARRAY(precisions)); 1057e5c31af7Sopenharmony_ci int numLocations = useArray ? arrayLen : 1; 1058e5c31af7Sopenharmony_ci 1059e5c31af7Sopenharmony_ci outputs.push_back(FragmentOutput(basicType, precision, curLoc, arrayLen)); 1060e5c31af7Sopenharmony_ci 1061e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numLocations; ndx++) 1062e5c31af7Sopenharmony_ci outTypes.push_back(basicType); 1063e5c31af7Sopenharmony_ci 1064e5c31af7Sopenharmony_ci curLoc += numLocations; 1065e5c31af7Sopenharmony_ci } 1066e5c31af7Sopenharmony_ci DE_ASSERT(curLoc == numTargets); 1067e5c31af7Sopenharmony_ci DE_ASSERT((int)outTypes.size() == numTargets); 1068e5c31af7Sopenharmony_ci 1069e5c31af7Sopenharmony_ci // Compute buffers. 1070e5c31af7Sopenharmony_ci while ((int)targets.size() < numTargets) 1071e5c31af7Sopenharmony_ci { 1072e5c31af7Sopenharmony_ci glu::DataType outType = outTypes[targets.size()]; 1073e5c31af7Sopenharmony_ci bool isFloat = glu::isDataTypeFloatOrVec(outType); 1074e5c31af7Sopenharmony_ci bool isInt = glu::isDataTypeIntOrIVec(outType); 1075e5c31af7Sopenharmony_ci bool isUint = glu::isDataTypeUintOrUVec(outType); 1076e5c31af7Sopenharmony_ci deUint32 format = 0; 1077e5c31af7Sopenharmony_ci 1078e5c31af7Sopenharmony_ci if (isFloat) 1079e5c31af7Sopenharmony_ci format = rnd.choose<deUint32>(&floatFormats[0], &floatFormats[0] + DE_LENGTH_OF_ARRAY(floatFormats)); 1080e5c31af7Sopenharmony_ci else if (isInt) 1081e5c31af7Sopenharmony_ci format = rnd.choose<deUint32>(&intFormats[0], &intFormats[0] + DE_LENGTH_OF_ARRAY(intFormats)); 1082e5c31af7Sopenharmony_ci else if (isUint) 1083e5c31af7Sopenharmony_ci format = rnd.choose<deUint32>(&uintFormats[0], &uintFormats[0] + DE_LENGTH_OF_ARRAY(uintFormats)); 1084e5c31af7Sopenharmony_ci else 1085e5c31af7Sopenharmony_ci DE_ASSERT(false); 1086e5c31af7Sopenharmony_ci 1087e5c31af7Sopenharmony_ci targets.push_back(BufferSpec(format, width, height, samples)); 1088e5c31af7Sopenharmony_ci } 1089e5c31af7Sopenharmony_ci 1090e5c31af7Sopenharmony_ci return new FragmentOutputCase(context, de::toString(seed).c_str(), "", targets, outputs); 1091e5c31af7Sopenharmony_ci} 1092e5c31af7Sopenharmony_ci 1093e5c31af7Sopenharmony_civoid FragmentOutputTests::init (void) 1094e5c31af7Sopenharmony_ci{ 1095e5c31af7Sopenharmony_ci static const deUint32 requiredFloatFormats[] = 1096e5c31af7Sopenharmony_ci { 1097e5c31af7Sopenharmony_ci GL_RGBA32F, 1098e5c31af7Sopenharmony_ci GL_RGBA16F, 1099e5c31af7Sopenharmony_ci GL_R11F_G11F_B10F, 1100e5c31af7Sopenharmony_ci GL_RG32F, 1101e5c31af7Sopenharmony_ci GL_RG16F, 1102e5c31af7Sopenharmony_ci GL_R32F, 1103e5c31af7Sopenharmony_ci GL_R16F 1104e5c31af7Sopenharmony_ci }; 1105e5c31af7Sopenharmony_ci static const deUint32 requiredFixedFormats[] = 1106e5c31af7Sopenharmony_ci { 1107e5c31af7Sopenharmony_ci GL_RGBA8, 1108e5c31af7Sopenharmony_ci GL_SRGB8_ALPHA8, 1109e5c31af7Sopenharmony_ci GL_RGB10_A2, 1110e5c31af7Sopenharmony_ci GL_RGBA4, 1111e5c31af7Sopenharmony_ci GL_RGB5_A1, 1112e5c31af7Sopenharmony_ci GL_RGB8, 1113e5c31af7Sopenharmony_ci GL_RGB565, 1114e5c31af7Sopenharmony_ci GL_RG8, 1115e5c31af7Sopenharmony_ci GL_R8 1116e5c31af7Sopenharmony_ci }; 1117e5c31af7Sopenharmony_ci static const deUint32 requiredIntFormats[] = 1118e5c31af7Sopenharmony_ci { 1119e5c31af7Sopenharmony_ci GL_RGBA32I, 1120e5c31af7Sopenharmony_ci GL_RGBA16I, 1121e5c31af7Sopenharmony_ci GL_RGBA8I, 1122e5c31af7Sopenharmony_ci GL_RG32I, 1123e5c31af7Sopenharmony_ci GL_RG16I, 1124e5c31af7Sopenharmony_ci GL_RG8I, 1125e5c31af7Sopenharmony_ci GL_R32I, 1126e5c31af7Sopenharmony_ci GL_R16I, 1127e5c31af7Sopenharmony_ci GL_R8I 1128e5c31af7Sopenharmony_ci }; 1129e5c31af7Sopenharmony_ci static const deUint32 requiredUintFormats[] = 1130e5c31af7Sopenharmony_ci { 1131e5c31af7Sopenharmony_ci GL_RGBA32UI, 1132e5c31af7Sopenharmony_ci GL_RGBA16UI, 1133e5c31af7Sopenharmony_ci GL_RGBA8UI, 1134e5c31af7Sopenharmony_ci GL_RGB10_A2UI, 1135e5c31af7Sopenharmony_ci GL_RG32UI, 1136e5c31af7Sopenharmony_ci GL_RG16UI, 1137e5c31af7Sopenharmony_ci GL_RG8UI, 1138e5c31af7Sopenharmony_ci GL_R32UI, 1139e5c31af7Sopenharmony_ci GL_R16UI, 1140e5c31af7Sopenharmony_ci GL_R8UI 1141e5c31af7Sopenharmony_ci }; 1142e5c31af7Sopenharmony_ci 1143e5c31af7Sopenharmony_ci static const glu::Precision precisions[] = 1144e5c31af7Sopenharmony_ci { 1145e5c31af7Sopenharmony_ci glu::PRECISION_LOWP, 1146e5c31af7Sopenharmony_ci glu::PRECISION_MEDIUMP, 1147e5c31af7Sopenharmony_ci glu::PRECISION_HIGHP 1148e5c31af7Sopenharmony_ci }; 1149e5c31af7Sopenharmony_ci 1150e5c31af7Sopenharmony_ci // .basic. 1151e5c31af7Sopenharmony_ci { 1152e5c31af7Sopenharmony_ci tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic fragment output tests"); 1153e5c31af7Sopenharmony_ci addChild(basicGroup); 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci const int width = 64; 1156e5c31af7Sopenharmony_ci const int height = 64; 1157e5c31af7Sopenharmony_ci const int samples = 0; 1158e5c31af7Sopenharmony_ci 1159e5c31af7Sopenharmony_ci // .float 1160e5c31af7Sopenharmony_ci tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point output tests"); 1161e5c31af7Sopenharmony_ci basicGroup->addChild(floatGroup); 1162e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFloatFormats); fmtNdx++) 1163e5c31af7Sopenharmony_ci { 1164e5c31af7Sopenharmony_ci deUint32 format = requiredFloatFormats[fmtNdx]; 1165e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1166e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1167e5c31af7Sopenharmony_ci 1168e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1169e5c31af7Sopenharmony_ci 1170e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1171e5c31af7Sopenharmony_ci { 1172e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1173e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1174e5c31af7Sopenharmony_ci 1175e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT, prec, 0)).toVec())); 1176e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2, prec, 0)).toVec())); 1177e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3, prec, 0)).toVec())); 1178e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4, prec, 0)).toVec())); 1179e5c31af7Sopenharmony_ci } 1180e5c31af7Sopenharmony_ci } 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ci // .fixed 1183e5c31af7Sopenharmony_ci tcu::TestCaseGroup* fixedGroup = new tcu::TestCaseGroup(m_testCtx, "fixed", "Fixed-point output tests"); 1184e5c31af7Sopenharmony_ci basicGroup->addChild(fixedGroup); 1185e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFixedFormats); fmtNdx++) 1186e5c31af7Sopenharmony_ci { 1187e5c31af7Sopenharmony_ci deUint32 format = requiredFixedFormats[fmtNdx]; 1188e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1189e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1190e5c31af7Sopenharmony_ci 1191e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1192e5c31af7Sopenharmony_ci 1193e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1194e5c31af7Sopenharmony_ci { 1195e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1196e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1197e5c31af7Sopenharmony_ci 1198e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT, prec, 0)).toVec())); 1199e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2, prec, 0)).toVec())); 1200e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3, prec, 0)).toVec())); 1201e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4, prec, 0)).toVec())); 1202e5c31af7Sopenharmony_ci } 1203e5c31af7Sopenharmony_ci } 1204e5c31af7Sopenharmony_ci 1205e5c31af7Sopenharmony_ci // .int 1206e5c31af7Sopenharmony_ci tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer output tests"); 1207e5c31af7Sopenharmony_ci basicGroup->addChild(intGroup); 1208e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredIntFormats); fmtNdx++) 1209e5c31af7Sopenharmony_ci { 1210e5c31af7Sopenharmony_ci deUint32 format = requiredIntFormats[fmtNdx]; 1211e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1212e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1213e5c31af7Sopenharmony_ci 1214e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1215e5c31af7Sopenharmony_ci 1216e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1217e5c31af7Sopenharmony_ci { 1218e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1219e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1220e5c31af7Sopenharmony_ci 1221e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_int").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT, prec, 0)).toVec())); 1222e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC2, prec, 0)).toVec())); 1223e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC3, prec, 0)).toVec())); 1224e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC4, prec, 0)).toVec())); 1225e5c31af7Sopenharmony_ci } 1226e5c31af7Sopenharmony_ci } 1227e5c31af7Sopenharmony_ci 1228e5c31af7Sopenharmony_ci // .uint 1229e5c31af7Sopenharmony_ci tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Usigned integer output tests"); 1230e5c31af7Sopenharmony_ci basicGroup->addChild(uintGroup); 1231e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredUintFormats); fmtNdx++) 1232e5c31af7Sopenharmony_ci { 1233e5c31af7Sopenharmony_ci deUint32 format = requiredUintFormats[fmtNdx]; 1234e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1235e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1236e5c31af7Sopenharmony_ci 1237e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1240e5c31af7Sopenharmony_ci { 1241e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1242e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1243e5c31af7Sopenharmony_ci 1244e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uint").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT, prec, 0)).toVec())); 1245e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC2, prec, 0)).toVec())); 1246e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC3, prec, 0)).toVec())); 1247e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC4, prec, 0)).toVec())); 1248e5c31af7Sopenharmony_ci } 1249e5c31af7Sopenharmony_ci } 1250e5c31af7Sopenharmony_ci } 1251e5c31af7Sopenharmony_ci 1252e5c31af7Sopenharmony_ci // .array 1253e5c31af7Sopenharmony_ci { 1254e5c31af7Sopenharmony_ci tcu::TestCaseGroup* arrayGroup = new tcu::TestCaseGroup(m_testCtx, "array", "Array outputs"); 1255e5c31af7Sopenharmony_ci addChild(arrayGroup); 1256e5c31af7Sopenharmony_ci 1257e5c31af7Sopenharmony_ci const int width = 64; 1258e5c31af7Sopenharmony_ci const int height = 64; 1259e5c31af7Sopenharmony_ci const int samples = 0; 1260e5c31af7Sopenharmony_ci const int numTargets = 3; 1261e5c31af7Sopenharmony_ci 1262e5c31af7Sopenharmony_ci // .float 1263e5c31af7Sopenharmony_ci tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point output tests"); 1264e5c31af7Sopenharmony_ci arrayGroup->addChild(floatGroup); 1265e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFloatFormats); fmtNdx++) 1266e5c31af7Sopenharmony_ci { 1267e5c31af7Sopenharmony_ci deUint32 format = requiredFloatFormats[fmtNdx]; 1268e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1269e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1270e5c31af7Sopenharmony_ci 1271e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numTargets; ndx++) 1272e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1273e5c31af7Sopenharmony_ci 1274e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1275e5c31af7Sopenharmony_ci { 1276e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1277e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1278e5c31af7Sopenharmony_ci 1279e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT, prec, 0, numTargets)).toVec())); 1280e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2, prec, 0, numTargets)).toVec())); 1281e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3, prec, 0, numTargets)).toVec())); 1282e5c31af7Sopenharmony_ci floatGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4, prec, 0, numTargets)).toVec())); 1283e5c31af7Sopenharmony_ci } 1284e5c31af7Sopenharmony_ci } 1285e5c31af7Sopenharmony_ci 1286e5c31af7Sopenharmony_ci // .fixed 1287e5c31af7Sopenharmony_ci tcu::TestCaseGroup* fixedGroup = new tcu::TestCaseGroup(m_testCtx, "fixed", "Fixed-point output tests"); 1288e5c31af7Sopenharmony_ci arrayGroup->addChild(fixedGroup); 1289e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredFixedFormats); fmtNdx++) 1290e5c31af7Sopenharmony_ci { 1291e5c31af7Sopenharmony_ci deUint32 format = requiredFixedFormats[fmtNdx]; 1292e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1293e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1294e5c31af7Sopenharmony_ci 1295e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numTargets; ndx++) 1296e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1297e5c31af7Sopenharmony_ci 1298e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1299e5c31af7Sopenharmony_ci { 1300e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1301e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1302e5c31af7Sopenharmony_ci 1303e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_float").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT, prec, 0, numTargets)).toVec())); 1304e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC2, prec, 0, numTargets)).toVec())); 1305e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC3, prec, 0, numTargets)).toVec())); 1306e5c31af7Sopenharmony_ci fixedGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_vec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_FLOAT_VEC4, prec, 0, numTargets)).toVec())); 1307e5c31af7Sopenharmony_ci } 1308e5c31af7Sopenharmony_ci } 1309e5c31af7Sopenharmony_ci 1310e5c31af7Sopenharmony_ci // .int 1311e5c31af7Sopenharmony_ci tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer output tests"); 1312e5c31af7Sopenharmony_ci arrayGroup->addChild(intGroup); 1313e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredIntFormats); fmtNdx++) 1314e5c31af7Sopenharmony_ci { 1315e5c31af7Sopenharmony_ci deUint32 format = requiredIntFormats[fmtNdx]; 1316e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1317e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numTargets; ndx++) 1320e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1321e5c31af7Sopenharmony_ci 1322e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1323e5c31af7Sopenharmony_ci { 1324e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1325e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1326e5c31af7Sopenharmony_ci 1327e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_int").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT, prec, 0, numTargets)).toVec())); 1328e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC2, prec, 0, numTargets)).toVec())); 1329e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC3, prec, 0, numTargets)).toVec())); 1330e5c31af7Sopenharmony_ci intGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_ivec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_INT_VEC4, prec, 0, numTargets)).toVec())); 1331e5c31af7Sopenharmony_ci } 1332e5c31af7Sopenharmony_ci } 1333e5c31af7Sopenharmony_ci 1334e5c31af7Sopenharmony_ci // .uint 1335e5c31af7Sopenharmony_ci tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Usigned integer output tests"); 1336e5c31af7Sopenharmony_ci arrayGroup->addChild(uintGroup); 1337e5c31af7Sopenharmony_ci for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(requiredUintFormats); fmtNdx++) 1338e5c31af7Sopenharmony_ci { 1339e5c31af7Sopenharmony_ci deUint32 format = requiredUintFormats[fmtNdx]; 1340e5c31af7Sopenharmony_ci string fmtName = getFormatName(format); 1341e5c31af7Sopenharmony_ci vector<BufferSpec> fboSpec; 1342e5c31af7Sopenharmony_ci 1343e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numTargets; ndx++) 1344e5c31af7Sopenharmony_ci fboSpec.push_back(BufferSpec(format, width, height, samples)); 1345e5c31af7Sopenharmony_ci 1346e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1347e5c31af7Sopenharmony_ci { 1348e5c31af7Sopenharmony_ci glu::Precision prec = precisions[precNdx]; 1349e5c31af7Sopenharmony_ci string precName = glu::getPrecisionName(prec); 1350e5c31af7Sopenharmony_ci 1351e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uint").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT, prec, 0, numTargets)).toVec())); 1352e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec2").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC2, prec, 0, numTargets)).toVec())); 1353e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec3").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC3, prec, 0, numTargets)).toVec())); 1354e5c31af7Sopenharmony_ci uintGroup->addChild(new FragmentOutputCase(m_context, (fmtName + "_" + precName + "_uvec4").c_str(), "", fboSpec, (OutputVec() << FragmentOutput(glu::TYPE_UINT_VEC4, prec, 0, numTargets)).toVec())); 1355e5c31af7Sopenharmony_ci } 1356e5c31af7Sopenharmony_ci } 1357e5c31af7Sopenharmony_ci } 1358e5c31af7Sopenharmony_ci 1359e5c31af7Sopenharmony_ci // .random 1360e5c31af7Sopenharmony_ci { 1361e5c31af7Sopenharmony_ci tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random fragment output cases"); 1362e5c31af7Sopenharmony_ci addChild(randomGroup); 1363e5c31af7Sopenharmony_ci 1364e5c31af7Sopenharmony_ci for (deUint32 seed = 0; seed < 100; seed++) 1365e5c31af7Sopenharmony_ci randomGroup->addChild(createRandomCase(m_context, 2, 4, seed)); 1366e5c31af7Sopenharmony_ci } 1367e5c31af7Sopenharmony_ci} 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci} // Functional 1370e5c31af7Sopenharmony_ci} // gles3 1371e5c31af7Sopenharmony_ci} // deqp 1372