1#ifndef _GLSVERTEXARRAYTESTS_HPP 2#define _GLSVERTEXARRAYTESTS_HPP 3/*------------------------------------------------------------------------- 4 * drawElements Quality Program OpenGL (ES) Module 5 * ----------------------------------------------- 6 * 7 * Copyright 2014 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Vertex array and buffer tests 24 *//*--------------------------------------------------------------------*/ 25 26#include "tcuTestCase.hpp" 27#include "tcuVector.hpp" 28#include "tcuSurface.hpp" 29#include "gluRenderContext.hpp" 30#include "gluCallLogWrapper.hpp" 31#include "tcuTestLog.hpp" 32#include "gluShaderProgram.hpp" 33#include "deFloat16.h" 34#include "deMath.h" 35#include "tcuFloat.hpp" 36#include "tcuPixelFormat.hpp" 37#include "sglrContext.hpp" 38 39namespace sglr 40{ 41 42class ReferenceContextBuffers; 43class ReferenceContext; 44class Context; 45 46} // sglr 47 48namespace deqp 49{ 50namespace gls 51{ 52 53class Array 54{ 55public: 56 enum Target 57 { 58 // \note [mika] Are these actualy used somewhere? 59 TARGET_ELEMENT_ARRAY = 0, 60 TARGET_ARRAY, 61 62 TARGET_LAST 63 }; 64 65 enum InputType 66 { 67 INPUTTYPE_FLOAT = 0, 68 INPUTTYPE_FIXED, 69 INPUTTYPE_DOUBLE, 70 71 INPUTTYPE_BYTE, 72 INPUTTYPE_SHORT, 73 74 INPUTTYPE_UNSIGNED_BYTE, 75 INPUTTYPE_UNSIGNED_SHORT, 76 77 INPUTTYPE_INT, 78 INPUTTYPE_UNSIGNED_INT, 79 INPUTTYPE_HALF, 80 INPUTTYPE_UNSIGNED_INT_2_10_10_10, 81 INPUTTYPE_INT_2_10_10_10, 82 83 INPUTTYPE_LAST 84 }; 85 86 enum OutputType 87 { 88 OUTPUTTYPE_FLOAT = 0, 89 OUTPUTTYPE_VEC2, 90 OUTPUTTYPE_VEC3, 91 OUTPUTTYPE_VEC4, 92 93 OUTPUTTYPE_INT, 94 OUTPUTTYPE_UINT, 95 96 OUTPUTTYPE_IVEC2, 97 OUTPUTTYPE_IVEC3, 98 OUTPUTTYPE_IVEC4, 99 100 OUTPUTTYPE_UVEC2, 101 OUTPUTTYPE_UVEC3, 102 OUTPUTTYPE_UVEC4, 103 104 OUTPUTTYPE_LAST 105 }; 106 107 enum Usage 108 { 109 USAGE_DYNAMIC_DRAW = 0, 110 USAGE_STATIC_DRAW, 111 USAGE_STREAM_DRAW, 112 113 USAGE_STREAM_READ, 114 USAGE_STREAM_COPY, 115 116 USAGE_STATIC_READ, 117 USAGE_STATIC_COPY, 118 119 USAGE_DYNAMIC_READ, 120 USAGE_DYNAMIC_COPY, 121 122 USAGE_LAST 123 }; 124 125 enum Storage 126 { 127 STORAGE_USER = 0, 128 STORAGE_BUFFER, 129 130 STORAGE_LAST 131 }; 132 133 enum Primitive 134 { 135 PRIMITIVE_POINTS = 0, 136 PRIMITIVE_TRIANGLES, 137 PRIMITIVE_TRIANGLE_FAN, 138 PRIMITIVE_TRIANGLE_STRIP, 139 140 PRIMITIVE_LAST 141 }; 142 143 static std::string targetToString (Target target); 144 static std::string inputTypeToString (InputType type); 145 static std::string outputTypeToString (OutputType type); 146 static std::string usageTypeToString (Usage usage); 147 static std::string storageToString (Storage storage); 148 static std::string primitiveToString (Primitive primitive); 149 static int inputTypeSize (InputType type); 150 151 virtual ~Array (void) {} 152 virtual void data (Target target, int size, const char* data, Usage usage) = 0; 153 virtual void subdata (Target target, int offset, int size, const char* data) = 0; 154 virtual void bind (int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride) = 0; 155 virtual void unBind (void) = 0; 156 157 virtual bool isBound (void) const = 0; 158 virtual int getComponentCount (void) const = 0; 159 virtual Target getTarget (void) const = 0; 160 virtual InputType getInputType (void) const = 0; 161 virtual OutputType getOutputType (void) const = 0; 162 virtual Storage getStorageType (void) const = 0; 163 virtual bool getNormalized (void) const = 0; 164 virtual int getStride (void) const = 0; 165 virtual int getAttribNdx (void) const = 0; 166 virtual void setAttribNdx (int attribNdx) = 0; 167}; 168 169class ContextArray : public Array 170{ 171public: 172 ContextArray (Storage storage, sglr::Context& context); 173 virtual ~ContextArray (void); 174 virtual void data (Target target, int size, const char* data, Usage usage); 175 virtual void subdata (Target target, int offset, int size, const char* data); 176 virtual void bind (int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride); 177 virtual void bindIndexArray (Array::Target storage); 178 virtual void unBind (void) { m_bound = false; } 179 virtual bool isBound (void) const { return m_bound; } 180 181 virtual int getComponentCount (void) const { return m_componentCount; } 182 virtual Array::Target getTarget (void) const { return m_target; } 183 virtual Array::InputType getInputType (void) const { return m_inputType; } 184 virtual Array::OutputType getOutputType (void) const { return m_outputType; } 185 virtual Array::Storage getStorageType (void) const { return m_storage; } 186 virtual bool getNormalized (void) const { return m_normalize; } 187 virtual int getStride (void) const { return m_stride; } 188 virtual int getAttribNdx (void) const { return m_attribNdx; } 189 virtual void setAttribNdx (int attribNdx) { m_attribNdx = attribNdx; } 190 191 void glBind (deUint32 loc); 192 static deUint32 targetToGL (Array::Target target); 193 static deUint32 usageToGL (Array::Usage usage); 194 static deUint32 inputTypeToGL (Array::InputType type); 195 static std::string outputTypeToGLType (Array::OutputType type); 196 static deUint32 primitiveToGL (Array::Primitive primitive); 197 198private: 199 Storage m_storage; 200 sglr::Context& m_ctx; 201 deUint32 m_glBuffer; 202 203 bool m_bound; 204 int m_attribNdx; 205 int m_size; 206 char* m_data; 207 int m_componentCount; 208 Array::Target m_target; 209 Array::InputType m_inputType; 210 Array::OutputType m_outputType; 211 bool m_normalize; 212 int m_stride; 213 int m_offset; 214}; 215 216class ContextArrayPack 217{ 218public: 219 ContextArrayPack (glu::RenderContext& renderCtx, sglr::Context& drawContext); 220 virtual ~ContextArrayPack (void); 221 virtual Array* getArray (int i); 222 virtual int getArrayCount (void); 223 virtual void newArray (Array::Storage storage); 224 virtual void render (Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale); 225 226 const tcu::Surface& getSurface (void) const { return m_screen; } 227private: 228 void updateProgram (void); 229 glu::RenderContext& m_renderCtx; 230 sglr::Context& m_ctx; 231 232 std::vector<ContextArray*> m_arrays; 233 sglr::ShaderProgram* m_program; 234 tcu::Surface m_screen; 235}; 236 237class GLValue 238{ 239public: 240 template<class Type> 241 class WrappedType 242 { 243 public: 244 static WrappedType<Type> create (Type value) { WrappedType<Type> v; v.m_value = value; return v; } 245 static WrappedType<Type> fromFloat (float value) { WrappedType<Type> v; v.m_value = (Type)value; return v; } 246 inline Type getValue (void) const { return m_value; } 247 248 inline WrappedType<Type> operator+ (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value + other.getValue())); } 249 inline WrappedType<Type> operator* (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value * other.getValue())); } 250 inline WrappedType<Type> operator/ (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value / other.getValue())); } 251 inline WrappedType<Type> operator% (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value % other.getValue())); } 252 inline WrappedType<Type> operator- (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value - other.getValue())); } 253 254 inline WrappedType<Type>& operator+= (const WrappedType<Type>& other) { m_value += other.getValue(); return *this; } 255 inline WrappedType<Type>& operator*= (const WrappedType<Type>& other) { m_value *= other.getValue(); return *this; } 256 inline WrappedType<Type>& operator/= (const WrappedType<Type>& other) { m_value /= other.getValue(); return *this; } 257 inline WrappedType<Type>& operator-= (const WrappedType<Type>& other) { m_value -= other.getValue(); return *this; } 258 259 inline bool operator== (const WrappedType<Type>& other) const { return m_value == other.m_value; } 260 inline bool operator!= (const WrappedType<Type>& other) const { return m_value != other.m_value; } 261 inline bool operator< (const WrappedType<Type>& other) const { return m_value < other.m_value; } 262 inline bool operator> (const WrappedType<Type>& other) const { return m_value > other.m_value; } 263 inline bool operator<= (const WrappedType<Type>& other) const { return m_value <= other.m_value; } 264 inline bool operator>= (const WrappedType<Type>& other) const { return m_value >= other.m_value; } 265 266 inline operator Type (void) const { return m_value; } 267 template<class T> 268 inline T to (void) const { return (T)m_value; } 269 private: 270 Type m_value; 271 }; 272 273 template<class Type> 274 class WrappedFloatType 275 { 276 public: 277 static WrappedFloatType<Type> create (Type value) { WrappedFloatType<Type> v; v.m_value = value; return v; } 278 static WrappedFloatType<Type> fromFloat (float value) { WrappedFloatType<Type> v; v.m_value = (Type)value; return v; } 279 inline Type getValue (void) const { return m_value; } 280 281 inline WrappedFloatType<Type> operator+ (const WrappedFloatType<Type>& other) const { return WrappedFloatType<Type>::create((Type)(m_value + other.getValue())); } 282 inline WrappedFloatType<Type> operator* (const WrappedFloatType<Type>& other) const { return WrappedFloatType<Type>::create((Type)(m_value * other.getValue())); } 283 inline WrappedFloatType<Type> operator/ (const WrappedFloatType<Type>& other) const { return WrappedFloatType<Type>::create((Type)(m_value / other.getValue())); } 284 inline WrappedFloatType<Type> operator% (const WrappedFloatType<Type>& other) const { return WrappedFloatType<Type>::create((Type)(deMod(m_value, other.getValue()))); } 285 inline WrappedFloatType<Type> operator- (const WrappedFloatType<Type>& other) const { return WrappedFloatType<Type>::create((Type)(m_value - other.getValue())); } 286 287 inline WrappedFloatType<Type>& operator+= (const WrappedFloatType<Type>& other) { m_value += other.getValue(); return *this; } 288 inline WrappedFloatType<Type>& operator*= (const WrappedFloatType<Type>& other) { m_value *= other.getValue(); return *this; } 289 inline WrappedFloatType<Type>& operator/= (const WrappedFloatType<Type>& other) { m_value /= other.getValue(); return *this; } 290 inline WrappedFloatType<Type>& operator-= (const WrappedFloatType<Type>& other) { m_value -= other.getValue(); return *this; } 291 292 inline bool operator== (const WrappedFloatType<Type>& other) const { return m_value == other.m_value; } 293 inline bool operator!= (const WrappedFloatType<Type>& other) const { return m_value != other.m_value; } 294 inline bool operator< (const WrappedFloatType<Type>& other) const { return m_value < other.m_value; } 295 inline bool operator> (const WrappedFloatType<Type>& other) const { return m_value > other.m_value; } 296 inline bool operator<= (const WrappedFloatType<Type>& other) const { return m_value <= other.m_value; } 297 inline bool operator>= (const WrappedFloatType<Type>& other) const { return m_value >= other.m_value; } 298 299 inline operator Type (void) const { return m_value; } 300 template<class T> 301 inline T to (void) const { return (T)m_value; } 302 private: 303 Type m_value; 304 }; 305 306 typedef WrappedType<deInt16> Short; 307 typedef WrappedType<deUint16> Ushort; 308 309 typedef WrappedType<deInt8> Byte; 310 typedef WrappedType<deUint8> Ubyte; 311 312 typedef WrappedFloatType<float> Float; 313 typedef WrappedFloatType<double> Double; 314 315 typedef WrappedType<deInt32> Int; 316 typedef WrappedType<deUint32> Uint; 317 318 class Half 319 { 320 public: 321 static Half create (float value) { Half h; h.m_value = floatToHalf(value); return h; } 322 static Half fromFloat (float value) { Half h; h.m_value = floatToHalf(value); return h; } 323 inline deFloat16 getValue (void) const { return m_value; } 324 325 inline Half operator+ (const Half& other) const { return create(halfToFloat(m_value) + halfToFloat(other.getValue())); } 326 inline Half operator* (const Half& other) const { return create(halfToFloat(m_value) * halfToFloat(other.getValue())); } 327 inline Half operator/ (const Half& other) const { return create(halfToFloat(m_value) / halfToFloat(other.getValue())); } 328 inline Half operator% (const Half& other) const { return create(deFloatMod(halfToFloat(m_value), halfToFloat(other.getValue()))); } 329 inline Half operator- (const Half& other) const { return create(halfToFloat(m_value) - halfToFloat(other.getValue())); } 330 331 inline Half& operator+= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; } 332 inline Half& operator*= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; } 333 inline Half& operator/= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; } 334 inline Half& operator-= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; } 335 336 inline bool operator== (const Half& other) const { return m_value == other.m_value; } 337 inline bool operator!= (const Half& other) const { return m_value != other.m_value; } 338 inline bool operator< (const Half& other) const { return halfToFloat(m_value) < halfToFloat(other.m_value); } 339 inline bool operator> (const Half& other) const { return halfToFloat(m_value) > halfToFloat(other.m_value); } 340 inline bool operator<= (const Half& other) const { return halfToFloat(m_value) <= halfToFloat(other.m_value); } 341 inline bool operator>= (const Half& other) const { return halfToFloat(m_value) >= halfToFloat(other.m_value); } 342 343 template<class T> 344 inline T to (void) const { return (T)halfToFloat(m_value); } 345 346 inline static deFloat16 floatToHalf (float f); 347 inline static float halfToFloat (deFloat16 h); 348 private: 349 deFloat16 m_value; 350 }; 351 352 class Fixed 353 { 354 public: 355 static Fixed create (deInt32 value) { Fixed v; v.m_value = value; return v; } 356 static Fixed fromFloat (float value) { Fixed v; v.m_value = (deInt32)(value * 32768.0f); return v; } 357 inline deInt32 getValue (void) const { return m_value; } 358 359 inline Fixed operator+ (const Fixed& other) const { return create(m_value + other.getValue()); } 360 inline Fixed operator* (const Fixed& other) const { return create(m_value * other.getValue()); } 361 inline Fixed operator/ (const Fixed& other) const { return create(m_value / other.getValue()); } 362 inline Fixed operator% (const Fixed& other) const { return create(m_value % other.getValue()); } 363 inline Fixed operator- (const Fixed& other) const { return create(m_value - other.getValue()); } 364 365 inline Fixed& operator+= (const Fixed& other) { m_value += other.getValue(); return *this; } 366 inline Fixed& operator*= (const Fixed& other) { m_value *= other.getValue(); return *this; } 367 inline Fixed& operator/= (const Fixed& other) { m_value /= other.getValue(); return *this; } 368 inline Fixed& operator-= (const Fixed& other) { m_value -= other.getValue(); return *this; } 369 370 inline bool operator== (const Fixed& other) const { return m_value == other.m_value; } 371 inline bool operator!= (const Fixed& other) const { return m_value != other.m_value; } 372 inline bool operator< (const Fixed& other) const { return m_value < other.m_value; } 373 inline bool operator> (const Fixed& other) const { return m_value > other.m_value; } 374 inline bool operator<= (const Fixed& other) const { return m_value <= other.m_value; } 375 inline bool operator>= (const Fixed& other) const { return m_value >= other.m_value; } 376 377 inline operator deInt32 (void) const { return m_value; } 378 template<class T> 379 inline T to (void) const { return (T)m_value; } 380 private: 381 deInt32 m_value; 382 }; 383 384 // \todo [mika] This is pretty messy 385 GLValue (void) : type(Array::INPUTTYPE_LAST) {} 386 explicit GLValue (Float value) : type(Array::INPUTTYPE_FLOAT), fl(value) {} 387 explicit GLValue (Fixed value) : type(Array::INPUTTYPE_FIXED), fi(value) {} 388 explicit GLValue (Byte value) : type(Array::INPUTTYPE_BYTE), b(value) {} 389 explicit GLValue (Ubyte value) : type(Array::INPUTTYPE_UNSIGNED_BYTE), ub(value) {} 390 explicit GLValue (Short value) : type(Array::INPUTTYPE_SHORT), s(value) {} 391 explicit GLValue (Ushort value) : type(Array::INPUTTYPE_UNSIGNED_SHORT), us(value) {} 392 explicit GLValue (Int value) : type(Array::INPUTTYPE_INT), i(value) {} 393 explicit GLValue (Uint value) : type(Array::INPUTTYPE_UNSIGNED_INT), ui(value) {} 394 explicit GLValue (Half value) : type(Array::INPUTTYPE_HALF), h(value) {} 395 explicit GLValue (Double value) : type(Array::INPUTTYPE_DOUBLE), d(value) {} 396 397 float toFloat (void) const; 398 399 static GLValue getMaxValue (Array::InputType type); 400 static GLValue getMinValue (Array::InputType type); 401 402 Array::InputType type; 403 404 union 405 { 406 Float fl; 407 Fixed fi; 408 Double d; 409 Byte b; 410 Ubyte ub; 411 Short s; 412 Ushort us; 413 Int i; 414 Uint ui; 415 Half h; 416 }; 417}; 418 419class VertexArrayTest : public tcu::TestCase 420{ 421public: 422 VertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc); 423 virtual ~VertexArrayTest (void); 424 virtual void init (void); 425 virtual void deinit (void); 426 427protected: 428 VertexArrayTest (const VertexArrayTest& other); 429 VertexArrayTest& operator= (const VertexArrayTest& other); 430 431 void compare (void); 432 433 glu::RenderContext& m_renderCtx; 434 435 sglr::ReferenceContextBuffers* m_refBuffers; 436 sglr::ReferenceContext* m_refContext; 437 sglr::Context* m_glesContext; 438 439 ContextArrayPack* m_glArrayPack; 440 ContextArrayPack* m_rrArrayPack; 441 bool m_isOk; 442 443 int m_maxDiffRed; 444 int m_maxDiffGreen; 445 int m_maxDiffBlue; 446}; 447 448class MultiVertexArrayTest : public VertexArrayTest 449{ 450public: 451 class Spec 452 { 453 public: 454 class ArraySpec 455 { 456 public: 457 ArraySpec (Array::InputType inputType, Array::OutputType outputType, Array::Storage storage, Array::Usage usage, int componetCount, int offset, int stride, bool normalize, GLValue min, GLValue max); 458 459 Array::InputType inputType; 460 Array::OutputType outputType; 461 Array::Storage storage; 462 Array::Usage usage; 463 int componentCount; 464 int offset; 465 int stride; 466 bool normalize; 467 GLValue min; 468 GLValue max; 469 }; 470 471 std::string getName (void) const; 472 std::string getDesc (void) const; 473 474 Array::Primitive primitive; 475 int drawCount; //!<Number of primitives to draw 476 int first; 477 478 std::vector<ArraySpec> arrays; 479 }; 480 481 MultiVertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc); 482 virtual ~MultiVertexArrayTest (void); 483 virtual IterateResult iterate (void); 484 485private: 486 bool isUnalignedBufferOffsetTest (void) const; 487 bool isUnalignedBufferStrideTest (void) const; 488 489 Spec m_spec; 490 int m_iteration; 491}; 492 493inline deFloat16 GLValue::Half::floatToHalf (float f) 494{ 495 // No denorm support. 496 tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f); 497 DE_ASSERT(!v.isNaN() && !v.isInf()); 498 return v.bits(); 499} 500 501inline float GLValue::Half::halfToFloat (deFloat16 h) 502{ 503 return tcu::Float16((deUint16)h).asFloat(); 504} 505 506} // gls 507} // deqp 508 509#endif // _GLSVERTEXARRAYTESTS_HPP 510