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 Instanced rendering tests. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es3fInstancedRenderingTests.hpp" 25e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 26e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 27e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp" 28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 29e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 30e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp" 31e5c31af7Sopenharmony_ci#include "tcuVector.hpp" 32e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 33e5c31af7Sopenharmony_ci#include "deRandom.hpp" 34e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 35e5c31af7Sopenharmony_ci#include "deString.h" 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci#include "glw.h" 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ciusing std::vector; 40e5c31af7Sopenharmony_ciusing std::string; 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_cinamespace deqp 43e5c31af7Sopenharmony_ci{ 44e5c31af7Sopenharmony_cinamespace gles3 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_cinamespace Functional 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_cistatic const int MAX_RENDER_WIDTH = 128; 50e5c31af7Sopenharmony_cistatic const int MAX_RENDER_HEIGHT = 128; 51e5c31af7Sopenharmony_ci 52e5c31af7Sopenharmony_cistatic const int QUAD_GRID_SIZE = 127; 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ci// Attribute divisors for the attributes defining the color's RGB components. 55e5c31af7Sopenharmony_cistatic const int ATTRIB_DIVISOR_R = 3; 56e5c31af7Sopenharmony_cistatic const int ATTRIB_DIVISOR_G = 2; 57e5c31af7Sopenharmony_cistatic const int ATTRIB_DIVISOR_B = 1; 58e5c31af7Sopenharmony_ci 59e5c31af7Sopenharmony_cistatic const int OFFSET_COMPONENTS = 3; // \note Affects whether a float or a vecN is used in shader, but only first component is non-zero. 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci// Scale and bias values when converting float to integer, when attribute is of integer type. 62e5c31af7Sopenharmony_cistatic const float FLOAT_INT_SCALE = 100.0f; 63e5c31af7Sopenharmony_cistatic const float FLOAT_INT_BIAS = -50.0f; 64e5c31af7Sopenharmony_cistatic const float FLOAT_UINT_SCALE = 100.0f; 65e5c31af7Sopenharmony_cistatic const float FLOAT_UINT_BIAS = 0.0f; 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci// \note Non-anonymous namespace needed; VarComp is used as a template parameter. 68e5c31af7Sopenharmony_cinamespace vcns 69e5c31af7Sopenharmony_ci{ 70e5c31af7Sopenharmony_ci 71e5c31af7Sopenharmony_ciunion VarComp 72e5c31af7Sopenharmony_ci{ 73e5c31af7Sopenharmony_ci float f32; 74e5c31af7Sopenharmony_ci deUint32 u32; 75e5c31af7Sopenharmony_ci deInt32 i32; 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci VarComp(float v) : f32(v) {} 78e5c31af7Sopenharmony_ci VarComp(deUint32 v) : u32(v) {} 79e5c31af7Sopenharmony_ci VarComp(deInt32 v) : i32(v) {} 80e5c31af7Sopenharmony_ci}; 81e5c31af7Sopenharmony_ciDE_STATIC_ASSERT(sizeof(VarComp) == sizeof(deUint32)); 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci} // vcns 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ciusing namespace vcns; 86e5c31af7Sopenharmony_ci 87e5c31af7Sopenharmony_ciclass InstancedRenderingCase : public TestCase 88e5c31af7Sopenharmony_ci{ 89e5c31af7Sopenharmony_cipublic: 90e5c31af7Sopenharmony_ci enum DrawFunction 91e5c31af7Sopenharmony_ci { 92e5c31af7Sopenharmony_ci FUNCTION_DRAW_ARRAYS_INSTANCED = 0, 93e5c31af7Sopenharmony_ci FUNCTION_DRAW_ELEMENTS_INSTANCED, 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci FUNCTION_LAST 96e5c31af7Sopenharmony_ci }; 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci enum InstancingType 99e5c31af7Sopenharmony_ci { 100e5c31af7Sopenharmony_ci TYPE_INSTANCE_ID = 0, 101e5c31af7Sopenharmony_ci TYPE_ATTRIB_DIVISOR, 102e5c31af7Sopenharmony_ci TYPE_MIXED, 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ci TYPE_LAST 105e5c31af7Sopenharmony_ci }; 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci InstancedRenderingCase (Context& context, const char* name, const char* description, DrawFunction function, InstancingType instancingType, glu::DataType rgbAttrType, int numInstances); 108e5c31af7Sopenharmony_ci ~InstancedRenderingCase (void); 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci void init (void); 111e5c31af7Sopenharmony_ci void deinit (void); 112e5c31af7Sopenharmony_ci IterateResult iterate (void); 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ciprivate: 115e5c31af7Sopenharmony_ci InstancedRenderingCase (const InstancedRenderingCase& other); 116e5c31af7Sopenharmony_ci InstancedRenderingCase& operator= (const InstancedRenderingCase& other); 117e5c31af7Sopenharmony_ci 118e5c31af7Sopenharmony_ci void pushVarCompAttrib (vector<VarComp>& vec, float val); 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ci void setupVarAttribPointer (const void* attrPtr, int startLocation, int divisor); 121e5c31af7Sopenharmony_ci void setupAndRender (void); 122e5c31af7Sopenharmony_ci void computeReference (tcu::Surface& dst); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci DrawFunction m_function; 125e5c31af7Sopenharmony_ci InstancingType m_instancingType; 126e5c31af7Sopenharmony_ci glu::DataType m_rgbAttrType; // \note Instance attribute types, color components only. Position offset attribute is always float/vecN. 127e5c31af7Sopenharmony_ci int m_numInstances; 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci vector<float> m_gridVertexPositions; // X and Y components per vertex. 130e5c31af7Sopenharmony_ci vector<deUint16> m_gridIndices; // \note Only used if m_function is FUNCTION_DRAW_ELEMENTS_INSTANCED. 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_ci // \note Some or all of the following instance attribute parameters may be unused with TYPE_INSTANCE_ID or TYPE_MIXED. 133e5c31af7Sopenharmony_ci vector<float> m_instanceOffsets; // Position offsets. OFFSET_COMPONENTS components per offset. 134e5c31af7Sopenharmony_ci // Attribute data for float, int or uint (or respective vector types) color components. 135e5c31af7Sopenharmony_ci vector<VarComp> m_instanceColorR; 136e5c31af7Sopenharmony_ci vector<VarComp> m_instanceColorG; 137e5c31af7Sopenharmony_ci vector<VarComp> m_instanceColorB; 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci glu::ShaderProgram* m_program; 140e5c31af7Sopenharmony_ci}; 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ciInstancedRenderingCase::InstancedRenderingCase (Context& context, const char* name, const char* description, DrawFunction function, InstancingType instancingType, glu::DataType rgbAttrType, int numInstances) 143e5c31af7Sopenharmony_ci : TestCase (context, name, description) 144e5c31af7Sopenharmony_ci , m_function (function) 145e5c31af7Sopenharmony_ci , m_instancingType (instancingType) 146e5c31af7Sopenharmony_ci , m_rgbAttrType (rgbAttrType) 147e5c31af7Sopenharmony_ci , m_numInstances (numInstances) 148e5c31af7Sopenharmony_ci , m_program (DE_NULL) 149e5c31af7Sopenharmony_ci{ 150e5c31af7Sopenharmony_ci} 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ciInstancedRenderingCase::~InstancedRenderingCase (void) 153e5c31af7Sopenharmony_ci{ 154e5c31af7Sopenharmony_ci InstancedRenderingCase::deinit(); 155e5c31af7Sopenharmony_ci} 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci// Helper function that does biasing and scaling when converting float to integer. 158e5c31af7Sopenharmony_civoid InstancedRenderingCase::pushVarCompAttrib (vector<VarComp>& vec, float val) 159e5c31af7Sopenharmony_ci{ 160e5c31af7Sopenharmony_ci bool isFloatCase = glu::isDataTypeFloatOrVec(m_rgbAttrType); 161e5c31af7Sopenharmony_ci bool isIntCase = glu::isDataTypeIntOrIVec(m_rgbAttrType); 162e5c31af7Sopenharmony_ci bool isUintCase = glu::isDataTypeUintOrUVec(m_rgbAttrType); 163e5c31af7Sopenharmony_ci bool isMatCase = glu::isDataTypeMatrix(m_rgbAttrType); 164e5c31af7Sopenharmony_ci 165e5c31af7Sopenharmony_ci if (isFloatCase || isMatCase) 166e5c31af7Sopenharmony_ci vec.push_back(VarComp(val)); 167e5c31af7Sopenharmony_ci else if (isIntCase) 168e5c31af7Sopenharmony_ci vec.push_back(VarComp((deInt32)(val*FLOAT_INT_SCALE + FLOAT_INT_BIAS))); 169e5c31af7Sopenharmony_ci else if (isUintCase) 170e5c31af7Sopenharmony_ci vec.push_back(VarComp((deUint32)(val*FLOAT_UINT_SCALE + FLOAT_UINT_BIAS))); 171e5c31af7Sopenharmony_ci else 172e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 173e5c31af7Sopenharmony_ci} 174e5c31af7Sopenharmony_ci 175e5c31af7Sopenharmony_civoid InstancedRenderingCase::init (void) 176e5c31af7Sopenharmony_ci{ 177e5c31af7Sopenharmony_ci bool isFloatCase = glu::isDataTypeFloatOrVec(m_rgbAttrType); 178e5c31af7Sopenharmony_ci bool isIntCase = glu::isDataTypeIntOrIVec(m_rgbAttrType); 179e5c31af7Sopenharmony_ci bool isUintCase = glu::isDataTypeUintOrUVec(m_rgbAttrType); 180e5c31af7Sopenharmony_ci bool isMatCase = glu::isDataTypeMatrix(m_rgbAttrType); 181e5c31af7Sopenharmony_ci int typeSize = glu::getDataTypeScalarSize(m_rgbAttrType); 182e5c31af7Sopenharmony_ci bool isScalarCase = typeSize == 1; 183e5c31af7Sopenharmony_ci string swizzleFirst = isScalarCase ? "" : ".x"; 184e5c31af7Sopenharmony_ci string typeName = glu::getDataTypeName(m_rgbAttrType); 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci string floatIntScaleStr = "(" + de::floatToString(FLOAT_INT_SCALE, 3) + ")"; 187e5c31af7Sopenharmony_ci string floatIntBiasStr = "(" + de::floatToString(FLOAT_INT_BIAS, 3) + ")"; 188e5c31af7Sopenharmony_ci string floatUintScaleStr = "(" + de::floatToString(FLOAT_UINT_SCALE, 3) + ")"; 189e5c31af7Sopenharmony_ci string floatUintBiasStr = "(" + de::floatToString(FLOAT_UINT_BIAS, 3) + ")"; 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_ci DE_ASSERT(isFloatCase || isIntCase || isUintCase || isMatCase); 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_ci // Generate shader. 194e5c31af7Sopenharmony_ci // \note For case TYPE_MIXED, vertex position offset and color red component get their values from instance id, while green and blue get their values from instanced attributes. 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci string numInstancesStr = de::toString(m_numInstances) + ".0"; 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci string instanceAttribs; 199e5c31af7Sopenharmony_ci string posExpression; 200e5c31af7Sopenharmony_ci string colorRExpression; 201e5c31af7Sopenharmony_ci string colorGExpression; 202e5c31af7Sopenharmony_ci string colorBExpression; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_INSTANCE_ID || m_instancingType == TYPE_MIXED) 205e5c31af7Sopenharmony_ci { 206e5c31af7Sopenharmony_ci posExpression = "a_position + vec4(float(gl_InstanceID) * 2.0 / " + numInstancesStr + ", 0.0, 0.0, 0.0)"; 207e5c31af7Sopenharmony_ci colorRExpression = "float(gl_InstanceID)/" + numInstancesStr; 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_INSTANCE_ID) 210e5c31af7Sopenharmony_ci { 211e5c31af7Sopenharmony_ci colorGExpression = "float(gl_InstanceID)*2.0/" + numInstancesStr; 212e5c31af7Sopenharmony_ci colorBExpression = "1.0 - float(gl_InstanceID)/" + numInstancesStr; 213e5c31af7Sopenharmony_ci } 214e5c31af7Sopenharmony_ci } 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED) 217e5c31af7Sopenharmony_ci { 218e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR) 219e5c31af7Sopenharmony_ci { 220e5c31af7Sopenharmony_ci posExpression = "a_position + vec4(a_instanceOffset"; 221e5c31af7Sopenharmony_ci 222e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(OFFSET_COMPONENTS >= 1 && OFFSET_COMPONENTS <= 4); 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci for (int i = 0; i < 4-OFFSET_COMPONENTS; i++) 225e5c31af7Sopenharmony_ci posExpression += ", 0.0"; 226e5c31af7Sopenharmony_ci posExpression += ")"; 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci if (isFloatCase) 229e5c31af7Sopenharmony_ci colorRExpression = "a_instanceR" + swizzleFirst; 230e5c31af7Sopenharmony_ci else if (isIntCase) 231e5c31af7Sopenharmony_ci colorRExpression = "(float(a_instanceR" + swizzleFirst + ") - " + floatIntBiasStr + ") / " + floatIntScaleStr; 232e5c31af7Sopenharmony_ci else if (isUintCase) 233e5c31af7Sopenharmony_ci colorRExpression = "(float(a_instanceR" + swizzleFirst + ") - " + floatUintBiasStr + ") / " + floatUintScaleStr; 234e5c31af7Sopenharmony_ci else if (isMatCase) 235e5c31af7Sopenharmony_ci colorRExpression = "a_instanceR[0][0]"; 236e5c31af7Sopenharmony_ci else 237e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 238e5c31af7Sopenharmony_ci 239e5c31af7Sopenharmony_ci instanceAttribs += "in highp " + (OFFSET_COMPONENTS == 1 ? string("float") : "vec" + de::toString(OFFSET_COMPONENTS)) + " a_instanceOffset;\n"; 240e5c31af7Sopenharmony_ci instanceAttribs += "in mediump " + typeName + " a_instanceR;\n"; 241e5c31af7Sopenharmony_ci } 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci if (isFloatCase) 244e5c31af7Sopenharmony_ci { 245e5c31af7Sopenharmony_ci colorGExpression = "a_instanceG" + swizzleFirst; 246e5c31af7Sopenharmony_ci colorBExpression = "a_instanceB" + swizzleFirst; 247e5c31af7Sopenharmony_ci } 248e5c31af7Sopenharmony_ci else if (isIntCase) 249e5c31af7Sopenharmony_ci { 250e5c31af7Sopenharmony_ci colorGExpression = "(float(a_instanceG" + swizzleFirst + ") - " + floatIntBiasStr + ") / " + floatIntScaleStr; 251e5c31af7Sopenharmony_ci colorBExpression = "(float(a_instanceB" + swizzleFirst + ") - " + floatIntBiasStr + ") / " + floatIntScaleStr; 252e5c31af7Sopenharmony_ci } 253e5c31af7Sopenharmony_ci else if (isUintCase) 254e5c31af7Sopenharmony_ci { 255e5c31af7Sopenharmony_ci colorGExpression = "(float(a_instanceG" + swizzleFirst + ") - " + floatUintBiasStr + ") / " + floatUintScaleStr; 256e5c31af7Sopenharmony_ci colorBExpression = "(float(a_instanceB" + swizzleFirst + ") - " + floatUintBiasStr + ") / " + floatUintScaleStr; 257e5c31af7Sopenharmony_ci } 258e5c31af7Sopenharmony_ci else if (isMatCase) 259e5c31af7Sopenharmony_ci { 260e5c31af7Sopenharmony_ci colorGExpression = "a_instanceG[0][0]"; 261e5c31af7Sopenharmony_ci colorBExpression = "a_instanceB[0][0]"; 262e5c31af7Sopenharmony_ci } 263e5c31af7Sopenharmony_ci else 264e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 265e5c31af7Sopenharmony_ci 266e5c31af7Sopenharmony_ci instanceAttribs += "in mediump " + typeName + " a_instanceG;\n"; 267e5c31af7Sopenharmony_ci instanceAttribs += "in mediump " + typeName + " a_instanceB;\n"; 268e5c31af7Sopenharmony_ci } 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci DE_ASSERT(!posExpression.empty()); 271e5c31af7Sopenharmony_ci DE_ASSERT(!colorRExpression.empty()); 272e5c31af7Sopenharmony_ci DE_ASSERT(!colorGExpression.empty()); 273e5c31af7Sopenharmony_ci DE_ASSERT(!colorBExpression.empty()); 274e5c31af7Sopenharmony_ci 275e5c31af7Sopenharmony_ci std::string vertShaderSourceStr = 276e5c31af7Sopenharmony_ci "#version 300 es\n" 277e5c31af7Sopenharmony_ci "in highp vec4 a_position;\n" + 278e5c31af7Sopenharmony_ci instanceAttribs + 279e5c31af7Sopenharmony_ci "out mediump vec4 v_color;\n" 280e5c31af7Sopenharmony_ci "\n" 281e5c31af7Sopenharmony_ci "void main()\n" 282e5c31af7Sopenharmony_ci "{\n" 283e5c31af7Sopenharmony_ci " gl_Position = " + posExpression + ";\n" 284e5c31af7Sopenharmony_ci " v_color.r = " + colorRExpression + ";\n" 285e5c31af7Sopenharmony_ci " v_color.g = " + colorGExpression + ";\n" 286e5c31af7Sopenharmony_ci " v_color.b = " + colorBExpression + ";\n" 287e5c31af7Sopenharmony_ci " v_color.a = 1.0;\n" 288e5c31af7Sopenharmony_ci "}\n"; 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci static const char* fragShaderSource = 291e5c31af7Sopenharmony_ci "#version 300 es\n" 292e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 o_color;\n" 293e5c31af7Sopenharmony_ci "in mediump vec4 v_color;\n" 294e5c31af7Sopenharmony_ci "\n" 295e5c31af7Sopenharmony_ci "void main()\n" 296e5c31af7Sopenharmony_ci "{\n" 297e5c31af7Sopenharmony_ci " o_color = v_color;\n" 298e5c31af7Sopenharmony_ci "}\n"; 299e5c31af7Sopenharmony_ci 300e5c31af7Sopenharmony_ci // Create shader program and log it. 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_ci DE_ASSERT(!m_program); 303e5c31af7Sopenharmony_ci m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSourceStr, fragShaderSource)); 304e5c31af7Sopenharmony_ci 305e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 306e5c31af7Sopenharmony_ci 307e5c31af7Sopenharmony_ci log << *m_program; 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci if(!m_program->isOk()) 310e5c31af7Sopenharmony_ci TCU_FAIL("Failed to compile shader"); 311e5c31af7Sopenharmony_ci 312e5c31af7Sopenharmony_ci // Vertex shader attributes. 313e5c31af7Sopenharmony_ci 314e5c31af7Sopenharmony_ci if (m_function == FUNCTION_DRAW_ELEMENTS_INSTANCED) 315e5c31af7Sopenharmony_ci { 316e5c31af7Sopenharmony_ci // Vertex positions. Positions form a vertical bar of width <screen width>/<number of instances>. 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci for (int y = 0; y < QUAD_GRID_SIZE + 1; y++) 319e5c31af7Sopenharmony_ci for (int x = 0; x < QUAD_GRID_SIZE + 1; x++) 320e5c31af7Sopenharmony_ci { 321e5c31af7Sopenharmony_ci float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)m_numInstances; 322e5c31af7Sopenharmony_ci float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f; 323e5c31af7Sopenharmony_ci 324e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx); 325e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy); 326e5c31af7Sopenharmony_ci } 327e5c31af7Sopenharmony_ci 328e5c31af7Sopenharmony_ci // Indices. 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci for (int y = 0; y < QUAD_GRID_SIZE; y++) 331e5c31af7Sopenharmony_ci for (int x = 0; x < QUAD_GRID_SIZE; x++) 332e5c31af7Sopenharmony_ci { 333e5c31af7Sopenharmony_ci int ndx00 = y*(QUAD_GRID_SIZE + 1) + x; 334e5c31af7Sopenharmony_ci int ndx10 = y*(QUAD_GRID_SIZE + 1) + x + 1; 335e5c31af7Sopenharmony_ci int ndx01 = (y + 1)*(QUAD_GRID_SIZE + 1) + x; 336e5c31af7Sopenharmony_ci int ndx11 = (y + 1)*(QUAD_GRID_SIZE + 1) + x + 1; 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci // Lower-left triangle of a quad. 339e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx00); 340e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx10); 341e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx01); 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci // Upper-right triangle of a quad. 344e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx11); 345e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx01); 346e5c31af7Sopenharmony_ci m_gridIndices.push_back((deUint16)ndx10); 347e5c31af7Sopenharmony_ci } 348e5c31af7Sopenharmony_ci } 349e5c31af7Sopenharmony_ci else 350e5c31af7Sopenharmony_ci { 351e5c31af7Sopenharmony_ci DE_ASSERT(m_function == FUNCTION_DRAW_ARRAYS_INSTANCED); 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_ci // Vertex positions. Positions form a vertical bar of width <screen width>/<number of instances>. 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci for (int y = 0; y < QUAD_GRID_SIZE; y++) 356e5c31af7Sopenharmony_ci for (int x = 0; x < QUAD_GRID_SIZE; x++) 357e5c31af7Sopenharmony_ci { 358e5c31af7Sopenharmony_ci float fx0 = -1.0f + (float)(x+0) / (float)QUAD_GRID_SIZE * 2.0f / (float)m_numInstances; 359e5c31af7Sopenharmony_ci float fx1 = -1.0f + (float)(x+1) / (float)QUAD_GRID_SIZE * 2.0f / (float)m_numInstances; 360e5c31af7Sopenharmony_ci float fy0 = -1.0f + (float)(y+0) / (float)QUAD_GRID_SIZE * 2.0f; 361e5c31af7Sopenharmony_ci float fy1 = -1.0f + (float)(y+1) / (float)QUAD_GRID_SIZE * 2.0f; 362e5c31af7Sopenharmony_ci 363e5c31af7Sopenharmony_ci // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1) 364e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx0); 365e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy0); 366e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx1); 367e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy0); 368e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx0); 369e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy1); 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0) 372e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx1); 373e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy1); 374e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx0); 375e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy1); 376e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fx1); 377e5c31af7Sopenharmony_ci m_gridVertexPositions.push_back(fy0); 378e5c31af7Sopenharmony_ci } 379e5c31af7Sopenharmony_ci } 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci // Instanced attributes: position offset and color RGB components. 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED) 384e5c31af7Sopenharmony_ci { 385e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR) 386e5c31af7Sopenharmony_ci { 387e5c31af7Sopenharmony_ci // Offsets are such that the vertical bars are drawn next to each other. 388e5c31af7Sopenharmony_ci for (int i = 0; i < m_numInstances; i++) 389e5c31af7Sopenharmony_ci { 390e5c31af7Sopenharmony_ci m_instanceOffsets.push_back((float)i * 2.0f / (float)m_numInstances); 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(OFFSET_COMPONENTS >= 1 && OFFSET_COMPONENTS <= 4); 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci for (int j = 0; j < OFFSET_COMPONENTS-1; j++) 395e5c31af7Sopenharmony_ci m_instanceOffsets.push_back(0.0f); 396e5c31af7Sopenharmony_ci } 397e5c31af7Sopenharmony_ci 398e5c31af7Sopenharmony_ci int rInstances = m_numInstances / ATTRIB_DIVISOR_R + (m_numInstances % ATTRIB_DIVISOR_R == 0 ? 0 : 1); 399e5c31af7Sopenharmony_ci for (int i = 0; i < rInstances; i++) 400e5c31af7Sopenharmony_ci { 401e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorR, (float)i / (float)rInstances); 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci for (int j = 0; j < typeSize - 1; j++) 404e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorR, 0.0f); 405e5c31af7Sopenharmony_ci } 406e5c31af7Sopenharmony_ci } 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci int gInstances = m_numInstances / ATTRIB_DIVISOR_G + (m_numInstances % ATTRIB_DIVISOR_G == 0 ? 0 : 1); 409e5c31af7Sopenharmony_ci for (int i = 0; i < gInstances; i++) 410e5c31af7Sopenharmony_ci { 411e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorG, (float)i*2.0f / (float)gInstances); 412e5c31af7Sopenharmony_ci 413e5c31af7Sopenharmony_ci for (int j = 0; j < typeSize - 1; j++) 414e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorG, 0.0f); 415e5c31af7Sopenharmony_ci } 416e5c31af7Sopenharmony_ci 417e5c31af7Sopenharmony_ci int bInstances = m_numInstances / ATTRIB_DIVISOR_B + (m_numInstances % ATTRIB_DIVISOR_B == 0 ? 0 : 1); 418e5c31af7Sopenharmony_ci for (int i = 0; i < bInstances; i++) 419e5c31af7Sopenharmony_ci { 420e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorB, 1.0f - (float)i / (float)bInstances); 421e5c31af7Sopenharmony_ci 422e5c31af7Sopenharmony_ci for (int j = 0; j < typeSize - 1; j++) 423e5c31af7Sopenharmony_ci pushVarCompAttrib(m_instanceColorB, 0.0f); 424e5c31af7Sopenharmony_ci } 425e5c31af7Sopenharmony_ci } 426e5c31af7Sopenharmony_ci} 427e5c31af7Sopenharmony_ci 428e5c31af7Sopenharmony_civoid InstancedRenderingCase::deinit (void) 429e5c31af7Sopenharmony_ci{ 430e5c31af7Sopenharmony_ci delete m_program; 431e5c31af7Sopenharmony_ci m_program = DE_NULL; 432e5c31af7Sopenharmony_ci} 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_ciInstancedRenderingCase::IterateResult InstancedRenderingCase::iterate (void) 435e5c31af7Sopenharmony_ci{ 436e5c31af7Sopenharmony_ci int width = deMin32(m_context.getRenderTarget().getWidth(), MAX_RENDER_WIDTH); 437e5c31af7Sopenharmony_ci int height = deMin32(m_context.getRenderTarget().getHeight(), MAX_RENDER_HEIGHT); 438e5c31af7Sopenharmony_ci 439e5c31af7Sopenharmony_ci int xOffsetMax = m_context.getRenderTarget().getWidth() - width; 440e5c31af7Sopenharmony_ci int yOffsetMax = m_context.getRenderTarget().getHeight() - height; 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci de::Random rnd (deStringHash(getName())); 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci int xOffset = rnd.getInt(0, xOffsetMax); 445e5c31af7Sopenharmony_ci int yOffset = rnd.getInt(0, yOffsetMax); 446e5c31af7Sopenharmony_ci tcu::Surface referenceImg (width, height); 447e5c31af7Sopenharmony_ci tcu::Surface resultImg (width, height); 448e5c31af7Sopenharmony_ci 449e5c31af7Sopenharmony_ci // Draw result. 450e5c31af7Sopenharmony_ci 451e5c31af7Sopenharmony_ci glViewport(xOffset, yOffset, width, height); 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_ci setupAndRender(); 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), xOffset, yOffset, resultImg.getAccess()); 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci // Compute reference. 458e5c31af7Sopenharmony_ci 459e5c31af7Sopenharmony_ci computeReference(referenceImg); 460e5c31af7Sopenharmony_ci 461e5c31af7Sopenharmony_ci // Compare. 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci bool testOk = tcu::fuzzyCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", referenceImg, resultImg, 0.05f, tcu::COMPARE_LOG_RESULT); 464e5c31af7Sopenharmony_ci 465e5c31af7Sopenharmony_ci m_testCtx.setTestResult(testOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 466e5c31af7Sopenharmony_ci testOk ? "Pass" : "Fail"); 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_ci return STOP; 469e5c31af7Sopenharmony_ci} 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_civoid InstancedRenderingCase::setupVarAttribPointer (const void* attrPtr, int location, int divisor) 472e5c31af7Sopenharmony_ci{ 473e5c31af7Sopenharmony_ci bool isFloatCase = glu::isDataTypeFloatOrVec(m_rgbAttrType); 474e5c31af7Sopenharmony_ci bool isIntCase = glu::isDataTypeIntOrIVec(m_rgbAttrType); 475e5c31af7Sopenharmony_ci bool isUintCase = glu::isDataTypeUintOrUVec(m_rgbAttrType); 476e5c31af7Sopenharmony_ci bool isMatCase = glu::isDataTypeMatrix(m_rgbAttrType); 477e5c31af7Sopenharmony_ci int typeSize = glu::getDataTypeScalarSize(m_rgbAttrType); 478e5c31af7Sopenharmony_ci int numSlots = isMatCase ? glu::getDataTypeMatrixNumColumns(m_rgbAttrType) : 1; // Matrix uses as many attribute slots as it has columns. 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_ci for (int slotNdx = 0; slotNdx < numSlots; slotNdx++) 481e5c31af7Sopenharmony_ci { 482e5c31af7Sopenharmony_ci int curLoc = location + slotNdx; 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci glEnableVertexAttribArray(curLoc); 485e5c31af7Sopenharmony_ci glVertexAttribDivisor(curLoc, divisor); 486e5c31af7Sopenharmony_ci 487e5c31af7Sopenharmony_ci if (isFloatCase) 488e5c31af7Sopenharmony_ci glVertexAttribPointer(curLoc, typeSize, GL_FLOAT, GL_FALSE, 0, attrPtr); 489e5c31af7Sopenharmony_ci else if (isIntCase) 490e5c31af7Sopenharmony_ci glVertexAttribIPointer(curLoc, typeSize, GL_INT, 0, attrPtr); 491e5c31af7Sopenharmony_ci else if (isUintCase) 492e5c31af7Sopenharmony_ci glVertexAttribIPointer(curLoc, typeSize, GL_UNSIGNED_INT, 0, attrPtr); 493e5c31af7Sopenharmony_ci else if (isMatCase) 494e5c31af7Sopenharmony_ci { 495e5c31af7Sopenharmony_ci int numRows = glu::getDataTypeMatrixNumRows(m_rgbAttrType); 496e5c31af7Sopenharmony_ci int numCols = glu::getDataTypeMatrixNumColumns(m_rgbAttrType); 497e5c31af7Sopenharmony_ci 498e5c31af7Sopenharmony_ci glVertexAttribPointer(curLoc, numRows, GL_FLOAT, GL_FALSE, numCols*numRows*(int)sizeof(float), attrPtr); 499e5c31af7Sopenharmony_ci } 500e5c31af7Sopenharmony_ci else 501e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 502e5c31af7Sopenharmony_ci } 503e5c31af7Sopenharmony_ci} 504e5c31af7Sopenharmony_ci 505e5c31af7Sopenharmony_civoid InstancedRenderingCase::setupAndRender (void) 506e5c31af7Sopenharmony_ci{ 507e5c31af7Sopenharmony_ci deUint32 program = m_program->getProgram(); 508e5c31af7Sopenharmony_ci 509e5c31af7Sopenharmony_ci glUseProgram(program); 510e5c31af7Sopenharmony_ci 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci // Setup attributes. 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci // Position attribute is non-instanced. 515e5c31af7Sopenharmony_ci int positionLoc = glGetAttribLocation(program, "a_position"); 516e5c31af7Sopenharmony_ci glEnableVertexAttribArray(positionLoc); 517e5c31af7Sopenharmony_ci glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, &m_gridVertexPositions[0]); 518e5c31af7Sopenharmony_ci 519e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED) 520e5c31af7Sopenharmony_ci { 521e5c31af7Sopenharmony_ci if (m_instancingType == TYPE_ATTRIB_DIVISOR) 522e5c31af7Sopenharmony_ci { 523e5c31af7Sopenharmony_ci // Position offset attribute is instanced with separate offset for every instance. 524e5c31af7Sopenharmony_ci int offsetLoc = glGetAttribLocation(program, "a_instanceOffset"); 525e5c31af7Sopenharmony_ci glEnableVertexAttribArray(offsetLoc); 526e5c31af7Sopenharmony_ci glVertexAttribDivisor(offsetLoc, 1); 527e5c31af7Sopenharmony_ci glVertexAttribPointer(offsetLoc, OFFSET_COMPONENTS, GL_FLOAT, GL_FALSE, 0, &m_instanceOffsets[0]); 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci int rLoc = glGetAttribLocation(program, "a_instanceR"); 530e5c31af7Sopenharmony_ci setupVarAttribPointer((void*)&m_instanceColorR[0].u32, rLoc, ATTRIB_DIVISOR_R); 531e5c31af7Sopenharmony_ci } 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci int gLoc = glGetAttribLocation(program, "a_instanceG"); 534e5c31af7Sopenharmony_ci setupVarAttribPointer((void*)&m_instanceColorG[0].u32, gLoc, ATTRIB_DIVISOR_G); 535e5c31af7Sopenharmony_ci 536e5c31af7Sopenharmony_ci int bLoc = glGetAttribLocation(program, "a_instanceB"); 537e5c31af7Sopenharmony_ci setupVarAttribPointer((void*)&m_instanceColorB[0].u32, bLoc, ATTRIB_DIVISOR_B); 538e5c31af7Sopenharmony_ci } 539e5c31af7Sopenharmony_ci } 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci // Draw using appropriate function. 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci if (m_function == FUNCTION_DRAW_ARRAYS_INSTANCED) 544e5c31af7Sopenharmony_ci { 545e5c31af7Sopenharmony_ci const int numPositionComponents = 2; 546e5c31af7Sopenharmony_ci glDrawArraysInstanced(GL_TRIANGLES, 0, ((int)m_gridVertexPositions.size() / numPositionComponents), m_numInstances); 547e5c31af7Sopenharmony_ci } 548e5c31af7Sopenharmony_ci else 549e5c31af7Sopenharmony_ci glDrawElementsInstanced(GL_TRIANGLES, (int)m_gridIndices.size(), GL_UNSIGNED_SHORT, &m_gridIndices[0], m_numInstances); 550e5c31af7Sopenharmony_ci 551e5c31af7Sopenharmony_ci glUseProgram(0); 552e5c31af7Sopenharmony_ci} 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_civoid InstancedRenderingCase::computeReference (tcu::Surface& dst) 555e5c31af7Sopenharmony_ci{ 556e5c31af7Sopenharmony_ci int wid = dst.getWidth(); 557e5c31af7Sopenharmony_ci int hei = dst.getHeight(); 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_ci // Draw a rectangle (vertical bar) for each instance. 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_ci for (int instanceNdx = 0; instanceNdx < m_numInstances; instanceNdx++) 562e5c31af7Sopenharmony_ci { 563e5c31af7Sopenharmony_ci int xStart = instanceNdx * wid / m_numInstances; 564e5c31af7Sopenharmony_ci int xEnd = (instanceNdx + 1) * wid / m_numInstances; 565e5c31af7Sopenharmony_ci 566e5c31af7Sopenharmony_ci // Emulate attribute divisors if that is the case. 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ci int clrNdxR = m_instancingType == TYPE_ATTRIB_DIVISOR ? instanceNdx / ATTRIB_DIVISOR_R : instanceNdx; 569e5c31af7Sopenharmony_ci int clrNdxG = m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED ? instanceNdx / ATTRIB_DIVISOR_G : instanceNdx; 570e5c31af7Sopenharmony_ci int clrNdxB = m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED ? instanceNdx / ATTRIB_DIVISOR_B : instanceNdx; 571e5c31af7Sopenharmony_ci 572e5c31af7Sopenharmony_ci int rInstances = m_instancingType == TYPE_ATTRIB_DIVISOR ? m_numInstances / ATTRIB_DIVISOR_R + (m_numInstances % ATTRIB_DIVISOR_R == 0 ? 0 : 1) : m_numInstances; 573e5c31af7Sopenharmony_ci int gInstances = m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED ? m_numInstances / ATTRIB_DIVISOR_G + (m_numInstances % ATTRIB_DIVISOR_G == 0 ? 0 : 1) : m_numInstances; 574e5c31af7Sopenharmony_ci int bInstances = m_instancingType == TYPE_ATTRIB_DIVISOR || m_instancingType == TYPE_MIXED ? m_numInstances / ATTRIB_DIVISOR_B + (m_numInstances % ATTRIB_DIVISOR_B == 0 ? 0 : 1) : m_numInstances; 575e5c31af7Sopenharmony_ci 576e5c31af7Sopenharmony_ci // Calculate colors. 577e5c31af7Sopenharmony_ci 578e5c31af7Sopenharmony_ci float r = (float)clrNdxR / (float)rInstances; 579e5c31af7Sopenharmony_ci float g = (float)clrNdxG * 2.0f / (float)gInstances; 580e5c31af7Sopenharmony_ci float b = 1.0f - (float)clrNdxB / (float)bInstances; 581e5c31af7Sopenharmony_ci 582e5c31af7Sopenharmony_ci // Convert to integer and back if shader inputs are integers. 583e5c31af7Sopenharmony_ci 584e5c31af7Sopenharmony_ci if (glu::isDataTypeIntOrIVec(m_rgbAttrType)) 585e5c31af7Sopenharmony_ci { 586e5c31af7Sopenharmony_ci deInt32 intR = (deInt32)(r*FLOAT_INT_SCALE + FLOAT_INT_BIAS); 587e5c31af7Sopenharmony_ci deInt32 intG = (deInt32)(g*FLOAT_INT_SCALE + FLOAT_INT_BIAS); 588e5c31af7Sopenharmony_ci deInt32 intB = (deInt32)(b*FLOAT_INT_SCALE + FLOAT_INT_BIAS); 589e5c31af7Sopenharmony_ci r = ((float)intR - FLOAT_INT_BIAS) / FLOAT_INT_SCALE; 590e5c31af7Sopenharmony_ci g = ((float)intG - FLOAT_INT_BIAS) / FLOAT_INT_SCALE; 591e5c31af7Sopenharmony_ci b = ((float)intB - FLOAT_INT_BIAS) / FLOAT_INT_SCALE; 592e5c31af7Sopenharmony_ci } 593e5c31af7Sopenharmony_ci else if(glu::isDataTypeUintOrUVec(m_rgbAttrType)) 594e5c31af7Sopenharmony_ci { 595e5c31af7Sopenharmony_ci deUint32 uintR = (deInt32)(r*FLOAT_UINT_SCALE + FLOAT_UINT_BIAS); 596e5c31af7Sopenharmony_ci deUint32 uintG = (deInt32)(g*FLOAT_UINT_SCALE + FLOAT_UINT_BIAS); 597e5c31af7Sopenharmony_ci deUint32 uintB = (deInt32)(b*FLOAT_UINT_SCALE + FLOAT_UINT_BIAS); 598e5c31af7Sopenharmony_ci r = ((float)uintR - FLOAT_UINT_BIAS) / FLOAT_UINT_SCALE; 599e5c31af7Sopenharmony_ci g = ((float)uintG - FLOAT_UINT_BIAS) / FLOAT_UINT_SCALE; 600e5c31af7Sopenharmony_ci b = ((float)uintB - FLOAT_UINT_BIAS) / FLOAT_UINT_SCALE; 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_ci // Draw rectangle. 604e5c31af7Sopenharmony_ci 605e5c31af7Sopenharmony_ci for (int y = 0; y < hei; y++) 606e5c31af7Sopenharmony_ci for (int x = xStart; x < xEnd; x++) 607e5c31af7Sopenharmony_ci dst.setPixel(x, y, tcu::RGBA(tcu::Vec4(r, g, b, 1.0f))); 608e5c31af7Sopenharmony_ci } 609e5c31af7Sopenharmony_ci} 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ciInstancedRenderingTests::InstancedRenderingTests (Context& context) 612e5c31af7Sopenharmony_ci : TestCaseGroup(context, "instanced", "Instanced rendering tests") 613e5c31af7Sopenharmony_ci{ 614e5c31af7Sopenharmony_ci} 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ciInstancedRenderingTests::~InstancedRenderingTests (void) 617e5c31af7Sopenharmony_ci{ 618e5c31af7Sopenharmony_ci} 619e5c31af7Sopenharmony_ci 620e5c31af7Sopenharmony_civoid InstancedRenderingTests::init (void) 621e5c31af7Sopenharmony_ci{ 622e5c31af7Sopenharmony_ci // Cases testing function, instancing method and instance count. 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci static const int instanceCounts[] = { 1, 2, 4, 20 }; 625e5c31af7Sopenharmony_ci 626e5c31af7Sopenharmony_ci for (int function = 0; function < (int)InstancedRenderingCase::FUNCTION_LAST; function++) 627e5c31af7Sopenharmony_ci { 628e5c31af7Sopenharmony_ci const char* functionName = function == (int)InstancedRenderingCase::FUNCTION_DRAW_ARRAYS_INSTANCED ? "draw_arrays_instanced" 629e5c31af7Sopenharmony_ci : function == (int)InstancedRenderingCase::FUNCTION_DRAW_ELEMENTS_INSTANCED ? "draw_elements_instanced" 630e5c31af7Sopenharmony_ci : DE_NULL; 631e5c31af7Sopenharmony_ci 632e5c31af7Sopenharmony_ci const char* functionDesc = function == (int)InstancedRenderingCase::FUNCTION_DRAW_ARRAYS_INSTANCED ? "Use glDrawArraysInstanced()" 633e5c31af7Sopenharmony_ci : function == (int)InstancedRenderingCase::FUNCTION_DRAW_ELEMENTS_INSTANCED ? "Use glDrawElementsInstanced()" 634e5c31af7Sopenharmony_ci : DE_NULL; 635e5c31af7Sopenharmony_ci 636e5c31af7Sopenharmony_ci DE_ASSERT(functionName != DE_NULL); 637e5c31af7Sopenharmony_ci DE_ASSERT(functionDesc != DE_NULL); 638e5c31af7Sopenharmony_ci 639e5c31af7Sopenharmony_ci TestCaseGroup* functionGroup = new TestCaseGroup(m_context, functionName, functionDesc); 640e5c31af7Sopenharmony_ci addChild(functionGroup); 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ci for (int instancingType = 0; instancingType < (int)InstancedRenderingCase::TYPE_LAST; instancingType++) 643e5c31af7Sopenharmony_ci { 644e5c31af7Sopenharmony_ci const char* instancingTypeName = instancingType == (int)InstancedRenderingCase::TYPE_INSTANCE_ID ? "instance_id" 645e5c31af7Sopenharmony_ci : instancingType == (int)InstancedRenderingCase::TYPE_ATTRIB_DIVISOR ? "attribute_divisor" 646e5c31af7Sopenharmony_ci : instancingType == (int)InstancedRenderingCase::TYPE_MIXED ? "mixed" 647e5c31af7Sopenharmony_ci : DE_NULL; 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci const char* instancingTypeDesc = instancingType == (int)InstancedRenderingCase::TYPE_INSTANCE_ID ? "Use gl_InstanceID for instancing" 650e5c31af7Sopenharmony_ci : instancingType == (int)InstancedRenderingCase::TYPE_ATTRIB_DIVISOR ? "Use vertex attribute divisors for instancing" 651e5c31af7Sopenharmony_ci : instancingType == (int)InstancedRenderingCase::TYPE_MIXED ? "Use both gl_InstanceID and vertex attribute divisors for instancing" 652e5c31af7Sopenharmony_ci : DE_NULL; 653e5c31af7Sopenharmony_ci 654e5c31af7Sopenharmony_ci DE_ASSERT(instancingTypeName != DE_NULL); 655e5c31af7Sopenharmony_ci DE_ASSERT(instancingTypeDesc != DE_NULL); 656e5c31af7Sopenharmony_ci 657e5c31af7Sopenharmony_ci TestCaseGroup* instancingTypeGroup = new TestCaseGroup(m_context, instancingTypeName, instancingTypeDesc); 658e5c31af7Sopenharmony_ci functionGroup->addChild(instancingTypeGroup); 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ci for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(instanceCounts); countNdx++) 661e5c31af7Sopenharmony_ci { 662e5c31af7Sopenharmony_ci std::string countName = de::toString(instanceCounts[countNdx]) + "_instances"; 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_ci instancingTypeGroup->addChild(new InstancedRenderingCase(m_context, countName.c_str(), "", 665e5c31af7Sopenharmony_ci (InstancedRenderingCase::DrawFunction)function, 666e5c31af7Sopenharmony_ci (InstancedRenderingCase::InstancingType)instancingType, 667e5c31af7Sopenharmony_ci glu::TYPE_FLOAT, 668e5c31af7Sopenharmony_ci instanceCounts[countNdx])); 669e5c31af7Sopenharmony_ci } 670e5c31af7Sopenharmony_ci } 671e5c31af7Sopenharmony_ci } 672e5c31af7Sopenharmony_ci 673e5c31af7Sopenharmony_ci // Data type specific cases. 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ci static const glu::DataType s_testTypes[] = 676e5c31af7Sopenharmony_ci { 677e5c31af7Sopenharmony_ci glu::TYPE_FLOAT, 678e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC2, 679e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC3, 680e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_VEC4, 681e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT2, 682e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT2X3, 683e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT2X4, 684e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT3X2, 685e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT3, 686e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT3X4, 687e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT4X2, 688e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT4X3, 689e5c31af7Sopenharmony_ci glu::TYPE_FLOAT_MAT4, 690e5c31af7Sopenharmony_ci 691e5c31af7Sopenharmony_ci glu::TYPE_INT, 692e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC2, 693e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC3, 694e5c31af7Sopenharmony_ci glu::TYPE_INT_VEC4, 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci glu::TYPE_UINT, 697e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC2, 698e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC3, 699e5c31af7Sopenharmony_ci glu::TYPE_UINT_VEC4 700e5c31af7Sopenharmony_ci }; 701e5c31af7Sopenharmony_ci 702e5c31af7Sopenharmony_ci const int typeTestNumInstances = 4; 703e5c31af7Sopenharmony_ci 704e5c31af7Sopenharmony_ci TestCaseGroup* typesGroup = new TestCaseGroup(m_context, "types", "Tests for instanced attributes of particular data types"); 705e5c31af7Sopenharmony_ci addChild(typesGroup); 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ci for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_testTypes); typeNdx++) 708e5c31af7Sopenharmony_ci { 709e5c31af7Sopenharmony_ci glu::DataType type = s_testTypes[typeNdx]; 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ci typesGroup->addChild(new InstancedRenderingCase(m_context, glu::getDataTypeName(type), "", 712e5c31af7Sopenharmony_ci InstancedRenderingCase::FUNCTION_DRAW_ARRAYS_INSTANCED, 713e5c31af7Sopenharmony_ci InstancedRenderingCase::TYPE_ATTRIB_DIVISOR, 714e5c31af7Sopenharmony_ci type, 715e5c31af7Sopenharmony_ci typeTestNumInstances)); 716e5c31af7Sopenharmony_ci } 717e5c31af7Sopenharmony_ci} 718e5c31af7Sopenharmony_ci 719e5c31af7Sopenharmony_ci} // Functional 720e5c31af7Sopenharmony_ci} // gles3 721e5c31af7Sopenharmony_ci} // deqp 722