1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Basic Geometry Shader Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktGeometryBasicGeometryShaderTests.hpp"
26 #include "vktGeometryBasicClass.hpp"
27 #include "vktGeometryTestsUtil.hpp"
28 
29 #include "gluTextureUtil.hpp"
30 #include "glwEnums.hpp"
31 #include "vkDefs.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkMemUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "tcuTextureUtil.hpp"
44 
45 #include <string>
46 
47 using namespace vk;
48 
49 namespace vkt
50 {
51 namespace geometry
52 {
53 namespace
54 {
55 using tcu::TestStatus;
56 using tcu::TestContext;
57 using tcu::TestCaseGroup;
58 using de::MovePtr;
59 using std::string;
60 using std::vector;
61 
62 enum VaryingSource
63 {
64 	READ_ATTRIBUTE = 0,
65 	READ_UNIFORM,
66 	READ_TEXTURE,
67 
68 	READ_LAST
69 };
70 enum ShaderInstancingMode
71 {
72 	MODE_WITHOUT_INSTANCING = 0,
73 	MODE_WITH_INSTANCING,
74 
75 	MODE_LAST
76 };
77 enum
78 {
79 	EMIT_COUNT_VERTEX_0 = 6,
80 	EMIT_COUNT_VERTEX_1 = 0,
81 	EMIT_COUNT_VERTEX_2 = -1,
82 	EMIT_COUNT_VERTEX_3 = 10,
83 };
84 enum VariableTest
85 {
86 	TEST_POINT_SIZE = 0,
87 	TEST_PRIMITIVE_ID_IN,
88 	TEST_PRIMITIVE_ID,
89 	TEST_LAST
90 };
91 
uploadImage(Context & context,const tcu::ConstPixelBufferAccess & access,VkImage destImage)92 void uploadImage (Context&								context,
93 				  const tcu::ConstPixelBufferAccess&	access,
94 				  VkImage								destImage)
95 {
96 	const DeviceInterface&			vk					= context.getDeviceInterface();
97 	const VkDevice					device				= context.getDevice();
98 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
99 	const VkQueue					queue				= context.getUniversalQueue();
100 	Allocator&						memAlloc			= context.getDefaultAllocator();
101 	const VkImageAspectFlags		aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
102 	const deUint32					bufferSize			= access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
103 	Move<VkBuffer>					buffer;
104 	de::MovePtr<Allocation>			bufferAlloc;
105 	Move<VkCommandPool>				cmdPool;
106 	Move<VkCommandBuffer>			cmdBuffer;
107 	Move<VkFence>					fence;
108 
109 	// Create source buffer
110 	{
111 		const VkBufferCreateInfo bufferParams =
112 		{
113 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
114 			DE_NULL,									// const void*			pNext;
115 			0u,											// VkBufferCreateFlags	flags;
116 			bufferSize,									// VkDeviceSize			size;
117 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
118 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
119 			0u,											// deUint32				queueFamilyIndexCount;
120 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
121 		};
122 		buffer		= createBuffer(vk, device, &bufferParams);
123 		bufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
124 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
125 	}
126 
127 	// Get copy regions and write buffer data
128 	const VkBufferImageCopy			copyRegion	=
129 	{
130 		0u,								// VkDeviceSize				bufferOffset;
131 		(deUint32)access.getWidth(),	// deUint32					bufferRowLength;
132 		(deUint32)access.getHeight(),	// deUint32					bufferImageHeight;
133 		{								// VkImageSubresourceLayers	imageSubresource;
134 				aspectMask,				// VkImageAspectFlags		aspectMask;
135 				(deUint32)0u,			// uint32_t					mipLevel;
136 				(deUint32)0u,			// uint32_t					baseArrayLayer;
137 				1u						// uint32_t					layerCount;
138 		},
139 		{ 0u, 0u, 0u },					// VkOffset3D			imageOffset;
140 		{								// VkExtent3D			imageExtent;
141 			(deUint32)access.getWidth(),
142 			(deUint32)access.getHeight(),
143 			(deUint32)access.getDepth()
144 		}
145 	};
146 
147 	vector<VkBufferImageCopy>		copyRegions	(1, copyRegion);
148 
149 	{
150 		const tcu::PixelBufferAccess	destAccess	(access.getFormat(), access.getSize(), bufferAlloc->getHostPtr());
151 		tcu::copy(destAccess, access);
152 		flushAlloc(vk, device, *bufferAlloc);
153 	}
154 
155 	// Copy buffer to image
156 	copyBufferToImage(vk, device, queue, queueFamilyIndex, *buffer, bufferSize, copyRegions, DE_NULL, aspectMask, 1, 1, destImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
157 }
158 
159 class GeometryOutputCountTestInstance : public GeometryExpanderRenderTestInstance
160 {
161 public:
162 								GeometryOutputCountTestInstance	(Context&					context,
163 																 const VkPrimitiveTopology	primitiveType,
164 																 const int					primitiveCount,
165 																 const char*				name);
166 	void						genVertexAttribData				(void);
167 private:
168 	const int					m_primitiveCount;
169 };
170 
GeometryOutputCountTestInstance(Context & context,const VkPrimitiveTopology primitiveType,const int primitiveCount,const char * name)171 GeometryOutputCountTestInstance::GeometryOutputCountTestInstance (Context&					context,
172 																  const VkPrimitiveTopology	primitiveType,
173 																  const int					primitiveCount,
174 																  const char*				name)
175 	: GeometryExpanderRenderTestInstance	(context, primitiveType, name)
176 	, m_primitiveCount						(primitiveCount)
177 
178 {
179 	genVertexAttribData();
180 }
181 
genVertexAttribData(void)182 void GeometryOutputCountTestInstance::genVertexAttribData (void)
183 {
184 	m_vertexPosData.resize(m_primitiveCount);
185 	m_vertexAttrData.resize(m_primitiveCount);
186 
187 	for (int ndx = 0; ndx < m_primitiveCount; ++ndx)
188 	{
189 		m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / (float)m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f);
190 		m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1);
191 	}
192 	m_numDrawVertices = m_primitiveCount;
193 }
194 
195 class VaryingOutputCountTestInstance : public GeometryExpanderRenderTestInstance
196 {
197 public:
198 								VaryingOutputCountTestInstance	(Context&					context,
199 																 const char*				name,
200 																 const VkPrimitiveTopology	primitiveType,
201 																 const VaryingSource		test,
202 																 const ShaderInstancingMode	mode);
203 	void						genVertexAttribData				(void);
204 protected:
205 	Move<VkPipelineLayout>		createPipelineLayout			(const DeviceInterface& vk, const VkDevice device);
206 	void						bindDescriptorSets				(const DeviceInterface&		vk,
207 																 const VkDevice				device,
208 																 Allocator&					memAlloc,
209 																 const VkCommandBuffer&		cmdBuffer,
210 																 const VkPipelineLayout&	pipelineLayout);
211 private:
212 	void						genVertexDataWithoutInstancing	(void);
213 	void						genVertexDataWithInstancing		(void);
214 
215 	const VaryingSource			m_test;
216 	const ShaderInstancingMode	m_mode;
217 	const deInt32				m_maxEmitCount;
218 	Move<VkDescriptorPool>		m_descriptorPool;
219 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
220 	Move<VkDescriptorSet>		m_descriptorSet;
221 	Move<VkBuffer>				m_buffer;
222 	Move<VkImage>				m_texture;
223 	Move<VkImageView>			m_imageView;
224 	Move<VkSampler>				m_sampler;
225 	de::MovePtr<Allocation>		m_allocation;
226 };
227 
VaryingOutputCountTestInstance(Context & context,const char * name,const VkPrimitiveTopology primitiveType,const VaryingSource test,const ShaderInstancingMode mode)228 VaryingOutputCountTestInstance::VaryingOutputCountTestInstance (Context&					context,
229 																const char*					name,
230 																const VkPrimitiveTopology	primitiveType,
231 																const VaryingSource			test,
232 																const ShaderInstancingMode	mode)
233 	: GeometryExpanderRenderTestInstance	(context, primitiveType, name)
234 	, m_test								(test)
235 	, m_mode								(mode)
236 	, m_maxEmitCount						(128)
237 {
238 	genVertexAttribData ();
239 }
240 
genVertexAttribData(void)241 void VaryingOutputCountTestInstance::genVertexAttribData (void)
242 {
243 	if (m_mode == MODE_WITHOUT_INSTANCING)
244 		genVertexDataWithoutInstancing();
245 	else if (m_mode == MODE_WITH_INSTANCING)
246 		genVertexDataWithInstancing();
247 	else
248 		DE_ASSERT(false);
249 }
250 
createPipelineLayout(const DeviceInterface & vk,const VkDevice device)251 Move<VkPipelineLayout> VaryingOutputCountTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device)
252 {
253 	if (m_test == READ_UNIFORM)
254 	{
255 		m_descriptorSetLayout	=	DescriptorSetLayoutBuilder()
256 									.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
257 									.build(vk, device);
258 		m_descriptorPool		=	DescriptorPoolBuilder()
259 									.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
260 									.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
261 		m_descriptorSet			=	makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
262 
263 		return makePipelineLayout(vk, device, *m_descriptorSetLayout);
264 	}
265 	else if (m_test == READ_TEXTURE)
266 	{
267 		const tcu::Vec4				data[4]				=
268 														{
269 															tcu::Vec4(255, 0, 0, 0),
270 															tcu::Vec4(0, 255, 0, 0),
271 															tcu::Vec4(0, 0, 255, 0),
272 															tcu::Vec4(0, 0, 0, 255)
273 														};
274 		const tcu::UVec2			viewportSize		(4, 1);
275 		const tcu::TextureFormat	texFormat			= glu::mapGLInternalFormat(GL_RGBA8);
276 		const VkFormat				format				= mapTextureFormat(texFormat);
277 		const VkImageUsageFlags		imageUsageFlags		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
278 		Allocator&					memAlloc			= m_context.getDefaultAllocator();
279 		tcu::TextureLevel			texture				(texFormat, static_cast<int>(viewportSize.x()), static_cast<int>(viewportSize.y()));
280 
281 		// Fill with data
282 		{
283 			tcu::PixelBufferAccess access = texture.getAccess();
284 			for (int x = 0; x < texture.getWidth(); ++x)
285 				access.setPixel(data[x], x, 0);
286 		}
287 		// Create image
288 		const VkImageCreateInfo			imageParams =
289 		{
290 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
291 			DE_NULL,								// const void*				pNext;
292 			0,										// VkImageCreateFlags		flags;
293 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
294 			format,									// VkFormat					format;
295 			{										// VkExtent3D				extent;
296 					viewportSize.x(),
297 					viewportSize.y(),
298 					1u,
299 			},
300 			1u,							// deUint32					mipLevels;
301 			1u,							// deUint32					arrayLayers;
302 			VK_SAMPLE_COUNT_1_BIT,		// VkSampleCountFlagBits	samples;
303 			VK_IMAGE_TILING_OPTIMAL,	// VkImageTiling			tiling;
304 			imageUsageFlags,			// VkImageUsageFlags		usage;
305 			VK_SHARING_MODE_EXCLUSIVE,	// VkSharingMode			sharingMode;
306 			0u,							// deUint32					queueFamilyIndexCount;
307 			DE_NULL,					// const deUint32*			pQueueFamilyIndices;
308 			VK_IMAGE_LAYOUT_UNDEFINED	// VkImageLayout			initialLayout;
309 		};
310 
311 		m_texture		= createImage(vk, device, &imageParams);
312 		m_allocation	= memAlloc.allocate(getImageMemoryRequirements(vk, device, *m_texture), MemoryRequirement::Any);
313 		VK_CHECK(vk.bindImageMemory(device, *m_texture, m_allocation->getMemory(), m_allocation->getOffset()));
314 		uploadImage(m_context, texture.getAccess(), *m_texture);
315 
316 		m_descriptorSetLayout	=	DescriptorSetLayoutBuilder()
317 									.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_GEOMETRY_BIT)
318 									.build(vk, device);
319 		m_descriptorPool		=	DescriptorPoolBuilder()
320 									.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
321 									.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
322 		m_descriptorSet			=	makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
323 
324 		return makePipelineLayout(vk, device, *m_descriptorSetLayout);
325 	}
326 	else
327 		return makePipelineLayout(vk, device);
328 }
329 
bindDescriptorSets(const DeviceInterface & vk,const VkDevice device,Allocator & memAlloc,const VkCommandBuffer & cmdBuffer,const VkPipelineLayout & pipelineLayout)330 void VaryingOutputCountTestInstance::bindDescriptorSets (const DeviceInterface& vk, const VkDevice device, Allocator& memAlloc,
331 														 const VkCommandBuffer& cmdBuffer, const VkPipelineLayout& pipelineLayout)
332 {
333 	if (m_test == READ_UNIFORM)
334 	{
335 		const deInt32				emitCount[4]		= { 6, 0, m_maxEmitCount, 10 };
336 		const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(sizeof(emitCount), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
337 		m_buffer										= createBuffer(vk, device, &bufferCreateInfo);
338 		m_allocation									= memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
339 
340 		VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
341 		{
342 			deMemcpy(m_allocation->getHostPtr(), &emitCount[0], sizeof(emitCount));
343 			flushAlloc(vk, device, *m_allocation);
344 
345 			const VkDescriptorBufferInfo bufferDescriptorInfo = makeDescriptorBufferInfo(*m_buffer, 0ull, sizeof(emitCount));
346 
347 			DescriptorSetUpdateBuilder()
348 				.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferDescriptorInfo)
349 				.update(vk, device);
350 			vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
351 		}
352 	}
353 	else if (m_test == READ_TEXTURE)
354 	{
355 		const tcu::TextureFormat	texFormat			= glu::mapGLInternalFormat(GL_RGBA8);
356 		const VkFormat				format				= mapTextureFormat(texFormat);
357 		const VkSamplerCreateInfo	samplerParams		=
358 														{
359 															VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
360 															DE_NULL,									// const void*				pNext;
361 															0u,											// VkSamplerCreateFlags		flags;
362 															VK_FILTER_NEAREST,							// VkFilter					magFilter;
363 															VK_FILTER_NEAREST,							// VkFilter					minFilter;
364 															VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
365 															VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
366 															VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
367 															VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
368 															0.0f,										// float					mipLodBias;
369 															VK_FALSE,									// VkBool32					anisotropyEnable;
370 															1.0f,										// float					maxAnisotropy;
371 															false,										// VkBool32					compareEnable;
372 															VK_COMPARE_OP_NEVER,						// VkCompareOp				compareOp;
373 															0.0f,										// float					minLod;
374 															0.0f,										// float					maxLod;
375 															VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor			borderColor;
376 															false										// VkBool32					unnormalizedCoordinates;
377 														};
378 		m_sampler										= createSampler(vk, device, &samplerParams);
379 		const VkImageViewCreateInfo	viewParams			=
380 														{
381 															VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
382 															NULL,										// const voide*				pNext;
383 															0u,											// VkImageViewCreateFlags	flags;
384 															*m_texture,									// VkImage					image;
385 															VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
386 															format,										// VkFormat					format;
387 															makeComponentMappingRGBA(),					// VkChannelMapping			channels;
388 															{
389 																VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
390 																0u,										// deUint32				baseMipLevel;
391 																1u,										// deUint32				mipLevels;
392 																0,										// deUint32				baseArraySlice;
393 																1u										// deUint32				arraySize;
394 															},											// VkImageSubresourceRange	subresourceRange;
395 														};
396 		m_imageView										= createImageView(vk, device, &viewParams);
397 		const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo (*m_sampler, *m_imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
398 		DescriptorSetUpdateBuilder()
399 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo)
400 			.update(vk, device);
401 		vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
402 	}
403 }
404 
genVertexDataWithoutInstancing(void)405 void VaryingOutputCountTestInstance::genVertexDataWithoutInstancing (void)
406 {
407 	m_numDrawVertices = 4;
408 	m_vertexPosData.resize(m_numDrawVertices);
409 	m_vertexAttrData.resize(m_numDrawVertices);
410 
411 	m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
412 	m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
413 	m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
414 	m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
415 
416 	if (m_test == READ_ATTRIBUTE)
417 	{
418 		m_vertexAttrData[0] = tcu::Vec4(((EMIT_COUNT_VERTEX_0 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_0)), 0.0f, 0.0f, 0.0f);
419 		m_vertexAttrData[1] = tcu::Vec4(((EMIT_COUNT_VERTEX_1 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_1)), 0.0f, 0.0f, 0.0f);
420 		m_vertexAttrData[2] = tcu::Vec4(((EMIT_COUNT_VERTEX_2 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_2)), 0.0f, 0.0f, 0.0f);
421 		m_vertexAttrData[3] = tcu::Vec4(((EMIT_COUNT_VERTEX_3 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_3)), 0.0f, 0.0f, 0.0f);
422 	}
423 	else
424 	{
425 		m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
426 		m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
427 		m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
428 		m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
429 	}
430 }
431 
genVertexDataWithInstancing(void)432 void VaryingOutputCountTestInstance::genVertexDataWithInstancing (void)
433 {
434 	m_numDrawVertices = 1;
435 	m_vertexPosData.resize(m_numDrawVertices);
436 	m_vertexAttrData.resize(m_numDrawVertices);
437 
438 	m_vertexPosData[0] = tcu::Vec4(0.0f,  0.0f, 0.0f, 1.0f);
439 
440 	if (m_test == READ_ATTRIBUTE)
441 	{
442 		const int emitCounts[] =
443 		{
444 			(EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_0),
445 			(EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_1),
446 			(EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_2),
447 			(EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_3),
448 		};
449 
450 		m_vertexAttrData[0] = tcu::Vec4((float)emitCounts[0], (float)emitCounts[1], (float)emitCounts[2], (float)emitCounts[3]);
451 	}
452 	else
453 	{
454 		// not used
455 		m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
456 	}
457 }
458 
459 class BuiltinVariableRenderTestInstance: public GeometryExpanderRenderTestInstance
460 {
461 public:
462 			BuiltinVariableRenderTestInstance	(Context&				context,
463 												 const char*			name,
464 												 const VariableTest		test,
465 												 const bool				indicesTest);
466 	void	genVertexAttribData					(void);
467 	void	createIndicesBuffer					(void);
468 
469 protected:
470 	void	drawCommand							(const VkCommandBuffer&	cmdBuffer);
471 
472 private:
473 	const bool				m_indicesTest;
474 	std::vector<deUint16>	m_indices;
475 	Move<vk::VkBuffer>		m_indicesBuffer;
476 	MovePtr<Allocation>		m_allocation;
477 };
478 
BuiltinVariableRenderTestInstance(Context & context,const char * name,const VariableTest test,const bool indicesTest)479 BuiltinVariableRenderTestInstance::BuiltinVariableRenderTestInstance (Context& context, const char* name, const VariableTest test, const bool indicesTest)
480 	: GeometryExpanderRenderTestInstance	(context, (test == TEST_PRIMITIVE_ID_IN) ? VK_PRIMITIVE_TOPOLOGY_LINE_STRIP : VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name)
481 	, m_indicesTest							(indicesTest)
482 {
483 	genVertexAttribData();
484 }
485 
genVertexAttribData(void)486 void BuiltinVariableRenderTestInstance::genVertexAttribData (void)
487 {
488 	m_numDrawVertices = 5;
489 
490 	m_vertexPosData.resize(m_numDrawVertices);
491 	m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
492 	m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
493 	m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
494 	m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
495 	m_vertexPosData[4] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
496 
497 	m_vertexAttrData.resize(m_numDrawVertices);
498 	m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
499 	m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
500 	m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
501 	m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
502 	m_vertexAttrData[4] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
503 
504 	if (m_indicesTest)
505 	{
506 		// Only used by primitive ID restart test
507 		m_indices.resize(m_numDrawVertices);
508 		m_indices[0] = 1;
509 		m_indices[1] = 4;
510 		m_indices[2] = 0xFFFF; // restart
511 		m_indices[3] = 2;
512 		m_indices[4] = 1;
513 		createIndicesBuffer();
514 	}
515 }
516 
createIndicesBuffer(void)517 void BuiltinVariableRenderTestInstance::createIndicesBuffer (void)
518 {
519 	// Create vertex indices buffer
520 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
521 	const VkDevice					device				= m_context.getDevice();
522 	Allocator&						memAlloc			= m_context.getDefaultAllocator();
523 	const VkDeviceSize				indexBufferSize		= m_indices.size() * sizeof(deUint16);
524 	const VkBufferCreateInfo		indexBufferParams	=
525 														{
526 															VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
527 															DE_NULL,								// const void*			pNext;
528 															0u,										// VkBufferCreateFlags	flags;
529 															indexBufferSize,						// VkDeviceSize			size;
530 															VK_BUFFER_USAGE_INDEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
531 															VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
532 															0u,										// deUint32				queueFamilyCount;
533 															DE_NULL									// const deUint32*		pQueueFamilyIndices;
534 														};
535 
536 	m_indicesBuffer = createBuffer(vk, device, &indexBufferParams);
537 	m_allocation = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_indicesBuffer), MemoryRequirement::HostVisible);
538 	VK_CHECK(vk.bindBufferMemory(device, *m_indicesBuffer, m_allocation->getMemory(), m_allocation->getOffset()));
539 	// Load indices into buffer
540 	deMemcpy(m_allocation->getHostPtr(), &m_indices[0], (size_t)indexBufferSize);
541 	flushAlloc(vk, device, *m_allocation);
542 }
543 
drawCommand(const VkCommandBuffer & cmdBuffer)544 void BuiltinVariableRenderTestInstance::drawCommand (const VkCommandBuffer&	cmdBuffer)
545 {
546 	const DeviceInterface&	vk = m_context.getDeviceInterface();
547 	if (m_indicesTest)
548 	{
549 		vk.cmdBindIndexBuffer(cmdBuffer, *m_indicesBuffer, 0, VK_INDEX_TYPE_UINT16);
550 		vk.cmdDrawIndexed(cmdBuffer, static_cast<deUint32>(m_indices.size()), 1, 0, 0, 0);
551 	}
552 	else
553 		vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
554 }
555 
556 class GeometryOutputCountTest : public TestCase
557 {
558 public:
559 							GeometryOutputCountTest	(TestContext&		testCtx,
560 													 const char*		name,
561 													 const char*		description,
562 													 const vector<int>	pattern);
563 
564 	void					initPrograms			(SourceCollections&			sourceCollections) const;
565 	virtual TestInstance*	createInstance			(Context&					context) const;
566 
567 protected:
568 	const vector<int> m_pattern;
569 };
570 
GeometryOutputCountTest(TestContext & testCtx,const char * name,const char * description,const vector<int> pattern)571 GeometryOutputCountTest::GeometryOutputCountTest (TestContext& testCtx, const char* name, const char* description, const vector<int> pattern)
572 	: TestCase	(testCtx, name, description)
573 	, m_pattern	(pattern)
574 {
575 
576 }
577 
initPrograms(SourceCollections & sourceCollections) const578 void GeometryOutputCountTest::initPrograms (SourceCollections& sourceCollections) const
579 {
580 	{
581 		std::ostringstream src;
582 		src	<< "#version 310 es\n"
583 			<<"layout(location = 0) in highp vec4 a_position;\n"
584 			<<"layout(location = 1) in highp vec4 a_color;\n"
585 			<<"layout(location = 0) out highp vec4 v_geom_FragColor;\n"
586 			<<"void main (void)\n"
587 			<<"{\n"
588 			<<"	gl_Position = a_position;\n"
589 			<<"	v_geom_FragColor = a_color;\n"
590 			<<"}\n";
591 		sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
592 	}
593 
594 	{
595 		const int max_vertices = m_pattern.size() == 2 ? std::max(m_pattern[0], m_pattern[1]) : m_pattern[0];
596 
597 		std::ostringstream src;
598 		src	<< "#version 310 es\n"
599 			<< "#extension GL_EXT_geometry_shader : require\n"
600 			<< "#extension GL_OES_texture_storage_multisample_2d_array : require\n"
601 			<< "layout(points) in;\n"
602 			<< "layout(triangle_strip, max_vertices = " << max_vertices << ") out;\n"
603 			<< "layout(location = 0) in highp vec4 v_geom_FragColor[];\n"
604 			<< "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
605 			<< "void main (void)\n"
606 			<< "{\n"
607 			<< "	const highp float rowHeight = 2.0 / float(" << m_pattern.size() << ");\n"
608 			<< "	const highp float colWidth = 2.0 / float(" << max_vertices << ");\n";
609 
610 		if (m_pattern.size() == 2)
611 			src	<< "	highp int emitCount = (gl_PrimitiveIDIn == 0) ? (" << m_pattern[0] << ") : (" << m_pattern[1] << ");\n";
612 		else
613 			src	<< "	highp int emitCount = " << m_pattern[0] << ";\n";
614 		src	<< "	for (highp int ndx = 0; ndx < emitCount / 2; ndx++)\n"
615 			<< "	{\n"
616 			<< "		gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, 0.0, 0.0, 0.0);\n"
617 			<< "		v_frag_FragColor = v_geom_FragColor[0];\n"
618 			<< "		EmitVertex();\n"
619 
620 			<< "		gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, rowHeight, 0.0, 0.0);\n"
621 			<< "		v_frag_FragColor = v_geom_FragColor[0];\n"
622 			<< "		EmitVertex();\n"
623 
624 			<< "	}\n"
625 			<< "}\n";
626 		sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
627 	}
628 
629 	{
630 		std::ostringstream src;
631 		src	<< "#version 310 es\n"
632 			<<"layout(location = 0) out mediump vec4 fragColor;\n"
633 			<<"layout(location = 0) in highp vec4 v_frag_FragColor;\n"
634 			<<"void main (void)\n"
635 			<<"{\n"
636 			<<"	fragColor = v_frag_FragColor;\n"
637 			<<"}\n";
638 		sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
639 	}
640 }
641 
createInstance(Context & context) const642 TestInstance* GeometryOutputCountTest::createInstance (Context& context) const
643 {
644 	return new GeometryOutputCountTestInstance (context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, static_cast<int>(m_pattern.size()), getName());
645 }
646 
647 class VaryingOutputCountCase : public TestCase
648 {
649 public:
650 							VaryingOutputCountCase	(TestContext&				testCtx,
651 													 const char*				name,
652 													 const char*				description,
653 													 const VaryingSource		test,
654 													 const ShaderInstancingMode	mode);
655 	void					initPrograms			(SourceCollections&			sourceCollections) const;
656 	virtual TestInstance*	createInstance			(Context&					context) const;
657 protected:
658 	const VaryingSource			m_test;
659 	const ShaderInstancingMode	m_mode;
660 };
661 
VaryingOutputCountCase(TestContext & testCtx,const char * name,const char * description,const VaryingSource test,const ShaderInstancingMode mode)662 VaryingOutputCountCase::VaryingOutputCountCase (TestContext& testCtx, const char* name, const char* description, const VaryingSource test, const ShaderInstancingMode mode)
663 	: TestCase	(testCtx, name, description)
664 	, m_test	(test)
665 	, m_mode	(mode)
666 {
667 }
668 
initPrograms(SourceCollections & sourceCollections) const669 void VaryingOutputCountCase::initPrograms (SourceCollections& sourceCollections) const
670 {
671 	{
672 		std::ostringstream src;
673 		switch(m_test)
674 		{
675 			case READ_ATTRIBUTE:
676 			case READ_TEXTURE:
677 				src	<< "#version 310 es\n"
678 					<< "layout(location = 0) in highp vec4 a_position;\n"
679 					<< "layout(location = 1) in highp vec4 a_emitCount;\n"
680 					<< "layout(location = 0) out highp vec4 v_geom_emitCount;\n"
681 					<< "void main (void)\n"
682 					<< "{\n"
683 					<< "	gl_Position = a_position;\n"
684 					<< "	v_geom_emitCount = a_emitCount;\n"
685 					<< "}\n";
686 				break;
687 			case READ_UNIFORM:
688 				src	<< "#version 310 es\n"
689 					<< "layout(location = 0) in highp vec4 a_position;\n"
690 					<< "layout(location = 1) in highp vec4 a_vertexNdx;\n"
691 					<< "layout(location = 0) out highp vec4 v_geom_vertexNdx;\n"
692 					<< "void main (void)\n"
693 					<< "{\n"
694 					<< "	gl_Position = a_position;\n"
695 					<< "	v_geom_vertexNdx = a_vertexNdx;\n"
696 					<< "}\n";
697 				break;
698 			default:
699 				DE_ASSERT(0);
700 				break;
701 		}
702 		sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
703 	}
704 
705 	{
706 		const bool instanced = MODE_WITH_INSTANCING == m_mode;
707 		std::ostringstream src;
708 		src	<< "#version 310 es\n"
709 			<< "#extension GL_EXT_geometry_shader : require\n"
710 			<< "#extension GL_OES_texture_storage_multisample_2d_array : require\n";
711 		if (instanced)
712 			src	<< "layout(points, invocations=4) in;\n";
713 		else
714 			src	<< "layout(points) in;\n";
715 
716 		switch(m_test)
717 		{
718 			case READ_ATTRIBUTE:
719 				src	<< "layout(triangle_strip, max_vertices = 128) out;\n"
720 					<< "layout(location = 0) in highp vec4 v_geom_emitCount[];\n"
721 					<< "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
722 					<< "void main (void)\n"
723 					<< "{\n"
724 					<< "	highp vec4 attrEmitCounts = v_geom_emitCount[0];\n"
725 					<< "	mediump int emitCount = int(attrEmitCounts[" << ((instanced) ? ("gl_InvocationID") : ("0")) << "]);\n"
726 					<< "	highp vec4 color = vec4((emitCount < 10) ? (0.0) : (1.0), (emitCount > 10) ? (0.0) : (1.0), 1.0, 1.0);\n"
727 					<< "	highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
728 					<< "	for (mediump int i = 0; i < emitCount / 2; i++)\n"
729 					<< "	{\n"
730 					<< "		highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
731 					<< "		gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
732 					<< "		v_frag_FragColor = color;\n"
733 					<< "		EmitVertex();\n"
734 					<< "		gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
735 					<< "		v_frag_FragColor = color;\n"
736 					<< "		EmitVertex();\n"
737 					<< "	}\n"
738 					<<"}\n";
739 				break;
740 			case READ_UNIFORM:
741 				src	<< "layout(triangle_strip, max_vertices = 128) out;\n"
742 					<< "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n"
743 					<< "layout(binding = 0) readonly uniform Input {\n"
744 					<< "	ivec4 u_emitCount;\n"
745 					<< "} emit;\n"
746 					<< "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
747 					<< "void main (void)\n"
748 					<< "{\n"
749 					<< "	mediump int primitiveNdx = " << ((instanced) ? ("gl_InvocationID") : ("int(v_geom_vertexNdx[0].x)")) << ";\n"
750 					<< "	mediump int emitCount = emit.u_emitCount[primitiveNdx];\n"
751 					<< "\n"
752 					<< "	const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
753 					<< "	const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
754 					<< "	const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
755 					<< "	const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
756 					<< "	const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
757 					<< "	highp vec4 color = colors[int(primitiveNdx)];\n"
758 					<< "\n"
759 					<< "	highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
760 					<< "	for (mediump int i = 0; i < emitCount / 2; i++)\n"
761 					<< "	{\n"
762 					<< "		highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
763 					<< "		gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
764 					<< "		v_frag_FragColor = color;\n"
765 					<< "		EmitVertex();\n"
766 					<< "		gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
767 					<< "		v_frag_FragColor = color;\n"
768 					<< "		EmitVertex();\n"
769 					<< "	}\n"
770 					<<"}\n";
771 				break;
772 			case READ_TEXTURE:
773 				src	<< "layout(triangle_strip, max_vertices = 128) out;\n"
774 					<< "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n"
775 					<< "layout(binding = 0) uniform highp sampler2D u_sampler;\n"
776 					<< "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
777 					<< "void main (void)\n"
778 					<< "{\n"
779 					<< "	highp float primitiveNdx = " << ((instanced) ? ("float(gl_InvocationID)") : ("v_geom_vertexNdx[0].x")) << ";\n"
780 					<< "	highp vec2 texCoord = vec2(1.0 / 8.0 + primitiveNdx / 4.0, 0.5);\n"
781 					<< "	highp vec4 texColor = texture(u_sampler, texCoord);\n"
782 					<< "	mediump int emitCount = 0;\n"
783 					<< "	if (texColor.x > 0.0)\n"
784 					<< "		emitCount += 6;\n"
785 					<< "	if (texColor.y > 0.0)\n"
786 					<< "		emitCount += 0;\n"
787 					<< "	if (texColor.z > 0.0)\n"
788 					<< "		emitCount += 128;\n"
789 					<< "	if (texColor.w > 0.0)\n"
790 					<< "		emitCount += 10;\n"
791 					<< "	const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
792 					<< "	const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
793 					<< "	const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
794 					<< "	const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
795 					<< "	const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
796 					<< "	highp vec4 color = colors[int(primitiveNdx)];\n"
797 					<< "	highp vec4 basePos = "<< ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
798 					<< "	for (mediump int i = 0; i < emitCount / 2; i++)\n"
799 					<< "	{\n"
800 					<< "		highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
801 					<< "		gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
802 					<< "		v_frag_FragColor = color;\n"
803 					<< "		EmitVertex();\n"
804 					<< "		gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
805 					<< "		v_frag_FragColor = color;\n"
806 					<< "		EmitVertex();\n"
807 					<< "	}\n"
808 					<<"}\n";
809 				break;
810 			default:
811 				DE_ASSERT(0);
812 				break;
813 		}
814 		sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
815 	}
816 
817 	{
818 		std::ostringstream src;
819 		src	<< "#version 310 es\n"
820 			<< "layout(location = 0) out mediump vec4 fragColor;\n"
821 			<< "layout(location = 0) in highp vec4 v_frag_FragColor;\n"
822 			<< "void main (void)\n"
823 			<< "{\n"
824 			<< "	fragColor = v_frag_FragColor;\n"
825 			<< "}\n";
826 		sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
827 	}
828 }
829 
createInstance(Context & context) const830 TestInstance* VaryingOutputCountCase::createInstance (Context& context) const
831 {
832 	return new VaryingOutputCountTestInstance (context, getName(), VK_PRIMITIVE_TOPOLOGY_POINT_LIST, m_test, m_mode);
833 }
834 
835 class BuiltinVariableRenderTest : public TestCase
836 {
837 public:
838 							BuiltinVariableRenderTest	(TestContext&		testCtx,
839 														const char*			name,
840 														const char*			desc,
841 														const VariableTest	test,
842 														const bool			flag = false);
843 	void					initPrograms				(SourceCollections&	sourceCollections) const;
844 	virtual TestInstance*	createInstance				(Context&			context) const;
845 protected:
846 	const VariableTest	m_test;
847 	const bool			m_flag;
848 };
849 
BuiltinVariableRenderTest(TestContext & testCtx,const char * name,const char * description,const VariableTest test,const bool flag)850 BuiltinVariableRenderTest::BuiltinVariableRenderTest (TestContext& testCtx, const char* name, const char* description, const VariableTest test, const bool flag)
851 	: TestCase	(testCtx, name, description)
852 	, m_test	(test)
853 	, m_flag	(flag)
854 {
855 }
856 
initPrograms(SourceCollections & sourceCollections) const857 void BuiltinVariableRenderTest::initPrograms (SourceCollections& sourceCollections) const
858 {
859 	{
860 		std::ostringstream src;
861 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
862 			<< "out gl_PerVertex\n"
863 			<<" {\n"
864 			<< "	vec4 gl_Position;\n"
865 			<< "	float gl_PointSize;\n"
866 			<< "};\n"
867 			<< "layout(location = 0) in vec4 a_position;\n";
868 		switch(m_test)
869 		{
870 			case TEST_POINT_SIZE:
871 				src	<< "layout(location = 1) in vec4 a_pointSize;\n"
872 					<< "layout(location = 0) out vec4 v_geom_pointSize;\n"
873 					<< "void main (void)\n"
874 					<< "{\n"
875 					<< "	gl_Position = a_position;\n"
876 					<< "	gl_PointSize = 1.0;\n"
877 					<< "	v_geom_pointSize = a_pointSize;\n"
878 					<< "}\n";
879 				break;
880 			case TEST_PRIMITIVE_ID_IN:
881 				src	<< "void main (void)\n"
882 					<< "{\n"
883 					<< "	gl_Position = a_position;\n"
884 					<< "}\n";
885 				break;
886 			case TEST_PRIMITIVE_ID:
887 				src	<< "layout(location = 1) in vec4 a_primitiveID;\n"
888 					<< "layout(location = 0) out vec4 v_geom_primitiveID;\n"
889 					<< "void main (void)\n"
890 					<< "{\n"
891 					<< "	gl_Position = a_position;\n"
892 					<< "	v_geom_primitiveID = a_primitiveID;\n"
893 					<< "}\n";
894 				break;
895 			default:
896 				DE_ASSERT(0);
897 				break;
898 		}
899 		sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
900 	}
901 
902 	{
903 		std::ostringstream src;
904 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
905 			<< "in gl_PerVertex\n"
906 			<<"{\n"
907 			<< "	vec4 gl_Position;\n"
908 			<< "	float gl_PointSize;\n"
909 			<< "} gl_in[];\n"
910 			<< "out gl_PerVertex\n"
911 			<<"{\n"
912 			<< "	vec4 gl_Position;\n"
913 			<< "	float gl_PointSize;\n"
914 			<< "};\n";
915 		switch(m_test)
916 		{
917 			case TEST_POINT_SIZE:
918 				src	<< "#extension GL_EXT_geometry_point_size : require\n"
919 					<< "layout(points) in;\n"
920 					<< "layout(points, max_vertices = 1) out;\n"
921 					<< "layout(location = 0) in vec4 v_geom_pointSize[];\n"
922 					<< "layout(location = 0) out vec4 v_frag_FragColor;\n"
923 					<< "void main (void)\n"
924 					<< "{\n"
925 					<< "	gl_Position = gl_in[0].gl_Position;\n"
926 					<< "	gl_PointSize = v_geom_pointSize[0].x + 1.0;\n"
927 					<< "	v_frag_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
928 					<< "	EmitVertex();\n"
929 					<< "}\n";
930 				break;
931 			case TEST_PRIMITIVE_ID_IN:
932 				src	<< "layout(lines) in;\n"
933 					<< "layout(triangle_strip, max_vertices = 10) out;\n"
934 					<< "layout(location = 0) out vec4 v_frag_FragColor;\n"
935 					<< "void main (void)\n"
936 					<< "{\n"
937 					<< "	const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
938 					<< "	const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
939 					<< "	const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
940 					<< "	const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
941 					<< "	const vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
942 					<< "	for (int counter = 0; counter < 3; ++counter)\n"
943 					<< "	{\n"
944 					<< "		float percent = 0.1 * counter;\n"
945 					<< "		gl_Position = gl_in[0].gl_Position * vec4(1.0 + percent, 1.0 + percent, 1.0, 1.0);\n"
946 					<< "		v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
947 					<< "		EmitVertex();\n"
948 					<< "		gl_Position = gl_in[1].gl_Position * vec4(1.0 + percent, 1.0 + percent, 1.0, 1.0);\n"
949 					<< "		v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
950 					<< "		EmitVertex();\n"
951 					<< "	}\n"
952 					<< "}\n";
953 				break;
954 			case TEST_PRIMITIVE_ID:
955 				src	<< "layout(points, invocations=1) in;\n"
956 					<< "layout(triangle_strip, max_vertices = 3) out;\n"
957 					<< "layout(location = 0) in vec4 v_geom_primitiveID[];\n"
958 					<< "void main (void)\n"
959 					<< "{\n"
960 					<< "	gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n"
961 					<< "	gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
962 					<< "	EmitVertex();\n"
963 					<< "	gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n"
964 					<< "	gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
965 					<< "	EmitVertex();\n"
966 					<< "	gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n"
967 					<< "	gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
968 					<< "	EmitVertex();\n"
969 					<< "}\n";
970 				break;
971 			default:
972 				DE_ASSERT(0);
973 				break;
974 		}
975 		sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
976 	}
977 
978 	{
979 		std::ostringstream src;
980 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
981 		switch(m_test)
982 		{
983 			case TEST_POINT_SIZE:
984 				src	<< "layout(location = 0) out vec4 fragColor;\n"
985 					<< "layout(location = 0) in vec4 v_frag_FragColor;\n"
986 					<< "void main (void)\n"
987 					<< "{\n"
988 					<< "	fragColor = v_frag_FragColor;\n"
989 					<< "}\n";
990 				break;
991 			case TEST_PRIMITIVE_ID_IN:
992 				src	<< "layout(location = 0) out vec4 fragColor;\n"
993 					<< "layout(location = 0) in vec4 v_frag_FragColor;\n"
994 					<< "void main (void)\n"
995 					<< "{\n"
996 					<< "	fragColor = v_frag_FragColor;\n"
997 					<< "}\n";
998 				break;
999 			case TEST_PRIMITIVE_ID:
1000 				src	<< "layout(location = 0) out vec4 fragColor;\n"
1001 					<< "void main (void)\n"
1002 					<< "{\n"
1003 					<< "	const vec4 red			= vec4(1.0, 0.0, 0.0, 1.0);\n"
1004 					<< "	const vec4 green		= vec4(0.0, 1.0, 0.0, 1.0);\n"
1005 					<< "	const vec4 blue			= vec4(0.0, 0.0, 1.0, 1.0);\n"
1006 					<< "	const vec4 yellow		= vec4(1.0, 1.0, 0.0, 1.0);\n"
1007 					<< "	const vec4 colors[4]	= vec4[4](yellow, red, green, blue);\n"
1008 					<< "	fragColor = colors[gl_PrimitiveID % 4];\n"
1009 					<< "}\n";
1010 				break;
1011 			default:
1012 				DE_ASSERT(0);
1013 				break;
1014 		}
1015 		sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
1016 	}
1017 }
1018 
createInstance(Context & context) const1019 TestInstance* BuiltinVariableRenderTest::createInstance (Context& context) const
1020 {
1021 	if (m_test == TEST_POINT_SIZE && !checkPointSize(context.getInstanceInterface(), context.getPhysicalDevice()))
1022 			TCU_THROW(NotSupportedError, "Missing feature: pointSize");
1023 	return new BuiltinVariableRenderTestInstance(context, getName(), m_test, m_flag);
1024 }
1025 
createPattern(int count)1026 inline vector<int> createPattern (int count)
1027 {
1028 	vector<int>	pattern;
1029 	pattern.push_back(count);
1030 	return pattern;
1031 }
1032 
createPattern(int count0,int count1)1033 inline vector<int> createPattern (int count0, int count1)
1034 {
1035 	vector<int>	pattern;
1036 	pattern.push_back(count0);
1037 	pattern.push_back(count1);
1038 	return pattern;
1039 }
1040 
1041 } // anonymous
1042 
createBasicGeometryShaderTests(TestContext & testCtx)1043 TestCaseGroup* createBasicGeometryShaderTests (TestContext& testCtx)
1044 {
1045 	MovePtr<TestCaseGroup> basicGroup	(new tcu::TestCaseGroup(testCtx, "basic", "Basic tests."));
1046 
1047 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_10",				"Output 10 vertices",								createPattern(10)));
1048 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_128",				"Output 128 vertices",								createPattern(128)));
1049 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_10_and_100",		"Output 10 and 100 vertices in two invocations",	createPattern(10, 100)));
1050 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_100_and_10",		"Output 100 and 10 vertices in two invocations",	createPattern(100, 10)));
1051 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_0_and_128",			"Output 0 and 128 vertices in two invocations",		createPattern(0, 128)));
1052 	basicGroup->addChild(new GeometryOutputCountTest	(testCtx,	"output_128_and_0",			"Output 128 and 0 vertices in two invocations",		createPattern(128, 0)));
1053 
1054 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_attribute",				"Output varying number of vertices",	READ_ATTRIBUTE,	MODE_WITHOUT_INSTANCING));
1055 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_uniform",				"Output varying number of vertices",	READ_UNIFORM,	MODE_WITHOUT_INSTANCING));
1056 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_texture",				"Output varying number of vertices",	READ_TEXTURE,	MODE_WITHOUT_INSTANCING));
1057 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_attribute_instancing",	"Output varying number of vertices",	READ_ATTRIBUTE,	MODE_WITH_INSTANCING));
1058 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_uniform_instancing",	"Output varying number of vertices",	READ_UNIFORM,	MODE_WITH_INSTANCING));
1059 	basicGroup->addChild(new VaryingOutputCountCase		(testCtx,	"output_vary_by_texture_instancing",	"Output varying number of vertices",	READ_TEXTURE,	MODE_WITH_INSTANCING));
1060 
1061 	basicGroup->addChild(new BuiltinVariableRenderTest	(testCtx,	"point_size",					"test gl_PointSize",								TEST_POINT_SIZE));
1062 	basicGroup->addChild(new BuiltinVariableRenderTest	(testCtx,	"primitive_id_in",				"test gl_PrimitiveIDIn",							TEST_PRIMITIVE_ID_IN));
1063 	basicGroup->addChild(new BuiltinVariableRenderTest	(testCtx,	"primitive_id_in_restarted",	"test gl_PrimitiveIDIn with primitive restart",		TEST_PRIMITIVE_ID_IN, true));
1064 	basicGroup->addChild(new BuiltinVariableRenderTest	(testCtx,	"primitive_id",					"test gl_PrimitiveID",								TEST_PRIMITIVE_ID));
1065 
1066 	return basicGroup.release();
1067 }
1068 
1069 } // geometry
1070 } // vkt
1071