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