1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Functional rasterization tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRasterizationTests.hpp"
27 #include "tcuRasterizationVerifier.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuResultCollector.hpp"
34 #include "vkImageUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "vktTestCase.hpp"
38 #include "vktTestCaseUtil.hpp"
39 #include "vktTestGroupUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkMemUtil.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vkQueryUtil.hpp"
44 #include "vkBuilderUtil.hpp"
45 #include "vkTypeUtil.hpp"
46 #include "vkCmdUtil.hpp"
47 #include "vkObjUtil.hpp"
48 
49 #include <vector>
50 
51 using namespace vk;
52 
53 namespace vkt
54 {
55 namespace rasterization
56 {
57 namespace
58 {
59 
60 using tcu::RasterizationArguments;
61 using tcu::TriangleSceneSpec;
62 using tcu::PointSceneSpec;
63 using tcu::LineSceneSpec;
64 using tcu::LineInterpolationMethod;
65 
66 static const char* const s_shaderVertexTemplate =	"#version 310 es\n"
67 													"layout(location = 0) in highp vec4 a_position;\n"
68 													"layout(location = 1) in highp vec4 a_color;\n"
69 													"layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
70 													"layout (set=0, binding=0) uniform PointSize {\n"
71 													"	highp float u_pointSize;\n"
72 													"};\n"
73 													"void main ()\n"
74 													"{\n"
75 													"	gl_Position = a_position;\n"
76 													"	gl_PointSize = u_pointSize;\n"
77 													"	v_color = a_color;\n"
78 													"}\n";
79 
80 static const char* const s_shaderFragmentTemplate =	"#version 310 es\n"
81 													"layout(location = 0) out highp vec4 fragColor;\n"
82 													"layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
83 													"void main ()\n"
84 													"{\n"
85 													"	fragColor = v_color;\n"
86 													"}\n";
87 enum InterpolationCaseFlags
88 {
89 	INTERPOLATIONFLAGS_NONE = 0,
90 	INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
91 	INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
92 };
93 
94 enum PrimitiveWideness
95 {
96 	PRIMITIVEWIDENESS_NARROW = 0,
97 	PRIMITIVEWIDENESS_WIDE,
98 
99 	PRIMITIVEWIDENESS_LAST
100 };
101 
102 class BaseRenderingTestCase : public TestCase
103 {
104 public:
105 								BaseRenderingTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
106 	virtual						~BaseRenderingTestCase	(void);
107 
108 	virtual void				initPrograms			(vk::SourceCollections& programCollection) const;
109 
110 protected:
111 	const VkSampleCountFlagBits	m_sampleCount;
112 	const deBool				m_flatshade;
113 };
114 
BaseRenderingTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkSampleCountFlagBits sampleCount,deBool flatshade)115 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
116 	: TestCase(context, name, description)
117 	, m_sampleCount	(sampleCount)
118 	, m_flatshade	(flatshade)
119 {
120 }
121 
initPrograms(vk::SourceCollections & programCollection) const122 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
123 {
124 	tcu::StringTemplate					vertexSource	(s_shaderVertexTemplate);
125 	tcu::StringTemplate					fragmentSource	(s_shaderFragmentTemplate);
126 	std::map<std::string, std::string>	params;
127 
128 	params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
129 
130 	programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
131 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
132 }
133 
~BaseRenderingTestCase(void)134 BaseRenderingTestCase::~BaseRenderingTestCase (void)
135 {
136 }
137 
138 class BaseRenderingTestInstance : public TestInstance
139 {
140 public:
141 	enum {
142 		DEFAULT_RENDER_SIZE = 256
143 	};
144 
145 													BaseRenderingTestInstance		(Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE);
146 													~BaseRenderingTestInstance		(void);
147 
148 protected:
149 	void											addImageTransitionBarrier		(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
150 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
151 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
152 	virtual float									getLineWidth					(void) const;
153 	virtual float									getPointSize					(void) const;
154 
155 	virtual
156 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo	(void) const;
157 
158 	virtual
159 	const VkPipelineColorBlendStateCreateInfo*		getColorBlendStateCreateInfo	(void) const;
160 
161 	const tcu::TextureFormat&						getTextureFormat				(void) const;
162 
163 	const deUint32									m_renderSize;
164 	const VkSampleCountFlagBits						m_sampleCount;
165 	const deUint32									m_subpixelBits;
166 	const deBool									m_multisampling;
167 
168 	const VkFormat									m_imageFormat;
169 	const tcu::TextureFormat						m_textureFormat;
170 	Move<VkCommandPool>								m_commandPool;
171 
172 	Move<VkImage>									m_image;
173 	de::MovePtr<Allocation>							m_imageMemory;
174 	Move<VkImageView>								m_imageView;
175 
176 	Move<VkImage>									m_resolvedImage;
177 	de::MovePtr<Allocation>							m_resolvedImageMemory;
178 	Move<VkImageView>								m_resolvedImageView;
179 
180 	Move<VkRenderPass>								m_renderPass;
181 	Move<VkFramebuffer>								m_frameBuffer;
182 
183 	Move<VkDescriptorPool>							m_descriptorPool;
184 	Move<VkDescriptorSet>							m_descriptorSet;
185 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
186 
187 	Move<VkBuffer>									m_uniformBuffer;
188 	de::MovePtr<Allocation>							m_uniformBufferMemory;
189 	const VkDeviceSize								m_uniformBufferSize;
190 
191 	Move<VkPipelineLayout>							m_pipelineLayout;
192 
193 	Move<VkShaderModule>							m_vertexShaderModule;
194 	Move<VkShaderModule>							m_fragmentShaderModule;
195 
196 	Move<VkBuffer>									m_resultBuffer;
197 	de::MovePtr<Allocation>							m_resultBufferMemory;
198 	const VkDeviceSize								m_resultBufferSize;
199 };
200 
BaseRenderingTestInstance(Context & context,VkSampleCountFlagBits sampleCount,deUint32 renderSize)201 BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
202 	: TestInstance			(context)
203 	, m_renderSize			(renderSize)
204 	, m_sampleCount			(sampleCount)
205 	, m_subpixelBits		(context.getDeviceProperties().limits.subPixelPrecisionBits)
206 	, m_multisampling		(m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
207 	, m_imageFormat			(VK_FORMAT_R8G8B8A8_UNORM)
208 	, m_textureFormat		(vk::mapVkFormat(m_imageFormat))
209 	, m_uniformBufferSize	(sizeof(float))
210 	, m_resultBufferSize	(renderSize * renderSize * m_textureFormat.getPixelSize())
211 {
212 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
213 	const VkDevice								vkDevice				= m_context.getDevice();
214 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
215 	Allocator&									allocator				= m_context.getDefaultAllocator();
216 	DescriptorPoolBuilder						descriptorPoolBuilder;
217 	DescriptorSetLayoutBuilder					descriptorSetLayoutBuilder;
218 
219 	// Command Pool
220 	m_commandPool = createCommandPool(vkd, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
221 
222 	// Image
223 	{
224 		const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
225 		VkImageFormatProperties	properties;
226 
227 		if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
228 																					 m_imageFormat,
229 																					 VK_IMAGE_TYPE_2D,
230 																					 VK_IMAGE_TILING_OPTIMAL,
231 																					 imageUsage,
232 																					 0,
233 																					 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
234 		{
235 			TCU_THROW(NotSupportedError, "Format not supported");
236 		}
237 
238 		if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
239 		{
240 			TCU_THROW(NotSupportedError, "Format not supported");
241 		}
242 
243 		const VkImageCreateInfo					imageCreateInfo			=
244 		{
245 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
246 			DE_NULL,									// const void*				pNext;
247 			0u,											// VkImageCreateFlags		flags;
248 			VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
249 			m_imageFormat,								// VkFormat					format;
250 			{ m_renderSize,	m_renderSize, 1u },			// VkExtent3D				extent;
251 			1u,											// deUint32					mipLevels;
252 			1u,											// deUint32					arrayLayers;
253 			m_sampleCount,								// VkSampleCountFlagBits	samples;
254 			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
255 			imageUsage,									// VkImageUsageFlags		usage;
256 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
257 			1u,											// deUint32					queueFamilyIndexCount;
258 			&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
259 			VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
260 		};
261 
262 		m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
263 
264 		m_imageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
265 		VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
266 	}
267 
268 	// Image View
269 	{
270 		const VkImageViewCreateInfo				imageViewCreateInfo		=
271 		{
272 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
273 			DE_NULL,									// const void*					pNext;
274 			0u,											// VkImageViewCreateFlags		flags;
275 			*m_image,									// VkImage						image;
276 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
277 			m_imageFormat,								// VkFormat						format;
278 			makeComponentMappingRGBA(),					// VkComponentMapping			components;
279 			{
280 				VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
281 				0u,											// deUint32						baseMipLevel;
282 				1u,											// deUint32						mipLevels;
283 				0u,											// deUint32						baseArrayLayer;
284 				1u,											// deUint32						arraySize;
285 			},											// VkImageSubresourceRange		subresourceRange;
286 		};
287 
288 		m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
289 	}
290 
291 	if (m_multisampling)
292 	{
293 		{
294 			// Resolved Image
295 			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
296 			VkImageFormatProperties	properties;
297 
298 			if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
299 																						 m_imageFormat,
300 																						 VK_IMAGE_TYPE_2D,
301 																						 VK_IMAGE_TILING_OPTIMAL,
302 																						 imageUsage,
303 																						 0,
304 																						 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
305 			{
306 				TCU_THROW(NotSupportedError, "Format not supported");
307 			}
308 
309 			const VkImageCreateInfo					imageCreateInfo			=
310 			{
311 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
312 				DE_NULL,									// const void*				pNext;
313 				0u,											// VkImageCreateFlags		flags;
314 				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
315 				m_imageFormat,								// VkFormat					format;
316 				{ m_renderSize,	m_renderSize, 1u },			// VkExtent3D				extent;
317 				1u,											// deUint32					mipLevels;
318 				1u,											// deUint32					arrayLayers;
319 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
320 				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
321 				imageUsage,									// VkImageUsageFlags		usage;
322 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
323 				1u,											// deUint32					queueFamilyIndexCount;
324 				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
325 				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
326 			};
327 
328 			m_resolvedImage			= vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
329 			m_resolvedImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
330 			VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
331 		}
332 
333 		// Resolved Image View
334 		{
335 			const VkImageViewCreateInfo				imageViewCreateInfo		=
336 			{
337 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
338 				DE_NULL,									// const void*					pNext;
339 				0u,											// VkImageViewCreateFlags		flags;
340 				*m_resolvedImage,							// VkImage						image;
341 				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
342 				m_imageFormat,								// VkFormat						format;
343 				makeComponentMappingRGBA(),					// VkComponentMapping			components;
344 				{
345 					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
346 					0u,											// deUint32						baseMipLevel;
347 					1u,											// deUint32						mipLevels;
348 					0u,											// deUint32						baseArrayLayer;
349 					1u,											// deUint32						arraySize;
350 				},											// VkImageSubresourceRange		subresourceRange;
351 			};
352 
353 			m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
354 		}
355 
356 	}
357 
358 	// Render Pass
359 	{
360 		const VkImageLayout						imageLayout				= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
361 		const VkAttachmentDescription			attachmentDesc[]		=
362 		{
363 			{
364 				0u,													// VkAttachmentDescriptionFlags		flags;
365 				m_imageFormat,										// VkFormat							format;
366 				m_sampleCount,										// VkSampleCountFlagBits			samples;
367 				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
368 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
369 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
370 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
371 				imageLayout,										// VkImageLayout					initialLayout;
372 				imageLayout,										// VkImageLayout					finalLayout;
373 			},
374 			{
375 				0u,													// VkAttachmentDescriptionFlags		flags;
376 				m_imageFormat,										// VkFormat							format;
377 				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
378 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				loadOp;
379 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
380 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
381 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
382 				imageLayout,										// VkImageLayout					initialLayout;
383 				imageLayout,										// VkImageLayout					finalLayout;
384 			}
385 		};
386 
387 		const VkAttachmentReference				attachmentRef			=
388 		{
389 			0u,													// deUint32							attachment;
390 			imageLayout,										// VkImageLayout					layout;
391 		};
392 
393 		const VkAttachmentReference				resolveAttachmentRef	=
394 		{
395 			1u,													// deUint32							attachment;
396 			imageLayout,										// VkImageLayout					layout;
397 		};
398 
399 		const VkSubpassDescription				subpassDesc				=
400 		{
401 			0u,													// VkSubpassDescriptionFlags		flags;
402 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
403 			0u,													// deUint32							inputAttachmentCount;
404 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
405 			1u,													// deUint32							colorAttachmentCount;
406 			&attachmentRef,										// const VkAttachmentReference*		pColorAttachments;
407 			m_multisampling ? &resolveAttachmentRef : DE_NULL,	// const VkAttachmentReference*		pResolveAttachments;
408 			DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
409 			0u,													// deUint32							preserveAttachmentCount;
410 			DE_NULL,											// const VkAttachmentReference*		pPreserveAttachments;
411 		};
412 
413 		const VkRenderPassCreateInfo			renderPassCreateInfo	=
414 		{
415 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
416 			DE_NULL,											// const void*						pNext;
417 			0u,													// VkRenderPassCreateFlags			flags;
418 			m_multisampling ? 2u : 1u,							// deUint32							attachmentCount;
419 			attachmentDesc,										// const VkAttachmentDescription*	pAttachments;
420 			1u,													// deUint32							subpassCount;
421 			&subpassDesc,										// const VkSubpassDescription*		pSubpasses;
422 			0u,													// deUint32							dependencyCount;
423 			DE_NULL,											// const VkSubpassDependency*		pDependencies;
424 		};
425 
426 		m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
427 	}
428 
429 	// FrameBuffer
430 	{
431 		const VkImageView						attachments[]			=
432 		{
433 			*m_imageView,
434 			*m_resolvedImageView
435 		};
436 
437 		const VkFramebufferCreateInfo			framebufferCreateInfo	=
438 		{
439 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
440 			DE_NULL,									// const void*				pNext;
441 			0u,											// VkFramebufferCreateFlags	flags;
442 			*m_renderPass,								// VkRenderPass				renderPass;
443 			m_multisampling ? 2u : 1u,					// deUint32					attachmentCount;
444 			attachments,								// const VkImageView*		pAttachments;
445 			m_renderSize,								// deUint32					width;
446 			m_renderSize,								// deUint32					height;
447 			1u,											// deUint32					layers;
448 		};
449 
450 		m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
451 	}
452 
453 	// Uniform Buffer
454 	{
455 		const VkBufferCreateInfo				bufferCreateInfo		=
456 		{
457 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
458 			DE_NULL,									// const void*			pNext;
459 			0u,											// VkBufferCreateFlags	flags;
460 			m_uniformBufferSize,						// VkDeviceSize			size;
461 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
462 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
463 			1u,											// deUint32				queueFamilyIndexCount;
464 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
465 		};
466 
467 		m_uniformBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
468 		m_uniformBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
469 
470 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
471 	}
472 
473 	// Descriptors
474 	{
475 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
476 		m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
477 
478 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
479 		m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
480 
481 		const VkDescriptorSetAllocateInfo		descriptorSetParams		=
482 		{
483 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
484 			DE_NULL,
485 			*m_descriptorPool,
486 			1u,
487 			&m_descriptorSetLayout.get(),
488 		};
489 
490 		m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
491 
492 		const VkDescriptorBufferInfo			descriptorBufferInfo	=
493 		{
494 			*m_uniformBuffer,							// VkBuffer		buffer;
495 			0u,											// VkDeviceSize	offset;
496 			VK_WHOLE_SIZE								// VkDeviceSize	range;
497 		};
498 
499 		const VkWriteDescriptorSet				writeDescritporSet		=
500 		{
501 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
502 			DE_NULL,									// const void*						pNext;
503 			*m_descriptorSet,							// VkDescriptorSet					destSet;
504 			0,											// deUint32							destBinding;
505 			0,											// deUint32							destArrayElement;
506 			1u,											// deUint32							count;
507 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			// VkDescriptorType					descriptorType;
508 			DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo;
509 			&descriptorBufferInfo,						// const VkDescriptorBufferInfo*	pBufferInfo;
510 			DE_NULL										// const VkBufferView*				pTexelBufferView;
511 		};
512 
513 		vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
514 	}
515 
516 	// Pipeline Layout
517 	{
518 		const VkPipelineLayoutCreateInfo		pipelineLayoutCreateInfo	=
519 		{
520 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
521 			DE_NULL,											// const void*					pNext;
522 			0u,													// VkPipelineLayoutCreateFlags	flags;
523 			1u,													// deUint32						descriptorSetCount;
524 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*	pSetLayouts;
525 			0u,													// deUint32						pushConstantRangeCount;
526 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
527 		};
528 
529 		m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
530 	}
531 
532 	// Shaders
533 	{
534 		m_vertexShaderModule	= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
535 		m_fragmentShaderModule	= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
536 	}
537 
538 	// Result Buffer
539 	{
540 		const VkBufferCreateInfo				bufferCreateInfo		=
541 		{
542 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
543 			DE_NULL,									// const void*			pNext;
544 			0u,											// VkBufferCreateFlags	flags;
545 			m_resultBufferSize,							// VkDeviceSize			size;
546 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
547 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
548 			1u,											// deUint32				queueFamilyIndexCount;
549 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
550 		};
551 
552 		m_resultBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
553 		m_resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
554 
555 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
556 	}
557 
558 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
559 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
560 }
561 
~BaseRenderingTestInstance(void)562 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
563 {
564 }
565 
566 
addImageTransitionBarrier(VkCommandBuffer commandBuffer,VkImage image,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkImageLayout oldLayout,VkImageLayout newLayout) const567 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
568 {
569 
570 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
571 
572 	const VkImageSubresourceRange	subResourcerange	=
573 	{
574 		VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
575 		0,								// deUint32				baseMipLevel;
576 		1,								// deUint32				levelCount;
577 		0,								// deUint32				baseArrayLayer;
578 		1								// deUint32				layerCount;
579 	};
580 
581 	const VkImageMemoryBarrier		imageBarrier		=
582 	{
583 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
584 		DE_NULL,									// const void*				pNext;
585 		srcAccessMask,								// VkAccessFlags			srcAccessMask;
586 		dstAccessMask,								// VkAccessFlags			dstAccessMask;
587 		oldLayout,									// VkImageLayout			oldLayout;
588 		newLayout,									// VkImageLayout			newLayout;
589 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
590 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
591 		image,										// VkImage					image;
592 		subResourcerange							// VkImageSubresourceRange	subresourceRange;
593 	};
594 
595 	vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
596 }
597 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,VkPrimitiveTopology primitiveTopology)598 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
599 {
600 	// default to color white
601 	const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
602 
603 	drawPrimitives(result, vertexData, colorData, primitiveTopology);
604 }
605 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,const std::vector<tcu::Vec4> & colorData,VkPrimitiveTopology primitiveTopology)606 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
607 {
608 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
609 	const VkDevice								vkDevice				= m_context.getDevice();
610 	const VkQueue								queue					= m_context.getUniversalQueue();
611 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
612 	Allocator&									allocator				= m_context.getDefaultAllocator();
613 	const size_t								attributeBatchSize		= positionData.size() * sizeof(tcu::Vec4);
614 
615 	Move<VkCommandBuffer>						commandBuffer;
616 	Move<VkPipeline>							graphicsPipeline;
617 	Move<VkBuffer>								vertexBuffer;
618 	de::MovePtr<Allocation>						vertexBufferMemory;
619 	const VkPhysicalDeviceProperties			properties				= m_context.getDeviceProperties();
620 
621 	if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
622 	{
623 		std::stringstream message;
624 		message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
625 		TCU_THROW(NotSupportedError, message.str().c_str());
626 	}
627 
628 	// Create Graphics Pipeline
629 	{
630 		const VkVertexInputBindingDescription	vertexInputBindingDescription =
631 		{
632 			0u,								// deUint32					binding;
633 			sizeof(tcu::Vec4),				// deUint32					strideInBytes;
634 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
635 		};
636 
637 		const VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2] =
638 		{
639 			{
640 				0u,									// deUint32	location;
641 				0u,									// deUint32	binding;
642 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
643 				0u									// deUint32	offsetInBytes;
644 			},
645 			{
646 				1u,									// deUint32	location;
647 				0u,									// deUint32	binding;
648 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
649 				(deUint32)attributeBatchSize		// deUint32	offsetInBytes;
650 			}
651 		};
652 
653 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams =
654 		{
655 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
656 			DE_NULL,														// const void*								pNext;
657 			0,																// VkPipelineVertexInputStateCreateFlags	flags;
658 			1u,																// deUint32									bindingCount;
659 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
660 			2u,																// deUint32									attributeCount;
661 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
662 		};
663 
664 		const std::vector<VkViewport>	viewports	(1, makeViewport(tcu::UVec2(m_renderSize)));
665 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(tcu::UVec2(m_renderSize)));
666 
667 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
668 		{
669 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
670 			DE_NULL,														// const void*								pNext;
671 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
672 			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
673 			VK_FALSE,														// VkBool32									sampleShadingEnable;
674 			0.0f,															// float									minSampleShading;
675 			DE_NULL,														// const VkSampleMask*						pSampleMask;
676 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
677 			VK_FALSE														// VkBool32									alphaToOneEnable;
678 		};
679 
680 		graphicsPipeline = makeGraphicsPipeline(vkd,								// const DeviceInterface&                        vk
681 												vkDevice,							// const VkDevice                                device
682 												*m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
683 												*m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
684 												DE_NULL,							// const VkShaderModule                          tessellationControlShaderModule
685 												DE_NULL,							// const VkShaderModule                          tessellationEvalShaderModule
686 												DE_NULL,							// const VkShaderModule                          geometryShaderModule
687 												*m_fragmentShaderModule,			// const VkShaderModule                          fragmentShaderModule
688 												*m_renderPass,						// const VkRenderPass                            renderPass
689 												viewports,							// const std::vector<VkViewport>&                viewports
690 												scissors,							// const std::vector<VkRect2D>&                  scissors
691 												primitiveTopology,					// const VkPrimitiveTopology                     topology
692 												0u,									// const deUint32                                subpass
693 												0u,									// const deUint32                                patchControlPoints
694 												&vertexInputStateParams,			// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
695 												getRasterizationStateCreateInfo(),	// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
696 												&multisampleStateParams,			// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
697 												DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo,
698 												getColorBlendStateCreateInfo());	// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
699 	}
700 
701 	// Create Vertex Buffer
702 	{
703 		const VkBufferCreateInfo			vertexBufferParams		=
704 		{
705 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
706 			DE_NULL,									// const void*			pNext;
707 			0u,											// VkBufferCreateFlags	flags;
708 			attributeBatchSize * 2,						// VkDeviceSize			size;
709 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
710 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
711 			1u,											// deUint32				queueFamilyCount;
712 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
713 		};
714 
715 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
716 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
717 
718 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
719 
720 		// Load vertices into vertex buffer
721 		deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
722 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, colorData.data(), attributeBatchSize);
723 		flushAlloc(vkd, vkDevice, *vertexBufferMemory);
724 	}
725 
726 	// Create Command Buffer
727 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
728 
729 	// Begin Command Buffer
730 	beginCommandBuffer(vkd, *commandBuffer);
731 
732 	addImageTransitionBarrier(*commandBuffer, *m_image,
733 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
734 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
735 							  0,												// VkAccessFlags			srcAccessMask
736 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
737 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
738 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
739 
740 	if (m_multisampling) {
741 		addImageTransitionBarrier(*commandBuffer, *m_resolvedImage,
742 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
743 								  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
744 								  0,												// VkAccessFlags			srcAccessMask
745 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
746 								  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
747 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
748 	}
749 
750 	// Begin Render Pass
751 	beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
752 
753 	const VkDeviceSize						vertexBufferOffset		= 0;
754 
755 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
756 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
757 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
758 	vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
759 	endRenderPass(vkd, *commandBuffer);
760 
761 	// Copy Image
762 	copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
763 
764 	endCommandBuffer(vkd, *commandBuffer);
765 
766 	// Set Point Size
767 	{
768 		float	pointSize	= getPointSize();
769 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
770 		flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
771 	}
772 
773 	// Submit
774 	submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
775 
776 	invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
777 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
778 }
779 
getLineWidth(void) const780 float BaseRenderingTestInstance::getLineWidth (void) const
781 {
782 	return 1.0f;
783 }
784 
getPointSize(void) const785 float BaseRenderingTestInstance::getPointSize (void) const
786 {
787 	return 1.0f;
788 }
789 
getRasterizationStateCreateInfo(void) const790 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
791 {
792 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
793 	{
794 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
795 		DE_NULL,														// const void*								pNext;
796 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
797 		false,															// VkBool32									depthClipEnable;
798 		false,															// VkBool32									rasterizerDiscardEnable;
799 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
800 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
801 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
802 		VK_FALSE,														// VkBool32									depthBiasEnable;
803 		0.0f,															// float									depthBias;
804 		0.0f,															// float									depthBiasClamp;
805 		0.0f,															// float									slopeScaledDepthBias;
806 		getLineWidth(),													// float									lineWidth;
807 	};
808 
809 	rasterizationStateCreateInfo.lineWidth = getLineWidth();
810 	return &rasterizationStateCreateInfo;
811 }
812 
getColorBlendStateCreateInfo(void) const813 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
814 {
815 	static const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
816 	{
817 		false,														// VkBool32			blendEnable;
818 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
819 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendColor;
820 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
821 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
822 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendAlpha;
823 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
824 		(VK_COLOR_COMPONENT_R_BIT |
825 		 VK_COLOR_COMPONENT_G_BIT |
826 		 VK_COLOR_COMPONENT_B_BIT |
827 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
828 	};
829 
830 	static const VkPipelineColorBlendStateCreateInfo	colorBlendStateParams		=
831 	{
832 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
833 		DE_NULL,													// const void*									pNext;
834 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
835 		false,														// VkBool32										logicOpEnable;
836 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
837 		1u,															// deUint32										attachmentCount;
838 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
839 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
840 	};
841 
842 	return &colorBlendStateParams;
843 }
844 
getTextureFormat(void) const845 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
846 {
847 	return m_textureFormat;
848 }
849 
850 class BaseTriangleTestInstance : public BaseRenderingTestInstance
851 {
852 public:
853 							BaseTriangleTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount);
854 	virtual tcu::TestStatus	iterate						(void);
855 
856 private:
857 	virtual void			generateTriangles			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
858 
859 	int						m_iteration;
860 	const int				m_iterationCount;
861 	VkPrimitiveTopology		m_primitiveTopology;
862 	bool					m_allIterationsPassed;
863 };
864 
BaseTriangleTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,VkSampleCountFlagBits sampleCount)865 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount)
866 	: BaseRenderingTestInstance		(context, sampleCount)
867 	, m_iteration					(0)
868 	, m_iterationCount				(3)
869 	, m_primitiveTopology			(primitiveTopology)
870 	, m_allIterationsPassed			(true)
871 {
872 }
873 
iterate(void)874 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
875 {
876 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
877 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
878 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
879 	std::vector<tcu::Vec4>							drawBuffer;
880 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
881 
882 	generateTriangles(m_iteration, drawBuffer, triangles);
883 
884 	// draw image
885 	drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
886 
887 	// compare
888 	{
889 		bool					compareOk;
890 		RasterizationArguments	args;
891 		TriangleSceneSpec		scene;
892 
893 		tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
894 
895 		args.numSamples		= m_multisampling ? 1 : 0;
896 		args.subpixelBits	= m_subpixelBits;
897 		args.redBits		= colorBits[0];
898 		args.greenBits		= colorBits[1];
899 		args.blueBits		= colorBits[2];
900 
901 		scene.triangles.swap(triangles);
902 
903 		compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
904 
905 		if (!compareOk)
906 			m_allIterationsPassed = false;
907 	}
908 
909 	// result
910 	if (++m_iteration == m_iterationCount)
911 	{
912 		if (m_allIterationsPassed)
913 			return tcu::TestStatus::pass("Pass");
914 		else
915 			return tcu::TestStatus::fail("Incorrect rasterization");
916 	}
917 	else
918 		return tcu::TestStatus::incomplete();
919 }
920 
921 class BaseLineTestInstance : public BaseRenderingTestInstance
922 {
923 public:
924 							BaseLineTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
925 	virtual tcu::TestStatus	iterate					(void);
926 	virtual float			getLineWidth			(void) const;
927 
928 private:
929 	virtual void			generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
930 
931 	int						m_iteration;
932 	const int				m_iterationCount;
933 	VkPrimitiveTopology		m_primitiveTopology;
934 	const PrimitiveWideness	m_primitiveWideness;
935 	bool					m_allIterationsPassed;
936 	float					m_maxLineWidth;
937 	std::vector<float>		m_lineWidths;
938 };
939 
BaseLineTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)940 BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
941 	: BaseRenderingTestInstance			(context, sampleCount)
942 	, m_iteration						(0)
943 	, m_iterationCount					(3)
944 	, m_primitiveTopology				(primitiveTopology)
945 	, m_primitiveWideness				(wideness)
946 	, m_allIterationsPassed				(true)
947 	, m_maxLineWidth					(1.0f)
948 {
949 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
950 
951 	if (!context.getDeviceProperties().limits.strictLines)
952 		TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
953 
954 	// create line widths
955 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
956 	{
957 		m_lineWidths.resize(m_iterationCount, 1.0f);
958 	}
959 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
960 	{
961 		if (!m_context.getDeviceFeatures().wideLines)
962 			TCU_THROW(NotSupportedError , "wide line support required");
963 
964 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
965 
966 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
967 
968 		// no wide line support
969 		if (range[1] <= 1.0f)
970 			TCU_THROW(NotSupportedError, "wide line support required");
971 
972 		// set hand picked sizes
973 		m_lineWidths.push_back(5.0f);
974 		m_lineWidths.push_back(10.0f);
975 		m_lineWidths.push_back(range[1]);
976 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
977 
978 		m_maxLineWidth = range[1];
979 	}
980 	else
981 		DE_ASSERT(false);
982 }
983 
iterate(void)984 tcu::TestStatus BaseLineTestInstance::iterate (void)
985 {
986 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
987 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
988 	const float								lineWidth				= getLineWidth();
989 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
990 	std::vector<tcu::Vec4>					drawBuffer;
991 	std::vector<LineSceneSpec::SceneLine>	lines;
992 
993 	// supported?
994 	if (lineWidth <= m_maxLineWidth)
995 	{
996 		// gen data
997 		generateLines(m_iteration, drawBuffer, lines);
998 
999 		// draw image
1000 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1001 
1002 		// compare
1003 		{
1004 			RasterizationArguments	args;
1005 			LineSceneSpec			scene;
1006 
1007 
1008 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1009 
1010 			args.numSamples		= m_multisampling ? 1 : 0;
1011 			args.subpixelBits	= m_subpixelBits;
1012 			args.redBits		= colorBits[0];
1013 			args.greenBits		= colorBits[1];
1014 			args.blueBits		= colorBits[2];
1015 
1016 			scene.lines.swap(lines);
1017 			scene.lineWidth = lineWidth;
1018 
1019 			if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
1020 				m_allIterationsPassed = false;
1021 		}
1022 	}
1023 	else
1024 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1025 
1026 	// result
1027 	if (++m_iteration == m_iterationCount)
1028 	{
1029 		if (m_allIterationsPassed)
1030 			return tcu::TestStatus::pass("Pass");
1031 		else
1032 			return tcu::TestStatus::fail("Incorrect rasterization");
1033 	}
1034 	else
1035 		return tcu::TestStatus::incomplete();
1036 }
1037 
1038 
getLineWidth(void) const1039 float BaseLineTestInstance::getLineWidth (void) const
1040 {
1041 	return m_lineWidths[m_iteration];
1042 }
1043 
1044 
1045 class PointTestInstance : public BaseRenderingTestInstance
1046 {
1047 public:
1048 							PointTestInstance		(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
1049 	virtual tcu::TestStatus	iterate					(void);
1050 	virtual float			getPointSize			(void) const;
1051 
1052 private:
1053 	virtual void			generatePoints			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
1054 
1055 	int						m_iteration;
1056 	const int				m_iterationCount;
1057 	const PrimitiveWideness	m_primitiveWideness;
1058 	bool					m_allIterationsPassed;
1059 	float					m_maxPointSize;
1060 	std::vector<float>		m_pointSizes;
1061 };
1062 
PointTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1063 PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1064 	: BaseRenderingTestInstance	(context, sampleCount)
1065 	, m_iteration				(0)
1066 	, m_iterationCount			(3)
1067 	, m_primitiveWideness		(wideness)
1068 	, m_allIterationsPassed		(true)
1069 	, m_maxPointSize			(1.0f)
1070 {
1071 	// create point sizes
1072 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1073 	{
1074 		m_pointSizes.resize(m_iterationCount, 1.0f);
1075 	}
1076 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1077 	{
1078 		if (!m_context.getDeviceFeatures().largePoints)
1079 			TCU_THROW(NotSupportedError , "large point support required");
1080 
1081 		const float*	range = context.getDeviceProperties().limits.pointSizeRange;
1082 
1083 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1084 
1085 		// no wide line support
1086 		if (range[1] <= 1.0f)
1087 			TCU_THROW(NotSupportedError , "wide point support required");
1088 
1089 		// set hand picked sizes
1090 		m_pointSizes.push_back(10.0f);
1091 		m_pointSizes.push_back(25.0f);
1092 		m_pointSizes.push_back(range[1]);
1093 		DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
1094 
1095 		m_maxPointSize = range[1];
1096 	}
1097 	else
1098 		DE_ASSERT(false);
1099 }
1100 
iterate(void)1101 tcu::TestStatus PointTestInstance::iterate (void)
1102 {
1103 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1104 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1105 	const float								pointSize				= getPointSize();
1106 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1107 	std::vector<tcu::Vec4>					drawBuffer;
1108 	std::vector<PointSceneSpec::ScenePoint>	points;
1109 
1110 	// supported?
1111 	if (pointSize <= m_maxPointSize)
1112 	{
1113 		// gen data
1114 		generatePoints(m_iteration, drawBuffer, points);
1115 
1116 		// draw image
1117 		drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1118 
1119 		// compare
1120 		{
1121 			bool					compareOk;
1122 			RasterizationArguments	args;
1123 			PointSceneSpec			scene;
1124 
1125 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1126 
1127 			args.numSamples		= m_multisampling ? 1 : 0;
1128 			args.subpixelBits	= m_subpixelBits;
1129 			args.redBits		= colorBits[0];
1130 			args.greenBits		= colorBits[1];
1131 			args.blueBits		= colorBits[2];
1132 
1133 			scene.points.swap(points);
1134 
1135 			compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1136 
1137 			if (!compareOk)
1138 				m_allIterationsPassed = false;
1139 		}
1140 	}
1141 	else
1142 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1143 
1144 	// result
1145 	if (++m_iteration == m_iterationCount)
1146 	{
1147 		if (m_allIterationsPassed)
1148 			return tcu::TestStatus::pass("Pass");
1149 		else
1150 			return tcu::TestStatus::fail("Incorrect rasterization");
1151 	}
1152 	else
1153 		return tcu::TestStatus::incomplete();
1154 }
1155 
getPointSize(void) const1156 float PointTestInstance::getPointSize (void) const
1157 {
1158 	return m_pointSizes[m_iteration];
1159 }
1160 
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)1161 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
1162 {
1163 	outData.resize(6);
1164 
1165 	switch (iteration)
1166 	{
1167 		case 0:
1168 			// \note: these values are chosen arbitrarily
1169 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1170 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1171 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1172 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1173 			outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
1174 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1175 			break;
1176 
1177 		case 1:
1178 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1179 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1180 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1181 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1182 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1183 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1184 			break;
1185 
1186 		case 2:
1187 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1188 			outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
1189 			outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
1190 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1191 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1192 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1193 			break;
1194 	}
1195 
1196 	outPoints.resize(outData.size());
1197 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1198 	{
1199 		outPoints[pointNdx].position = outData[pointNdx];
1200 		outPoints[pointNdx].pointSize = getPointSize();
1201 	}
1202 
1203 	// log
1204 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
1205 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1206 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
1207 }
1208 
1209 template <typename ConcreteTestInstance>
1210 class BaseTestCase : public BaseRenderingTestCase
1211 {
1212 public:
BaseTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1213 							BaseTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1214 								: BaseRenderingTestCase(context, name, description, sampleCount)
1215 							{}
1216 
createInstance(Context & context) const1217 	virtual TestInstance*	createInstance	(Context& context) const
1218 							{
1219 								return new ConcreteTestInstance(context, m_sampleCount);
1220 							}
1221 };
1222 
1223 class TrianglesTestInstance : public BaseTriangleTestInstance
1224 {
1225 public:
TrianglesTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1226 							TrianglesTestInstance	(Context& context, VkSampleCountFlagBits sampleCount)
1227 								: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
1228 							{}
1229 
1230 	void					generateTriangles		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1231 };
1232 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1233 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1234 {
1235 	outData.resize(6);
1236 
1237 	switch (iteration)
1238 	{
1239 		case 0:
1240 			// \note: these values are chosen arbitrarily
1241 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1242 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1243 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1244 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1245 			outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1246 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1247 			break;
1248 
1249 		case 1:
1250 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1251 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1252 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1253 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1254 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1255 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1256 			break;
1257 
1258 		case 2:
1259 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1260 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1261 			outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
1262 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1263 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1264 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1265 			break;
1266 	}
1267 
1268 	outTriangles.resize(2);
1269 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
1270 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
1271 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
1272 
1273 	outTriangles[1].positions[0] = outData[3];	outTriangles[1].sharedEdge[0] = false;
1274 	outTriangles[1].positions[1] = outData[4];	outTriangles[1].sharedEdge[1] = false;
1275 	outTriangles[1].positions[2] = outData[5];	outTriangles[1].sharedEdge[2] = false;
1276 
1277 	// log
1278 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
1279 	for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
1280 	{
1281 		m_context.getTestContext().getLog()
1282 			<< tcu::TestLog::Message
1283 			<< "Triangle " << (triangleNdx+1) << ":"
1284 			<< "\n\t" << outTriangles[triangleNdx].positions[0]
1285 			<< "\n\t" << outTriangles[triangleNdx].positions[1]
1286 			<< "\n\t" << outTriangles[triangleNdx].positions[2]
1287 			<< tcu::TestLog::EndMessage;
1288 	}
1289 }
1290 
1291 class TriangleStripTestInstance : public BaseTriangleTestInstance
1292 {
1293 public:
TriangleStripTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1294 				TriangleStripTestInstance		(Context& context, VkSampleCountFlagBits sampleCount)
1295 					: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
1296 				{}
1297 
1298 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1299 };
1300 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1301 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1302 {
1303 	outData.resize(5);
1304 
1305 	switch (iteration)
1306 	{
1307 		case 0:
1308 			// \note: these values are chosen arbitrarily
1309 			outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
1310 			outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
1311 			outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
1312 			outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
1313 			outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
1314 			break;
1315 
1316 		case 1:
1317 			outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
1318 			outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
1319 			outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
1320 			outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
1321 			outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
1322 			break;
1323 
1324 		case 2:
1325 			outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
1326 			outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
1327 			outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
1328 			outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
1329 			outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
1330 			break;
1331 	}
1332 
1333 	outTriangles.resize(3);
1334 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
1335 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = true;
1336 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
1337 
1338 	outTriangles[1].positions[0] = outData[2];	outTriangles[1].sharedEdge[0] = true;
1339 	outTriangles[1].positions[1] = outData[1];	outTriangles[1].sharedEdge[1] = false;
1340 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
1341 
1342 	outTriangles[2].positions[0] = outData[2];	outTriangles[2].sharedEdge[0] = true;
1343 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
1344 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
1345 
1346 	// log
1347 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1348 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1349 	{
1350 		m_context.getTestContext().getLog()
1351 			<< tcu::TestLog::Message
1352 			<< "\t" << outData[vtxNdx]
1353 			<< tcu::TestLog::EndMessage;
1354 	}
1355 }
1356 
1357 class TriangleFanTestInstance : public BaseTriangleTestInstance
1358 {
1359 public:
TriangleFanTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1360 				TriangleFanTestInstance			(Context& context, VkSampleCountFlagBits sampleCount)
1361 					: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
1362 				{}
1363 
1364 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1365 };
1366 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1367 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1368 {
1369 	outData.resize(5);
1370 
1371 	switch (iteration)
1372 	{
1373 		case 0:
1374 			// \note: these values are chosen arbitrarily
1375 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1376 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1377 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1378 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1379 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
1380 			break;
1381 
1382 		case 1:
1383 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1384 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1385 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1386 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1387 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1388 			break;
1389 
1390 		case 2:
1391 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1392 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1393 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1394 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1395 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1396 			break;
1397 	}
1398 
1399 	outTriangles.resize(3);
1400 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
1401 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
1402 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = true;
1403 
1404 	outTriangles[1].positions[0] = outData[0];	outTriangles[1].sharedEdge[0] = true;
1405 	outTriangles[1].positions[1] = outData[2];	outTriangles[1].sharedEdge[1] = false;
1406 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
1407 
1408 	outTriangles[2].positions[0] = outData[0];	outTriangles[2].sharedEdge[0] = true;
1409 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
1410 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
1411 
1412 	// log
1413 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1414 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1415 	{
1416 		m_context.getTestContext().getLog()
1417 			<< tcu::TestLog::Message
1418 			<< "\t" << outData[vtxNdx]
1419 			<< tcu::TestLog::EndMessage;
1420 	}
1421 }
1422 
1423 template <typename ConcreteTestInstance>
1424 class WidenessTestCase : public BaseRenderingTestCase
1425 {
1426 public:
WidenessTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1427 								WidenessTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1428 									: BaseRenderingTestCase(context, name, description, sampleCount)
1429 									, m_wideness(wideness)
1430 								{}
1431 
createInstance(Context & context) const1432 	virtual TestInstance*		createInstance		(Context& context) const
1433 								{
1434 									return new ConcreteTestInstance(context, m_wideness, m_sampleCount);
1435 								}
1436 protected:
1437 	const PrimitiveWideness		m_wideness;
1438 };
1439 
1440 class LinesTestInstance : public BaseLineTestInstance
1441 {
1442 public:
LinesTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1443 								LinesTestInstance	(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1444 									: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount)
1445 								{}
1446 
1447 	virtual void				generateLines		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1448 };
1449 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1450 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1451 {
1452 	outData.resize(6);
1453 
1454 	switch (iteration)
1455 	{
1456 		case 0:
1457 			// \note: these values are chosen arbitrarily
1458 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1459 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1460 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1461 			outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
1462 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
1463 			outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
1464 			break;
1465 
1466 		case 1:
1467 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1468 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1469 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1470 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1471 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1472 			outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
1473 			break;
1474 
1475 		case 2:
1476 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1477 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1478 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1479 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1480 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1481 			outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
1482 			break;
1483 	}
1484 
1485 	outLines.resize(3);
1486 	outLines[0].positions[0] = outData[0];
1487 	outLines[0].positions[1] = outData[1];
1488 	outLines[1].positions[0] = outData[2];
1489 	outLines[1].positions[1] = outData[3];
1490 	outLines[2].positions[0] = outData[4];
1491 	outLines[2].positions[1] = outData[5];
1492 
1493 	// log
1494 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
1495 	for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
1496 	{
1497 		m_context.getTestContext().getLog()
1498 			<< tcu::TestLog::Message
1499 			<< "Line " << (lineNdx+1) << ":"
1500 			<< "\n\t" << outLines[lineNdx].positions[0]
1501 			<< "\n\t" << outLines[lineNdx].positions[1]
1502 			<< tcu::TestLog::EndMessage;
1503 	}
1504 }
1505 
1506 class LineStripTestInstance : public BaseLineTestInstance
1507 {
1508 public:
LineStripTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1509 					LineStripTestInstance	(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1510 						: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount)
1511 					{}
1512 
1513 	virtual void	generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1514 };
1515 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1516 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1517 {
1518 	outData.resize(4);
1519 
1520 	switch (iteration)
1521 	{
1522 		case 0:
1523 			// \note: these values are chosen arbitrarily
1524 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1525 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1526 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1527 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1528 			break;
1529 
1530 		case 1:
1531 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1532 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1533 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1534 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1535 			break;
1536 
1537 		case 2:
1538 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1539 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1540 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1541 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1542 			break;
1543 	}
1544 
1545 	outLines.resize(3);
1546 	outLines[0].positions[0] = outData[0];
1547 	outLines[0].positions[1] = outData[1];
1548 	outLines[1].positions[0] = outData[1];
1549 	outLines[1].positions[1] = outData[2];
1550 	outLines[2].positions[0] = outData[2];
1551 	outLines[2].positions[1] = outData[3];
1552 
1553 	// log
1554 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1555 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1556 	{
1557 		m_context.getTestContext().getLog()
1558 			<< tcu::TestLog::Message
1559 			<< "\t" << outData[vtxNdx]
1560 			<< tcu::TestLog::EndMessage;
1561 	}
1562 }
1563 
1564 class FillRuleTestInstance : public BaseRenderingTestInstance
1565 {
1566 public:
1567 	enum FillRuleCaseType
1568 	{
1569 		FILLRULECASE_BASIC = 0,
1570 		FILLRULECASE_REVERSED,
1571 		FILLRULECASE_CLIPPED_FULL,
1572 		FILLRULECASE_CLIPPED_PARTIAL,
1573 		FILLRULECASE_PROJECTED,
1574 
1575 		FILLRULECASE_LAST
1576 	};
1577 														FillRuleTestInstance			(Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
1578 	virtual tcu::TestStatus								iterate							(void);
1579 
1580 private:
1581 
1582 	virtual const VkPipelineColorBlendStateCreateInfo*	getColorBlendStateCreateInfo	(void) const;
1583 	int													getRenderSize					(FillRuleCaseType type) const;
1584 	int													getNumIterations				(FillRuleCaseType type) const;
1585 	void												generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData) const;
1586 
1587 	const FillRuleCaseType								m_caseType;
1588 	int													m_iteration;
1589 	const int											m_iterationCount;
1590 	bool												m_allIterationsPassed;
1591 
1592 };
1593 
FillRuleTestInstance(Context & context,FillRuleCaseType type,VkSampleCountFlagBits sampleCount)1594 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
1595 	: BaseRenderingTestInstance		(context, sampleCount, getRenderSize(type))
1596 	, m_caseType					(type)
1597 	, m_iteration					(0)
1598 	, m_iterationCount				(getNumIterations(type))
1599 	, m_allIterationsPassed			(true)
1600 {
1601 	DE_ASSERT(type < FILLRULECASE_LAST);
1602 }
1603 
iterate(void)1604 tcu::TestStatus FillRuleTestInstance::iterate (void)
1605 {
1606 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1607 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1608 	tcu::IVec4								colorBits				= tcu::getTextureFormatBitDepth(getTextureFormat());
1609 	const int								thresholdRed			= 1 << (8 - colorBits[0]);
1610 	const int								thresholdGreen			= 1 << (8 - colorBits[1]);
1611 	const int								thresholdBlue			= 1 << (8 - colorBits[2]);
1612 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1613 	std::vector<tcu::Vec4>					drawBuffer;
1614 
1615 	generateTriangles(m_iteration, drawBuffer);
1616 
1617 	// draw image
1618 	{
1619 		const std::vector<tcu::Vec4>	colorBuffer		(drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1620 
1621 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1622 
1623 		drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1624 	}
1625 
1626 	// verify no overdraw
1627 	{
1628 		const tcu::RGBA	triangleColor	= tcu::RGBA(127, 127, 127, 255);
1629 		bool			overdraw		= false;
1630 
1631 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1632 
1633 		for (int y = 0; y < resultImage.getHeight(); ++y)
1634 		for (int x = 0; x < resultImage.getWidth();  ++x)
1635 		{
1636 			const tcu::RGBA color = resultImage.getPixel(x, y);
1637 
1638 			// color values are greater than triangle color? Allow lower values for multisampled edges and background.
1639 			if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
1640 				(color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1641 				(color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
1642 				overdraw = true;
1643 		}
1644 
1645 		// results
1646 		if (!overdraw)
1647 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1648 		else
1649 		{
1650 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1651 			m_allIterationsPassed = false;
1652 		}
1653 	}
1654 
1655 	// verify no missing fragments in the full viewport case
1656 	if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1657 	{
1658 		bool missingFragments = false;
1659 
1660 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1661 
1662 		for (int y = 0; y < resultImage.getHeight(); ++y)
1663 		for (int x = 0; x < resultImage.getWidth();  ++x)
1664 		{
1665 			const tcu::RGBA color = resultImage.getPixel(x, y);
1666 
1667 			// black? (background)
1668 			if (color.getRed()   <= thresholdRed   ||
1669 				color.getGreen() <= thresholdGreen ||
1670 				color.getBlue()  <= thresholdBlue)
1671 				missingFragments = true;
1672 		}
1673 
1674 		// results
1675 		if (!missingFragments)
1676 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1677 		else
1678 		{
1679 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1680 
1681 			m_allIterationsPassed = false;
1682 		}
1683 	}
1684 
1685 	m_context.getTestContext().getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1686 										<< tcu::TestLog::Image("Result", "Result", resultImage)
1687 										<< tcu::TestLog::EndImageSet;
1688 
1689 	// result
1690 	if (++m_iteration == m_iterationCount)
1691 	{
1692 		if (m_allIterationsPassed)
1693 			return tcu::TestStatus::pass("Pass");
1694 		else
1695 			return tcu::TestStatus::fail("Found invalid pixels");
1696 	}
1697 	else
1698 		return tcu::TestStatus::incomplete();
1699 }
1700 
getRenderSize(FillRuleCaseType type) const1701 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
1702 {
1703 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1704 		return DEFAULT_RENDER_SIZE / 4;
1705 	else
1706 		return DEFAULT_RENDER_SIZE;
1707 }
1708 
getNumIterations(FillRuleCaseType type) const1709 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
1710 {
1711 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1712 		return 15;
1713 	else
1714 		return 2;
1715 }
1716 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const1717 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1718 {
1719 	switch (m_caseType)
1720 	{
1721 		case FILLRULECASE_BASIC:
1722 		case FILLRULECASE_REVERSED:
1723 		case FILLRULECASE_PROJECTED:
1724 		{
1725 			const int	numRows		= 4;
1726 			const int	numColumns	= 4;
1727 			const float	quadSide	= 0.15f;
1728 			de::Random	rnd			(0xabcd);
1729 
1730 			outData.resize(6 * numRows * numColumns);
1731 
1732 			for (int col = 0; col < numColumns; ++col)
1733 			for (int row = 0; row < numRows;    ++row)
1734 			{
1735 				const tcu::Vec2 center		= tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f);
1736 				const float		rotation	= (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1737 				const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1738 				const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1739 				const tcu::Vec2 quad[4]		=
1740 				{
1741 					center + sideH + sideV,
1742 					center + sideH - sideV,
1743 					center - sideH - sideV,
1744 					center - sideH + sideV,
1745 				};
1746 
1747 				if (m_caseType == FILLRULECASE_BASIC)
1748 				{
1749 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1750 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1751 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1752 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1753 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1754 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1755 				}
1756 				else if (m_caseType == FILLRULECASE_REVERSED)
1757 				{
1758 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1759 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1760 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1761 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1762 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1763 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1764 				}
1765 				else if (m_caseType == FILLRULECASE_PROJECTED)
1766 				{
1767 					const float w0 = rnd.getFloat(0.1f, 4.0f);
1768 					const float w1 = rnd.getFloat(0.1f, 4.0f);
1769 					const float w2 = rnd.getFloat(0.1f, 4.0f);
1770 					const float w3 = rnd.getFloat(0.1f, 4.0f);
1771 
1772 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1773 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1774 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1775 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1776 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1777 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1778 				}
1779 				else
1780 					DE_ASSERT(DE_FALSE);
1781 			}
1782 
1783 			break;
1784 		}
1785 
1786 		case FILLRULECASE_CLIPPED_PARTIAL:
1787 		case FILLRULECASE_CLIPPED_FULL:
1788 		{
1789 			const float		quadSide	= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1790 			const tcu::Vec2 center		= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1791 			const float		rotation	= (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1792 			const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1793 			const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1794 			const tcu::Vec2 quad[4]		=
1795 			{
1796 				center + sideH + sideV,
1797 				center + sideH - sideV,
1798 				center - sideH - sideV,
1799 				center - sideH + sideV,
1800 			};
1801 
1802 			outData.resize(6);
1803 			outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1804 			outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1805 			outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1806 			outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1807 			outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1808 			outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1809 			break;
1810 		}
1811 
1812 		default:
1813 			DE_ASSERT(DE_FALSE);
1814 	}
1815 }
1816 
getColorBlendStateCreateInfo(void) const1817 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
1818 {
1819 	static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1820 	{
1821 		true,														// VkBool32			blendEnable;
1822 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
1823 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendColor;
1824 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
1825 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
1826 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendAlpha;
1827 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
1828 		(VK_COLOR_COMPONENT_R_BIT |
1829 		 VK_COLOR_COMPONENT_G_BIT |
1830 		 VK_COLOR_COMPONENT_B_BIT |
1831 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
1832 	};
1833 
1834 	static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1835 	{
1836 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1837 		DE_NULL,													// const void*									pNext;
1838 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
1839 		false,														// VkBool32										logicOpEnable;
1840 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1841 		1u,															// deUint32										attachmentCount;
1842 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1843 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1844 	};
1845 
1846 	return &colorBlendStateParams;
1847 }
1848 
1849 
1850 class FillRuleTestCase : public BaseRenderingTestCase
1851 {
1852 public:
FillRuleTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,FillRuleTestInstance::FillRuleCaseType type,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1853 								FillRuleTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1854 									: BaseRenderingTestCase	(context, name, description, sampleCount)
1855 									, m_type				(type)
1856 								{}
1857 
createInstance(Context & context) const1858 	virtual TestInstance*		createInstance		(Context& context) const
1859 								{
1860 									return new FillRuleTestInstance(context, m_type, m_sampleCount);
1861 								}
1862 protected:
1863 	const FillRuleTestInstance::FillRuleCaseType m_type;
1864 };
1865 
1866 class CullingTestInstance : public BaseRenderingTestInstance
1867 {
1868 public:
CullingTestInstance(Context & context,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode)1869 													CullingTestInstance				(Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
1870 														: BaseRenderingTestInstance		(context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
1871 														, m_cullMode					(cullMode)
1872 														, m_primitiveTopology			(primitiveTopology)
1873 														, m_frontFace					(frontFace)
1874 														, m_polygonMode					(polygonMode)
1875 														, m_multisampling				(true)
1876 													{}
1877 	virtual
1878 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo (void) const;
1879 
1880 	tcu::TestStatus									iterate							(void);
1881 
1882 private:
1883 	void											generateVertices				(std::vector<tcu::Vec4>& outData) const;
1884 	void											extractTriangles				(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1885 	void											extractLines					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
1886 	void											extractPoints					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
1887 	bool											triangleOrder					(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1888 
1889 	const VkCullModeFlags							m_cullMode;
1890 	const VkPrimitiveTopology						m_primitiveTopology;
1891 	const VkFrontFace								m_frontFace;
1892 	const VkPolygonMode								m_polygonMode;
1893 	const bool										m_multisampling;
1894 };
1895 
1896 
iterate(void)1897 tcu::TestStatus CullingTestInstance::iterate (void)
1898 {
1899 	DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
1900 
1901 	tcu::Surface									resultImage						(m_renderSize, m_renderSize);
1902 	std::vector<tcu::Vec4>							drawBuffer;
1903 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1904 	std::vector<PointSceneSpec::ScenePoint>			points;
1905 	std::vector<LineSceneSpec::SceneLine>			lines;
1906 
1907 	const InstanceInterface&						vk				= m_context.getInstanceInterface();
1908 	const VkPhysicalDevice							physicalDevice	= m_context.getPhysicalDevice();
1909 	const VkPhysicalDeviceFeatures					deviceFeatures	= getPhysicalDeviceFeatures(vk, physicalDevice);
1910 
1911 	if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
1912 		TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
1913 
1914 	// generate scene
1915 	generateVertices(drawBuffer);
1916 	extractTriangles(triangles, drawBuffer);
1917 
1918 	if (m_polygonMode == VK_POLYGON_MODE_LINE)
1919 		extractLines(triangles ,lines);
1920 	else if (m_polygonMode == VK_POLYGON_MODE_POINT)
1921 		extractPoints(triangles, points);
1922 
1923 	// draw image
1924 	{
1925 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
1926 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
1927 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
1928 
1929 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1930 	}
1931 
1932 	// compare
1933 	{
1934 		RasterizationArguments	args;
1935 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
1936 		bool					isCompareOk	= false;
1937 
1938 		args.numSamples		= m_multisampling ? 1 : 0;
1939 		args.subpixelBits	= m_subpixelBits;
1940 		args.redBits		= colorBits[0];
1941 		args.greenBits		= colorBits[1];
1942 		args.blueBits		= colorBits[2];
1943 
1944 		switch (m_polygonMode)
1945 		{
1946 			case VK_POLYGON_MODE_LINE:
1947 			{
1948 				LineSceneSpec scene;
1949 				scene.lineWidth = 0;
1950 				scene.lines.swap(lines);
1951 				isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1952 				break;
1953 			}
1954 			case VK_POLYGON_MODE_POINT:
1955 			{
1956 				PointSceneSpec scene;
1957 				scene.points.swap(points);
1958 				isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1959 				break;
1960 			}
1961 			default:
1962 			{
1963 				TriangleSceneSpec scene;
1964 				scene.triangles.swap(triangles);
1965 				isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
1966 				break;
1967 			}
1968 		}
1969 
1970 		if (isCompareOk)
1971 			return tcu::TestStatus::pass("Pass");
1972 		else
1973 			return tcu::TestStatus::fail("Incorrect rendering");
1974 	}
1975 }
1976 
generateVertices(std::vector<tcu::Vec4> & outData) const1977 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
1978 {
1979 	de::Random rnd(543210);
1980 
1981 	outData.resize(6);
1982 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1983 	{
1984 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1985 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1986 		outData[vtxNdx].z() = 0.0f;
1987 		outData[vtxNdx].w() = 1.0f;
1988 	}
1989 }
1990 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const1991 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1992 {
1993 	const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
1994 
1995 	// No triangles
1996 	if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
1997 		return;
1998 
1999 	switch (m_primitiveTopology)
2000 	{
2001 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2002 		{
2003 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2004 			{
2005 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2006 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2007 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2008 
2009 				if (triangleOrder(v0, v1, v2) != cullDirection)
2010 				{
2011 					TriangleSceneSpec::SceneTriangle tri;
2012 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
2013 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
2014 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
2015 
2016 					outTriangles.push_back(tri);
2017 				}
2018 			}
2019 			break;
2020 		}
2021 
2022 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2023 		{
2024 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2025 			{
2026 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2027 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2028 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2029 
2030 				if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
2031 				{
2032 					TriangleSceneSpec::SceneTriangle tri;
2033 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
2034 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
2035 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
2036 
2037 					outTriangles.push_back(tri);
2038 				}
2039 			}
2040 			break;
2041 		}
2042 
2043 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2044 		{
2045 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2046 			{
2047 				const tcu::Vec4& v0 = vertices[0];
2048 				const tcu::Vec4& v1 = vertices[vtxNdx + 0];
2049 				const tcu::Vec4& v2 = vertices[vtxNdx + 1];
2050 
2051 				if (triangleOrder(v0, v1, v2) != cullDirection)
2052 				{
2053 					TriangleSceneSpec::SceneTriangle tri;
2054 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
2055 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
2056 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
2057 
2058 					outTriangles.push_back(tri);
2059 				}
2060 			}
2061 			break;
2062 		}
2063 
2064 		default:
2065 			DE_ASSERT(false);
2066 	}
2067 }
2068 
extractLines(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<LineSceneSpec::SceneLine> & outLines) const2069 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles,
2070 										std::vector<LineSceneSpec::SceneLine>&			outLines) const
2071 {
2072 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2073 	{
2074 		for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
2075 		{
2076 			LineSceneSpec::SceneLine line;
2077 			line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
2078 			line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
2079 
2080 			outLines.push_back(line);
2081 		}
2082 		LineSceneSpec::SceneLine line;
2083 		line.positions[0] = outTriangles.at(triNdx).positions[2];
2084 		line.positions[1] = outTriangles.at(triNdx).positions[0];
2085 		outLines.push_back(line);
2086 	}
2087 }
2088 
extractPoints(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<PointSceneSpec::ScenePoint> & outPoints) const2089 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>	&outTriangles,
2090 										std::vector<PointSceneSpec::ScenePoint>			&outPoints) const
2091 {
2092 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2093 	{
2094 		for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2095 		{
2096 			PointSceneSpec::ScenePoint point;
2097 			point.position = outTriangles.at(triNdx).positions[vrtxNdx];
2098 			point.pointSize = 1.0f;
2099 
2100 			outPoints.push_back(point);
2101 		}
2102 	}
2103 }
2104 
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const2105 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
2106 {
2107 	const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
2108 	const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
2109 	const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
2110 
2111 	// cross
2112 	return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
2113 }
2114 
2115 
getRasterizationStateCreateInfo(void) const2116 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
2117 {
2118 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
2119 	{
2120 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
2121 		DE_NULL,														// const void*								pNext;
2122 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
2123 		false,															// VkBool32									depthClipEnable;
2124 		false,															// VkBool32									rasterizerDiscardEnable;
2125 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
2126 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
2127 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
2128 		VK_FALSE,														// VkBool32									depthBiasEnable;
2129 		0.0f,															// float									depthBias;
2130 		0.0f,															// float									depthBiasClamp;
2131 		0.0f,															// float									slopeScaledDepthBias;
2132 		getLineWidth(),													// float									lineWidth;
2133 	};
2134 
2135 	rasterizationStateCreateInfo.lineWidth		= getLineWidth();
2136 	rasterizationStateCreateInfo.cullMode		= m_cullMode;
2137 	rasterizationStateCreateInfo.frontFace		= m_frontFace;
2138 	rasterizationStateCreateInfo.polygonMode	= m_polygonMode;
2139 
2140 	return &rasterizationStateCreateInfo;
2141 }
2142 
2143 class CullingTestCase : public BaseRenderingTestCase
2144 {
2145 public:
CullingTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2146 								CullingTestCase		(tcu::TestContext& context, const std::string& name, const std::string& description, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2147 									: BaseRenderingTestCase	(context, name, description, sampleCount)
2148 									, m_cullMode			(cullMode)
2149 									, m_primitiveTopology	(primitiveTopology)
2150 									, m_frontFace			(frontFace)
2151 									, m_polygonMode			(polygonMode)
2152 								{}
2153 
createInstance(Context & context) const2154 	virtual TestInstance*		createInstance		(Context& context) const
2155 								{
2156 									return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
2157 								}
2158 protected:
2159 	const VkCullModeFlags		m_cullMode;
2160 	const VkPrimitiveTopology	m_primitiveTopology;
2161 	const VkFrontFace			m_frontFace;
2162 	const VkPolygonMode			m_polygonMode;
2163 };
2164 
2165 class DiscardTestInstance : public BaseRenderingTestInstance
2166 {
2167 public:
DiscardTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations)2168 															DiscardTestInstance					(Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
2169 																: BaseRenderingTestInstance			(context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
2170 																, m_primitiveTopology				(primitiveTopology)
2171 																, m_queryFragmentShaderInvocations	(queryFragmentShaderInvocations)
2172 															{}
2173 
2174 	virtual const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo		(void) const;
2175 	tcu::TestStatus											iterate								(void);
2176 
2177 private:
2178 	void													generateVertices					(std::vector<tcu::Vec4>& outData) const;
2179 	void													extractTriangles					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
2180 	void													extractLines						(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
2181 	void													extractPoints						(std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
2182 	void													drawPrimitives						(tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
2183 
2184 	const VkPrimitiveTopology								m_primitiveTopology;
2185 	const deBool											m_queryFragmentShaderInvocations;
2186 };
2187 
iterate(void)2188 tcu::TestStatus DiscardTestInstance::iterate (void)
2189 {
2190 	const DeviceInterface&							vkd			= m_context.getDeviceInterface();
2191 	const VkDevice									vkDevice	= m_context.getDevice();
2192 	deUint64										queryResult	= 0u;
2193 	tcu::Surface									resultImage	(m_renderSize, m_renderSize);
2194 	std::vector<tcu::Vec4>							drawBuffer;
2195 	std::vector<PointSceneSpec::ScenePoint>			points;
2196 	std::vector<LineSceneSpec::SceneLine>			lines;
2197 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
2198 
2199 	generateVertices(drawBuffer);
2200 
2201 	switch (m_primitiveTopology)
2202 	{
2203 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2204 			extractPoints(points, drawBuffer);
2205 			break;
2206 
2207 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2208 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2209 			extractLines(lines, drawBuffer);
2210 			break;
2211 
2212 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2213 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2214 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2215 			extractTriangles(triangles, drawBuffer);
2216 			break;
2217 
2218 		default:
2219 			DE_ASSERT(false);
2220 	}
2221 
2222 	const VkQueryPoolCreateInfo queryPoolCreateInfo =
2223 	{
2224 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,						// VkStructureType					sType
2225 		DE_NULL,														// const void*						pNext
2226 		(VkQueryPoolCreateFlags)0,										// VkQueryPoolCreateFlags			flags
2227 		VK_QUERY_TYPE_PIPELINE_STATISTICS ,								// VkQueryType						queryType
2228 		1u,																// deUint32							entryCount
2229 		VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,	// VkQueryPipelineStatisticFlags	pipelineStatistics
2230 	};
2231 
2232 	if (m_queryFragmentShaderInvocations)
2233 	{
2234 		Move<VkQueryPool> queryPool	= createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
2235 
2236 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology, queryPool);
2237 		vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2238 	}
2239 	else
2240 		BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
2241 
2242 	// compare
2243 	{
2244 		tcu::IVec4						colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
2245 
2246 		const RasterizationArguments	args		=
2247 		{
2248 			0,							// int	numSamples;
2249 			(int)m_subpixelBits,		// int	subpixelBits;
2250 			colorBits[0],				// int	redBits;
2251 			colorBits[1],				// int	greenBits;
2252 			colorBits[2]				// int	blueBits;
2253 		};
2254 
2255 		// Empty scene to compare to, primitives should be discarded before rasterization
2256 		TriangleSceneSpec				scene;
2257 
2258 		const bool						isCompareOk	= verifyTriangleGroupRasterization(resultImage,
2259 																					   scene,
2260 																					   args,
2261 																					   m_context.getTestContext().getLog(),
2262 																					   tcu::VERIFICATIONMODE_STRICT);
2263 
2264 		if (isCompareOk)
2265 		{
2266 			if (m_queryFragmentShaderInvocations && queryResult > 0u)
2267 				return tcu::TestStatus::fail("Fragment shader invocations occured");
2268 			else
2269 				return tcu::TestStatus::pass("Pass");
2270 		}
2271 		else
2272 			return tcu::TestStatus::fail("Incorrect rendering");
2273 	}
2274 }
2275 
generateVertices(std::vector<tcu::Vec4> & outData) const2276 void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
2277 {
2278 	de::Random rnd(12345);
2279 
2280 	outData.resize(6);
2281 
2282 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2283 	{
2284 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2285 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2286 		outData[vtxNdx].z() = 0.0f;
2287 		outData[vtxNdx].w() = 1.0f;
2288 	}
2289 }
2290 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const2291 void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
2292 {
2293 	switch (m_primitiveTopology)
2294 	{
2295 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2296 		{
2297 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2298 			{
2299 				TriangleSceneSpec::SceneTriangle	tri;
2300 				const tcu::Vec4&					v0	= vertices[vtxNdx + 0];
2301 				const tcu::Vec4&					v1	= vertices[vtxNdx + 1];
2302 				const tcu::Vec4&					v2	= vertices[vtxNdx + 2];
2303 
2304 				tri.positions[0] = v0;
2305 				tri.positions[1] = v1;
2306 				tri.positions[2] = v2;
2307 
2308 				outTriangles.push_back(tri);
2309 			}
2310 
2311 			break;
2312 		}
2313 
2314 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2315 		{
2316 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2317 			{
2318 				TriangleSceneSpec::SceneTriangle	tri;
2319 				const tcu::Vec4&					v0	= vertices[vtxNdx + 0];
2320 				const tcu::Vec4&					v1	= vertices[vtxNdx + 1];
2321 				const tcu::Vec4&					v2	= vertices[vtxNdx + 2];
2322 
2323 				tri.positions[0] = v0;
2324 				tri.positions[1] = v1;
2325 				tri.positions[2] = v2;
2326 
2327 				outTriangles.push_back(tri);
2328 			}
2329 
2330 			break;
2331 		}
2332 
2333 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2334 		{
2335 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2336 			{
2337 				TriangleSceneSpec::SceneTriangle	tri;
2338 				const tcu::Vec4&					v0	= vertices[0];
2339 				const tcu::Vec4&					v1	= vertices[vtxNdx + 0];
2340 				const tcu::Vec4&					v2	= vertices[vtxNdx + 1];
2341 
2342 				tri.positions[0] = v0;
2343 				tri.positions[1] = v1;
2344 				tri.positions[2] = v2;
2345 
2346 				outTriangles.push_back(tri);
2347 			}
2348 
2349 			break;
2350 		}
2351 
2352 		default:
2353 			DE_ASSERT(false);
2354 	}
2355 }
2356 
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices) const2357 void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
2358 {
2359 	switch (m_primitiveTopology)
2360 	{
2361 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2362 		{
2363 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2364 			{
2365 				LineSceneSpec::SceneLine line;
2366 
2367 				line.positions[0] = vertices[vtxNdx + 0];
2368 				line.positions[1] = vertices[vtxNdx + 1];
2369 
2370 				outLines.push_back(line);
2371 			}
2372 
2373 			break;
2374 		}
2375 
2376 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2377 		{
2378 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2379 			{
2380 				LineSceneSpec::SceneLine line;
2381 
2382 				line.positions[0] = vertices[vtxNdx + 0];
2383 				line.positions[1] = vertices[vtxNdx + 1];
2384 
2385 				outLines.push_back(line);
2386 			}
2387 
2388 			break;
2389 		}
2390 
2391 		default:
2392 			DE_ASSERT(false);
2393 		}
2394 }
2395 
extractPoints(std::vector<PointSceneSpec::ScenePoint> & outPoints,const std::vector<tcu::Vec4> & vertices) const2396 void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
2397 {
2398 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
2399 	{
2400 		for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2401 		{
2402 			PointSceneSpec::ScenePoint point;
2403 
2404 			point.position	= vertices[vrtxNdx];
2405 			point.pointSize	= 1.0f;
2406 
2407 			outPoints.push_back(point);
2408 		}
2409 	}
2410 }
2411 
getRasterizationStateCreateInfo(void) const2412 const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
2413 {
2414 	static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2415 	{
2416 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
2417 		NULL,														// const void*								pNext;
2418 		0,															// VkPipelineRasterizationStateCreateFlags	flags;
2419 		VK_FALSE,													// VkBool32									depthClipEnable;
2420 		VK_TRUE,													// VkBool32									rasterizerDiscardEnable;
2421 		VK_POLYGON_MODE_FILL,										// VkFillMode								fillMode;
2422 		VK_CULL_MODE_NONE,											// VkCullMode								cullMode;
2423 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
2424 		VK_FALSE,													// VkBool32									depthBiasEnable;
2425 		0.0f,														// float									depthBias;
2426 		0.0f,														// float									depthBiasClamp;
2427 		0.0f,														// float									slopeScaledDepthBias;
2428 		getLineWidth(),												// float									lineWidth;
2429 	};
2430 
2431 	return &rasterizationStateCreateInfo;
2432 }
2433 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,VkPrimitiveTopology primitiveTopology,Move<VkQueryPool> & queryPool)2434 void DiscardTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
2435 {
2436 	const DeviceInterface&				vkd					= m_context.getDeviceInterface();
2437 	const VkDevice						vkDevice			= m_context.getDevice();
2438 	const VkPhysicalDeviceProperties	properties			= m_context.getDeviceProperties();
2439 	const VkQueue						queue				= m_context.getUniversalQueue();
2440 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
2441 	Allocator&							allocator			= m_context.getDefaultAllocator();
2442 
2443 	const size_t						attributeBatchSize	= positionData.size() * sizeof(tcu::Vec4);
2444 	const VkDeviceSize					vertexBufferOffset	= 0;
2445 	de::MovePtr<Allocation>				vertexBufferMemory;
2446 	Move<VkBuffer>						vertexBuffer;
2447 	Move<VkCommandBuffer>				commandBuffer;
2448 	Move<VkPipeline>					graphicsPipeline;
2449 
2450 	if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
2451 	{
2452 		std::stringstream message;
2453 		message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
2454 		TCU_THROW(NotSupportedError, message.str().c_str());
2455 	}
2456 
2457 	// Create Graphics Pipeline
2458 	{
2459 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
2460 		{
2461 			0u,										// deUint32					binding;
2462 			sizeof(tcu::Vec4),						// deUint32					strideInBytes;
2463 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	stepRate;
2464 		};
2465 
2466 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
2467 		{
2468 			{
2469 				0u,									// deUint32	location;
2470 				0u,									// deUint32	binding;
2471 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2472 				0u									// deUint32	offsetInBytes;
2473 			},
2474 			{
2475 				1u,									// deUint32	location;
2476 				0u,									// deUint32	binding;
2477 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2478 				(deUint32)attributeBatchSize		// deUint32	offsetInBytes;
2479 			}
2480 		};
2481 
2482 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
2483 		{
2484 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
2485 			DE_NULL,													// const void*								pNext;
2486 			0,															// VkPipelineVertexInputStateCreateFlags	flags;
2487 			1u,															// deUint32									bindingCount;
2488 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2489 			2u,															// deUint32									attributeCount;
2490 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2491 		};
2492 
2493 		const std::vector<VkViewport>				viewports							(1, makeViewport(tcu::UVec2(m_renderSize)));
2494 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(tcu::UVec2(m_renderSize)));
2495 
2496 		const VkPipelineMultisampleStateCreateInfo	multisampleStateParams				=
2497 		{
2498 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
2499 			DE_NULL,													// const void*								pNext;
2500 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
2501 			m_sampleCount,												// VkSampleCountFlagBits					rasterizationSamples;
2502 			VK_FALSE,													// VkBool32									sampleShadingEnable;
2503 			0.0f,														// float									minSampleShading;
2504 			DE_NULL,													// const VkSampleMask*						pSampleMask;
2505 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
2506 			VK_FALSE													// VkBool32									alphaToOneEnable;
2507 		};
2508 
2509 		graphicsPipeline = makeGraphicsPipeline(vkd,								// const DeviceInterface&							vk
2510 												vkDevice,							// const VkDevice									device
2511 												*m_pipelineLayout,					// const VkPipelineLayout							pipelineLayout
2512 												*m_vertexShaderModule,				// const VkShaderModule								vertexShaderModule
2513 												DE_NULL,							// const VkShaderModule								tessellationControlShaderModule
2514 												DE_NULL,							// const VkShaderModule								tessellationEvalShaderModule
2515 												DE_NULL,							// const VkShaderModule								geometryShaderModule
2516 												*m_fragmentShaderModule,			// const VkShaderModule								fragmentShaderModule
2517 												*m_renderPass,						// const VkRenderPass								renderPass
2518 												viewports,							// const std::vector<VkViewport>&					viewports
2519 												scissors,							// const std::vector<VkRect2D>&						scissors
2520 												primitiveTopology,					// const VkPrimitiveTopology						topology
2521 												0u,									// const deUint32									subpass
2522 												0u,									// const deUint32									patchControlPoints
2523 												&vertexInputStateParams,			// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
2524 												getRasterizationStateCreateInfo(),	// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
2525 												&multisampleStateParams,			// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
2526 												DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo,
2527 												getColorBlendStateCreateInfo());	// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
2528 	}
2529 
2530 	// Create Vertex Buffer
2531 	{
2532 		const VkBufferCreateInfo					vertexBufferParams		=
2533 		{
2534 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
2535 			DE_NULL,								// const void*			pNext;
2536 			0u,										// VkBufferCreateFlags	flags;
2537 			attributeBatchSize * 2,					// VkDeviceSize			size;
2538 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
2539 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2540 			1u,										// deUint32				queueFamilyCount;
2541 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
2542 		};
2543 
2544 		const std::vector<tcu::Vec4>				colorData				(positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
2545 
2546 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
2547 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
2548 
2549 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2550 
2551 		// Load vertices into vertex buffer
2552 		deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
2553 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
2554 		flushAlloc(vkd, vkDevice, *vertexBufferMemory);
2555 	}
2556 
2557 	// Create Command Buffer
2558 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2559 
2560 	// Begin Command Buffer
2561 	beginCommandBuffer(vkd, *commandBuffer);
2562 
2563 	addImageTransitionBarrier(*commandBuffer,									// VkCommandBuffer			commandBuffer
2564 							  *m_image,											// VkImage					image
2565 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
2566 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
2567 							  0,												// VkAccessFlags			srcAccessMask
2568 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
2569 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
2570 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
2571 
2572 	if (m_multisampling)
2573 	{
2574 		addImageTransitionBarrier(*commandBuffer,								// VkCommandBuffer			commandBuffer
2575 								  *m_resolvedImage,								// VkImage					image
2576 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,			// VkPipelineStageFlags		srcStageMask
2577 								  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,			// VkPipelineStageFlags		dstStageMask
2578 								  0,											// VkAccessFlags			srcAccessMask
2579 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask
2580 								  VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			oldLayout;
2581 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);	// VkImageLayout			newLayout;
2582 	}
2583 
2584 	// Reset query pool
2585 	vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
2586 
2587 	// Begin render pass and start query
2588 	beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
2589 	vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
2590 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2591 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
2592 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
2593 	vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
2594 	endRenderPass(vkd, *commandBuffer);
2595 	vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
2596 
2597 	// Copy Image
2598 	copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
2599 
2600 	endCommandBuffer(vkd, *commandBuffer);
2601 
2602 	// Set Point Size
2603 	{
2604 		float pointSize = getPointSize();
2605 
2606 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
2607 		flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
2608 	}
2609 
2610 	// Submit
2611 	submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
2612 
2613 	invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
2614 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
2615 }
2616 
2617 class DiscardTestCase : public BaseRenderingTestCase
2618 {
2619 public:
DiscardTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2620 								DiscardTestCase					(tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2621 									: BaseRenderingTestCase				(context, name, description, sampleCount)
2622 									, m_primitiveTopology				(primitiveTopology)
2623 									, m_queryFragmentShaderInvocations	(queryFragmentShaderInvocations)
2624 								{}
2625 
createInstance(Context & context) const2626 	virtual TestInstance*		createInstance		(Context& context) const
2627 								{
2628 									if (m_queryFragmentShaderInvocations && !context.getDeviceFeatures().pipelineStatisticsQuery)
2629 										throw tcu::NotSupportedError("Pipeline statistics queries are not supported");
2630 
2631 									return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
2632 								}
2633 
2634 protected:
2635 	const VkPrimitiveTopology	m_primitiveTopology;
2636 	const deBool				m_queryFragmentShaderInvocations;
2637 };
2638 
2639 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
2640 {
2641 public:
2642 
TriangleInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount)2643 								TriangleInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
2644 									: BaseRenderingTestInstance	(context, sampleCount, DEFAULT_RENDER_SIZE)
2645 									, m_primitiveTopology		(primitiveTopology)
2646 									, m_projective				((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2647 									, m_iterationCount			(3)
2648 									, m_iteration				(0)
2649 									, m_allIterationsPassed		(true)
2650 									, m_flatshade				((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2651 								{}
2652 
2653 	tcu::TestStatus				iterate								(void);
2654 
2655 
2656 private:
2657 	void						generateVertices					(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2658 	void						extractTriangles					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2659 
2660 
2661 	VkPrimitiveTopology			m_primitiveTopology;
2662 	const bool					m_projective;
2663 	const int					m_iterationCount;
2664 	int							m_iteration;
2665 	bool						m_allIterationsPassed;
2666 	const deBool				m_flatshade;
2667 };
2668 
iterate(void)2669 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
2670 {
2671 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2672 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2673 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
2674 	std::vector<tcu::Vec4>							drawBuffer;
2675 	std::vector<tcu::Vec4>							colorBuffer;
2676 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
2677 
2678 	// generate scene
2679 	generateVertices(m_iteration, drawBuffer, colorBuffer);
2680 	extractTriangles(triangles, drawBuffer, colorBuffer);
2681 
2682 	// log
2683 	{
2684 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2685 		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2686 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2687 	}
2688 
2689 	// draw image
2690 	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2691 
2692 	// compare
2693 	{
2694 		RasterizationArguments	args;
2695 		TriangleSceneSpec		scene;
2696 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
2697 
2698 		args.numSamples		= m_multisampling ? 1 : 0;
2699 		args.subpixelBits	= m_subpixelBits;
2700 		args.redBits		= colorBits[0];
2701 		args.greenBits		= colorBits[1];
2702 		args.blueBits		= colorBits[2];
2703 
2704 		scene.triangles.swap(triangles);
2705 
2706 		if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2707 			m_allIterationsPassed = false;
2708 	}
2709 
2710 	// result
2711 	if (++m_iteration == m_iterationCount)
2712 	{
2713 		if (m_allIterationsPassed)
2714 			return tcu::TestStatus::pass("Pass");
2715 		else
2716 			return tcu::TestStatus::fail("Found invalid pixel values");
2717 	}
2718 	else
2719 		return tcu::TestStatus::incomplete();
2720 }
2721 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const2722 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2723 {
2724 	// use only red, green and blue
2725 	const tcu::Vec4 colors[] =
2726 	{
2727 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2728 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2729 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2730 	};
2731 
2732 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
2733 
2734 	outVertices.resize(6);
2735 	outColors.resize(6);
2736 
2737 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2738 	{
2739 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2740 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2741 		outVertices[vtxNdx].z() = 0.0f;
2742 
2743 		if (!m_projective)
2744 			outVertices[vtxNdx].w() = 1.0f;
2745 		else
2746 		{
2747 			const float w = rnd.getFloat(0.2f, 4.0f);
2748 
2749 			outVertices[vtxNdx].x() *= w;
2750 			outVertices[vtxNdx].y() *= w;
2751 			outVertices[vtxNdx].z() *= w;
2752 			outVertices[vtxNdx].w() = w;
2753 		}
2754 
2755 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2756 	}
2757 }
2758 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const2759 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2760 {
2761 	switch (m_primitiveTopology)
2762 	{
2763 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2764 		{
2765 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2766 			{
2767 				TriangleSceneSpec::SceneTriangle tri;
2768 				tri.positions[0]	= vertices[vtxNdx + 0];
2769 				tri.positions[1]	= vertices[vtxNdx + 1];
2770 				tri.positions[2]	= vertices[vtxNdx + 2];
2771 				tri.sharedEdge[0]	= false;
2772 				tri.sharedEdge[1]	= false;
2773 				tri.sharedEdge[2]	= false;
2774 
2775 				if (m_flatshade)
2776 				{
2777 					tri.colors[0] = colors[vtxNdx];
2778 					tri.colors[1] = colors[vtxNdx];
2779 					tri.colors[2] = colors[vtxNdx];
2780 				}
2781 				else
2782 				{
2783 					tri.colors[0] = colors[vtxNdx + 0];
2784 					tri.colors[1] = colors[vtxNdx + 1];
2785 					tri.colors[2] = colors[vtxNdx + 2];
2786 				}
2787 
2788 				outTriangles.push_back(tri);
2789 			}
2790 			break;
2791 		}
2792 
2793 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2794 		{
2795 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2796 			{
2797 				TriangleSceneSpec::SceneTriangle tri;
2798 				tri.positions[0]	= vertices[vtxNdx + 0];
2799 				tri.positions[1]	= vertices[vtxNdx + 1];
2800 				tri.positions[2]	= vertices[vtxNdx + 2];
2801 				tri.sharedEdge[0]	= false;
2802 				tri.sharedEdge[1]	= false;
2803 				tri.sharedEdge[2]	= false;
2804 
2805 				if (m_flatshade)
2806 				{
2807 					tri.colors[0] = colors[vtxNdx];
2808 					tri.colors[1] = colors[vtxNdx];
2809 					tri.colors[2] = colors[vtxNdx];
2810 				}
2811 				else
2812 				{
2813 					tri.colors[0] = colors[vtxNdx + 0];
2814 					tri.colors[1] = colors[vtxNdx + 1];
2815 					tri.colors[2] = colors[vtxNdx + 2];
2816 				}
2817 
2818 				outTriangles.push_back(tri);
2819 			}
2820 			break;
2821 		}
2822 
2823 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2824 		{
2825 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2826 			{
2827 				TriangleSceneSpec::SceneTriangle tri;
2828 				tri.positions[0]	= vertices[0];
2829 				tri.positions[1]	= vertices[vtxNdx + 0];
2830 				tri.positions[2]	= vertices[vtxNdx + 1];
2831 				tri.sharedEdge[0]	= false;
2832 				tri.sharedEdge[1]	= false;
2833 				tri.sharedEdge[2]	= false;
2834 
2835 				if (m_flatshade)
2836 				{
2837 					tri.colors[0] = colors[vtxNdx];
2838 					tri.colors[1] = colors[vtxNdx];
2839 					tri.colors[2] = colors[vtxNdx];
2840 				}
2841 				else
2842 				{
2843 					tri.colors[0] = colors[0];
2844 					tri.colors[1] = colors[vtxNdx + 0];
2845 					tri.colors[2] = colors[vtxNdx + 1];
2846 				}
2847 
2848 				outTriangles.push_back(tri);
2849 			}
2850 			break;
2851 		}
2852 
2853 		default:
2854 			DE_ASSERT(false);
2855 	}
2856 }
2857 
2858 class TriangleInterpolationTestCase : public BaseRenderingTestCase
2859 {
2860 public:
TriangleInterpolationTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2861 								TriangleInterpolationTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2862 									: BaseRenderingTestCase		(context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2863 									, m_primitiveTopology		(primitiveTopology)
2864 									, m_flags					(flags)
2865 								{}
2866 
createInstance(Context & context) const2867 	virtual TestInstance*		createInstance					(Context& context) const
2868 								{
2869 									return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
2870 								}
2871 protected:
2872 	const VkPrimitiveTopology	m_primitiveTopology;
2873 	const int					m_flags;
2874 };
2875 
2876 class LineInterpolationTestInstance : public BaseRenderingTestInstance
2877 {
2878 public:
2879 							LineInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
2880 
2881 	virtual tcu::TestStatus	iterate							(void);
2882 
2883 private:
2884 	void					generateVertices				(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2885 	void					extractLines					(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2886 	virtual float			getLineWidth					(void) const;
2887 
2888 	VkPrimitiveTopology		m_primitiveTopology;
2889 	const bool				m_projective;
2890 	const int				m_iterationCount;
2891 	const PrimitiveWideness	m_primitiveWideness;
2892 
2893 	int						m_iteration;
2894 	bool					m_allIterationsPassed;
2895 	float					m_maxLineWidth;
2896 	std::vector<float>		m_lineWidths;
2897 	bool					m_flatshade;
2898 };
2899 
LineInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)2900 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
2901 	: BaseRenderingTestInstance			(context, sampleCount)
2902 	, m_primitiveTopology				(primitiveTopology)
2903 	, m_projective						((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2904 	, m_iterationCount					(3)
2905 	, m_primitiveWideness				(wideness)
2906 	, m_iteration						(0)
2907 	, m_allIterationsPassed				(true)
2908 	, m_maxLineWidth					(1.0f)
2909 	, m_flatshade						((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2910 {
2911 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
2912 
2913 	if (!context.getDeviceProperties().limits.strictLines)
2914 		TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
2915 
2916 	// create line widths
2917 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
2918 	{
2919 		m_lineWidths.resize(m_iterationCount, 1.0f);
2920 	}
2921 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
2922 	{
2923 		if (!m_context.getDeviceFeatures().wideLines)
2924 			TCU_THROW(NotSupportedError , "wide line support required");
2925 
2926 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
2927 
2928 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
2929 
2930 		// no wide line support
2931 		if (range[1] <= 1.0f)
2932 			throw tcu::NotSupportedError("wide line support required");
2933 
2934 		// set hand picked sizes
2935 		m_lineWidths.push_back(5.0f);
2936 		m_lineWidths.push_back(10.0f);
2937 		m_lineWidths.push_back(range[1]);
2938 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
2939 
2940 		m_maxLineWidth = range[1];
2941 	}
2942 	else
2943 		DE_ASSERT(false);
2944 }
2945 
iterate(void)2946 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
2947 {
2948 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2949 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2950 	const float								lineWidth				= getLineWidth();
2951 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
2952 	std::vector<tcu::Vec4>					drawBuffer;
2953 	std::vector<tcu::Vec4>					colorBuffer;
2954 	std::vector<LineSceneSpec::SceneLine>	lines;
2955 
2956 	// supported?
2957 	if (lineWidth <= m_maxLineWidth)
2958 	{
2959 		// generate scene
2960 		generateVertices(m_iteration, drawBuffer, colorBuffer);
2961 		extractLines(lines, drawBuffer, colorBuffer);
2962 
2963 		// log
2964 		{
2965 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2966 			for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2967 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2968 		}
2969 
2970 		// draw image
2971 		drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2972 
2973 		// compare
2974 		{
2975 			RasterizationArguments	args;
2976 			LineSceneSpec			scene;
2977 
2978 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
2979 
2980 			args.numSamples		= m_multisampling ? 1 : 0;
2981 			args.subpixelBits	= m_subpixelBits;
2982 			args.redBits		= colorBits[0];
2983 			args.greenBits		= colorBits[1];
2984 			args.blueBits		= colorBits[2];
2985 
2986 			scene.lines.swap(lines);
2987 			scene.lineWidth = getLineWidth();
2988 
2989 			if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2990 				m_allIterationsPassed = false;
2991 		}
2992 	}
2993 	else
2994 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
2995 
2996 	// result
2997 	if (++m_iteration == m_iterationCount)
2998 	{
2999 		if (m_allIterationsPassed)
3000 			return tcu::TestStatus::pass("Pass");
3001 		else
3002 			return tcu::TestStatus::fail("Incorrect rasterization");
3003 	}
3004 	else
3005 		return tcu::TestStatus::incomplete();
3006 }
3007 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const3008 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
3009 {
3010 	// use only red, green and blue
3011 	const tcu::Vec4 colors[] =
3012 	{
3013 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
3014 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
3015 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
3016 	};
3017 
3018 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
3019 
3020 	outVertices.resize(6);
3021 	outColors.resize(6);
3022 
3023 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
3024 	{
3025 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
3026 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
3027 		outVertices[vtxNdx].z() = 0.0f;
3028 
3029 		if (!m_projective)
3030 			outVertices[vtxNdx].w() = 1.0f;
3031 		else
3032 		{
3033 			const float w = rnd.getFloat(0.2f, 4.0f);
3034 
3035 			outVertices[vtxNdx].x() *= w;
3036 			outVertices[vtxNdx].y() *= w;
3037 			outVertices[vtxNdx].z() *= w;
3038 			outVertices[vtxNdx].w() = w;
3039 		}
3040 
3041 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
3042 	}
3043 }
3044 
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const3045 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
3046 {
3047 	switch (m_primitiveTopology)
3048 	{
3049 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
3050 		{
3051 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
3052 			{
3053 				LineSceneSpec::SceneLine line;
3054 				line.positions[0] = vertices[vtxNdx + 0];
3055 				line.positions[1] = vertices[vtxNdx + 1];
3056 
3057 				if (m_flatshade)
3058 				{
3059 					line.colors[0] = colors[vtxNdx];
3060 					line.colors[1] = colors[vtxNdx];
3061 				}
3062 				else
3063 				{
3064 					line.colors[0] = colors[vtxNdx + 0];
3065 					line.colors[1] = colors[vtxNdx + 1];
3066 				}
3067 
3068 				outLines.push_back(line);
3069 			}
3070 			break;
3071 		}
3072 
3073 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
3074 		{
3075 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
3076 			{
3077 				LineSceneSpec::SceneLine line;
3078 				line.positions[0] = vertices[vtxNdx + 0];
3079 				line.positions[1] = vertices[vtxNdx + 1];
3080 
3081 				if (m_flatshade)
3082 				{
3083 					line.colors[0] = colors[vtxNdx];
3084 					line.colors[1] = colors[vtxNdx];
3085 				}
3086 				else
3087 				{
3088 					line.colors[0] = colors[vtxNdx + 0];
3089 					line.colors[1] = colors[vtxNdx + 1];
3090 				}
3091 
3092 				outLines.push_back(line);
3093 			}
3094 			break;
3095 		}
3096 
3097 		default:
3098 			DE_ASSERT(false);
3099 	}
3100 }
3101 
getLineWidth(void) const3102 float LineInterpolationTestInstance::getLineWidth (void) const
3103 {
3104 	return m_lineWidths[m_iteration];
3105 }
3106 
3107 class LineInterpolationTestCase : public BaseRenderingTestCase
3108 {
3109 public:
LineInterpolationTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)3110 								LineInterpolationTestCase		(tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
3111 									: BaseRenderingTestCase		(context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
3112 									, m_primitiveTopology		(primitiveTopology)
3113 									, m_flags					(flags)
3114 									, m_wideness				(wideness)
3115 								{}
3116 
createInstance(Context & context) const3117 	virtual TestInstance*		createInstance					(Context& context) const
3118 								{
3119 									return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
3120 								}
3121 protected:
3122 	const VkPrimitiveTopology	m_primitiveTopology;
3123 	const int					m_flags;
3124 	const PrimitiveWideness		m_wideness;
3125 };
3126 
createRasterizationTests(tcu::TestCaseGroup * rasterizationTests)3127 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
3128 {
3129 	tcu::TestContext&	testCtx		=	rasterizationTests->getTestContext();
3130 
3131 	// .primitives
3132 	{
3133 		tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
3134 
3135 		rasterizationTests->addChild(primitives);
3136 
3137 		primitives->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
3138 		primitives->addChild(new BaseTestCase<TriangleStripTestInstance>	(testCtx, "triangle_strip",		"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
3139 		primitives->addChild(new BaseTestCase<TriangleFanTestInstance>		(testCtx, "triangle_fan",		"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
3140 		primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
3141 		primitives->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
3142 		primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines_wide",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
3143 		primitives->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip_wide",	"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
3144 		primitives->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",						PRIMITIVEWIDENESS_WIDE));
3145 	}
3146 
3147 	// .fill_rules
3148 	{
3149 		tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
3150 
3151 		rasterizationTests->addChild(fillRules);
3152 
3153 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_BASIC));
3154 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse",	"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_REVERSED));
3155 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
3156 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly",		"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
3157 		fillRules->addChild(new FillRuleTestCase(testCtx,	"projected",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_PROJECTED));
3158 	}
3159 
3160 	// .culling
3161 	{
3162 		static const struct CullMode
3163 		{
3164 			VkCullModeFlags	mode;
3165 			const char*		prefix;
3166 		} cullModes[] =
3167 		{
3168 			{ VK_CULL_MODE_FRONT_BIT,				"front_"	},
3169 			{ VK_CULL_MODE_BACK_BIT,				"back_"		},
3170 			{ VK_CULL_MODE_FRONT_AND_BACK,			"both_"		},
3171 		};
3172 		static const struct PrimitiveType
3173 		{
3174 			VkPrimitiveTopology	type;
3175 			const char*			name;
3176 		} primitiveTypes[] =
3177 		{
3178 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			"triangles"			},
3179 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,			"triangle_strip"	},
3180 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,			"triangle_fan"		},
3181 		};
3182 		static const struct FrontFaceOrder
3183 		{
3184 			VkFrontFace	mode;
3185 			const char*	postfix;
3186 		} frontOrders[] =
3187 		{
3188 			{ VK_FRONT_FACE_COUNTER_CLOCKWISE,	""			},
3189 			{ VK_FRONT_FACE_CLOCKWISE,			"_reverse"	},
3190 		};
3191 
3192 		static const struct PolygonMode
3193 		{
3194 			VkPolygonMode	mode;
3195 			const char*		name;
3196 		} polygonModes[] =
3197 		{
3198 			{ VK_POLYGON_MODE_FILL,		""		},
3199 			{ VK_POLYGON_MODE_LINE,		"_line"		},
3200 			{ VK_POLYGON_MODE_POINT,	"_point"	}
3201 		};
3202 
3203 		tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
3204 
3205 		rasterizationTests->addChild(culling);
3206 
3207 		for (int cullModeNdx	= 0; cullModeNdx	< DE_LENGTH_OF_ARRAY(cullModes);		++cullModeNdx)
3208 		for (int primitiveNdx	= 0; primitiveNdx	< DE_LENGTH_OF_ARRAY(primitiveTypes);	++primitiveNdx)
3209 		for (int frontOrderNdx	= 0; frontOrderNdx	< DE_LENGTH_OF_ARRAY(frontOrders);		++frontOrderNdx)
3210 		for (int polygonModeNdx = 0; polygonModeNdx	< DE_LENGTH_OF_ARRAY(polygonModes);		++polygonModeNdx)
3211 		{
3212 			if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
3213 			{
3214 				const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
3215 				culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
3216 			}
3217 		}
3218 	}
3219 
3220 	// .discard
3221 	{
3222 		static const struct PrimitiveType
3223 		{
3224 			VkPrimitiveTopology	type;
3225 			const char*			name;
3226 		} primitiveTypes[] =
3227 		{
3228 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	"triangle_list"		},
3229 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	"triangle_strip"	},
3230 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,	"triangle_fan"		},
3231 			{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		"line_list"			},
3232 			{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		"line_strip"		},
3233 			{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		"point_list"		}
3234 		};
3235 
3236 		static const struct queryPipeline
3237 		{
3238 			deBool			useQuery;
3239 			const char*		name;
3240 		} queryPipeline[] =
3241 		{
3242 			{ DE_FALSE,	"query_pipeline_false"	},
3243 			{ DE_TRUE,	"query_pipeline_true"	},
3244 		};
3245 
3246 		tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
3247 
3248 		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
3249 		{
3250 			tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard");
3251 
3252 			for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
3253 			{
3254 				const std::string name = std::string(queryPipeline[useQueryNdx].name);
3255 
3256 				primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
3257 			}
3258 
3259 			discard->addChild(primitive);
3260 		}
3261 
3262 		rasterizationTests->addChild(discard);
3263 	}
3264 
3265 	// .interpolation
3266 	{
3267 		tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
3268 
3269 		rasterizationTests->addChild(interpolation);
3270 
3271 		// .basic
3272 		{
3273 			tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
3274 
3275 			interpolation->addChild(basic);
3276 
3277 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE));
3278 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip",	"Verify triangle strip interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_NONE));
3279 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan",	"Verify triangle fan interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_NONE));
3280 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
3281 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip",		"Verify line strip interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
3282 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
3283 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide","Verify wide line strip interpolation",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
3284 		}
3285 
3286 		// .projected
3287 		{
3288 			tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
3289 
3290 			interpolation->addChild(projected);
3291 
3292 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_PROJECTED));
3293 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_strip",	"Verify triangle strip interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_PROJECTED));
3294 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_fan",	"Verify triangle fan interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_PROJECTED));
3295 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
3296 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip",		"Verify line strip interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
3297 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
3298 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip_wide","Verify wide line strip interpolation",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
3299 		}
3300 	}
3301 
3302 	// .flatshading
3303 	{
3304 		tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
3305 
3306 		rasterizationTests->addChild(flatshading);
3307 
3308 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle flatshading",			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_FLATSHADE));
3309 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip",	"Verify triangle strip flatshading",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_FLATSHADE));
3310 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan",	"Verify triangle fan flatshading",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_FLATSHADE));
3311 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line flatshading",				VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
3312 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip",		"Verify line strip flatshading",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
3313 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line flatshading",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
3314 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide","Verify wide line strip flatshading",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
3315 	}
3316 
3317 	const VkSampleCountFlagBits samples[] =
3318 	{
3319 		VK_SAMPLE_COUNT_2_BIT,
3320 		VK_SAMPLE_COUNT_4_BIT,
3321 		VK_SAMPLE_COUNT_8_BIT,
3322 		VK_SAMPLE_COUNT_16_BIT,
3323 		VK_SAMPLE_COUNT_32_BIT,
3324 		VK_SAMPLE_COUNT_64_BIT
3325 	};
3326 
3327 	for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
3328 	{
3329 		std::ostringstream caseName;
3330 
3331 		caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
3332 
3333 		// .primitives
3334 		{
3335 			tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
3336 
3337 			rasterizationTests->addChild(primitives);
3338 
3339 			primitives->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",					samples[samplesNdx]));
3340 			primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",						PRIMITIVEWIDENESS_NARROW,	samples[samplesNdx]));
3341 			primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines_wide",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE,		samples[samplesNdx]));
3342 			primitives->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",						PRIMITIVEWIDENESS_WIDE,		samples[samplesNdx]));
3343 		}
3344 
3345 		// .fill_rules
3346 		{
3347 			tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
3348 
3349 			rasterizationTests->addChild(fillRules);
3350 
3351 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_BASIC,			samples[samplesNdx]));
3352 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse",	"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_REVERSED,		samples[samplesNdx]));
3353 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,	samples[samplesNdx]));
3354 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly",		"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,	samples[samplesNdx]));
3355 			fillRules->addChild(new FillRuleTestCase(testCtx,	"projected",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_PROJECTED,		samples[samplesNdx]));
3356 		}
3357 
3358 		// .interpolation
3359 		{
3360 			tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
3361 
3362 			rasterizationTests->addChild(interpolation);
3363 
3364 			interpolation->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE,								samples[samplesNdx]));
3365 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	samples[samplesNdx]));
3366 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		samples[samplesNdx]));
3367 		}
3368 	}
3369 }
3370 
3371 } // anonymous
3372 
createTests(tcu::TestContext & testCtx)3373 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
3374 {
3375 	return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
3376 }
3377 
3378 } // rasterization
3379 } // vkt
3380