| #ifndef _GLSVERTEXARRAYTESTS_HPP |
| #define _GLSVERTEXARRAYTESTS_HPP |
| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL (ES) Module |
| * ----------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Vertex array and buffer tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuTestCase.hpp" |
| #include "tcuVector.hpp" |
| #include "tcuSurface.hpp" |
| #include "gluRenderContext.hpp" |
| #include "gluCallLogWrapper.hpp" |
| #include "tcuTestLog.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "deFloat16.h" |
| #include "deMath.h" |
| #include "tcuFloat.hpp" |
| #include "tcuPixelFormat.hpp" |
| #include "sglrContext.hpp" |
| |
| namespace sglr |
| { |
| |
| class ReferenceContextBuffers; |
| class ReferenceContext; |
| class Context; |
| |
| } // namespace sglr |
| |
| namespace deqp |
| { |
| namespace gls |
| { |
| |
| class Array |
| { |
| public: |
| enum Target |
| { |
| // \note [mika] Are these actualy used somewhere? |
| TARGET_ELEMENT_ARRAY = 0, |
| TARGET_ARRAY, |
| |
| TARGET_LAST |
| }; |
| |
| enum InputType |
| { |
| INPUTTYPE_FLOAT = 0, |
| INPUTTYPE_FIXED, |
| INPUTTYPE_DOUBLE, |
| |
| INPUTTYPE_BYTE, |
| INPUTTYPE_SHORT, |
| |
| INPUTTYPE_UNSIGNED_BYTE, |
| INPUTTYPE_UNSIGNED_SHORT, |
| |
| INPUTTYPE_INT, |
| INPUTTYPE_UNSIGNED_INT, |
| INPUTTYPE_HALF, |
| INPUTTYPE_UNSIGNED_INT_2_10_10_10, |
| INPUTTYPE_INT_2_10_10_10, |
| |
| INPUTTYPE_LAST |
| }; |
| |
| enum OutputType |
| { |
| OUTPUTTYPE_FLOAT = 0, |
| OUTPUTTYPE_VEC2, |
| OUTPUTTYPE_VEC3, |
| OUTPUTTYPE_VEC4, |
| |
| OUTPUTTYPE_INT, |
| OUTPUTTYPE_UINT, |
| |
| OUTPUTTYPE_IVEC2, |
| OUTPUTTYPE_IVEC3, |
| OUTPUTTYPE_IVEC4, |
| |
| OUTPUTTYPE_UVEC2, |
| OUTPUTTYPE_UVEC3, |
| OUTPUTTYPE_UVEC4, |
| |
| OUTPUTTYPE_LAST |
| }; |
| |
| enum Usage |
| { |
| USAGE_DYNAMIC_DRAW = 0, |
| USAGE_STATIC_DRAW, |
| USAGE_STREAM_DRAW, |
| |
| USAGE_STREAM_READ, |
| USAGE_STREAM_COPY, |
| |
| USAGE_STATIC_READ, |
| USAGE_STATIC_COPY, |
| |
| USAGE_DYNAMIC_READ, |
| USAGE_DYNAMIC_COPY, |
| |
| USAGE_LAST |
| }; |
| |
| enum Storage |
| { |
| STORAGE_USER = 0, |
| STORAGE_BUFFER, |
| |
| STORAGE_LAST |
| }; |
| |
| enum Primitive |
| { |
| PRIMITIVE_POINTS = 0, |
| PRIMITIVE_TRIANGLES, |
| PRIMITIVE_TRIANGLE_FAN, |
| PRIMITIVE_TRIANGLE_STRIP, |
| |
| PRIMITIVE_LAST |
| }; |
| |
| static std::string targetToString(Target target); |
| static std::string inputTypeToString(InputType type); |
| static std::string outputTypeToString(OutputType type); |
| static std::string usageTypeToString(Usage usage); |
| static std::string storageToString(Storage storage); |
| static std::string primitiveToString(Primitive primitive); |
| static int inputTypeSize(InputType type); |
| |
| virtual ~Array(void) |
| { |
| } |
| virtual void data(Target target, int size, const char *data, Usage usage) = 0; |
| virtual void subdata(Target target, int offset, int size, const char *data) = 0; |
| virtual void bind(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, |
| int stride) = 0; |
| virtual void unBind(void) = 0; |
| |
| virtual bool isBound(void) const = 0; |
| virtual int getComponentCount(void) const = 0; |
| virtual Target getTarget(void) const = 0; |
| virtual InputType getInputType(void) const = 0; |
| virtual OutputType getOutputType(void) const = 0; |
| virtual Storage getStorageType(void) const = 0; |
| virtual bool getNormalized(void) const = 0; |
| virtual int getStride(void) const = 0; |
| virtual int getAttribNdx(void) const = 0; |
| virtual void setAttribNdx(int attribNdx) = 0; |
| }; |
| |
| class ContextArray : public Array |
| { |
| public: |
| ContextArray(Storage storage, sglr::Context &context); |
| virtual ~ContextArray(void); |
| virtual void data(Target target, int size, const char *data, Usage usage); |
| virtual void subdata(Target target, int offset, int size, const char *data); |
| virtual void bind(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, |
| int stride); |
| virtual void bindIndexArray(Array::Target storage); |
| virtual void unBind(void) |
| { |
| m_bound = false; |
| } |
| virtual bool isBound(void) const |
| { |
| return m_bound; |
| } |
| |
| virtual int getComponentCount(void) const |
| { |
| return m_componentCount; |
| } |
| virtual Array::Target getTarget(void) const |
| { |
| return m_target; |
| } |
| virtual Array::InputType getInputType(void) const |
| { |
| return m_inputType; |
| } |
| virtual Array::OutputType getOutputType(void) const |
| { |
| return m_outputType; |
| } |
| virtual Array::Storage getStorageType(void) const |
| { |
| return m_storage; |
| } |
| virtual bool getNormalized(void) const |
| { |
| return m_normalize; |
| } |
| virtual int getStride(void) const |
| { |
| return m_stride; |
| } |
| virtual int getAttribNdx(void) const |
| { |
| return m_attribNdx; |
| } |
| virtual void setAttribNdx(int attribNdx) |
| { |
| m_attribNdx = attribNdx; |
| } |
| |
| void glBind(uint32_t loc); |
| static uint32_t targetToGL(Array::Target target); |
| static uint32_t usageToGL(Array::Usage usage); |
| static uint32_t inputTypeToGL(Array::InputType type); |
| static std::string outputTypeToGLType(Array::OutputType type); |
| static uint32_t primitiveToGL(Array::Primitive primitive); |
| |
| private: |
| Storage m_storage; |
| sglr::Context &m_ctx; |
| uint32_t m_glBuffer; |
| |
| bool m_bound; |
| int m_attribNdx; |
| int m_size; |
| char *m_data; |
| int m_componentCount; |
| Array::Target m_target; |
| Array::InputType m_inputType; |
| Array::OutputType m_outputType; |
| bool m_normalize; |
| int m_stride; |
| int m_offset; |
| }; |
| |
| class ContextArrayPack |
| { |
| public: |
| ContextArrayPack(glu::RenderContext &renderCtx, sglr::Context &drawContext); |
| virtual ~ContextArrayPack(void); |
| virtual Array *getArray(int i); |
| virtual int getArrayCount(void); |
| virtual void newArray(Array::Storage storage); |
| virtual void render(Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, |
| float colorScale); |
| |
| const tcu::Surface &getSurface(void) const |
| { |
| return m_screen; |
| } |
| |
| private: |
| void updateProgram(void); |
| glu::RenderContext &m_renderCtx; |
| sglr::Context &m_ctx; |
| |
| std::vector<ContextArray *> m_arrays; |
| sglr::ShaderProgram *m_program; |
| tcu::Surface m_screen; |
| }; |
| |
| class GLValue |
| { |
| public: |
| template <class Type> |
| class WrappedType |
| { |
| public: |
| static WrappedType<Type> create(Type value) |
| { |
| WrappedType<Type> v; |
| v.m_value = value; |
| return v; |
| } |
| static WrappedType<Type> fromFloat(float value) |
| { |
| WrappedType<Type> v; |
| v.m_value = (Type)value; |
| return v; |
| } |
| inline Type getValue(void) const |
| { |
| return m_value; |
| } |
| |
| inline WrappedType<Type> operator+(const WrappedType<Type> &other) const |
| { |
| return WrappedType<Type>::create((Type)(m_value + other.getValue())); |
| } |
| inline WrappedType<Type> operator*(const WrappedType<Type> &other) const |
| { |
| return WrappedType<Type>::create((Type)(m_value * other.getValue())); |
| } |
| inline WrappedType<Type> operator/(const WrappedType<Type> &other) const |
| { |
| return WrappedType<Type>::create((Type)(m_value / other.getValue())); |
| } |
| inline WrappedType<Type> operator%(const WrappedType<Type> &other) const |
| { |
| return WrappedType<Type>::create((Type)(m_value % other.getValue())); |
| } |
| inline WrappedType<Type> operator-(const WrappedType<Type> &other) const |
| { |
| return WrappedType<Type>::create((Type)(m_value - other.getValue())); |
| } |
| |
| inline WrappedType<Type> &operator+=(const WrappedType<Type> &other) |
| { |
| m_value += other.getValue(); |
| return *this; |
| } |
| inline WrappedType<Type> &operator*=(const WrappedType<Type> &other) |
| { |
| m_value *= other.getValue(); |
| return *this; |
| } |
| inline WrappedType<Type> &operator/=(const WrappedType<Type> &other) |
| { |
| m_value /= other.getValue(); |
| return *this; |
| } |
| inline WrappedType<Type> &operator-=(const WrappedType<Type> &other) |
| { |
| m_value -= other.getValue(); |
| return *this; |
| } |
| |
| inline bool operator==(const WrappedType<Type> &other) const |
| { |
| return m_value == other.m_value; |
| } |
| inline bool operator!=(const WrappedType<Type> &other) const |
| { |
| return m_value != other.m_value; |
| } |
| inline bool operator<(const WrappedType<Type> &other) const |
| { |
| return m_value < other.m_value; |
| } |
| inline bool operator>(const WrappedType<Type> &other) const |
| { |
| return m_value > other.m_value; |
| } |
| inline bool operator<=(const WrappedType<Type> &other) const |
| { |
| return m_value <= other.m_value; |
| } |
| inline bool operator>=(const WrappedType<Type> &other) const |
| { |
| return m_value >= other.m_value; |
| } |
| |
| inline operator Type(void) const |
| { |
| return m_value; |
| } |
| template <class T> |
| inline T to(void) const |
| { |
| return (T)m_value; |
| } |
| |
| private: |
| Type m_value; |
| }; |
| |
| template <class Type> |
| class WrappedFloatType |
| { |
| public: |
| static WrappedFloatType<Type> create(Type value) |
| { |
| WrappedFloatType<Type> v; |
| v.m_value = value; |
| return v; |
| } |
| static WrappedFloatType<Type> fromFloat(float value) |
| { |
| WrappedFloatType<Type> v; |
| v.m_value = (Type)value; |
| return v; |
| } |
| inline Type getValue(void) const |
| { |
| return m_value; |
| } |
| |
| inline WrappedFloatType<Type> operator+(const WrappedFloatType<Type> &other) const |
| { |
| return WrappedFloatType<Type>::create((Type)(m_value + other.getValue())); |
| } |
| inline WrappedFloatType<Type> operator*(const WrappedFloatType<Type> &other) const |
| { |
| return WrappedFloatType<Type>::create((Type)(m_value * other.getValue())); |
| } |
| inline WrappedFloatType<Type> operator/(const WrappedFloatType<Type> &other) const |
| { |
| return WrappedFloatType<Type>::create((Type)(m_value / other.getValue())); |
| } |
| inline WrappedFloatType<Type> operator%(const WrappedFloatType<Type> &other) const |
| { |
| return WrappedFloatType<Type>::create((Type)(deMod(m_value, other.getValue()))); |
| } |
| inline WrappedFloatType<Type> operator-(const WrappedFloatType<Type> &other) const |
| { |
| return WrappedFloatType<Type>::create((Type)(m_value - other.getValue())); |
| } |
| |
| inline WrappedFloatType<Type> &operator+=(const WrappedFloatType<Type> &other) |
| { |
| m_value += other.getValue(); |
| return *this; |
| } |
| inline WrappedFloatType<Type> &operator*=(const WrappedFloatType<Type> &other) |
| { |
| m_value *= other.getValue(); |
| return *this; |
| } |
| inline WrappedFloatType<Type> &operator/=(const WrappedFloatType<Type> &other) |
| { |
| m_value /= other.getValue(); |
| return *this; |
| } |
| inline WrappedFloatType<Type> &operator-=(const WrappedFloatType<Type> &other) |
| { |
| m_value -= other.getValue(); |
| return *this; |
| } |
| |
| inline bool operator==(const WrappedFloatType<Type> &other) const |
| { |
| return m_value == other.m_value; |
| } |
| inline bool operator!=(const WrappedFloatType<Type> &other) const |
| { |
| return m_value != other.m_value; |
| } |
| inline bool operator<(const WrappedFloatType<Type> &other) const |
| { |
| return m_value < other.m_value; |
| } |
| inline bool operator>(const WrappedFloatType<Type> &other) const |
| { |
| return m_value > other.m_value; |
| } |
| inline bool operator<=(const WrappedFloatType<Type> &other) const |
| { |
| return m_value <= other.m_value; |
| } |
| inline bool operator>=(const WrappedFloatType<Type> &other) const |
| { |
| return m_value >= other.m_value; |
| } |
| |
| inline operator Type(void) const |
| { |
| return m_value; |
| } |
| template <class T> |
| inline T to(void) const |
| { |
| return (T)m_value; |
| } |
| |
| private: |
| Type m_value; |
| }; |
| |
| typedef WrappedType<int16_t> Short; |
| typedef WrappedType<uint16_t> Ushort; |
| |
| typedef WrappedType<int8_t> Byte; |
| typedef WrappedType<uint8_t> Ubyte; |
| |
| typedef WrappedFloatType<float> Float; |
| typedef WrappedFloatType<double> Double; |
| |
| typedef WrappedType<int32_t> Int; |
| typedef WrappedType<uint32_t> Uint; |
| |
| class Half |
| { |
| public: |
| static Half create(float value) |
| { |
| Half h; |
| h.m_value = floatToHalf(value); |
| return h; |
| } |
| static Half fromFloat(float value) |
| { |
| Half h; |
| h.m_value = floatToHalf(value); |
| return h; |
| } |
| inline deFloat16 getValue(void) const |
| { |
| return m_value; |
| } |
| |
| inline Half operator+(const Half &other) const |
| { |
| return create(halfToFloat(m_value) + halfToFloat(other.getValue())); |
| } |
| inline Half operator*(const Half &other) const |
| { |
| return create(halfToFloat(m_value) * halfToFloat(other.getValue())); |
| } |
| inline Half operator/(const Half &other) const |
| { |
| return create(halfToFloat(m_value) / halfToFloat(other.getValue())); |
| } |
| inline Half operator%(const Half &other) const |
| { |
| return create(deFloatMod(halfToFloat(m_value), halfToFloat(other.getValue()))); |
| } |
| inline Half operator-(const Half &other) const |
| { |
| return create(halfToFloat(m_value) - halfToFloat(other.getValue())); |
| } |
| |
| inline Half &operator+=(const Half &other) |
| { |
| m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); |
| return *this; |
| } |
| inline Half &operator*=(const Half &other) |
| { |
| m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); |
| return *this; |
| } |
| inline Half &operator/=(const Half &other) |
| { |
| m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); |
| return *this; |
| } |
| inline Half &operator-=(const Half &other) |
| { |
| m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); |
| return *this; |
| } |
| |
| inline bool operator==(const Half &other) const |
| { |
| return m_value == other.m_value; |
| } |
| inline bool operator!=(const Half &other) const |
| { |
| return m_value != other.m_value; |
| } |
| inline bool operator<(const Half &other) const |
| { |
| return halfToFloat(m_value) < halfToFloat(other.m_value); |
| } |
| inline bool operator>(const Half &other) const |
| { |
| return halfToFloat(m_value) > halfToFloat(other.m_value); |
| } |
| inline bool operator<=(const Half &other) const |
| { |
| return halfToFloat(m_value) <= halfToFloat(other.m_value); |
| } |
| inline bool operator>=(const Half &other) const |
| { |
| return halfToFloat(m_value) >= halfToFloat(other.m_value); |
| } |
| |
| template <class T> |
| inline T to(void) const |
| { |
| return (T)halfToFloat(m_value); |
| } |
| |
| inline static deFloat16 floatToHalf(float f); |
| inline static float halfToFloat(deFloat16 h); |
| |
| private: |
| deFloat16 m_value; |
| }; |
| |
| class Fixed |
| { |
| public: |
| static Fixed create(int32_t value) |
| { |
| Fixed v; |
| v.m_value = value; |
| return v; |
| } |
| static Fixed fromFloat(float value) |
| { |
| Fixed v; |
| v.m_value = (int32_t)(value * 32768.0f); |
| return v; |
| } |
| inline int32_t getValue(void) const |
| { |
| return m_value; |
| } |
| |
| inline Fixed operator+(const Fixed &other) const |
| { |
| return create(m_value + other.getValue()); |
| } |
| inline Fixed operator*(const Fixed &other) const |
| { |
| return create(m_value * other.getValue()); |
| } |
| inline Fixed operator/(const Fixed &other) const |
| { |
| return create(m_value / other.getValue()); |
| } |
| inline Fixed operator%(const Fixed &other) const |
| { |
| return create(m_value % other.getValue()); |
| } |
| inline Fixed operator-(const Fixed &other) const |
| { |
| return create(m_value - other.getValue()); |
| } |
| |
| inline Fixed &operator+=(const Fixed &other) |
| { |
| m_value += other.getValue(); |
| return *this; |
| } |
| inline Fixed &operator*=(const Fixed &other) |
| { |
| m_value *= other.getValue(); |
| return *this; |
| } |
| inline Fixed &operator/=(const Fixed &other) |
| { |
| m_value /= other.getValue(); |
| return *this; |
| } |
| inline Fixed &operator-=(const Fixed &other) |
| { |
| m_value -= other.getValue(); |
| return *this; |
| } |
| |
| inline bool operator==(const Fixed &other) const |
| { |
| return m_value == other.m_value; |
| } |
| inline bool operator!=(const Fixed &other) const |
| { |
| return m_value != other.m_value; |
| } |
| inline bool operator<(const Fixed &other) const |
| { |
| return m_value < other.m_value; |
| } |
| inline bool operator>(const Fixed &other) const |
| { |
| return m_value > other.m_value; |
| } |
| inline bool operator<=(const Fixed &other) const |
| { |
| return m_value <= other.m_value; |
| } |
| inline bool operator>=(const Fixed &other) const |
| { |
| return m_value >= other.m_value; |
| } |
| |
| inline operator int32_t(void) const |
| { |
| return m_value; |
| } |
| template <class T> |
| inline T to(void) const |
| { |
| return (T)m_value; |
| } |
| |
| private: |
| int32_t m_value; |
| }; |
| |
| // \todo [mika] This is pretty messy |
| GLValue(void) : type(Array::INPUTTYPE_LAST) |
| { |
| } |
| explicit GLValue(Float value) : type(Array::INPUTTYPE_FLOAT), fl(value) |
| { |
| } |
| explicit GLValue(Fixed value) : type(Array::INPUTTYPE_FIXED), fi(value) |
| { |
| } |
| explicit GLValue(Byte value) : type(Array::INPUTTYPE_BYTE), b(value) |
| { |
| } |
| explicit GLValue(Ubyte value) : type(Array::INPUTTYPE_UNSIGNED_BYTE), ub(value) |
| { |
| } |
| explicit GLValue(Short value) : type(Array::INPUTTYPE_SHORT), s(value) |
| { |
| } |
| explicit GLValue(Ushort value) : type(Array::INPUTTYPE_UNSIGNED_SHORT), us(value) |
| { |
| } |
| explicit GLValue(Int value) : type(Array::INPUTTYPE_INT), i(value) |
| { |
| } |
| explicit GLValue(Uint value) : type(Array::INPUTTYPE_UNSIGNED_INT), ui(value) |
| { |
| } |
| explicit GLValue(Half value) : type(Array::INPUTTYPE_HALF), h(value) |
| { |
| } |
| explicit GLValue(Double value) : type(Array::INPUTTYPE_DOUBLE), d(value) |
| { |
| } |
| |
| float toFloat(void) const; |
| |
| static GLValue getMaxValue(Array::InputType type); |
| static GLValue getMinValue(Array::InputType type); |
| |
| Array::InputType type; |
| |
| union |
| { |
| Float fl; |
| Fixed fi; |
| Double d; |
| Byte b; |
| Ubyte ub; |
| Short s; |
| Ushort us; |
| Int i; |
| Uint ui; |
| Half h; |
| }; |
| }; |
| |
| class VertexArrayTest : public tcu::TestCase |
| { |
| public: |
| VertexArrayTest(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const char *name, const char *desc); |
| virtual ~VertexArrayTest(void); |
| virtual void init(void); |
| virtual void deinit(void); |
| |
| protected: |
| VertexArrayTest(const VertexArrayTest &other); |
| VertexArrayTest &operator=(const VertexArrayTest &other); |
| |
| void compare(void); |
| |
| glu::RenderContext &m_renderCtx; |
| |
| sglr::ReferenceContextBuffers *m_refBuffers; |
| sglr::ReferenceContext *m_refContext; |
| sglr::Context *m_glesContext; |
| |
| ContextArrayPack *m_glArrayPack; |
| ContextArrayPack *m_rrArrayPack; |
| bool m_isOk; |
| |
| int m_maxDiffRed; |
| int m_maxDiffGreen; |
| int m_maxDiffBlue; |
| }; |
| |
| class MultiVertexArrayTest : public VertexArrayTest |
| { |
| public: |
| class Spec |
| { |
| public: |
| class ArraySpec |
| { |
| public: |
| 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); |
| |
| Array::InputType inputType; |
| Array::OutputType outputType; |
| Array::Storage storage; |
| Array::Usage usage; |
| int componentCount; |
| int offset; |
| int stride; |
| bool normalize; |
| GLValue min; |
| GLValue max; |
| }; |
| |
| std::string getName(void) const; |
| std::string getDesc(void) const; |
| |
| Array::Primitive primitive; |
| int drawCount; //!<Number of primitives to draw |
| int first; |
| |
| std::vector<ArraySpec> arrays; |
| }; |
| |
| MultiVertexArrayTest(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const Spec &spec, const char *name, |
| const char *desc); |
| virtual ~MultiVertexArrayTest(void); |
| virtual IterateResult iterate(void); |
| |
| private: |
| bool isUnalignedBufferOffsetTest(void) const; |
| bool isUnalignedBufferStrideTest(void) const; |
| |
| Spec m_spec; |
| int m_iteration; |
| }; |
| |
| inline deFloat16 GLValue::Half::floatToHalf(float f) |
| { |
| // No denorm support. |
| tcu::Float<uint16_t, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f); |
| DE_ASSERT(!v.isNaN() && !v.isInf()); |
| return v.bits(); |
| } |
| |
| inline float GLValue::Half::halfToFloat(deFloat16 h) |
| { |
| return tcu::Float16((uint16_t)h).asFloat(); |
| } |
| |
| } // namespace gls |
| } // namespace deqp |
| |
| #endif // _GLSVERTEXARRAYTESTS_HPP |