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