Home | History | Annotate | Download | only in ubo
      1 #ifndef _VKTUNIFORMBLOCKCASE_HPP
      2 #define _VKTUNIFORMBLOCKCASE_HPP
      3 /*------------------------------------------------------------------------
      4  * Vulkan Conformance Tests
      5  * ------------------------
      6  *
      7  * Copyright (c) 2015 The Khronos Group Inc.
      8  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
      9  *
     10  * Licensed under the Apache License, Version 2.0 (the "License");
     11  * you may not use this file except in compliance with the License.
     12  * You may obtain a copy of the License at
     13  *
     14  *      http://www.apache.org/licenses/LICENSE-2.0
     15  *
     16  * Unless required by applicable law or agreed to in writing, software
     17  * distributed under the License is distributed on an "AS IS" BASIS,
     18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     19  * See the License for the specific language governing permissions and
     20  * limitations under the License.
     21  *
     22  *//*!
     23  * \file
     24  * \brief Uniform block tests.
     25  *//*--------------------------------------------------------------------*/
     26 
     27 #include "deSharedPtr.hpp"
     28 #include "vktTestCase.hpp"
     29 #include "tcuDefs.hpp"
     30 #include "gluShaderUtil.hpp"
     31 
     32 #include <map>
     33 
     34 namespace vkt
     35 {
     36 namespace ubo
     37 {
     38 
     39 // Uniform block details.
     40 
     41 enum UniformFlags
     42 {
     43 	PRECISION_LOW		= (1<<0),
     44 	PRECISION_MEDIUM	= (1<<1),
     45 	PRECISION_HIGH		= (1<<2),
     46 	PRECISION_MASK		= PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH,
     47 
     48 	LAYOUT_SHARED		= (1<<3),
     49 	LAYOUT_PACKED		= (1<<4),
     50 	LAYOUT_STD140		= (1<<5),
     51 	LAYOUT_ROW_MAJOR	= (1<<6),
     52 	LAYOUT_COLUMN_MAJOR	= (1<<7),	//!< \note Lack of both flags means column-major matrix.
     53 	LAYOUT_OFFSET		= (1<<8),
     54 	LAYOUT_STD430		= (1<<9),
     55 	LAYOUT_SCALAR		= (1<<10),
     56 	LAYOUT_MASK			= LAYOUT_SHARED|LAYOUT_PACKED|LAYOUT_STD140|LAYOUT_STD430|LAYOUT_SCALAR|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR|LAYOUT_OFFSET,
     57 
     58 	DECLARE_VERTEX		= (1<<11),
     59 	DECLARE_FRAGMENT	= (1<<12),
     60 	DECLARE_BOTH		= DECLARE_VERTEX|DECLARE_FRAGMENT,
     61 
     62 	UNUSED_VERTEX		= (1<<13),	//!< Uniform or struct member is not read in vertex shader.
     63 	UNUSED_FRAGMENT		= (1<<14),	//!< Uniform or struct member is not read in fragment shader.
     64 	UNUSED_BOTH			= UNUSED_VERTEX|UNUSED_FRAGMENT,
     65 
     66 	LAYOUT_16BIT_STORAGE= (1<<15),  //!< Support VK_KHR_16bit_storage extension
     67 	LAYOUT_8BIT_STORAGE	= (1<<16),  //!< Support VK_KHR_8bit_storage extension
     68 };
     69 
     70 enum MatrixLoadFlags
     71 {
     72 	LOAD_FULL_MATRIX		= 0,
     73 	LOAD_MATRIX_COMPONENTS	= 1,
     74 };
     75 
     76 class StructType;
     77 
     78 class VarType
     79 {
     80 public:
     81 						VarType			(void);
     82 						VarType			(const VarType& other);
     83 						VarType			(glu::DataType basicType, deUint32 flags);
     84 						VarType			(const VarType& elementType, int arraySize);
     85 	explicit			VarType			(const StructType* structPtr, deUint32 flags = 0u);
     86 						~VarType		(void);
     87 
     88 	bool				isBasicType		(void) const	{ return m_type == TYPE_BASIC;	}
     89 	bool				isArrayType		(void) const	{ return m_type == TYPE_ARRAY;	}
     90 	bool				isStructType	(void) const	{ return m_type == TYPE_STRUCT;	}
     91 
     92 	deUint32			getFlags		(void) const	{ return m_flags;					}
     93 	glu::DataType		getBasicType	(void) const	{ return m_data.basicType;			}
     94 
     95 	const VarType&		getElementType	(void) const	{ return *m_data.array.elementType;	}
     96 	int					getArraySize	(void) const	{ return m_data.array.size;			}
     97 
     98 	const StructType&	getStruct		(void) const	{ return *m_data.structPtr;			}
     99 	const StructType*	getStructPtr	(void) const	{ DE_ASSERT(isStructType()); return m_data.structPtr;			}
    100 
    101 	VarType&			operator=		(const VarType& other);
    102 
    103 private:
    104 	enum Type
    105 	{
    106 		TYPE_BASIC,
    107 		TYPE_ARRAY,
    108 		TYPE_STRUCT,
    109 
    110 		TYPE_LAST
    111 	};
    112 
    113 	Type				m_type;
    114 	deUint32			m_flags;
    115 	union Data
    116 	{
    117 		glu::DataType		basicType;
    118 		struct
    119 		{
    120 			VarType*		elementType;
    121 			int				size;
    122 		} array;
    123 		const StructType*	structPtr;
    124 
    125 		Data (void)
    126 		{
    127 			array.elementType	= DE_NULL;
    128 			array.size			= 0;
    129 		};
    130 	} m_data;
    131 };
    132 
    133 class StructMember
    134 {
    135 public:
    136 						StructMember	(const std::string& name, const VarType& type, deUint32 flags)
    137 							: m_name(name), m_type(type), m_flags(flags)
    138 						{}
    139 						StructMember	(void)
    140 							: m_flags(0)
    141 						{}
    142 
    143 	const std::string&	getName			(void) const { return m_name;	}
    144 	const VarType&		getType			(void) const { return m_type;	}
    145 	deUint32			getFlags		(void) const { return m_flags;	}
    146 
    147 private:
    148 	std::string			m_name;
    149 	VarType				m_type;
    150 	deUint32			m_flags;
    151 };
    152 
    153 class StructType
    154 {
    155 public:
    156 	typedef std::vector<StructMember>::iterator			Iterator;
    157 	typedef std::vector<StructMember>::const_iterator	ConstIterator;
    158 
    159 								StructType		(const std::string& typeName) : m_typeName(typeName) {}
    160 								~StructType		(void) {}
    161 
    162 	const std::string&			getTypeName		(void) const	{ return m_typeName;			}
    163 	bool						hasTypeName		(void) const	{ return !m_typeName.empty();	}
    164 
    165 	inline Iterator				begin			(void)			{ return m_members.begin();		}
    166 	inline ConstIterator		begin			(void) const	{ return m_members.begin();		}
    167 	inline Iterator				end				(void)			{ return m_members.end();		}
    168 	inline ConstIterator		end				(void) const	{ return m_members.end();		}
    169 
    170 	void						addMember		(const std::string& name, const VarType& type, deUint32 flags = 0);
    171 
    172 private:
    173 	std::string					m_typeName;
    174 	std::vector<StructMember>	m_members;
    175 };
    176 
    177 class Uniform
    178 {
    179 public:
    180 						Uniform			(const std::string& name, const VarType& type, deUint32 flags = 0);
    181 
    182 	const std::string&	getName			(void) const { return m_name;	}
    183 	const VarType&		getType			(void) const { return m_type;	}
    184 	deUint32			getFlags		(void) const { return m_flags;	}
    185 
    186 private:
    187 	std::string			m_name;
    188 	VarType				m_type;
    189 	deUint32			m_flags;
    190 };
    191 
    192 class UniformBlock
    193 {
    194 public:
    195 	typedef std::vector<Uniform>::iterator			Iterator;
    196 	typedef std::vector<Uniform>::const_iterator	ConstIterator;
    197 
    198 							UniformBlock		(const std::string& blockName);
    199 
    200 	const std::string&		getBlockName		(void) const { return m_blockName;		}
    201 	const std::string&		getInstanceName		(void) const { return m_instanceName;	}
    202 	bool					hasInstanceName		(void) const { return !m_instanceName.empty();	}
    203 	bool					isArray				(void) const { return m_arraySize > 0;			}
    204 	int						getArraySize		(void) const { return m_arraySize;				}
    205 	deUint32				getFlags			(void) const { return m_flags;					}
    206 
    207 	void					setInstanceName		(const std::string& name)	{ m_instanceName = name;			}
    208 	void					setFlags			(deUint32 flags)			{ m_flags = flags;					}
    209 	void					setArraySize		(int arraySize)				{ m_arraySize = arraySize;			}
    210 	void					addUniform			(const Uniform& uniform)	{ m_uniforms.push_back(uniform);	}
    211 
    212 	inline Iterator			begin				(void)			{ return m_uniforms.begin();	}
    213 	inline ConstIterator	begin				(void) const	{ return m_uniforms.begin();	}
    214 	inline Iterator			end					(void)			{ return m_uniforms.end();		}
    215 	inline ConstIterator	end					(void) const	{ return m_uniforms.end();		}
    216 
    217 private:
    218 	std::string				m_blockName;
    219 	std::string				m_instanceName;
    220 	std::vector<Uniform>	m_uniforms;
    221 	int						m_arraySize;	//!< Array size or 0 if not interface block array.
    222 	deUint32				m_flags;
    223 };
    224 
    225 typedef de::SharedPtr<StructType>	StructTypeSP;
    226 typedef de::SharedPtr<UniformBlock>	UniformBlockSP;
    227 
    228 class ShaderInterface
    229 {
    230 public:
    231 								ShaderInterface			(void);
    232 								~ShaderInterface		(void);
    233 
    234 	StructType&					allocStruct				(const std::string& name);
    235 	void						getNamedStructs			(std::vector<const StructType*>& structs) const;
    236 
    237 	UniformBlock&				allocBlock				(const std::string& name);
    238 
    239 	int							getNumUniformBlocks		(void) const	{ return (int)m_uniformBlocks.size();	}
    240 	const UniformBlock&			getUniformBlock			(int ndx) const	{ return *m_uniformBlocks[ndx];			}
    241 	bool						usesBlockLayout			(UniformFlags layoutFlag) const;
    242 
    243 private:
    244 	std::vector<StructTypeSP>		m_structs;
    245 	std::vector<UniformBlockSP>		m_uniformBlocks;
    246 };
    247 
    248 struct BlockLayoutEntry
    249 {
    250 	BlockLayoutEntry (void)
    251 		: size					(0)
    252 		, blockDeclarationNdx	(-1)
    253 		, bindingNdx			(-1)
    254 		, instanceNdx			(-1)
    255 	{
    256 	}
    257 
    258 	std::string			name;
    259 	int					size;
    260 	std::vector<int>	activeUniformIndices;
    261 	int					blockDeclarationNdx;
    262 	int					bindingNdx;
    263 	int					instanceNdx;
    264 };
    265 
    266 struct UniformLayoutEntry
    267 {
    268 	UniformLayoutEntry (void)
    269 		: type			(glu::TYPE_LAST)
    270 		, size			(0)
    271 		, blockNdx		(-1)
    272 		, offset		(-1)
    273 		, arraySize		(-1)
    274 		, arrayStride	(-1)
    275 		, matrixStride	(-1)
    276 		, topLevelArraySize		(-1)
    277 		, topLevelArrayStride	(-1)
    278 		, isRowMajor	(false)
    279 		, instanceNdx	(0)
    280 	{
    281 	}
    282 
    283 	std::string			name;
    284 	glu::DataType		type;
    285 	int					size;
    286 	int					blockNdx;
    287 	int					offset;
    288 	int					arraySize;
    289 	int					arrayStride;
    290 	int					matrixStride;
    291 	int					topLevelArraySize;
    292 	int					topLevelArrayStride;
    293 	bool				isRowMajor;
    294 	int					instanceNdx;
    295 };
    296 
    297 class UniformLayout
    298 {
    299 public:
    300 	std::vector<BlockLayoutEntry>		blocks;
    301 	std::vector<UniformLayoutEntry>		uniforms;
    302 
    303 	int									getUniformLayoutIndex	(int blockDeclarationNdx, const std::string& name) const;
    304 	int									getBlockLayoutIndex		(int blockDeclarationNdx, int instanceNdx) const;
    305 };
    306 
    307 class UniformBlockCase : public vkt::TestCase
    308 {
    309 public:
    310 	enum BufferMode
    311 	{
    312 		BUFFERMODE_SINGLE = 0,	//!< Single buffer shared between uniform blocks.
    313 		BUFFERMODE_PER_BLOCK,	//!< Per-block buffers
    314 
    315 		BUFFERMODE_LAST
    316 	};
    317 
    318 								UniformBlockCase			(tcu::TestContext&	testCtx,
    319 															 const std::string&	name,
    320 															 const std::string&	description,
    321 															 BufferMode			bufferMode,
    322 															 MatrixLoadFlags	matrixLoadFlag,
    323 															 bool				shuffleUniformMembers = false);
    324 								~UniformBlockCase			(void);
    325 
    326 	virtual	void				initPrograms				(vk::SourceCollections& programCollection) const;
    327 	virtual TestInstance*		createInstance				(Context& context) const;
    328 	bool						usesBlockLayout				(UniformFlags layoutFlag) const { return m_interface.usesBlockLayout(layoutFlag); }
    329 
    330 protected:
    331 	void						init						(void);
    332 
    333 	BufferMode					m_bufferMode;
    334 	ShaderInterface				m_interface;
    335 	MatrixLoadFlags				m_matrixLoadFlag;
    336 	const bool					m_shuffleUniformMembers;	//!< Used with explicit offsets to test out of order member offsets
    337 
    338 private:
    339 	std::string					m_vertShaderSource;
    340 	std::string					m_fragShaderSource;
    341 
    342 	std::vector<deUint8>		m_data;						//!< Data.
    343 	std::map<int, void*>		m_blockPointers;			//!< Reference block pointers.
    344 	UniformLayout				m_uniformLayout;			//!< std140 layout.
    345 };
    346 
    347 } // ubo
    348 } // vkt
    349 
    350 #endif // _VKTUNIFORMBLOCKCASE_HPP
    351