Home | History | Annotate | Download | only in rasterization
      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 
     47 #include <vector>
     48 
     49 using namespace vk;
     50 
     51 namespace vkt
     52 {
     53 namespace rasterization
     54 {
     55 namespace
     56 {
     57 
     58 using tcu::RasterizationArguments;
     59 using tcu::TriangleSceneSpec;
     60 using tcu::PointSceneSpec;
     61 using tcu::LineSceneSpec;
     62 using tcu::LineInterpolationMethod;
     63 
     64 static const char* const s_shaderVertexTemplate =	"#version 310 es\n"
     65 													"layout(location = 0) in highp vec4 a_position;\n"
     66 													"layout(location = 1) in highp vec4 a_color;\n"
     67 													"layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
     68 													"layout (set=0, binding=0) uniform PointSize {\n"
     69 													"	highp float u_pointSize;\n"
     70 													"};\n"
     71 													"void main ()\n"
     72 													"{\n"
     73 													"	gl_Position = a_position;\n"
     74 													"	gl_PointSize = u_pointSize;\n"
     75 													"	v_color = a_color;\n"
     76 													"}\n";
     77 
     78 static const char* const s_shaderFragmentTemplate =	"#version 310 es\n"
     79 													"layout(location = 0) out highp vec4 fragColor;\n"
     80 													"layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
     81 													"void main ()\n"
     82 													"{\n"
     83 													"	fragColor = v_color;\n"
     84 													"}\n";
     85 enum InterpolationCaseFlags
     86 {
     87 	INTERPOLATIONFLAGS_NONE = 0,
     88 	INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
     89 	INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
     90 };
     91 
     92 enum PrimitiveWideness
     93 {
     94 	PRIMITIVEWIDENESS_NARROW = 0,
     95 	PRIMITIVEWIDENESS_WIDE,
     96 
     97 	PRIMITIVEWIDENESS_LAST
     98 };
     99 
    100 class BaseRenderingTestCase : public TestCase
    101 {
    102 public:
    103 								BaseRenderingTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
    104 	virtual						~BaseRenderingTestCase	(void);
    105 
    106 	virtual void				initPrograms			(vk::SourceCollections& programCollection) const;
    107 
    108 protected:
    109 	const VkSampleCountFlagBits	m_sampleCount;
    110 	const deBool				m_flatshade;
    111 };
    112 
    113 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
    114 	: TestCase(context, name, description)
    115 	, m_sampleCount	(sampleCount)
    116 	, m_flatshade	(flatshade)
    117 {
    118 }
    119 
    120 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
    121 {
    122 	tcu::StringTemplate					vertexSource	(s_shaderVertexTemplate);
    123 	tcu::StringTemplate					fragmentSource	(s_shaderFragmentTemplate);
    124 	std::map<std::string, std::string>	params;
    125 
    126 	params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
    127 
    128 	programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
    129 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
    130 }
    131 
    132 BaseRenderingTestCase::~BaseRenderingTestCase (void)
    133 {
    134 }
    135 
    136 class BaseRenderingTestInstance : public TestInstance
    137 {
    138 public:
    139 	enum {
    140 		DEFAULT_RENDER_SIZE = 256
    141 	};
    142 
    143 													BaseRenderingTestInstance		(Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE);
    144 													~BaseRenderingTestInstance		(void);
    145 
    146 protected:
    147 	void											addImageTransitionBarrier		(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
    148 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
    149 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
    150 	virtual float									getLineWidth					(void) const;
    151 	virtual float									getPointSize					(void) const;
    152 
    153 	virtual
    154 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo	(void) const;
    155 
    156 	virtual
    157 	const VkPipelineColorBlendStateCreateInfo*		getColorBlendStateCreateInfo	(void) const;
    158 
    159 	const tcu::TextureFormat&						getTextureFormat				(void) const;
    160 
    161 	const deUint32									m_renderSize;
    162 	const VkSampleCountFlagBits						m_sampleCount;
    163 	const deUint32									m_subpixelBits;
    164 	const deBool									m_multisampling;
    165 
    166 	const VkFormat									m_imageFormat;
    167 	const tcu::TextureFormat						m_textureFormat;
    168 	Move<VkCommandPool>								m_commandPool;
    169 
    170 	Move<VkImage>									m_image;
    171 	de::MovePtr<Allocation>							m_imageMemory;
    172 	Move<VkImageView>								m_imageView;
    173 
    174 	Move<VkImage>									m_resolvedImage;
    175 	de::MovePtr<Allocation>							m_resolvedImageMemory;
    176 	Move<VkImageView>								m_resolvedImageView;
    177 
    178 	Move<VkRenderPass>								m_renderPass;
    179 	Move<VkFramebuffer>								m_frameBuffer;
    180 
    181 	Move<VkDescriptorPool>							m_descriptorPool;
    182 	Move<VkDescriptorSet>							m_descriptorSet;
    183 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
    184 
    185 	Move<VkBuffer>									m_uniformBuffer;
    186 	de::MovePtr<Allocation>							m_uniformBufferMemory;
    187 	const VkDeviceSize								m_uniformBufferSize;
    188 
    189 	Move<VkPipelineLayout>							m_pipelineLayout;
    190 
    191 	Move<VkShaderModule>							m_vertexShaderModule;
    192 	Move<VkShaderModule>							m_fragmentShaderModule;
    193 
    194 	Move<VkFence>									m_fence;
    195 
    196 	Move<VkBuffer>									m_resultBuffer;
    197 	de::MovePtr<Allocation>							m_resultBufferMemory;
    198 	const VkDeviceSize								m_resultBufferSize;
    199 };
    200 
    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 	// Fence
    539 	m_fence = createFence(vkd, vkDevice);
    540 
    541 	// Result Buffer
    542 	{
    543 		const VkBufferCreateInfo				bufferCreateInfo		=
    544 		{
    545 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    546 			DE_NULL,									// const void*			pNext;
    547 			0u,											// VkBufferCreateFlags	flags;
    548 			m_resultBufferSize,							// VkDeviceSize			size;
    549 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
    550 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    551 			1u,											// deUint32				queueFamilyIndexCount;
    552 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    553 		};
    554 
    555 		m_resultBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
    556 		m_resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
    557 
    558 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
    559 	}
    560 
    561 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
    562 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
    563 }
    564 
    565 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
    566 {
    567 }
    568 
    569 
    570 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
    571 {
    572 
    573 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
    574 
    575 	const VkImageSubresourceRange	subResourcerange	=
    576 	{
    577 		VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
    578 		0,								// deUint32				baseMipLevel;
    579 		1,								// deUint32				levelCount;
    580 		0,								// deUint32				baseArrayLayer;
    581 		1								// deUint32				layerCount;
    582 	};
    583 
    584 	const VkImageMemoryBarrier		imageBarrier		=
    585 	{
    586 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
    587 		DE_NULL,									// const void*				pNext;
    588 		srcAccessMask,								// VkAccessFlags			srcAccessMask;
    589 		dstAccessMask,								// VkAccessFlags			dstAccessMask;
    590 		oldLayout,									// VkImageLayout			oldLayout;
    591 		newLayout,									// VkImageLayout			newLayout;
    592 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
    593 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
    594 		image,										// VkImage					image;
    595 		subResourcerange							// VkImageSubresourceRange	subresourceRange;
    596 	};
    597 
    598 	vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
    599 }
    600 
    601 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
    602 {
    603 	// default to color white
    604 	const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    605 
    606 	drawPrimitives(result, vertexData, colorData, primitiveTopology);
    607 }
    608 
    609 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
    610 {
    611 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
    612 	const VkDevice								vkDevice				= m_context.getDevice();
    613 	const VkQueue								queue					= m_context.getUniversalQueue();
    614 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
    615 	Allocator&									allocator				= m_context.getDefaultAllocator();
    616 	const size_t								attributeBatchSize		= positionData.size() * sizeof(tcu::Vec4);
    617 
    618 	Move<VkCommandBuffer>						commandBuffer;
    619 	Move<VkPipeline>							graphicsPipeline;
    620 	Move<VkBuffer>								vertexBuffer;
    621 	de::MovePtr<Allocation>						vertexBufferMemory;
    622 	const VkPhysicalDeviceProperties			properties				= m_context.getDeviceProperties();
    623 
    624 	if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
    625 	{
    626 		std::stringstream message;
    627 		message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
    628 		TCU_THROW(NotSupportedError, message.str().c_str());
    629 	}
    630 
    631 	// Create Graphics Pipeline
    632 	{
    633 		const VkPipelineShaderStageCreateInfo	shaderStageParams[2]	=
    634 		{
    635 			{
    636 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType					sType;
    637 				DE_NULL,													// const void*						pNext;
    638 				0,															// VkPipelineShaderStageCreateFlags flags;
    639 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage					stage;
    640 				*m_vertexShaderModule,										// VkShader							shader;
    641 				"main",														// const char*						pName;
    642 				DE_NULL														// const VkSpecializationInfo*		pSpecializationInfo;
    643 			},
    644 			{
    645 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType					sType;
    646 				DE_NULL,													// const void*						pNext;
    647 				0,															// VkPipelineShaderStageCreateFlags flags;
    648 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage					stage;
    649 				*m_fragmentShaderModule,									// VkShader							shader;
    650 				"main",														// const char*						pName;
    651 				DE_NULL														// const VkSpecializationInfo*		pSpecializationInfo;
    652 			}
    653 		};
    654 
    655 		const VkVertexInputBindingDescription	vertexInputBindingDescription =
    656 		{
    657 			0u,								// deUint32					binding;
    658 			sizeof(tcu::Vec4),				// deUint32					strideInBytes;
    659 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
    660 		};
    661 
    662 		const VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2] =
    663 		{
    664 			{
    665 				0u,									// deUint32	location;
    666 				0u,									// deUint32	binding;
    667 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
    668 				0u									// deUint32	offsetInBytes;
    669 			},
    670 			{
    671 				1u,									// deUint32	location;
    672 				0u,									// deUint32	binding;
    673 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
    674 				(deUint32)attributeBatchSize		// deUint32	offsetInBytes;
    675 			}
    676 		};
    677 
    678 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams =
    679 		{
    680 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
    681 			DE_NULL,														// const void*								pNext;
    682 			0,																// VkPipelineVertexInputStateCreateFlags	flags;
    683 			1u,																// deUint32									bindingCount;
    684 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    685 			2u,																// deUint32									attributeCount;
    686 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    687 		};
    688 
    689 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams =
    690 		{
    691 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
    692 			DE_NULL,														// const void*								pNext;
    693 			0,																// VkPipelineInputAssemblyStateCreateFlags	flags;
    694 			primitiveTopology,												// VkPrimitiveTopology						topology;
    695 			false															// VkBool32									primitiveRestartEnable;
    696 		};
    697 
    698 		const VkViewport						viewport =
    699 		{
    700 			0.0f,						// float	originX;
    701 			0.0f,						// float	originY;
    702 			(float)m_renderSize,		// float	width;
    703 			(float)m_renderSize,		// float	height;
    704 			0.0f,						// float	minDepth;
    705 			1.0f						// float	maxDepth;
    706 		};
    707 
    708 		const VkRect2D							scissor =
    709 		{
    710 			{ 0, 0 },														// VkOffset2D  offset;
    711 			{ m_renderSize, m_renderSize }									// VkExtent2D  extent;
    712 		};
    713 
    714 		const VkPipelineViewportStateCreateInfo	viewportStateParams =
    715 		{
    716 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
    717 			DE_NULL,														// const void*							pNext;
    718 			0,																// VkPipelineViewportStateCreateFlags	flags;
    719 			1u,																// deUint32								viewportCount;
    720 			&viewport,														// const VkViewport*					pViewports;
    721 			1u,																// deUint32								scissorCount;
    722 			&scissor														// const VkRect2D*						pScissors;
    723 		};
    724 
    725 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
    726 		{
    727 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
    728 			DE_NULL,														// const void*								pNext;
    729 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
    730 			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
    731 			VK_FALSE,														// VkBool32									sampleShadingEnable;
    732 			0.0f,															// float									minSampleShading;
    733 			DE_NULL,														// const VkSampleMask*						pSampleMask;
    734 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
    735 			VK_FALSE														// VkBool32									alphaToOneEnable;
    736 		};
    737 
    738 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
    739 		{
    740 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
    741 			DE_NULL,											// const void*										pNext;
    742 			0u,													// VkPipelineCreateFlags							flags;
    743 			2u,													// deUint32											stageCount;
    744 			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
    745 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    746 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    747 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    748 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
    749 			getRasterizationStateCreateInfo(),					// const VkPipelineRasterStateCreateInfo*			pRasterizationState;
    750 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    751 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    752 			getColorBlendStateCreateInfo(),						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    753 			DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    754 			*m_pipelineLayout,									// VkPipelineLayout									layout;
    755 			*m_renderPass,										// VkRenderPass										renderPass;
    756 			0u,													// deUint32											subpass;
    757 			0u,													// VkPipeline										basePipelineHandle;
    758 			0u													// deInt32											basePipelineIndex;
    759 		};
    760 
    761 		graphicsPipeline		= createGraphicsPipeline(vkd, vkDevice, DE_NULL, &graphicsPipelineParams);
    762 	}
    763 
    764 	// Create Vertex Buffer
    765 	{
    766 		const VkBufferCreateInfo			vertexBufferParams		=
    767 		{
    768 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    769 			DE_NULL,									// const void*			pNext;
    770 			0u,											// VkBufferCreateFlags	flags;
    771 			attributeBatchSize * 2,						// VkDeviceSize			size;
    772 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    773 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    774 			1u,											// deUint32				queueFamilyCount;
    775 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    776 		};
    777 
    778 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
    779 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
    780 
    781 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
    782 
    783 		// Load vertices into vertex buffer
    784 		deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
    785 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, colorData.data(), attributeBatchSize);
    786 		flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size);
    787 	}
    788 
    789 	// Create Command Buffer
    790 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    791 
    792 	// Begin Command Buffer
    793 	{
    794 		const VkCommandBufferBeginInfo		cmdBufferBeginInfo		=
    795 		{
    796 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType							sType;
    797 			DE_NULL,										// const void*								pNext;
    798 			0u,												// VkCmdBufferOptimizeFlags					flags;
    799 			DE_NULL											// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
    800 		};
    801 
    802 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &cmdBufferBeginInfo));
    803 	}
    804 
    805 	addImageTransitionBarrier(*commandBuffer, *m_image,
    806 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
    807 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
    808 							  0,												// VkAccessFlags			srcAccessMask
    809 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
    810 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
    811 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
    812 
    813 	if (m_multisampling) {
    814 		addImageTransitionBarrier(*commandBuffer, *m_resolvedImage,
    815 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
    816 								  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
    817 								  0,												// VkAccessFlags			srcAccessMask
    818 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
    819 								  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
    820 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
    821 	}
    822 
    823 	// Begin Render Pass
    824 	{
    825 		const VkClearValue					clearValue				= makeClearValueColorF32(0.0, 0.0, 0.0, 1.0);
    826 
    827 		const VkRenderPassBeginInfo			renderPassBeginInfo		=
    828 		{
    829 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
    830 			DE_NULL,												// const void*			pNext;
    831 			*m_renderPass,											// VkRenderPass			renderPass;
    832 			*m_frameBuffer,											// VkFramebuffer		framebuffer;
    833 			{
    834 				{ 0, 0 },
    835 				{ m_renderSize, m_renderSize }
    836 			},														// VkRect2D				renderArea;
    837 			1u,														// deUint32				clearValueCount;
    838 			&clearValue												// const VkClearValue*	pClearValues;
    839 		};
    840 
    841 		vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    842 	}
    843 
    844 	const VkDeviceSize						vertexBufferOffset		= 0;
    845 
    846 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
    847 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
    848 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
    849 	vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
    850 	vkd.cmdEndRenderPass(*commandBuffer);
    851 
    852 	// Copy Image
    853 	{
    854 
    855 		const VkBufferMemoryBarrier			bufferBarrier			=
    856 		{
    857 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType		sType;
    858 			DE_NULL,									// const void*			pNext;
    859 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkMemoryOutputFlags	outputMask;
    860 			VK_ACCESS_HOST_READ_BIT,					// VkMemoryInputFlags	inputMask;
    861 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				srcQueueFamilyIndex;
    862 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				destQueueFamilyIndex;
    863 			*m_resultBuffer,							// VkBuffer				buffer;
    864 			0u,											// VkDeviceSize			offset;
    865 			m_resultBufferSize							// VkDeviceSize			size;
    866 		};
    867 
    868 		const VkBufferImageCopy				copyRegion				=
    869 		{
    870 			0u,											// VkDeviceSize				bufferOffset;
    871 			m_renderSize,								// deUint32					bufferRowLength;
    872 			m_renderSize,								// deUint32					bufferImageHeight;
    873 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u },	// VkImageSubresourceCopy	imageSubresource;
    874 			{ 0, 0, 0 },								// VkOffset3D				imageOffset;
    875 			{ m_renderSize, m_renderSize, 1u }			// VkExtent3D				imageExtent;
    876 		};
    877 
    878 		addImageTransitionBarrier(*commandBuffer,
    879 								  m_multisampling ? *m_resolvedImage : *m_image,
    880 								  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags		srcStageMask
    881 								  VK_PIPELINE_STAGE_TRANSFER_BIT,						// VkPipelineStageFlags		dstStageMask
    882 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags			srcAccessMask
    883 								  VK_ACCESS_TRANSFER_READ_BIT,							// VkAccessFlags			dstAccessMask
    884 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			oldLayout;
    885 								  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);				// VkImageLayout			newLayout;)
    886 
    887 		if (m_multisampling)
    888 			vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
    889 		else
    890 			vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
    891 
    892 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
    893 	}
    894 
    895 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
    896 
    897 	// Set Point Size
    898 	{
    899 		float	pointSize	= getPointSize();
    900 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
    901 		flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize);
    902 	}
    903 
    904 	// Submit
    905 	{
    906 		const VkSubmitInfo					submitInfo				=
    907 		{
    908 			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType				sType;
    909 			DE_NULL,								// const void*					pNext;
    910 			0u,										// deUint32						waitSemaphoreCount;
    911 			DE_NULL,								// const VkSemaphore*			pWaitSemaphores;
    912 			DE_NULL,								// const VkPipelineStageFlags*	pWaitDstStageMask;
    913 			1u,										// deUint32						commandBufferCount;
    914 			&commandBuffer.get(),					// const VkCommandBuffer*		pCommandBuffers;
    915 			0u,										// deUint32						signalSemaphoreCount;
    916 			DE_NULL,								// const VkSemaphore*			pSignalSemaphores;
    917 		};
    918 
    919 		VK_CHECK(vkd.resetFences(vkDevice, 1, &m_fence.get()));
    920 		VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, *m_fence));
    921 		VK_CHECK(vkd.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
    922 	}
    923 
    924 	invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize);
    925 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
    926 }
    927 
    928 float BaseRenderingTestInstance::getLineWidth (void) const
    929 {
    930 	return 1.0f;
    931 }
    932 
    933 float BaseRenderingTestInstance::getPointSize (void) const
    934 {
    935 	return 1.0f;
    936 }
    937 
    938 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
    939 {
    940 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
    941 	{
    942 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    943 		DE_NULL,														// const void*								pNext;
    944 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
    945 		false,															// VkBool32									depthClipEnable;
    946 		false,															// VkBool32									rasterizerDiscardEnable;
    947 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
    948 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
    949 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    950 		VK_FALSE,														// VkBool32									depthBiasEnable;
    951 		0.0f,															// float									depthBias;
    952 		0.0f,															// float									depthBiasClamp;
    953 		0.0f,															// float									slopeScaledDepthBias;
    954 		getLineWidth(),													// float									lineWidth;
    955 	};
    956 
    957 	rasterizationStateCreateInfo.lineWidth = getLineWidth();
    958 	return &rasterizationStateCreateInfo;
    959 }
    960 
    961 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
    962 {
    963 	static const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
    964 	{
    965 		false,														// VkBool32			blendEnable;
    966 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
    967 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendColor;
    968 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
    969 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
    970 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendAlpha;
    971 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
    972 		(VK_COLOR_COMPONENT_R_BIT |
    973 		 VK_COLOR_COMPONENT_G_BIT |
    974 		 VK_COLOR_COMPONENT_B_BIT |
    975 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
    976 	};
    977 
    978 	static const VkPipelineColorBlendStateCreateInfo	colorBlendStateParams		=
    979 	{
    980 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    981 		DE_NULL,													// const void*									pNext;
    982 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
    983 		false,														// VkBool32										logicOpEnable;
    984 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    985 		1u,															// deUint32										attachmentCount;
    986 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
    987 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
    988 	};
    989 
    990 	return &colorBlendStateParams;
    991 }
    992 
    993 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
    994 {
    995 	return m_textureFormat;
    996 }
    997 
    998 class BaseTriangleTestInstance : public BaseRenderingTestInstance
    999 {
   1000 public:
   1001 							BaseTriangleTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount);
   1002 	virtual tcu::TestStatus	iterate						(void);
   1003 
   1004 private:
   1005 	virtual void			generateTriangles			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
   1006 
   1007 	int						m_iteration;
   1008 	const int				m_iterationCount;
   1009 	VkPrimitiveTopology		m_primitiveTopology;
   1010 	bool					m_allIterationsPassed;
   1011 };
   1012 
   1013 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount)
   1014 	: BaseRenderingTestInstance		(context, sampleCount)
   1015 	, m_iteration					(0)
   1016 	, m_iterationCount				(3)
   1017 	, m_primitiveTopology			(primitiveTopology)
   1018 	, m_allIterationsPassed			(true)
   1019 {
   1020 }
   1021 
   1022 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
   1023 {
   1024 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   1025 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
   1026 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
   1027 	std::vector<tcu::Vec4>							drawBuffer;
   1028 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
   1029 
   1030 	generateTriangles(m_iteration, drawBuffer, triangles);
   1031 
   1032 	// draw image
   1033 	drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
   1034 
   1035 	// compare
   1036 	{
   1037 		bool					compareOk;
   1038 		RasterizationArguments	args;
   1039 		TriangleSceneSpec		scene;
   1040 
   1041 		tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
   1042 
   1043 		args.numSamples		= m_multisampling ? 1 : 0;
   1044 		args.subpixelBits	= m_subpixelBits;
   1045 		args.redBits		= colorBits[0];
   1046 		args.greenBits		= colorBits[1];
   1047 		args.blueBits		= colorBits[2];
   1048 
   1049 		scene.triangles.swap(triangles);
   1050 
   1051 		compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
   1052 
   1053 		if (!compareOk)
   1054 			m_allIterationsPassed = false;
   1055 	}
   1056 
   1057 	// result
   1058 	if (++m_iteration == m_iterationCount)
   1059 	{
   1060 		if (m_allIterationsPassed)
   1061 			return tcu::TestStatus::pass("Pass");
   1062 		else
   1063 			return tcu::TestStatus::fail("Incorrect rasterization");
   1064 	}
   1065 	else
   1066 		return tcu::TestStatus::incomplete();
   1067 }
   1068 
   1069 class BaseLineTestInstance : public BaseRenderingTestInstance
   1070 {
   1071 public:
   1072 							BaseLineTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
   1073 	virtual tcu::TestStatus	iterate					(void);
   1074 	virtual float			getLineWidth			(void) const;
   1075 
   1076 private:
   1077 	virtual void			generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
   1078 
   1079 	int						m_iteration;
   1080 	const int				m_iterationCount;
   1081 	VkPrimitiveTopology		m_primitiveTopology;
   1082 	const PrimitiveWideness	m_primitiveWideness;
   1083 	bool					m_allIterationsPassed;
   1084 	float					m_maxLineWidth;
   1085 	std::vector<float>		m_lineWidths;
   1086 };
   1087 
   1088 BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
   1089 	: BaseRenderingTestInstance			(context, sampleCount)
   1090 	, m_iteration						(0)
   1091 	, m_iterationCount					(3)
   1092 	, m_primitiveTopology				(primitiveTopology)
   1093 	, m_primitiveWideness				(wideness)
   1094 	, m_allIterationsPassed				(true)
   1095 	, m_maxLineWidth					(1.0f)
   1096 {
   1097 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
   1098 
   1099 	if (!context.getDeviceProperties().limits.strictLines)
   1100 		TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
   1101 
   1102 	// create line widths
   1103 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
   1104 	{
   1105 		m_lineWidths.resize(m_iterationCount, 1.0f);
   1106 	}
   1107 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
   1108 	{
   1109 		if (!m_context.getDeviceFeatures().wideLines)
   1110 			TCU_THROW(NotSupportedError , "wide line support required");
   1111 
   1112 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
   1113 
   1114 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
   1115 
   1116 		// no wide line support
   1117 		if (range[1] <= 1.0f)
   1118 			TCU_THROW(NotSupportedError, "wide line support required");
   1119 
   1120 		// set hand picked sizes
   1121 		m_lineWidths.push_back(5.0f);
   1122 		m_lineWidths.push_back(10.0f);
   1123 		m_lineWidths.push_back(range[1]);
   1124 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
   1125 
   1126 		m_maxLineWidth = range[1];
   1127 	}
   1128 	else
   1129 		DE_ASSERT(false);
   1130 }
   1131 
   1132 tcu::TestStatus BaseLineTestInstance::iterate (void)
   1133 {
   1134 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   1135 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
   1136 	const float								lineWidth				= getLineWidth();
   1137 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
   1138 	std::vector<tcu::Vec4>					drawBuffer;
   1139 	std::vector<LineSceneSpec::SceneLine>	lines;
   1140 
   1141 	// supported?
   1142 	if (lineWidth <= m_maxLineWidth)
   1143 	{
   1144 		// gen data
   1145 		generateLines(m_iteration, drawBuffer, lines);
   1146 
   1147 		// draw image
   1148 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
   1149 
   1150 		// compare
   1151 		{
   1152 			RasterizationArguments	args;
   1153 			LineSceneSpec			scene;
   1154 
   1155 
   1156 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
   1157 
   1158 			args.numSamples		= m_multisampling ? 1 : 0;
   1159 			args.subpixelBits	= m_subpixelBits;
   1160 			args.redBits		= colorBits[0];
   1161 			args.greenBits		= colorBits[1];
   1162 			args.blueBits		= colorBits[2];
   1163 
   1164 			scene.lines.swap(lines);
   1165 			scene.lineWidth = lineWidth;
   1166 
   1167 			if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
   1168 				m_allIterationsPassed = false;
   1169 		}
   1170 	}
   1171 	else
   1172 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
   1173 
   1174 	// result
   1175 	if (++m_iteration == m_iterationCount)
   1176 	{
   1177 		if (m_allIterationsPassed)
   1178 			return tcu::TestStatus::pass("Pass");
   1179 		else
   1180 			return tcu::TestStatus::fail("Incorrect rasterization");
   1181 	}
   1182 	else
   1183 		return tcu::TestStatus::incomplete();
   1184 }
   1185 
   1186 
   1187 float BaseLineTestInstance::getLineWidth (void) const
   1188 {
   1189 	return m_lineWidths[m_iteration];
   1190 }
   1191 
   1192 
   1193 class PointTestInstance : public BaseRenderingTestInstance
   1194 {
   1195 public:
   1196 							PointTestInstance		(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
   1197 	virtual tcu::TestStatus	iterate					(void);
   1198 	virtual float			getPointSize			(void) const;
   1199 
   1200 private:
   1201 	virtual void			generatePoints			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
   1202 
   1203 	int						m_iteration;
   1204 	const int				m_iterationCount;
   1205 	const PrimitiveWideness	m_primitiveWideness;
   1206 	bool					m_allIterationsPassed;
   1207 	float					m_maxPointSize;
   1208 	std::vector<float>		m_pointSizes;
   1209 };
   1210 
   1211 PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
   1212 	: BaseRenderingTestInstance	(context, sampleCount)
   1213 	, m_iteration				(0)
   1214 	, m_iterationCount			(3)
   1215 	, m_primitiveWideness		(wideness)
   1216 	, m_allIterationsPassed		(true)
   1217 	, m_maxPointSize			(1.0f)
   1218 {
   1219 	// create point sizes
   1220 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
   1221 	{
   1222 		m_pointSizes.resize(m_iterationCount, 1.0f);
   1223 	}
   1224 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
   1225 	{
   1226 		if (!m_context.getDeviceFeatures().largePoints)
   1227 			TCU_THROW(NotSupportedError , "large point support required");
   1228 
   1229 		const float*	range = context.getDeviceProperties().limits.pointSizeRange;
   1230 
   1231 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
   1232 
   1233 		// no wide line support
   1234 		if (range[1] <= 1.0f)
   1235 			TCU_THROW(NotSupportedError , "wide point support required");
   1236 
   1237 		// set hand picked sizes
   1238 		m_pointSizes.push_back(10.0f);
   1239 		m_pointSizes.push_back(25.0f);
   1240 		m_pointSizes.push_back(range[1]);
   1241 		DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
   1242 
   1243 		m_maxPointSize = range[1];
   1244 	}
   1245 	else
   1246 		DE_ASSERT(false);
   1247 }
   1248 
   1249 tcu::TestStatus PointTestInstance::iterate (void)
   1250 {
   1251 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   1252 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
   1253 	const float								pointSize				= getPointSize();
   1254 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
   1255 	std::vector<tcu::Vec4>					drawBuffer;
   1256 	std::vector<PointSceneSpec::ScenePoint>	points;
   1257 
   1258 	// supported?
   1259 	if (pointSize <= m_maxPointSize)
   1260 	{
   1261 		// gen data
   1262 		generatePoints(m_iteration, drawBuffer, points);
   1263 
   1264 		// draw image
   1265 		drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
   1266 
   1267 		// compare
   1268 		{
   1269 			bool					compareOk;
   1270 			RasterizationArguments	args;
   1271 			PointSceneSpec			scene;
   1272 
   1273 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
   1274 
   1275 			args.numSamples		= m_multisampling ? 1 : 0;
   1276 			args.subpixelBits	= m_subpixelBits;
   1277 			args.redBits		= colorBits[0];
   1278 			args.greenBits		= colorBits[1];
   1279 			args.blueBits		= colorBits[2];
   1280 
   1281 			scene.points.swap(points);
   1282 
   1283 			compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
   1284 
   1285 			if (!compareOk)
   1286 				m_allIterationsPassed = false;
   1287 		}
   1288 	}
   1289 	else
   1290 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
   1291 
   1292 	// result
   1293 	if (++m_iteration == m_iterationCount)
   1294 	{
   1295 		if (m_allIterationsPassed)
   1296 			return tcu::TestStatus::pass("Pass");
   1297 		else
   1298 			return tcu::TestStatus::fail("Incorrect rasterization");
   1299 	}
   1300 	else
   1301 		return tcu::TestStatus::incomplete();
   1302 }
   1303 
   1304 float PointTestInstance::getPointSize (void) const
   1305 {
   1306 	return m_pointSizes[m_iteration];
   1307 }
   1308 
   1309 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
   1310 {
   1311 	outData.resize(6);
   1312 
   1313 	switch (iteration)
   1314 	{
   1315 		case 0:
   1316 			// \note: these values are chosen arbitrarily
   1317 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
   1318 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
   1319 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
   1320 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
   1321 			outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
   1322 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
   1323 			break;
   1324 
   1325 		case 1:
   1326 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
   1327 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
   1328 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
   1329 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
   1330 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
   1331 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
   1332 			break;
   1333 
   1334 		case 2:
   1335 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
   1336 			outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
   1337 			outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
   1338 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
   1339 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
   1340 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
   1341 			break;
   1342 	}
   1343 
   1344 	outPoints.resize(outData.size());
   1345 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
   1346 	{
   1347 		outPoints[pointNdx].position = outData[pointNdx];
   1348 		outPoints[pointNdx].pointSize = getPointSize();
   1349 	}
   1350 
   1351 	// log
   1352 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
   1353 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
   1354 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
   1355 }
   1356 
   1357 template <typename ConcreteTestInstance>
   1358 class BaseTestCase : public BaseRenderingTestCase
   1359 {
   1360 public:
   1361 							BaseTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
   1362 								: BaseRenderingTestCase(context, name, description, sampleCount)
   1363 							{}
   1364 
   1365 	virtual TestInstance*	createInstance	(Context& context) const
   1366 							{
   1367 								return new ConcreteTestInstance(context, m_sampleCount);
   1368 							}
   1369 };
   1370 
   1371 class TrianglesTestInstance : public BaseTriangleTestInstance
   1372 {
   1373 public:
   1374 							TrianglesTestInstance	(Context& context, VkSampleCountFlagBits sampleCount)
   1375 								: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
   1376 							{}
   1377 
   1378 	void					generateTriangles		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
   1379 };
   1380 
   1381 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
   1382 {
   1383 	outData.resize(6);
   1384 
   1385 	switch (iteration)
   1386 	{
   1387 		case 0:
   1388 			// \note: these values are chosen arbitrarily
   1389 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
   1390 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
   1391 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
   1392 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
   1393 			outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
   1394 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
   1395 			break;
   1396 
   1397 		case 1:
   1398 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
   1399 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
   1400 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
   1401 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
   1402 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
   1403 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
   1404 			break;
   1405 
   1406 		case 2:
   1407 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
   1408 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
   1409 			outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
   1410 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
   1411 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
   1412 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
   1413 			break;
   1414 	}
   1415 
   1416 	outTriangles.resize(2);
   1417 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
   1418 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
   1419 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
   1420 
   1421 	outTriangles[1].positions[0] = outData[3];	outTriangles[1].sharedEdge[0] = false;
   1422 	outTriangles[1].positions[1] = outData[4];	outTriangles[1].sharedEdge[1] = false;
   1423 	outTriangles[1].positions[2] = outData[5];	outTriangles[1].sharedEdge[2] = false;
   1424 
   1425 	// log
   1426 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
   1427 	for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
   1428 	{
   1429 		m_context.getTestContext().getLog()
   1430 			<< tcu::TestLog::Message
   1431 			<< "Triangle " << (triangleNdx+1) << ":"
   1432 			<< "\n\t" << outTriangles[triangleNdx].positions[0]
   1433 			<< "\n\t" << outTriangles[triangleNdx].positions[1]
   1434 			<< "\n\t" << outTriangles[triangleNdx].positions[2]
   1435 			<< tcu::TestLog::EndMessage;
   1436 	}
   1437 }
   1438 
   1439 class TriangleStripTestInstance : public BaseTriangleTestInstance
   1440 {
   1441 public:
   1442 				TriangleStripTestInstance		(Context& context, VkSampleCountFlagBits sampleCount)
   1443 					: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
   1444 				{}
   1445 
   1446 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
   1447 };
   1448 
   1449 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
   1450 {
   1451 	outData.resize(5);
   1452 
   1453 	switch (iteration)
   1454 	{
   1455 		case 0:
   1456 			// \note: these values are chosen arbitrarily
   1457 			outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
   1458 			outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
   1459 			outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
   1460 			outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
   1461 			outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
   1462 			break;
   1463 
   1464 		case 1:
   1465 			outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
   1466 			outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
   1467 			outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
   1468 			outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
   1469 			outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
   1470 			break;
   1471 
   1472 		case 2:
   1473 			outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
   1474 			outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
   1475 			outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
   1476 			outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
   1477 			outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
   1478 			break;
   1479 	}
   1480 
   1481 	outTriangles.resize(3);
   1482 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
   1483 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = true;
   1484 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
   1485 
   1486 	outTriangles[1].positions[0] = outData[2];	outTriangles[1].sharedEdge[0] = true;
   1487 	outTriangles[1].positions[1] = outData[1];	outTriangles[1].sharedEdge[1] = false;
   1488 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
   1489 
   1490 	outTriangles[2].positions[0] = outData[2];	outTriangles[2].sharedEdge[0] = true;
   1491 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
   1492 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
   1493 
   1494 	// log
   1495 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
   1496 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
   1497 	{
   1498 		m_context.getTestContext().getLog()
   1499 			<< tcu::TestLog::Message
   1500 			<< "\t" << outData[vtxNdx]
   1501 			<< tcu::TestLog::EndMessage;
   1502 	}
   1503 }
   1504 
   1505 class TriangleFanTestInstance : public BaseTriangleTestInstance
   1506 {
   1507 public:
   1508 				TriangleFanTestInstance			(Context& context, VkSampleCountFlagBits sampleCount)
   1509 					: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
   1510 				{}
   1511 
   1512 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
   1513 };
   1514 
   1515 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
   1516 {
   1517 	outData.resize(5);
   1518 
   1519 	switch (iteration)
   1520 	{
   1521 		case 0:
   1522 			// \note: these values are chosen arbitrarily
   1523 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
   1524 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
   1525 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
   1526 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
   1527 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 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 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
   1536 			break;
   1537 
   1538 		case 2:
   1539 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
   1540 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
   1541 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
   1542 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
   1543 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
   1544 			break;
   1545 	}
   1546 
   1547 	outTriangles.resize(3);
   1548 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
   1549 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
   1550 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = true;
   1551 
   1552 	outTriangles[1].positions[0] = outData[0];	outTriangles[1].sharedEdge[0] = true;
   1553 	outTriangles[1].positions[1] = outData[2];	outTriangles[1].sharedEdge[1] = false;
   1554 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
   1555 
   1556 	outTriangles[2].positions[0] = outData[0];	outTriangles[2].sharedEdge[0] = true;
   1557 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
   1558 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
   1559 
   1560 	// log
   1561 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
   1562 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
   1563 	{
   1564 		m_context.getTestContext().getLog()
   1565 			<< tcu::TestLog::Message
   1566 			<< "\t" << outData[vtxNdx]
   1567 			<< tcu::TestLog::EndMessage;
   1568 	}
   1569 }
   1570 
   1571 template <typename ConcreteTestInstance>
   1572 class WidenessTestCase : public BaseRenderingTestCase
   1573 {
   1574 public:
   1575 								WidenessTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
   1576 									: BaseRenderingTestCase(context, name, description, sampleCount)
   1577 									, m_wideness(wideness)
   1578 								{}
   1579 
   1580 	virtual TestInstance*		createInstance		(Context& context) const
   1581 								{
   1582 									return new ConcreteTestInstance(context, m_wideness, m_sampleCount);
   1583 								}
   1584 protected:
   1585 	const PrimitiveWideness		m_wideness;
   1586 };
   1587 
   1588 class LinesTestInstance : public BaseLineTestInstance
   1589 {
   1590 public:
   1591 								LinesTestInstance	(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
   1592 									: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount)
   1593 								{}
   1594 
   1595 	virtual void				generateLines		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
   1596 };
   1597 
   1598 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
   1599 {
   1600 	outData.resize(6);
   1601 
   1602 	switch (iteration)
   1603 	{
   1604 		case 0:
   1605 			// \note: these values are chosen arbitrarily
   1606 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
   1607 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
   1608 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
   1609 			outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
   1610 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
   1611 			outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
   1612 			break;
   1613 
   1614 		case 1:
   1615 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
   1616 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
   1617 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
   1618 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
   1619 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
   1620 			outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
   1621 			break;
   1622 
   1623 		case 2:
   1624 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
   1625 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
   1626 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
   1627 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
   1628 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
   1629 			outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
   1630 			break;
   1631 	}
   1632 
   1633 	outLines.resize(3);
   1634 	outLines[0].positions[0] = outData[0];
   1635 	outLines[0].positions[1] = outData[1];
   1636 	outLines[1].positions[0] = outData[2];
   1637 	outLines[1].positions[1] = outData[3];
   1638 	outLines[2].positions[0] = outData[4];
   1639 	outLines[2].positions[1] = outData[5];
   1640 
   1641 	// log
   1642 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
   1643 	for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
   1644 	{
   1645 		m_context.getTestContext().getLog()
   1646 			<< tcu::TestLog::Message
   1647 			<< "Line " << (lineNdx+1) << ":"
   1648 			<< "\n\t" << outLines[lineNdx].positions[0]
   1649 			<< "\n\t" << outLines[lineNdx].positions[1]
   1650 			<< tcu::TestLog::EndMessage;
   1651 	}
   1652 }
   1653 
   1654 class LineStripTestInstance : public BaseLineTestInstance
   1655 {
   1656 public:
   1657 					LineStripTestInstance	(Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
   1658 						: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount)
   1659 					{}
   1660 
   1661 	virtual void	generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
   1662 };
   1663 
   1664 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
   1665 {
   1666 	outData.resize(4);
   1667 
   1668 	switch (iteration)
   1669 	{
   1670 		case 0:
   1671 			// \note: these values are chosen arbitrarily
   1672 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
   1673 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
   1674 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
   1675 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
   1676 			break;
   1677 
   1678 		case 1:
   1679 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
   1680 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
   1681 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
   1682 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
   1683 			break;
   1684 
   1685 		case 2:
   1686 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
   1687 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
   1688 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
   1689 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
   1690 			break;
   1691 	}
   1692 
   1693 	outLines.resize(3);
   1694 	outLines[0].positions[0] = outData[0];
   1695 	outLines[0].positions[1] = outData[1];
   1696 	outLines[1].positions[0] = outData[1];
   1697 	outLines[1].positions[1] = outData[2];
   1698 	outLines[2].positions[0] = outData[2];
   1699 	outLines[2].positions[1] = outData[3];
   1700 
   1701 	// log
   1702 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
   1703 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
   1704 	{
   1705 		m_context.getTestContext().getLog()
   1706 			<< tcu::TestLog::Message
   1707 			<< "\t" << outData[vtxNdx]
   1708 			<< tcu::TestLog::EndMessage;
   1709 	}
   1710 }
   1711 
   1712 class FillRuleTestInstance : public BaseRenderingTestInstance
   1713 {
   1714 public:
   1715 	enum FillRuleCaseType
   1716 	{
   1717 		FILLRULECASE_BASIC = 0,
   1718 		FILLRULECASE_REVERSED,
   1719 		FILLRULECASE_CLIPPED_FULL,
   1720 		FILLRULECASE_CLIPPED_PARTIAL,
   1721 		FILLRULECASE_PROJECTED,
   1722 
   1723 		FILLRULECASE_LAST
   1724 	};
   1725 														FillRuleTestInstance			(Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
   1726 	virtual tcu::TestStatus								iterate							(void);
   1727 
   1728 private:
   1729 
   1730 	virtual const VkPipelineColorBlendStateCreateInfo*	getColorBlendStateCreateInfo	(void) const;
   1731 	int													getRenderSize					(FillRuleCaseType type) const;
   1732 	int													getNumIterations				(FillRuleCaseType type) const;
   1733 	void												generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData) const;
   1734 
   1735 	const FillRuleCaseType								m_caseType;
   1736 	int													m_iteration;
   1737 	const int											m_iterationCount;
   1738 	bool												m_allIterationsPassed;
   1739 
   1740 };
   1741 
   1742 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
   1743 	: BaseRenderingTestInstance		(context, sampleCount, getRenderSize(type))
   1744 	, m_caseType					(type)
   1745 	, m_iteration					(0)
   1746 	, m_iterationCount				(getNumIterations(type))
   1747 	, m_allIterationsPassed			(true)
   1748 {
   1749 	DE_ASSERT(type < FILLRULECASE_LAST);
   1750 }
   1751 
   1752 tcu::TestStatus FillRuleTestInstance::iterate (void)
   1753 {
   1754 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   1755 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
   1756 	tcu::IVec4								colorBits				= tcu::getTextureFormatBitDepth(getTextureFormat());
   1757 	const int								thresholdRed			= 1 << (8 - colorBits[0]);
   1758 	const int								thresholdGreen			= 1 << (8 - colorBits[1]);
   1759 	const int								thresholdBlue			= 1 << (8 - colorBits[2]);
   1760 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
   1761 	std::vector<tcu::Vec4>					drawBuffer;
   1762 
   1763 	generateTriangles(m_iteration, drawBuffer);
   1764 
   1765 	// draw image
   1766 	{
   1767 		const std::vector<tcu::Vec4>	colorBuffer		(drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
   1768 
   1769 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
   1770 
   1771 		drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
   1772 	}
   1773 
   1774 	// verify no overdraw
   1775 	{
   1776 		const tcu::RGBA	triangleColor	= tcu::RGBA(127, 127, 127, 255);
   1777 		bool			overdraw		= false;
   1778 
   1779 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
   1780 
   1781 		for (int y = 0; y < resultImage.getHeight(); ++y)
   1782 		for (int x = 0; x < resultImage.getWidth();  ++x)
   1783 		{
   1784 			const tcu::RGBA color = resultImage.getPixel(x, y);
   1785 
   1786 			// color values are greater than triangle color? Allow lower values for multisampled edges and background.
   1787 			if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
   1788 				(color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
   1789 				(color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
   1790 				overdraw = true;
   1791 		}
   1792 
   1793 		// results
   1794 		if (!overdraw)
   1795 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
   1796 		else
   1797 		{
   1798 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
   1799 			m_allIterationsPassed = false;
   1800 		}
   1801 	}
   1802 
   1803 	// verify no missing fragments in the full viewport case
   1804 	if (m_caseType == FILLRULECASE_CLIPPED_FULL)
   1805 	{
   1806 		bool missingFragments = false;
   1807 
   1808 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
   1809 
   1810 		for (int y = 0; y < resultImage.getHeight(); ++y)
   1811 		for (int x = 0; x < resultImage.getWidth();  ++x)
   1812 		{
   1813 			const tcu::RGBA color = resultImage.getPixel(x, y);
   1814 
   1815 			// black? (background)
   1816 			if (color.getRed()   <= thresholdRed   ||
   1817 				color.getGreen() <= thresholdGreen ||
   1818 				color.getBlue()  <= thresholdBlue)
   1819 				missingFragments = true;
   1820 		}
   1821 
   1822 		// results
   1823 		if (!missingFragments)
   1824 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
   1825 		else
   1826 		{
   1827 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
   1828 
   1829 			m_allIterationsPassed = false;
   1830 		}
   1831 	}
   1832 
   1833 	m_context.getTestContext().getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
   1834 										<< tcu::TestLog::Image("Result", "Result", resultImage)
   1835 										<< tcu::TestLog::EndImageSet;
   1836 
   1837 	// result
   1838 	if (++m_iteration == m_iterationCount)
   1839 	{
   1840 		if (m_allIterationsPassed)
   1841 			return tcu::TestStatus::pass("Pass");
   1842 		else
   1843 			return tcu::TestStatus::fail("Found invalid pixels");
   1844 	}
   1845 	else
   1846 		return tcu::TestStatus::incomplete();
   1847 }
   1848 
   1849 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
   1850 {
   1851 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
   1852 		return DEFAULT_RENDER_SIZE / 4;
   1853 	else
   1854 		return DEFAULT_RENDER_SIZE;
   1855 }
   1856 
   1857 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
   1858 {
   1859 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
   1860 		return 15;
   1861 	else
   1862 		return 2;
   1863 }
   1864 
   1865 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
   1866 {
   1867 	switch (m_caseType)
   1868 	{
   1869 		case FILLRULECASE_BASIC:
   1870 		case FILLRULECASE_REVERSED:
   1871 		case FILLRULECASE_PROJECTED:
   1872 		{
   1873 			const int	numRows		= 4;
   1874 			const int	numColumns	= 4;
   1875 			const float	quadSide	= 0.15f;
   1876 			de::Random	rnd			(0xabcd);
   1877 
   1878 			outData.resize(6 * numRows * numColumns);
   1879 
   1880 			for (int col = 0; col < numColumns; ++col)
   1881 			for (int row = 0; row < numRows;    ++row)
   1882 			{
   1883 				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);
   1884 				const float		rotation	= (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
   1885 				const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
   1886 				const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
   1887 				const tcu::Vec2 quad[4]		=
   1888 				{
   1889 					center + sideH + sideV,
   1890 					center + sideH - sideV,
   1891 					center - sideH - sideV,
   1892 					center - sideH + sideV,
   1893 				};
   1894 
   1895 				if (m_caseType == FILLRULECASE_BASIC)
   1896 				{
   1897 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1898 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
   1899 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1900 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1901 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1902 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
   1903 				}
   1904 				else if (m_caseType == FILLRULECASE_REVERSED)
   1905 				{
   1906 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1907 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
   1908 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1909 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1910 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1911 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
   1912 				}
   1913 				else if (m_caseType == FILLRULECASE_PROJECTED)
   1914 				{
   1915 					const float w0 = rnd.getFloat(0.1f, 4.0f);
   1916 					const float w1 = rnd.getFloat(0.1f, 4.0f);
   1917 					const float w2 = rnd.getFloat(0.1f, 4.0f);
   1918 					const float w3 = rnd.getFloat(0.1f, 4.0f);
   1919 
   1920 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
   1921 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
   1922 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
   1923 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
   1924 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
   1925 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
   1926 				}
   1927 				else
   1928 					DE_ASSERT(DE_FALSE);
   1929 			}
   1930 
   1931 			break;
   1932 		}
   1933 
   1934 		case FILLRULECASE_CLIPPED_PARTIAL:
   1935 		case FILLRULECASE_CLIPPED_FULL:
   1936 		{
   1937 			const float		quadSide	= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
   1938 			const tcu::Vec2 center		= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
   1939 			const float		rotation	= (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
   1940 			const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
   1941 			const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
   1942 			const tcu::Vec2 quad[4]		=
   1943 			{
   1944 				center + sideH + sideV,
   1945 				center + sideH - sideV,
   1946 				center - sideH - sideV,
   1947 				center - sideH + sideV,
   1948 			};
   1949 
   1950 			outData.resize(6);
   1951 			outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1952 			outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
   1953 			outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1954 			outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
   1955 			outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
   1956 			outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
   1957 			break;
   1958 		}
   1959 
   1960 		default:
   1961 			DE_ASSERT(DE_FALSE);
   1962 	}
   1963 }
   1964 
   1965 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
   1966 {
   1967 	static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
   1968 	{
   1969 		true,														// VkBool32			blendEnable;
   1970 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
   1971 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendColor;
   1972 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
   1973 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
   1974 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendAlpha;
   1975 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
   1976 		(VK_COLOR_COMPONENT_R_BIT |
   1977 		 VK_COLOR_COMPONENT_G_BIT |
   1978 		 VK_COLOR_COMPONENT_B_BIT |
   1979 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
   1980 	};
   1981 
   1982 	static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
   1983 	{
   1984 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
   1985 		DE_NULL,													// const void*									pNext;
   1986 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
   1987 		false,														// VkBool32										logicOpEnable;
   1988 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
   1989 		1u,															// deUint32										attachmentCount;
   1990 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
   1991 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
   1992 	};
   1993 
   1994 	return &colorBlendStateParams;
   1995 }
   1996 
   1997 
   1998 class FillRuleTestCase : public BaseRenderingTestCase
   1999 {
   2000 public:
   2001 								FillRuleTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
   2002 									: BaseRenderingTestCase	(context, name, description, sampleCount)
   2003 									, m_type				(type)
   2004 								{}
   2005 
   2006 	virtual TestInstance*		createInstance		(Context& context) const
   2007 								{
   2008 									return new FillRuleTestInstance(context, m_type, m_sampleCount);
   2009 								}
   2010 protected:
   2011 	const FillRuleTestInstance::FillRuleCaseType m_type;
   2012 };
   2013 
   2014 class CullingTestInstance : public BaseRenderingTestInstance
   2015 {
   2016 public:
   2017 													CullingTestInstance				(Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
   2018 														: BaseRenderingTestInstance		(context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
   2019 														, m_cullMode					(cullMode)
   2020 														, m_primitiveTopology			(primitiveTopology)
   2021 														, m_frontFace					(frontFace)
   2022 														, m_polygonMode					(polygonMode)
   2023 														, m_multisampling				(true)
   2024 													{}
   2025 	virtual
   2026 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo (void) const;
   2027 
   2028 	tcu::TestStatus									iterate							(void);
   2029 
   2030 private:
   2031 	void											generateVertices				(std::vector<tcu::Vec4>& outData) const;
   2032 	void											extractTriangles				(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
   2033 	void											extractLines					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
   2034 	void											extractPoints					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
   2035 	bool											triangleOrder					(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
   2036 
   2037 	const VkCullModeFlags							m_cullMode;
   2038 	const VkPrimitiveTopology						m_primitiveTopology;
   2039 	const VkFrontFace								m_frontFace;
   2040 	const VkPolygonMode								m_polygonMode;
   2041 	const bool										m_multisampling;
   2042 };
   2043 
   2044 
   2045 tcu::TestStatus CullingTestInstance::iterate (void)
   2046 {
   2047 	DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
   2048 
   2049 	tcu::Surface									resultImage						(m_renderSize, m_renderSize);
   2050 	std::vector<tcu::Vec4>							drawBuffer;
   2051 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
   2052 	std::vector<PointSceneSpec::ScenePoint>			points;
   2053 	std::vector<LineSceneSpec::SceneLine>			lines;
   2054 
   2055 	const InstanceInterface&						vk				= m_context.getInstanceInterface();
   2056 	const VkPhysicalDevice							physicalDevice	= m_context.getPhysicalDevice();
   2057 	const VkPhysicalDeviceFeatures					deviceFeatures	= getPhysicalDeviceFeatures(vk, physicalDevice);
   2058 
   2059 	if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
   2060 		TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
   2061 
   2062 	// generate scene
   2063 	generateVertices(drawBuffer);
   2064 	extractTriangles(triangles, drawBuffer);
   2065 
   2066 	if (m_polygonMode == VK_POLYGON_MODE_LINE)
   2067 		extractLines(triangles ,lines);
   2068 	else if (m_polygonMode == VK_POLYGON_MODE_POINT)
   2069 		extractPoints(triangles, points);
   2070 
   2071 	// draw image
   2072 	{
   2073 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
   2074 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
   2075 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
   2076 
   2077 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
   2078 	}
   2079 
   2080 	// compare
   2081 	{
   2082 		RasterizationArguments	args;
   2083 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
   2084 		bool					isCompareOk	= false;
   2085 
   2086 		args.numSamples		= m_multisampling ? 1 : 0;
   2087 		args.subpixelBits	= m_subpixelBits;
   2088 		args.redBits		= colorBits[0];
   2089 		args.greenBits		= colorBits[1];
   2090 		args.blueBits		= colorBits[2];
   2091 
   2092 		switch (m_polygonMode)
   2093 		{
   2094 			case VK_POLYGON_MODE_LINE:
   2095 			{
   2096 				LineSceneSpec scene;
   2097 				scene.lineWidth = 0;
   2098 				scene.lines.swap(lines);
   2099 				isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
   2100 				break;
   2101 			}
   2102 			case VK_POLYGON_MODE_POINT:
   2103 			{
   2104 				PointSceneSpec scene;
   2105 				scene.points.swap(points);
   2106 				isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
   2107 				break;
   2108 			}
   2109 			default:
   2110 			{
   2111 				TriangleSceneSpec scene;
   2112 				scene.triangles.swap(triangles);
   2113 				isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
   2114 				break;
   2115 			}
   2116 		}
   2117 
   2118 		if (isCompareOk)
   2119 			return tcu::TestStatus::pass("Pass");
   2120 		else
   2121 			return tcu::TestStatus::fail("Incorrect rendering");
   2122 	}
   2123 }
   2124 
   2125 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
   2126 {
   2127 	de::Random rnd(543210);
   2128 
   2129 	outData.resize(6);
   2130 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
   2131 	{
   2132 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
   2133 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
   2134 		outData[vtxNdx].z() = 0.0f;
   2135 		outData[vtxNdx].w() = 1.0f;
   2136 	}
   2137 }
   2138 
   2139 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
   2140 {
   2141 	const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
   2142 
   2143 	// No triangles
   2144 	if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
   2145 		return;
   2146 
   2147 	switch (m_primitiveTopology)
   2148 	{
   2149 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
   2150 		{
   2151 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
   2152 			{
   2153 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
   2154 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
   2155 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
   2156 
   2157 				if (triangleOrder(v0, v1, v2) != cullDirection)
   2158 				{
   2159 					TriangleSceneSpec::SceneTriangle tri;
   2160 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
   2161 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
   2162 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
   2163 
   2164 					outTriangles.push_back(tri);
   2165 				}
   2166 			}
   2167 			break;
   2168 		}
   2169 
   2170 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
   2171 		{
   2172 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
   2173 			{
   2174 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
   2175 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
   2176 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
   2177 
   2178 				if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
   2179 				{
   2180 					TriangleSceneSpec::SceneTriangle tri;
   2181 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
   2182 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
   2183 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
   2184 
   2185 					outTriangles.push_back(tri);
   2186 				}
   2187 			}
   2188 			break;
   2189 		}
   2190 
   2191 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
   2192 		{
   2193 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
   2194 			{
   2195 				const tcu::Vec4& v0 = vertices[0];
   2196 				const tcu::Vec4& v1 = vertices[vtxNdx + 0];
   2197 				const tcu::Vec4& v2 = vertices[vtxNdx + 1];
   2198 
   2199 				if (triangleOrder(v0, v1, v2) != cullDirection)
   2200 				{
   2201 					TriangleSceneSpec::SceneTriangle tri;
   2202 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
   2203 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
   2204 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
   2205 
   2206 					outTriangles.push_back(tri);
   2207 				}
   2208 			}
   2209 			break;
   2210 		}
   2211 
   2212 		default:
   2213 			DE_ASSERT(false);
   2214 	}
   2215 }
   2216 
   2217 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles,
   2218 										std::vector<LineSceneSpec::SceneLine>&			outLines) const
   2219 {
   2220 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
   2221 	{
   2222 		for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
   2223 		{
   2224 			LineSceneSpec::SceneLine line;
   2225 			line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
   2226 			line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
   2227 
   2228 			outLines.push_back(line);
   2229 		}
   2230 		LineSceneSpec::SceneLine line;
   2231 		line.positions[0] = outTriangles.at(triNdx).positions[2];
   2232 		line.positions[1] = outTriangles.at(triNdx).positions[0];
   2233 		outLines.push_back(line);
   2234 	}
   2235 }
   2236 
   2237 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>	&outTriangles,
   2238 										std::vector<PointSceneSpec::ScenePoint>			&outPoints) const
   2239 {
   2240 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
   2241 	{
   2242 		for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
   2243 		{
   2244 			PointSceneSpec::ScenePoint point;
   2245 			point.position = outTriangles.at(triNdx).positions[vrtxNdx];
   2246 			point.pointSize = 1.0f;
   2247 
   2248 			outPoints.push_back(point);
   2249 		}
   2250 	}
   2251 }
   2252 
   2253 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
   2254 {
   2255 	const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
   2256 	const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
   2257 	const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
   2258 
   2259 	// cross
   2260 	return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
   2261 }
   2262 
   2263 
   2264 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
   2265 {
   2266 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
   2267 	{
   2268 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
   2269 		DE_NULL,														// const void*								pNext;
   2270 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
   2271 		false,															// VkBool32									depthClipEnable;
   2272 		false,															// VkBool32									rasterizerDiscardEnable;
   2273 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
   2274 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
   2275 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
   2276 		VK_FALSE,														// VkBool32									depthBiasEnable;
   2277 		0.0f,															// float									depthBias;
   2278 		0.0f,															// float									depthBiasClamp;
   2279 		0.0f,															// float									slopeScaledDepthBias;
   2280 		getLineWidth(),													// float									lineWidth;
   2281 	};
   2282 
   2283 	rasterizationStateCreateInfo.lineWidth		= getLineWidth();
   2284 	rasterizationStateCreateInfo.cullMode		= m_cullMode;
   2285 	rasterizationStateCreateInfo.frontFace		= m_frontFace;
   2286 	rasterizationStateCreateInfo.polygonMode	= m_polygonMode;
   2287 
   2288 	return &rasterizationStateCreateInfo;
   2289 }
   2290 
   2291 class CullingTestCase : public BaseRenderingTestCase
   2292 {
   2293 public:
   2294 								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)
   2295 									: BaseRenderingTestCase	(context, name, description, sampleCount)
   2296 									, m_cullMode			(cullMode)
   2297 									, m_primitiveTopology	(primitiveTopology)
   2298 									, m_frontFace			(frontFace)
   2299 									, m_polygonMode			(polygonMode)
   2300 								{}
   2301 
   2302 	virtual TestInstance*		createInstance		(Context& context) const
   2303 								{
   2304 									return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
   2305 								}
   2306 protected:
   2307 	const VkCullModeFlags		m_cullMode;
   2308 	const VkPrimitiveTopology	m_primitiveTopology;
   2309 	const VkFrontFace			m_frontFace;
   2310 	const VkPolygonMode			m_polygonMode;
   2311 };
   2312 
   2313 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
   2314 {
   2315 public:
   2316 
   2317 								TriangleInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
   2318 									: BaseRenderingTestInstance	(context, sampleCount, DEFAULT_RENDER_SIZE)
   2319 									, m_primitiveTopology		(primitiveTopology)
   2320 									, m_projective				((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
   2321 									, m_iterationCount			(3)
   2322 									, m_iteration				(0)
   2323 									, m_allIterationsPassed		(true)
   2324 									, m_flatshade				((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
   2325 								{}
   2326 
   2327 	tcu::TestStatus				iterate								(void);
   2328 
   2329 
   2330 private:
   2331 	void						generateVertices					(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
   2332 	void						extractTriangles					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
   2333 
   2334 
   2335 	VkPrimitiveTopology			m_primitiveTopology;
   2336 	const bool					m_projective;
   2337 	const int					m_iterationCount;
   2338 	int							m_iteration;
   2339 	bool						m_allIterationsPassed;
   2340 	const deBool				m_flatshade;
   2341 };
   2342 
   2343 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
   2344 {
   2345 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   2346 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
   2347 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
   2348 	std::vector<tcu::Vec4>							drawBuffer;
   2349 	std::vector<tcu::Vec4>							colorBuffer;
   2350 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
   2351 
   2352 	// generate scene
   2353 	generateVertices(m_iteration, drawBuffer, colorBuffer);
   2354 	extractTriangles(triangles, drawBuffer, colorBuffer);
   2355 
   2356 	// log
   2357 	{
   2358 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
   2359 		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
   2360 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
   2361 	}
   2362 
   2363 	// draw image
   2364 	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
   2365 
   2366 	// compare
   2367 	{
   2368 		RasterizationArguments	args;
   2369 		TriangleSceneSpec		scene;
   2370 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
   2371 
   2372 		args.numSamples		= m_multisampling ? 1 : 0;
   2373 		args.subpixelBits	= m_subpixelBits;
   2374 		args.redBits		= colorBits[0];
   2375 		args.greenBits		= colorBits[1];
   2376 		args.blueBits		= colorBits[2];
   2377 
   2378 		scene.triangles.swap(triangles);
   2379 
   2380 		if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
   2381 			m_allIterationsPassed = false;
   2382 	}
   2383 
   2384 	// result
   2385 	if (++m_iteration == m_iterationCount)
   2386 	{
   2387 		if (m_allIterationsPassed)
   2388 			return tcu::TestStatus::pass("Pass");
   2389 		else
   2390 			return tcu::TestStatus::fail("Found invalid pixel values");
   2391 	}
   2392 	else
   2393 		return tcu::TestStatus::incomplete();
   2394 }
   2395 
   2396 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
   2397 {
   2398 	// use only red, green and blue
   2399 	const tcu::Vec4 colors[] =
   2400 	{
   2401 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
   2402 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
   2403 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
   2404 	};
   2405 
   2406 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
   2407 
   2408 	outVertices.resize(6);
   2409 	outColors.resize(6);
   2410 
   2411 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
   2412 	{
   2413 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
   2414 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
   2415 		outVertices[vtxNdx].z() = 0.0f;
   2416 
   2417 		if (!m_projective)
   2418 			outVertices[vtxNdx].w() = 1.0f;
   2419 		else
   2420 		{
   2421 			const float w = rnd.getFloat(0.2f, 4.0f);
   2422 
   2423 			outVertices[vtxNdx].x() *= w;
   2424 			outVertices[vtxNdx].y() *= w;
   2425 			outVertices[vtxNdx].z() *= w;
   2426 			outVertices[vtxNdx].w() = w;
   2427 		}
   2428 
   2429 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
   2430 	}
   2431 }
   2432 
   2433 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
   2434 {
   2435 	switch (m_primitiveTopology)
   2436 	{
   2437 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
   2438 		{
   2439 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
   2440 			{
   2441 				TriangleSceneSpec::SceneTriangle tri;
   2442 				tri.positions[0]	= vertices[vtxNdx + 0];
   2443 				tri.positions[1]	= vertices[vtxNdx + 1];
   2444 				tri.positions[2]	= vertices[vtxNdx + 2];
   2445 				tri.sharedEdge[0]	= false;
   2446 				tri.sharedEdge[1]	= false;
   2447 				tri.sharedEdge[2]	= false;
   2448 
   2449 				if (m_flatshade)
   2450 				{
   2451 					tri.colors[0] = colors[vtxNdx];
   2452 					tri.colors[1] = colors[vtxNdx];
   2453 					tri.colors[2] = colors[vtxNdx];
   2454 				}
   2455 				else
   2456 				{
   2457 					tri.colors[0] = colors[vtxNdx + 0];
   2458 					tri.colors[1] = colors[vtxNdx + 1];
   2459 					tri.colors[2] = colors[vtxNdx + 2];
   2460 				}
   2461 
   2462 				outTriangles.push_back(tri);
   2463 			}
   2464 			break;
   2465 		}
   2466 
   2467 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
   2468 		{
   2469 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
   2470 			{
   2471 				TriangleSceneSpec::SceneTriangle tri;
   2472 				tri.positions[0]	= vertices[vtxNdx + 0];
   2473 				tri.positions[1]	= vertices[vtxNdx + 1];
   2474 				tri.positions[2]	= vertices[vtxNdx + 2];
   2475 				tri.sharedEdge[0]	= false;
   2476 				tri.sharedEdge[1]	= false;
   2477 				tri.sharedEdge[2]	= false;
   2478 
   2479 				if (m_flatshade)
   2480 				{
   2481 					tri.colors[0] = colors[vtxNdx];
   2482 					tri.colors[1] = colors[vtxNdx];
   2483 					tri.colors[2] = colors[vtxNdx];
   2484 				}
   2485 				else
   2486 				{
   2487 					tri.colors[0] = colors[vtxNdx + 0];
   2488 					tri.colors[1] = colors[vtxNdx + 1];
   2489 					tri.colors[2] = colors[vtxNdx + 2];
   2490 				}
   2491 
   2492 				outTriangles.push_back(tri);
   2493 			}
   2494 			break;
   2495 		}
   2496 
   2497 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
   2498 		{
   2499 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
   2500 			{
   2501 				TriangleSceneSpec::SceneTriangle tri;
   2502 				tri.positions[0]	= vertices[0];
   2503 				tri.positions[1]	= vertices[vtxNdx + 0];
   2504 				tri.positions[2]	= vertices[vtxNdx + 1];
   2505 				tri.sharedEdge[0]	= false;
   2506 				tri.sharedEdge[1]	= false;
   2507 				tri.sharedEdge[2]	= false;
   2508 
   2509 				if (m_flatshade)
   2510 				{
   2511 					tri.colors[0] = colors[vtxNdx];
   2512 					tri.colors[1] = colors[vtxNdx];
   2513 					tri.colors[2] = colors[vtxNdx];
   2514 				}
   2515 				else
   2516 				{
   2517 					tri.colors[0] = colors[0];
   2518 					tri.colors[1] = colors[vtxNdx + 0];
   2519 					tri.colors[2] = colors[vtxNdx + 1];
   2520 				}
   2521 
   2522 				outTriangles.push_back(tri);
   2523 			}
   2524 			break;
   2525 		}
   2526 
   2527 		default:
   2528 			DE_ASSERT(false);
   2529 	}
   2530 }
   2531 
   2532 class TriangleInterpolationTestCase : public BaseRenderingTestCase
   2533 {
   2534 public:
   2535 								TriangleInterpolationTestCase	(tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
   2536 									: BaseRenderingTestCase		(context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
   2537 									, m_primitiveTopology		(primitiveTopology)
   2538 									, m_flags					(flags)
   2539 								{}
   2540 
   2541 	virtual TestInstance*		createInstance					(Context& context) const
   2542 								{
   2543 									return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
   2544 								}
   2545 protected:
   2546 	const VkPrimitiveTopology	m_primitiveTopology;
   2547 	const int					m_flags;
   2548 };
   2549 
   2550 class LineInterpolationTestInstance : public BaseRenderingTestInstance
   2551 {
   2552 public:
   2553 							LineInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
   2554 
   2555 	virtual tcu::TestStatus	iterate							(void);
   2556 
   2557 private:
   2558 	void					generateVertices				(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
   2559 	void					extractLines					(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
   2560 	virtual float			getLineWidth					(void) const;
   2561 
   2562 	VkPrimitiveTopology		m_primitiveTopology;
   2563 	const bool				m_projective;
   2564 	const int				m_iterationCount;
   2565 	const PrimitiveWideness	m_primitiveWideness;
   2566 
   2567 	int						m_iteration;
   2568 	bool					m_allIterationsPassed;
   2569 	float					m_maxLineWidth;
   2570 	std::vector<float>		m_lineWidths;
   2571 	bool					m_flatshade;
   2572 };
   2573 
   2574 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
   2575 	: BaseRenderingTestInstance			(context, sampleCount)
   2576 	, m_primitiveTopology				(primitiveTopology)
   2577 	, m_projective						((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
   2578 	, m_iterationCount					(3)
   2579 	, m_primitiveWideness				(wideness)
   2580 	, m_iteration						(0)
   2581 	, m_allIterationsPassed				(true)
   2582 	, m_maxLineWidth					(1.0f)
   2583 	, m_flatshade						((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
   2584 {
   2585 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
   2586 
   2587 	if (!context.getDeviceProperties().limits.strictLines)
   2588 		TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
   2589 
   2590 	// create line widths
   2591 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
   2592 	{
   2593 		m_lineWidths.resize(m_iterationCount, 1.0f);
   2594 	}
   2595 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
   2596 	{
   2597 		if (!m_context.getDeviceFeatures().wideLines)
   2598 			TCU_THROW(NotSupportedError , "wide line support required");
   2599 
   2600 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
   2601 
   2602 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
   2603 
   2604 		// no wide line support
   2605 		if (range[1] <= 1.0f)
   2606 			throw tcu::NotSupportedError("wide line support required");
   2607 
   2608 		// set hand picked sizes
   2609 		m_lineWidths.push_back(5.0f);
   2610 		m_lineWidths.push_back(10.0f);
   2611 		m_lineWidths.push_back(range[1]);
   2612 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
   2613 
   2614 		m_maxLineWidth = range[1];
   2615 	}
   2616 	else
   2617 		DE_ASSERT(false);
   2618 }
   2619 
   2620 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
   2621 {
   2622 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
   2623 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
   2624 	const float								lineWidth				= getLineWidth();
   2625 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
   2626 	std::vector<tcu::Vec4>					drawBuffer;
   2627 	std::vector<tcu::Vec4>					colorBuffer;
   2628 	std::vector<LineSceneSpec::SceneLine>	lines;
   2629 
   2630 	// supported?
   2631 	if (lineWidth <= m_maxLineWidth)
   2632 	{
   2633 		// generate scene
   2634 		generateVertices(m_iteration, drawBuffer, colorBuffer);
   2635 		extractLines(lines, drawBuffer, colorBuffer);
   2636 
   2637 		// log
   2638 		{
   2639 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
   2640 			for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
   2641 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
   2642 		}
   2643 
   2644 		// draw image
   2645 		drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
   2646 
   2647 		// compare
   2648 		{
   2649 			RasterizationArguments	args;
   2650 			LineSceneSpec			scene;
   2651 
   2652 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
   2653 
   2654 			args.numSamples		= m_multisampling ? 1 : 0;
   2655 			args.subpixelBits	= m_subpixelBits;
   2656 			args.redBits		= colorBits[0];
   2657 			args.greenBits		= colorBits[1];
   2658 			args.blueBits		= colorBits[2];
   2659 
   2660 			scene.lines.swap(lines);
   2661 			scene.lineWidth = getLineWidth();
   2662 
   2663 			if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
   2664 				m_allIterationsPassed = false;
   2665 		}
   2666 	}
   2667 	else
   2668 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
   2669 
   2670 	// result
   2671 	if (++m_iteration == m_iterationCount)
   2672 	{
   2673 		if (m_allIterationsPassed)
   2674 			return tcu::TestStatus::pass("Pass");
   2675 		else
   2676 			return tcu::TestStatus::fail("Incorrect rasterization");
   2677 	}
   2678 	else
   2679 		return tcu::TestStatus::incomplete();
   2680 }
   2681 
   2682 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
   2683 {
   2684 	// use only red, green and blue
   2685 	const tcu::Vec4 colors[] =
   2686 	{
   2687 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
   2688 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
   2689 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
   2690 	};
   2691 
   2692 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
   2693 
   2694 	outVertices.resize(6);
   2695 	outColors.resize(6);
   2696 
   2697 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
   2698 	{
   2699 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
   2700 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
   2701 		outVertices[vtxNdx].z() = 0.0f;
   2702 
   2703 		if (!m_projective)
   2704 			outVertices[vtxNdx].w() = 1.0f;
   2705 		else
   2706 		{
   2707 			const float w = rnd.getFloat(0.2f, 4.0f);
   2708 
   2709 			outVertices[vtxNdx].x() *= w;
   2710 			outVertices[vtxNdx].y() *= w;
   2711 			outVertices[vtxNdx].z() *= w;
   2712 			outVertices[vtxNdx].w() = w;
   2713 		}
   2714 
   2715 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
   2716 	}
   2717 }
   2718 
   2719 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
   2720 {
   2721 	switch (m_primitiveTopology)
   2722 	{
   2723 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
   2724 		{
   2725 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
   2726 			{
   2727 				LineSceneSpec::SceneLine line;
   2728 				line.positions[0] = vertices[vtxNdx + 0];
   2729 				line.positions[1] = vertices[vtxNdx + 1];
   2730 
   2731 				if (m_flatshade)
   2732 				{
   2733 					line.colors[0] = colors[vtxNdx];
   2734 					line.colors[1] = colors[vtxNdx];
   2735 				}
   2736 				else
   2737 				{
   2738 					line.colors[0] = colors[vtxNdx + 0];
   2739 					line.colors[1] = colors[vtxNdx + 1];
   2740 				}
   2741 
   2742 				outLines.push_back(line);
   2743 			}
   2744 			break;
   2745 		}
   2746 
   2747 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
   2748 		{
   2749 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
   2750 			{
   2751 				LineSceneSpec::SceneLine line;
   2752 				line.positions[0] = vertices[vtxNdx + 0];
   2753 				line.positions[1] = vertices[vtxNdx + 1];
   2754 
   2755 				if (m_flatshade)
   2756 				{
   2757 					line.colors[0] = colors[vtxNdx];
   2758 					line.colors[1] = colors[vtxNdx];
   2759 				}
   2760 				else
   2761 				{
   2762 					line.colors[0] = colors[vtxNdx + 0];
   2763 					line.colors[1] = colors[vtxNdx + 1];
   2764 				}
   2765 
   2766 				outLines.push_back(line);
   2767 			}
   2768 			break;
   2769 		}
   2770 
   2771 		default:
   2772 			DE_ASSERT(false);
   2773 	}
   2774 }
   2775 
   2776 float LineInterpolationTestInstance::getLineWidth (void) const
   2777 {
   2778 	return m_lineWidths[m_iteration];
   2779 }
   2780 
   2781 class LineInterpolationTestCase : public BaseRenderingTestCase
   2782 {
   2783 public:
   2784 								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)
   2785 									: BaseRenderingTestCase		(context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
   2786 									, m_primitiveTopology		(primitiveTopology)
   2787 									, m_flags					(flags)
   2788 									, m_wideness				(wideness)
   2789 								{}
   2790 
   2791 	virtual TestInstance*		createInstance					(Context& context) const
   2792 								{
   2793 									return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
   2794 								}
   2795 protected:
   2796 	const VkPrimitiveTopology	m_primitiveTopology;
   2797 	const int					m_flags;
   2798 	const PrimitiveWideness		m_wideness;
   2799 };
   2800 
   2801 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
   2802 {
   2803 	tcu::TestContext&	testCtx		=	rasterizationTests->getTestContext();
   2804 
   2805 	// .primitives
   2806 	{
   2807 		tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
   2808 
   2809 		rasterizationTests->addChild(primitives);
   2810 
   2811 		primitives->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
   2812 		primitives->addChild(new BaseTestCase<TriangleStripTestInstance>	(testCtx, "triangle_strip",		"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
   2813 		primitives->addChild(new BaseTestCase<TriangleFanTestInstance>		(testCtx, "triangle_fan",		"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
   2814 		primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
   2815 		primitives->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
   2816 		primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines_wide",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
   2817 		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));
   2818 		primitives->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",						PRIMITIVEWIDENESS_WIDE));
   2819 	}
   2820 
   2821 	// .fill_rules
   2822 	{
   2823 		tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
   2824 
   2825 		rasterizationTests->addChild(fillRules);
   2826 
   2827 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_BASIC));
   2828 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse",	"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_REVERSED));
   2829 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
   2830 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly",		"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
   2831 		fillRules->addChild(new FillRuleTestCase(testCtx,	"projected",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_PROJECTED));
   2832 	}
   2833 
   2834 	// .culling
   2835 	{
   2836 		static const struct CullMode
   2837 		{
   2838 			VkCullModeFlags	mode;
   2839 			const char*		prefix;
   2840 		} cullModes[] =
   2841 		{
   2842 			{ VK_CULL_MODE_FRONT_BIT,				"front_"	},
   2843 			{ VK_CULL_MODE_BACK_BIT,				"back_"		},
   2844 			{ VK_CULL_MODE_FRONT_AND_BACK,			"both_"		},
   2845 		};
   2846 		static const struct PrimitiveType
   2847 		{
   2848 			VkPrimitiveTopology	type;
   2849 			const char*			name;
   2850 		} primitiveTypes[] =
   2851 		{
   2852 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			"triangles"			},
   2853 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,			"triangle_strip"	},
   2854 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,			"triangle_fan"		},
   2855 		};
   2856 		static const struct FrontFaceOrder
   2857 		{
   2858 			VkFrontFace	mode;
   2859 			const char*	postfix;
   2860 		} frontOrders[] =
   2861 		{
   2862 			{ VK_FRONT_FACE_COUNTER_CLOCKWISE,	""			},
   2863 			{ VK_FRONT_FACE_CLOCKWISE,			"_reverse"	},
   2864 		};
   2865 
   2866 		static const struct PolygonMode
   2867 		{
   2868 			VkPolygonMode	mode;
   2869 			const char*		name;
   2870 		} polygonModes[] =
   2871 		{
   2872 			{ VK_POLYGON_MODE_FILL,		""		},
   2873 			{ VK_POLYGON_MODE_LINE,		"_line"		},
   2874 			{ VK_POLYGON_MODE_POINT,	"_point"	}
   2875 		};
   2876 
   2877 		tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
   2878 
   2879 		rasterizationTests->addChild(culling);
   2880 
   2881 		for (int cullModeNdx	= 0; cullModeNdx	< DE_LENGTH_OF_ARRAY(cullModes);		++cullModeNdx)
   2882 		for (int primitiveNdx	= 0; primitiveNdx	< DE_LENGTH_OF_ARRAY(primitiveTypes);	++primitiveNdx)
   2883 		for (int frontOrderNdx	= 0; frontOrderNdx	< DE_LENGTH_OF_ARRAY(frontOrders);		++frontOrderNdx)
   2884 		for (int polygonModeNdx = 0; polygonModeNdx	< DE_LENGTH_OF_ARRAY(polygonModes);		++polygonModeNdx)
   2885 		{
   2886 			if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
   2887 			{
   2888 				const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
   2889 				culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
   2890 			}
   2891 		}
   2892 	}
   2893 
   2894 	// .interpolation
   2895 	{
   2896 		tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
   2897 
   2898 		rasterizationTests->addChild(interpolation);
   2899 
   2900 		// .basic
   2901 		{
   2902 			tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
   2903 
   2904 			interpolation->addChild(basic);
   2905 
   2906 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE));
   2907 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip",	"Verify triangle strip interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_NONE));
   2908 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan",	"Verify triangle fan interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_NONE));
   2909 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
   2910 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip",		"Verify line strip interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
   2911 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
   2912 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide","Verify wide line strip interpolation",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
   2913 		}
   2914 
   2915 		// .projected
   2916 		{
   2917 			tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
   2918 
   2919 			interpolation->addChild(projected);
   2920 
   2921 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_PROJECTED));
   2922 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_strip",	"Verify triangle strip interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_PROJECTED));
   2923 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_fan",	"Verify triangle fan interpolation",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_PROJECTED));
   2924 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
   2925 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip",		"Verify line strip interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
   2926 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
   2927 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip_wide","Verify wide line strip interpolation",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
   2928 		}
   2929 	}
   2930 
   2931 	// .flatshading
   2932 	{
   2933 		tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
   2934 
   2935 		rasterizationTests->addChild(flatshading);
   2936 
   2937 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle flatshading",			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_FLATSHADE));
   2938 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip",	"Verify triangle strip flatshading",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_FLATSHADE));
   2939 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan",	"Verify triangle fan flatshading",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_FLATSHADE));
   2940 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line flatshading",				VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
   2941 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip",		"Verify line strip flatshading",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
   2942 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line flatshading",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
   2943 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide","Verify wide line strip flatshading",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
   2944 	}
   2945 
   2946 	const VkSampleCountFlagBits samples[] =
   2947 	{
   2948 		VK_SAMPLE_COUNT_2_BIT,
   2949 		VK_SAMPLE_COUNT_4_BIT,
   2950 		VK_SAMPLE_COUNT_8_BIT,
   2951 		VK_SAMPLE_COUNT_16_BIT,
   2952 		VK_SAMPLE_COUNT_32_BIT,
   2953 		VK_SAMPLE_COUNT_64_BIT
   2954 	};
   2955 
   2956 	for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
   2957 	{
   2958 		std::ostringstream caseName;
   2959 
   2960 		caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
   2961 
   2962 		// .primitives
   2963 		{
   2964 			tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
   2965 
   2966 			rasterizationTests->addChild(primitives);
   2967 
   2968 			primitives->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles",			"Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",					samples[samplesNdx]));
   2969 			primitives->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",						PRIMITIVEWIDENESS_NARROW,	samples[samplesNdx]));
   2970 			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]));
   2971 			primitives->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points",				"Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",						PRIMITIVEWIDENESS_WIDE,		samples[samplesNdx]));
   2972 		}
   2973 
   2974 		// .fill_rules
   2975 		{
   2976 			tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
   2977 
   2978 			rasterizationTests->addChild(fillRules);
   2979 
   2980 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_BASIC,			samples[samplesNdx]));
   2981 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse",	"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_REVERSED,		samples[samplesNdx]));
   2982 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,	samples[samplesNdx]));
   2983 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly",		"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,	samples[samplesNdx]));
   2984 			fillRules->addChild(new FillRuleTestCase(testCtx,	"projected",			"Verify fill rules",	FillRuleTestInstance::FILLRULECASE_PROJECTED,		samples[samplesNdx]));
   2985 		}
   2986 
   2987 		// .interpolation
   2988 		{
   2989 			tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
   2990 
   2991 			rasterizationTests->addChild(interpolation);
   2992 
   2993 			interpolation->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles",		"Verify triangle interpolation",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE,								samples[samplesNdx]));
   2994 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines",			"Verify line interpolation",			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	samples[samplesNdx]));
   2995 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide",		"Verify wide line interpolation",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		samples[samplesNdx]));
   2996 		}
   2997 	}
   2998 }
   2999 
   3000 } // anonymous
   3001 
   3002 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
   3003 {
   3004 	return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
   3005 }
   3006 
   3007 } // rasterization
   3008 } // vkt
   3009