1 #ifndef _VKTSSBOLAYOUTCASE_HPP
2 #define _VKTSSBOLAYOUTCASE_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 SSBO layout tests.
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktTestCase.hpp"
28 #include "tcuDefs.hpp"
29 #include "gluShaderUtil.hpp"
30 #include "gluVarType.hpp"
31 
32 namespace vkt
33 {
34 
35 namespace ssbo
36 {
37 
38 enum BufferVarFlags
39 {
40 	LAYOUT_STD140		= (1<<0),
41 	LAYOUT_STD430		= (1<<1),
42 	LAYOUT_ROW_MAJOR	= (1<<2),
43 	LAYOUT_COLUMN_MAJOR	= (1<<3),	//!< \note Lack of both flags means column-major matrix.
44 	LAYOUT_SCALAR		= (1<<4),
45 	LAYOUT_MASK			= LAYOUT_STD430|LAYOUT_STD140|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR|LAYOUT_SCALAR,
46 
47 	// \todo [2013-10-14 pyry] Investigate adding these.
48 /*	QUALIFIER_COHERENT	= (1<<4),
49 	QUALIFIER_VOLATILE	= (1<<5),
50 	QUALIFIER_RESTRICT	= (1<<6),
51 	QUALIFIER_READONLY	= (1<<7),
52 	QUALIFIER_WRITEONLY	= (1<<8),*/
53 	ACCESS_READ			= (1<<9),	//!< Buffer variable is read in the shader.
54 	ACCESS_WRITE		= (1<<10),	//!< Buffer variable is written in the shader.
55 	LAYOUT_RELAXED		= (1<<11),	//!< Support VK_KHR_relaxed_block_layout extension
56 	LAYOUT_16BIT_STORAGE= (1<<12),  //!< Support VK_KHR_16bit_storage extension
57 	LAYOUT_8BIT_STORAGE	= (1<<13),  //!< Support VK_KHR_8bit_storage extension
58 };
59 
60 enum MatrixLoadFlags
61 {
62 	LOAD_FULL_MATRIX		= 0,
63 	LOAD_MATRIX_COMPONENTS	= 1,
64 };
65 
66 class BufferVar
67 {
68 public:
69 						BufferVar		(const char* name, const glu::VarType& type, deUint32 flags);
70 
getName(void) const71 	const char*			getName			(void) const		{ return m_name.c_str();	}
getType(void) const72 	const glu::VarType&	getType			(void) const		{ return m_type;			}
getFlags(void) const73 	deUint32			getFlags		(void) const		{ return m_flags;			}
getOffset(void) const74 	deUint32			getOffset		(void) const		{ return m_offset;			}
75 
setOffset(deUint32 offset)76 	void				setOffset		(deUint32 offset)	{ m_offset = offset;		}
77 
78 private:
79 	std::string			m_name;
80 	glu::VarType		m_type;
81 	deUint32			m_flags;
82 	deUint32			m_offset;
83 };
84 
85 class BufferBlock
86 {
87 public:
88 	typedef std::vector<BufferVar>::iterator		iterator;
89 	typedef std::vector<BufferVar>::const_iterator	const_iterator;
90 
91 							BufferBlock				(const char* blockName);
92 
getBlockName(void) const93 	const char*				getBlockName			(void) const				{ return m_blockName.c_str();										}
getInstanceName(void) const94 	const char*				getInstanceName			(void) const				{ return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str();	}
isArray(void) const95 	bool					isArray					(void) const				{ return m_arraySize > 0;											}
getArraySize(void) const96 	int						getArraySize			(void) const				{ return m_arraySize;												}
getFlags(void) const97 	deUint32				getFlags				(void) const				{ return m_flags;													}
98 
setInstanceName(const char * name)99 	void					setInstanceName			(const char* name)			{ m_instanceName = name;											}
setFlags(deUint32 flags)100 	void					setFlags				(deUint32 flags)			{ m_flags = flags;													}
addMember(const BufferVar & var)101 	void					addMember				(const BufferVar& var)		{ m_variables.push_back(var);										}
102 	void					setArraySize			(int arraySize);
103 
getLastUnsizedArraySize(int instanceNdx) const104 	int						getLastUnsizedArraySize	(int instanceNdx) const		{ return m_lastUnsizedArraySizes[instanceNdx];						}
setLastUnsizedArraySize(int instanceNdx,int size)105 	void					setLastUnsizedArraySize	(int instanceNdx, int size)	{ m_lastUnsizedArraySizes[instanceNdx] = size;						}
106 
begin(void)107 	inline iterator			begin					(void)						{ return m_variables.begin();										}
begin(void) const108 	inline const_iterator	begin					(void) const				{ return m_variables.begin();										}
end(void)109 	inline iterator			end						(void)						{ return m_variables.end();											}
end(void) const110 	inline const_iterator	end						(void) const				{ return m_variables.end();											}
111 
112 private:
113 	std::string				m_blockName;
114 	std::string				m_instanceName;
115 	std::vector<BufferVar>	m_variables;
116 	int						m_arraySize;				//!< Array size or 0 if not interface block array.
117 	std::vector<int>		m_lastUnsizedArraySizes;	//!< Sizes of last unsized array element, can be different per instance.
118 	deUint32				m_flags;
119 };
120 
121 class ShaderInterface
122 {
123 public:
124 									ShaderInterface			(void);
125 									~ShaderInterface		(void);
126 
127 	glu::StructType&				allocStruct				(const char* name);
128 	const glu::StructType*			findStruct				(const char* name) const;
129 	void							getNamedStructs			(std::vector<const glu::StructType*>& structs) const;
130 
131 	BufferBlock&					allocBlock				(const char* name);
132 
getNumBlocks(void) const133 	int								getNumBlocks			(void) const	{ return (int)m_bufferBlocks.size();	}
getBlock(int ndx) const134 	const BufferBlock&				getBlock				(int ndx) const	{ return *m_bufferBlocks[ndx];			}
getBlock(int ndx)135 	BufferBlock&					getBlock				(int ndx)		{ return *m_bufferBlocks[ndx];			}
136 
137 private:
138 									ShaderInterface			(const ShaderInterface&);
139 	ShaderInterface&				operator=				(const ShaderInterface&);
140 
141 	std::vector<glu::StructType*>	m_structs;
142 	std::vector<BufferBlock*>		m_bufferBlocks;
143 };
144 
145 struct BufferVarLayoutEntry
146 {
BufferVarLayoutEntryvkt::ssbo::BufferVarLayoutEntry147 	BufferVarLayoutEntry (void)
148 		: type					(glu::TYPE_LAST)
149 		, blockNdx				(-1)
150 		, offset				(-1)
151 		, arraySize				(-1)
152 		, arrayStride			(-1)
153 		, matrixStride			(-1)
154 		, topLevelArraySize		(-1)
155 		, topLevelArrayStride	(-1)
156 		, isRowMajor			(false)
157 	{
158 	}
159 
160 	std::string			name;
161 	glu::DataType		type;
162 	int					blockNdx;
163 	int					offset;
164 	int					arraySize;
165 	int					arrayStride;
166 	int					matrixStride;
167 	int					topLevelArraySize;
168 	int					topLevelArrayStride;
169 	bool				isRowMajor;
170 };
171 
172 struct BlockLayoutEntry
173 {
BlockLayoutEntryvkt::ssbo::BlockLayoutEntry174 	BlockLayoutEntry (void)
175 		: size(0)
176 	{
177 	}
178 
179 	std::string			name;
180 	int					size;
181 	std::vector<int>	activeVarIndices;
182 };
183 
184 class BufferLayout
185 {
186 public:
187 	std::vector<BlockLayoutEntry>		blocks;
188 	std::vector<BufferVarLayoutEntry>	bufferVars;
189 
190 	int									getVariableIndex		(const std::string& name) const;
191 	int									getBlockIndex			(const std::string& name) const;
192 };
193 
194 // BlockDataPtr
195 
196 struct BlockDataPtr
197 {
198 	void*		ptr;
199 	int			size;						//!< Redundant, for debugging purposes.
200 	int			lastUnsizedArraySize;
201 
BlockDataPtrvkt::ssbo::BlockDataPtr202 	BlockDataPtr (void* ptr_, int size_, int lastUnsizedArraySize_)
203 		: ptr					(ptr_)
204 		, size					(size_)
205 		, lastUnsizedArraySize	(lastUnsizedArraySize_)
206 	{
207 	}
208 
BlockDataPtrvkt::ssbo::BlockDataPtr209 	BlockDataPtr (void)
210 		: ptr					(DE_NULL)
211 		, size					(0)
212 		, lastUnsizedArraySize	(0)
213 	{
214 	}
215 };
216 
217 struct RefDataStorage
218 {
219 	std::vector<deUint8>			data;
220 	std::vector<BlockDataPtr>	pointers;
221 };
222 
223 class SSBOLayoutCase : public vkt::TestCase
224 {
225 public:
226 	enum BufferMode
227 	{
228 		BUFFERMODE_SINGLE = 0,	//!< Single buffer shared between uniform blocks.
229 		BUFFERMODE_PER_BLOCK,	//!< Per-block buffers
230 
231 		BUFFERMODE_LAST
232 	};
233 
234 								SSBOLayoutCase				(tcu::TestContext& testCtx, const char* name, const char* description, BufferMode bufferMode, MatrixLoadFlags matrixLoadFlag);
235 	virtual						~SSBOLayoutCase				(void);
236 
237 	virtual void				initPrograms				(vk::SourceCollections& programCollection) const;
238 	virtual TestInstance*		createInstance				(Context& context) const;
239 
240 protected:
241 	void						init						(void);
242 
243 	BufferMode					m_bufferMode;
244 	ShaderInterface				m_interface;
245 	MatrixLoadFlags				m_matrixLoadFlag;
246 	std::string					m_computeShaderSrc;
247 
248 private:
249 								SSBOLayoutCase				(const SSBOLayoutCase&);
250 	SSBOLayoutCase&				operator=					(const SSBOLayoutCase&);
251 
252 	BufferLayout				m_refLayout;
253 	RefDataStorage				m_initialData;	// Initial data stored in buffer.
254 	RefDataStorage				m_writeData;		// Data written by compute shader.
255 };
256 
257 } // ssbo
258 } // vkt
259 
260 #endif // _VKTSSBOLAYOUTCASE_HPP
261