blob: e74e3fc96a104e53669b5f71c100612a39264fb0 [file] [log] [blame]
#ifndef _GLCUNIFORMBLOCKCASE_HPP
#define _GLCUNIFORMBLOCKCASE_HPP
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2016 Google Inc.
* Copyright (c) 2016 The Khronos Group Inc.
*
* 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 Uniform block tests.
*/ /*-------------------------------------------------------------------*/
#include "glcTestCase.hpp"
#include "gluShaderProgram.hpp"
#include "gluShaderUtil.hpp"
#include "tcuDefs.hpp"
namespace deqp
{
// Uniform block details.
namespace ub
{
enum UniformFlags
{
PRECISION_LOW = (1 << 0),
PRECISION_MEDIUM = (1 << 1),
PRECISION_HIGH = (1 << 2),
PRECISION_MASK = PRECISION_LOW | PRECISION_MEDIUM | PRECISION_HIGH,
LAYOUT_SHARED = (1 << 3),
LAYOUT_PACKED = (1 << 4),
LAYOUT_STD140 = (1 << 5),
LAYOUT_ROW_MAJOR = (1 << 6),
LAYOUT_COLUMN_MAJOR = (1 << 7), //!< \note Lack of both flags means column-major matrix.
LAYOUT_MASK = LAYOUT_SHARED | LAYOUT_PACKED | LAYOUT_STD140 | LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR,
DECLARE_VERTEX = (1 << 8),
DECLARE_FRAGMENT = (1 << 9),
DECLARE_BOTH = DECLARE_VERTEX | DECLARE_FRAGMENT,
UNUSED_VERTEX = (1 << 10), //!< Uniform or struct member is not read in vertex shader.
UNUSED_FRAGMENT = (1 << 11), //!< Uniform or struct member is not read in fragment shader.
UNUSED_BOTH = UNUSED_VERTEX | UNUSED_FRAGMENT
};
// \todo [2012-07-25 pyry] Use glu::VarType.
class StructType;
class VarType
{
public:
VarType(void);
VarType(const VarType& other);
VarType(glu::DataType basicType, deUint32 flags);
VarType(const VarType& elementType, int arraySize);
explicit VarType(const StructType* structPtr);
~VarType(void);
bool isBasicType(void) const
{
return m_type == TYPE_BASIC;
}
bool isArrayType(void) const
{
return m_type == TYPE_ARRAY;
}
bool isStructType(void) const
{
return m_type == TYPE_STRUCT;
}
deUint32 getFlags(void) const
{
return m_flags;
}
glu::DataType getBasicType(void) const
{
return m_data.basicType;
}
const VarType& getElementType(void) const
{
return *m_data.array.elementType;
}
int getArraySize(void) const
{
return m_data.array.size;
}
const StructType& getStruct(void) const
{
return *m_data.structPtr;
}
VarType& operator=(const VarType& other);
private:
enum Type
{
TYPE_BASIC,
TYPE_ARRAY,
TYPE_STRUCT,
TYPE_LAST
};
Type m_type;
deUint32 m_flags;
union Data {
glu::DataType basicType;
struct
{
VarType* elementType;
int size;
} array;
const StructType* structPtr;
Data(void)
{
array.elementType = DE_NULL;
array.size = 0;
};
} m_data;
};
class StructMember
{
public:
StructMember(const char* name, const VarType& type, deUint32 flags) : m_name(name), m_type(type), m_flags(flags)
{
}
StructMember(void) : m_flags(0)
{
}
const char* getName(void) const
{
return m_name.c_str();
}
const VarType& getType(void) const
{
return m_type;
}
deUint32 getFlags(void) const
{
return m_flags;
}
private:
std::string m_name;
VarType m_type;
deUint32 m_flags;
};
class StructType
{
public:
typedef std::vector<StructMember>::iterator Iterator;
typedef std::vector<StructMember>::const_iterator ConstIterator;
StructType(const char* typeName) : m_typeName(typeName)
{
}
~StructType(void)
{
}
const char* getTypeName(void) const
{
return m_typeName.empty() ? DE_NULL : m_typeName.c_str();
}
inline Iterator begin(void)
{
return m_members.begin();
}
inline ConstIterator begin(void) const
{
return m_members.begin();
}
inline Iterator end(void)
{
return m_members.end();
}
inline ConstIterator end(void) const
{
return m_members.end();
}
void addMember(const char* name, const VarType& type, deUint32 flags = 0);
private:
std::string m_typeName;
std::vector<StructMember> m_members;
};
class Uniform
{
public:
Uniform(const char* name, const VarType& type, deUint32 flags = 0);
const char* getName(void) const
{
return m_name.c_str();
}
const VarType& getType(void) const
{
return m_type;
}
deUint32 getFlags(void) const
{
return m_flags;
}
private:
std::string m_name;
VarType m_type;
deUint32 m_flags;
};
class UniformBlock
{
public:
typedef std::vector<Uniform>::iterator Iterator;
typedef std::vector<Uniform>::const_iterator ConstIterator;
UniformBlock(const char* blockName);
const char* getBlockName(void) const
{
return m_blockName.c_str();
}
const char* getInstanceName(void) const
{
return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str();
}
bool isArray(void) const
{
return m_arraySize > 0;
}
int getArraySize(void) const
{
return m_arraySize;
}
deUint32 getFlags(void) const
{
return m_flags;
}
void setInstanceName(const char* name)
{
m_instanceName = name;
}
void setFlags(deUint32 flags)
{
m_flags = flags;
}
void setArraySize(int arraySize)
{
m_arraySize = arraySize;
}
void addUniform(const Uniform& uniform)
{
m_uniforms.push_back(uniform);
}
inline Iterator begin(void)
{
return m_uniforms.begin();
}
inline ConstIterator begin(void) const
{
return m_uniforms.begin();
}
inline Iterator end(void)
{
return m_uniforms.end();
}
inline ConstIterator end(void) const
{
return m_uniforms.end();
}
private:
std::string m_blockName;
std::string m_instanceName;
std::vector<Uniform> m_uniforms;
int m_arraySize; //!< Array size or 0 if not interface block array.
deUint32 m_flags;
};
class ShaderInterface
{
public:
ShaderInterface(void);
~ShaderInterface(void);
StructType& allocStruct(const char* name);
const StructType* findStruct(const char* name) const;
void getNamedStructs(std::vector<const StructType*>& structs) const;
UniformBlock& allocBlock(const char* name);
int getNumUniformBlocks(void) const
{
return (int)m_uniformBlocks.size();
}
const UniformBlock& getUniformBlock(int ndx) const
{
return *m_uniformBlocks[ndx];
}
private:
std::vector<StructType*> m_structs;
std::vector<UniformBlock*> m_uniformBlocks;
};
class UniformLayout;
} // ub
class UniformBlockCase : public TestCase
{
public:
enum BufferMode
{
BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks.
BUFFERMODE_PER_BLOCK, //!< Per-block buffers
BUFFERMODE_LAST
};
UniformBlockCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
BufferMode bufferMode);
~UniformBlockCase(void);
IterateResult iterate(void);
protected:
bool compareStd140Blocks(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
bool compareSharedBlocks(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
bool compareTypes(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
bool checkLayoutIndices(const ub::UniformLayout& layout) const;
bool checkLayoutBounds(const ub::UniformLayout& layout) const;
bool checkIndexQueries(deUint32 program, const ub::UniformLayout& layout) const;
bool render(glu::ShaderProgram& program) const;
glu::GLSLVersion m_glslVersion;
BufferMode m_bufferMode;
ub::ShaderInterface m_interface;
};
} // deqp
#endif // _GLCUNIFORMBLOCKCASE_HPP