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